ruby-magic 0.4.0 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +38 -0
- data/CONTRIBUTORS.md +1 -2
- data/dependencies.yml +6 -77
- data/ext/magic/common.h +11 -7
- data/ext/magic/extconf.rb +21 -2
- data/ext/magic/functions.c +32 -14
- data/ext/magic/functions.h +18 -12
- data/ext/magic/ruby-magic.c +536 -315
- data/ext/magic/ruby-magic.h +96 -135
- data/lib/magic/version.rb +1 -1
- data/lib/magic.rb +19 -1
- data.tar.gz.sig +3 -0
- metadata +33 -8
- metadata.gz.sig +1 -0
    
        data/ext/magic/ruby-magic.c
    CHANGED
    
    | @@ -4,6 +4,77 @@ extern "C" { | |
| 4 4 |  | 
| 5 5 | 
             
            #include "ruby-magic.h"
         | 
| 6 6 |  | 
| 7 | 
            +
            static int rb_mgc_do_not_auto_load;
         | 
| 8 | 
            +
            static int rb_mgc_do_not_stop_on_error;
         | 
| 9 | 
            +
            static int rb_mgc_warning;
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            static ID id_at_flags;
         | 
| 12 | 
            +
            static ID id_at_paths;
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            static VALUE rb_cMagic;
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            static VALUE rb_mgc_eError;
         | 
| 17 | 
            +
            static VALUE rb_mgc_eMagicError;
         | 
| 18 | 
            +
            static VALUE rb_mgc_eLibraryError;
         | 
| 19 | 
            +
            static VALUE rb_mgc_eNotImplementedError;
         | 
| 20 | 
            +
            static VALUE rb_mgc_eParameterError;
         | 
| 21 | 
            +
            static VALUE rb_mgc_eFlagsError;
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            static const rb_data_type_t rb_mgc_type;
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            static VALUE magic_get_parameter_internal(void *data);
         | 
| 26 | 
            +
            static VALUE magic_set_parameter_internal(void *data);
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            static VALUE magic_get_flags_internal(void *data);
         | 
| 29 | 
            +
            static VALUE magic_set_flags_internal(void *data);
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            static VALUE magic_load_internal(void *data);
         | 
| 32 | 
            +
            static VALUE magic_load_buffers_internal(void *data);
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            static VALUE magic_compile_internal(void *data);
         | 
| 35 | 
            +
            static VALUE magic_check_internal(void *data);
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            static VALUE magic_file_internal(void *data);
         | 
| 38 | 
            +
            static VALUE magic_buffer_internal(void *data);
         | 
| 39 | 
            +
            static VALUE magic_descriptor_internal(void *data);
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            static VALUE magic_close_internal(void *data);
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            static void *nogvl_magic_load(void *data);
         | 
| 44 | 
            +
            static void *nogvl_magic_compile(void *data);
         | 
| 45 | 
            +
            static void *nogvl_magic_check(void *data);
         | 
| 46 | 
            +
            static void *nogvl_magic_file(void *data);
         | 
| 47 | 
            +
            static void *nogvl_magic_descriptor(void *data);
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            static void *magic_library_open(void);
         | 
| 50 | 
            +
            static void magic_library_close(void *data);
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            static VALUE magic_allocate(VALUE klass);
         | 
| 53 | 
            +
            static void magic_mark(void *data);
         | 
| 54 | 
            +
            static void magic_free(void *data);
         | 
| 55 | 
            +
            static size_t magic_size(const void *data);
         | 
| 56 | 
            +
            #if defined(HAVE_RUBY_GC_COMPACT)
         | 
| 57 | 
            +
            static void magic_compact(void *data);
         | 
| 58 | 
            +
            #endif
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            static VALUE magic_exception_wrapper(VALUE value);
         | 
| 61 | 
            +
            static VALUE magic_exception(void *data);
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            static VALUE magic_library_error(VALUE klass, void *data);
         | 
| 64 | 
            +
            static VALUE magic_generic_error(VALUE klass, int magic_errno,
         | 
| 65 | 
            +
            				 const char *magic_error);
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            static VALUE magic_lock(VALUE object, VALUE (*function)(ANYARGS),
         | 
| 68 | 
            +
            			void *data);
         | 
| 69 | 
            +
            static VALUE magic_unlock(VALUE object);
         | 
| 70 | 
            +
             | 
| 71 | 
            +
            static VALUE magic_return(void *data);
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            static int magic_get_flags(VALUE object);
         | 
| 74 | 
            +
            static void magic_set_flags(VALUE object, int flags);
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            static VALUE magic_set_paths(VALUE object, VALUE value);
         | 
| 77 | 
            +
             | 
| 7 78 | 
             
            /*
         | 
| 8 79 | 
             
             * call-seq:
         | 
| 9 80 | 
             
             *    Magic.do_not_auto_load -> boolean
         | 
| @@ -56,6 +127,7 @@ VALUE | |
| 56 127 | 
             
            rb_mgc_set_do_not_auto_load_global(RB_UNUSED_VAR(VALUE object), VALUE value)
         | 
| 57 128 | 
             
            {
         | 
| 58 129 | 
             
            	rb_mgc_do_not_auto_load = RVAL2CBOOL(value);
         | 
| 130 | 
            +
             | 
| 59 131 | 
             
            	return value;
         | 
| 60 132 | 
             
            }
         | 
| 61 133 |  | 
| @@ -96,6 +168,7 @@ VALUE | |
| 96 168 | 
             
            rb_mgc_set_do_not_stop_on_error_global(RB_UNUSED_VAR(VALUE object), VALUE value)
         | 
| 97 169 | 
             
            {
         | 
| 98 170 | 
             
            	rb_mgc_do_not_stop_on_error = RVAL2CBOOL(value);
         | 
| 171 | 
            +
             | 
| 99 172 | 
             
            	return value;
         | 
| 100 173 | 
             
            }
         | 
| 101 174 |  | 
| @@ -117,7 +190,7 @@ rb_mgc_set_do_not_stop_on_error_global(RB_UNUSED_VAR(VALUE object), VALUE value) | |
| 117 190 | 
             
            VALUE
         | 
| 118 191 | 
             
            rb_mgc_initialize(VALUE object, VALUE arguments)
         | 
| 119 192 | 
             
            {
         | 
| 120 | 
            -
            	 | 
| 193 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 121 194 | 
             
            	const char *klass = "Magic";
         | 
| 122 195 |  | 
| 123 196 | 
             
            	if (!NIL_P(object))
         | 
| @@ -127,21 +200,22 @@ rb_mgc_initialize(VALUE object, VALUE arguments) | |
| 127 200 | 
             
            		MAGIC_WARNING(0, "%s::new() does not take block; use %s::open() instead",
         | 
| 128 201 | 
             
            				 klass, klass);
         | 
| 129 202 |  | 
| 130 | 
            -
            	if(RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_STOP_ON_ERROR']")))
         | 
| 203 | 
            +
            	if (RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_STOP_ON_ERROR']")))
         | 
| 131 204 | 
             
            		rb_mgc_do_not_stop_on_error = 1;
         | 
| 132 205 |  | 
| 133 | 
            -
            	if(RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_AUTOLOAD']")))
         | 
| 206 | 
            +
            	if (RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_AUTOLOAD']")))
         | 
| 134 207 | 
             
            		rb_mgc_do_not_auto_load = 1;
         | 
| 135 208 |  | 
| 136 | 
            -
            	MAGIC_OBJECT( | 
| 137 | 
            -
             | 
| 209 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 210 | 
            +
             | 
| 211 | 
            +
            	mgc->stop_on_errors = 1;
         | 
| 138 212 | 
             
            	if (rb_mgc_do_not_stop_on_error)
         | 
| 139 | 
            -
            		 | 
| 213 | 
            +
            		mgc->stop_on_errors = 0;
         | 
| 140 214 |  | 
| 141 | 
            -
            	 | 
| 142 | 
            -
             | 
| 215 | 
            +
            	mgc->mutex = rb_class_new_instance(0, 0, rb_const_get(rb_cObject,
         | 
| 216 | 
            +
            					   rb_intern("Mutex")));
         | 
| 143 217 |  | 
| 144 | 
            -
            	magic_set_flags(object,  | 
| 218 | 
            +
            	magic_set_flags(object, MAGIC_NONE);
         | 
| 145 219 | 
             
            	magic_set_paths(object, RARRAY_EMPTY);
         | 
| 146 220 |  | 
| 147 221 | 
             
            	if (rb_mgc_do_not_auto_load) {
         | 
| @@ -153,6 +227,7 @@ rb_mgc_initialize(VALUE object, VALUE arguments) | |
| 153 227 | 
             
            	}
         | 
| 154 228 |  | 
| 155 229 | 
             
            	rb_mgc_load(object, arguments);
         | 
| 230 | 
            +
             | 
| 156 231 | 
             
            	return object;
         | 
| 157 232 | 
             
            }
         | 
| 158 233 |  | 
| @@ -165,12 +240,12 @@ rb_mgc_initialize(VALUE object, VALUE arguments) | |
| 165 240 | 
             
            VALUE
         | 
| 166 241 | 
             
            rb_mgc_get_do_not_stop_on_error(VALUE object)
         | 
| 167 242 | 
             
            {
         | 
| 168 | 
            -
            	 | 
| 243 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 169 244 |  | 
| 170 245 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 171 | 
            -
            	MAGIC_OBJECT( | 
| 246 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 172 247 |  | 
| 173 | 
            -
            	return CBOOL2RVAL(! | 
| 248 | 
            +
            	return CBOOL2RVAL(!mgc->stop_on_errors);
         | 
| 174 249 | 
             
            }
         | 
| 175 250 |  | 
| 176 251 | 
             
            /*
         | 
| @@ -182,12 +257,13 @@ rb_mgc_get_do_not_stop_on_error(VALUE object) | |
| 182 257 | 
             
            VALUE
         | 
| 183 258 | 
             
            rb_mgc_set_do_not_stop_on_error(VALUE object, VALUE value)
         | 
| 184 259 | 
             
            {
         | 
| 185 | 
            -
            	 | 
| 260 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 186 261 |  | 
| 187 262 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 188 | 
            -
            	MAGIC_OBJECT( | 
| 263 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 264 | 
            +
             | 
| 265 | 
            +
            	mgc->stop_on_errors = !RVAL2CBOOL(value);
         | 
| 189 266 |  | 
| 190 | 
            -
            	mo->stop_on_errors = !RVAL2CBOOL(value);
         | 
| 191 267 | 
             
            	return value;
         | 
| 192 268 | 
             
            }
         | 
| 193 269 |  | 
| @@ -229,14 +305,15 @@ rb_mgc_open_p(VALUE object) | |
| 229 305 | 
             
            VALUE
         | 
| 230 306 | 
             
            rb_mgc_close(VALUE object)
         | 
| 231 307 | 
             
            {
         | 
| 232 | 
            -
            	 | 
| 308 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 233 309 |  | 
| 234 310 | 
             
            	if (MAGIC_CLOSED_P(object))
         | 
| 235 311 | 
             
            		return Qnil;
         | 
| 236 312 |  | 
| 237 | 
            -
            	MAGIC_OBJECT( | 
| 238 | 
            -
             | 
| 239 | 
            -
             | 
| 313 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 314 | 
            +
             | 
| 315 | 
            +
            	if (mgc) {
         | 
| 316 | 
            +
            		MAGIC_SYNCHRONIZED(magic_close_internal, mgc);
         | 
| 240 317 | 
             
            		if (DATA_P(object))
         | 
| 241 318 | 
             
            			DATA_PTR(object) = NULL;
         | 
| 242 319 | 
             
            	}
         | 
| @@ -263,12 +340,13 @@ rb_mgc_close(VALUE object) | |
| 263 340 | 
             
            VALUE
         | 
| 264 341 | 
             
            rb_mgc_close_p(VALUE object)
         | 
| 265 342 | 
             
            {
         | 
| 266 | 
            -
            	 | 
| 343 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 267 344 | 
             
            	magic_t cookie = NULL;
         | 
| 268 345 |  | 
| 269 | 
            -
            	MAGIC_OBJECT( | 
| 270 | 
            -
             | 
| 271 | 
            -
             | 
| 346 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 347 | 
            +
             | 
| 348 | 
            +
            	if (mgc)
         | 
| 349 | 
            +
            		cookie = mgc->cookie;
         | 
| 272 350 |  | 
| 273 351 | 
             
            	if (DATA_P(object) && cookie)
         | 
| 274 352 | 
             
            		return Qfalse;
         | 
| @@ -295,14 +373,17 @@ rb_mgc_get_paths(VALUE object) | |
| 295 373 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 296 374 |  | 
| 297 375 | 
             
            	value = rb_ivar_get(object, id_at_paths);
         | 
| 298 | 
            -
            	if (!NIL_P(value) && !RARRAY_EMPTY_P(value) | 
| 376 | 
            +
            	if (!NIL_P(value) && !RARRAY_EMPTY_P(value))
         | 
| 299 377 | 
             
            		return value;
         | 
| 300 378 |  | 
| 301 | 
            -
            	 | 
| 302 | 
            -
            	 | 
| 303 | 
            -
             | 
| 379 | 
            +
            	value = rb_funcall(rb_cMagic, rb_intern("default_paths"), 0);
         | 
| 380 | 
            +
            	if (getenv("MAGIC") || NIL_P(value)) {
         | 
| 381 | 
            +
            		cstring = magic_getpath_wrapper();
         | 
| 382 | 
            +
            		value = magic_split(CSTR2RVAL(cstring), CSTR2RVAL(":"));
         | 
| 383 | 
            +
            		RB_GC_GUARD(value);
         | 
| 384 | 
            +
            	}
         | 
| 304 385 |  | 
| 305 | 
            -
            	return value;
         | 
| 386 | 
            +
            	return magic_set_paths(object, value);
         | 
| 306 387 | 
             
            }
         | 
| 307 388 |  | 
| 308 389 | 
             
            /*
         | 
| @@ -313,28 +394,34 @@ VALUE | |
| 313 394 | 
             
            rb_mgc_get_parameter(VALUE object, VALUE tag)
         | 
| 314 395 | 
             
            {
         | 
| 315 396 | 
             
            	int local_errno;
         | 
| 316 | 
            -
            	 | 
| 317 | 
            -
            	 | 
| 397 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 398 | 
            +
            	rb_mgc_arguments_t mga;
         | 
| 318 399 |  | 
| 319 400 | 
             
            	MAGIC_CHECK_INTEGER_TYPE(tag);
         | 
| 401 | 
            +
             | 
| 320 402 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 321 | 
            -
            	 | 
| 403 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 322 404 |  | 
| 323 | 
            -
            	 | 
| 405 | 
            +
            	mga = (rb_mgc_arguments_t) {
         | 
| 406 | 
            +
            		.magic_object = mgc,
         | 
| 407 | 
            +
            		.parameter = {
         | 
| 408 | 
            +
            			.tag = NUM2INT(tag),
         | 
| 409 | 
            +
            		},
         | 
| 410 | 
            +
            	};
         | 
| 324 411 |  | 
| 325 | 
            -
            	MAGIC_SYNCHRONIZED(magic_get_parameter_internal, & | 
| 412 | 
            +
            	MAGIC_SYNCHRONIZED(magic_get_parameter_internal, &mga);
         | 
| 326 413 | 
             
            	local_errno = errno;
         | 
| 327 414 |  | 
| 328 | 
            -
            	if ( | 
| 415 | 
            +
            	if (mga.status < 0)  {
         | 
| 329 416 | 
             
            		if (local_errno == EINVAL)
         | 
| 330 417 | 
             
            			MAGIC_GENERIC_ERROR(rb_mgc_eParameterError,
         | 
| 331 418 | 
             
            					    local_errno,
         | 
| 332 419 | 
             
            					    E_PARAM_INVALID_TYPE);
         | 
| 333 420 |  | 
| 334 | 
            -
            		MAGIC_LIBRARY_ERROR( | 
| 421 | 
            +
            		MAGIC_LIBRARY_ERROR(mgc);
         | 
| 335 422 | 
             
            	}
         | 
| 336 423 |  | 
| 337 | 
            -
            	return SIZET2NUM( | 
| 424 | 
            +
            	return SIZET2NUM(mga.parameter.value);
         | 
| 338 425 | 
             
            }
         | 
| 339 426 |  | 
| 340 427 | 
             
            /*
         | 
| @@ -345,21 +432,27 @@ VALUE | |
| 345 432 | 
             
            rb_mgc_set_parameter(VALUE object, VALUE tag, VALUE value)
         | 
| 346 433 | 
             
            {
         | 
| 347 434 | 
             
            	int local_errno;
         | 
| 348 | 
            -
            	 | 
| 349 | 
            -
            	 | 
| 435 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 436 | 
            +
            	rb_mgc_arguments_t mga;
         | 
| 350 437 |  | 
| 351 438 | 
             
            	MAGIC_CHECK_INTEGER_TYPE(tag);
         | 
| 352 439 | 
             
            	MAGIC_CHECK_INTEGER_TYPE(value);
         | 
| 440 | 
            +
             | 
| 353 441 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 354 | 
            -
            	 | 
| 442 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 355 443 |  | 
| 356 | 
            -
            	 | 
| 357 | 
            -
             | 
| 444 | 
            +
            	mga = (rb_mgc_arguments_t) {
         | 
| 445 | 
            +
            		.magic_object = mgc,
         | 
| 446 | 
            +
            		.parameter = {
         | 
| 447 | 
            +
            			.tag   = NUM2INT(tag),
         | 
| 448 | 
            +
            			.value = NUM2SIZET(value),
         | 
| 449 | 
            +
            		},
         | 
| 450 | 
            +
            	};
         | 
| 358 451 |  | 
| 359 | 
            -
            	MAGIC_SYNCHRONIZED(magic_set_parameter_internal, & | 
| 452 | 
            +
            	MAGIC_SYNCHRONIZED(magic_set_parameter_internal, &mga);
         | 
| 360 453 | 
             
            	local_errno = errno;
         | 
| 361 454 |  | 
| 362 | 
            -
            	if ( | 
| 455 | 
            +
            	if (mga.status < 0)  {
         | 
| 363 456 | 
             
            		switch (local_errno) {
         | 
| 364 457 | 
             
            		case EINVAL:
         | 
| 365 458 | 
             
            			MAGIC_GENERIC_ERROR(rb_mgc_eParameterError,
         | 
| @@ -370,7 +463,8 @@ rb_mgc_set_parameter(VALUE object, VALUE tag, VALUE value) | |
| 370 463 | 
             
            					    local_errno,
         | 
| 371 464 | 
             
            					    E_PARAM_INVALID_VALUE);
         | 
| 372 465 | 
             
            		}
         | 
| 373 | 
            -
             | 
| 466 | 
            +
             | 
| 467 | 
            +
            		MAGIC_LIBRARY_ERROR(mgc);
         | 
| 374 468 | 
             
            	}
         | 
| 375 469 |  | 
| 376 470 | 
             
            	return Qnil;
         | 
| @@ -393,19 +487,23 @@ VALUE | |
| 393 487 | 
             
            rb_mgc_get_flags(VALUE object)
         | 
| 394 488 | 
             
            {
         | 
| 395 489 | 
             
            	int local_errno;
         | 
| 396 | 
            -
            	 | 
| 397 | 
            -
            	 | 
| 490 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 491 | 
            +
            	rb_mgc_arguments_t mga;
         | 
| 398 492 |  | 
| 399 493 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 400 | 
            -
            	 | 
| 494 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 495 | 
            +
             | 
| 496 | 
            +
            	mga = (rb_mgc_arguments_t) {
         | 
| 497 | 
            +
            		.magic_object = mgc,
         | 
| 498 | 
            +
            	};
         | 
| 401 499 |  | 
| 402 | 
            -
            	MAGIC_SYNCHRONIZED(magic_get_flags_internal, & | 
| 500 | 
            +
            	MAGIC_SYNCHRONIZED(magic_get_flags_internal, &mga);
         | 
| 403 501 | 
             
            	local_errno = errno;
         | 
| 404 502 |  | 
| 405 | 
            -
            	if ( | 
| 503 | 
            +
            	if (mga.status < 0 && local_errno == ENOSYS)
         | 
| 406 504 | 
             
            		return rb_ivar_get(object, id_at_flags);
         | 
| 407 505 |  | 
| 408 | 
            -
            	return INT2NUM( | 
| 506 | 
            +
            	return INT2NUM(mga.flags);
         | 
| 409 507 | 
             
            }
         | 
| 410 508 |  | 
| 411 509 | 
             
            /*
         | 
| @@ -422,19 +520,43 @@ VALUE | |
| 422 520 | 
             
            rb_mgc_set_flags(VALUE object, VALUE value)
         | 
| 423 521 | 
             
            {
         | 
| 424 522 | 
             
            	int local_errno;
         | 
| 425 | 
            -
            	 | 
| 426 | 
            -
            	 | 
| 523 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 524 | 
            +
            	rb_mgc_arguments_t mga;
         | 
| 525 | 
            +
            	const char *klass = "Magic";
         | 
| 526 | 
            +
            	const char *flag = NULL;
         | 
| 427 527 |  | 
| 428 528 | 
             
            	MAGIC_CHECK_INTEGER_TYPE(value);
         | 
| 529 | 
            +
             | 
| 429 530 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 430 | 
            -
            	 | 
| 531 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 532 | 
            +
             | 
| 533 | 
            +
            	mga = (rb_mgc_arguments_t) {
         | 
| 534 | 
            +
            		.magic_object = mgc,
         | 
| 535 | 
            +
            		.flags = NUM2INT(value),
         | 
| 536 | 
            +
            	};
         | 
| 537 | 
            +
             | 
| 538 | 
            +
            	if (mga.flags < 0)
         | 
| 539 | 
            +
            		MAGIC_GENERIC_ERROR(rb_mgc_eFlagsError, EINVAL,
         | 
| 540 | 
            +
            				    E_FLAG_INVALID_TYPE);
         | 
| 541 | 
            +
             | 
| 542 | 
            +
            	if (mga.flags & MAGIC_DEBUG)
         | 
| 543 | 
            +
            		flag = "DEBUG";
         | 
| 544 | 
            +
            	else if (mga.flags & MAGIC_CHECK)
         | 
| 545 | 
            +
            		flag = "CHECK";
         | 
| 546 | 
            +
             | 
| 547 | 
            +
            	if (flag) {
         | 
| 548 | 
            +
            		if (!NIL_P(object))
         | 
| 549 | 
            +
            			klass = rb_obj_classname(object);
         | 
| 431 550 |  | 
| 432 | 
            -
             | 
| 551 | 
            +
            		MAGIC_WARNING(0, "%s::%s flag is set; verbose information will "
         | 
| 552 | 
            +
            				 "now be printed to the standard error output",
         | 
| 553 | 
            +
            				 klass, flag);
         | 
| 554 | 
            +
            	}
         | 
| 433 555 |  | 
| 434 | 
            -
            	MAGIC_SYNCHRONIZED(magic_set_flags_internal, & | 
| 556 | 
            +
            	MAGIC_SYNCHRONIZED(magic_set_flags_internal, &mga);
         | 
| 435 557 | 
             
            	local_errno = errno;
         | 
| 436 558 |  | 
| 437 | 
            -
            	if ( | 
| 559 | 
            +
            	if (mga.status < 0)  {
         | 
| 438 560 | 
             
            		switch (local_errno) {
         | 
| 439 561 | 
             
            		case EINVAL:
         | 
| 440 562 | 
             
            			MAGIC_GENERIC_ERROR(rb_mgc_eFlagsError,
         | 
| @@ -445,10 +567,11 @@ rb_mgc_set_flags(VALUE object, VALUE value) | |
| 445 567 | 
             
            					    local_errno,
         | 
| 446 568 | 
             
            					    E_FLAG_NOT_IMPLEMENTED);
         | 
| 447 569 | 
             
            		}
         | 
| 448 | 
            -
             | 
| 570 | 
            +
             | 
| 571 | 
            +
            		MAGIC_LIBRARY_ERROR(mgc);
         | 
| 449 572 | 
             
            	}
         | 
| 450 573 |  | 
| 451 | 
            -
            	return rb_ivar_set(object, id_at_flags, INT2NUM( | 
| 574 | 
            +
            	return rb_ivar_set(object, id_at_flags, INT2NUM(mga.flags));
         | 
| 452 575 | 
             
            }
         | 
| 453 576 |  | 
| 454 577 | 
             
            /*
         | 
| @@ -464,8 +587,8 @@ rb_mgc_set_flags(VALUE object, VALUE value) | |
| 464 587 | 
             
            VALUE
         | 
| 465 588 | 
             
            rb_mgc_load(VALUE object, VALUE arguments)
         | 
| 466 589 | 
             
            {
         | 
| 467 | 
            -
            	 | 
| 468 | 
            -
            	 | 
| 590 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 591 | 
            +
            	rb_mgc_arguments_t mga;
         | 
| 469 592 | 
             
            	const char *klass = "Magic";
         | 
| 470 593 | 
             
            	VALUE value = Qundef;
         | 
| 471 594 |  | 
| @@ -473,40 +596,48 @@ rb_mgc_load(VALUE object, VALUE arguments) | |
| 473 596 | 
             
            		arguments = magic_flatten(arguments);
         | 
| 474 597 |  | 
| 475 598 | 
             
            	MAGIC_CHECK_ARRAY_OF_STRINGS(arguments);
         | 
| 599 | 
            +
             | 
| 476 600 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 477 | 
            -
            	 | 
| 601 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 478 602 |  | 
| 479 603 | 
             
            	if (rb_mgc_do_not_auto_load) {
         | 
| 480 604 | 
             
            		if (!NIL_P(object))
         | 
| 481 605 | 
             
            			klass = rb_obj_classname(object);
         | 
| 482 606 |  | 
| 483 607 | 
             
            		MAGIC_WARNING(2, "%s::do_not_auto_load is set; using %s#load "
         | 
| 484 | 
            -
             | 
| 485 | 
            -
             | 
| 608 | 
            +
            				 "will load Magic database from a file",
         | 
| 609 | 
            +
            				 klass, klass);
         | 
| 486 610 | 
             
            	}
         | 
| 487 611 |  | 
| 488 | 
            -
            	 | 
| 612 | 
            +
            	if (RARRAY_EMPTY_P(arguments))
         | 
| 613 | 
            +
            		arguments = rb_mgc_get_paths(object);
         | 
| 489 614 |  | 
| 490 | 
            -
            	 | 
| 491 | 
            -
             | 
| 492 | 
            -
            		ma.type.file.path = RVAL2CSTR(value);
         | 
| 493 | 
            -
            	}
         | 
| 494 | 
            -
            	else
         | 
| 495 | 
            -
            		ma.type.file.path = magic_getpath_wrapper();
         | 
| 615 | 
            +
            	value = magic_join(arguments, CSTR2RVAL(":"));
         | 
| 616 | 
            +
            	RB_GC_GUARD(value);
         | 
| 496 617 |  | 
| 497 618 | 
             
            	magic_set_paths(object, RARRAY_EMPTY);
         | 
| 498 619 |  | 
| 499 | 
            -
            	 | 
| 500 | 
            -
             | 
| 501 | 
            -
            		 | 
| 502 | 
            -
             | 
| 620 | 
            +
            	mga = (rb_mgc_arguments_t) {
         | 
| 621 | 
            +
            		.magic_object = mgc,
         | 
| 622 | 
            +
            		.file = {
         | 
| 623 | 
            +
            			.path = RVAL2CSTR(value),
         | 
| 624 | 
            +
            		},
         | 
| 625 | 
            +
            		.flags = magic_get_flags(object),
         | 
| 626 | 
            +
            	};
         | 
| 627 | 
            +
             | 
| 628 | 
            +
            	MAGIC_SYNCHRONIZED(magic_load_internal, &mga);
         | 
| 629 | 
            +
            	if (mga.status < 0) {
         | 
| 630 | 
            +
            		mgc->database_loaded = 0;
         | 
| 631 | 
            +
            		MAGIC_LIBRARY_ERROR(mgc);
         | 
| 503 632 | 
             
            	}
         | 
| 504 | 
            -
            	mo->database_loaded = 1;
         | 
| 505 633 |  | 
| 506 | 
            -
            	 | 
| 507 | 
            -
             | 
| 634 | 
            +
            	mgc->database_loaded = 1;
         | 
| 635 | 
            +
             | 
| 636 | 
            +
            	value = magic_split(CSTR2RVAL(mga.file.path), CSTR2RVAL(":"));
         | 
| 508 637 | 
             
            	RB_GC_GUARD(value);
         | 
| 509 638 |  | 
| 639 | 
            +
            	magic_set_paths(object, value);
         | 
| 640 | 
            +
             | 
| 510 641 | 
             
            	return Qnil;
         | 
| 511 642 | 
             
            }
         | 
| 512 643 |  | 
| @@ -522,8 +653,8 @@ rb_mgc_load_buffers(VALUE object, VALUE arguments) | |
| 522 653 | 
             
            {
         | 
| 523 654 | 
             
            	size_t count;
         | 
| 524 655 | 
             
            	int local_errno;
         | 
| 525 | 
            -
            	 | 
| 526 | 
            -
            	 | 
| 656 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 657 | 
            +
            	rb_mgc_arguments_t mga;
         | 
| 527 658 | 
             
            	void **pointers = NULL;
         | 
| 528 659 | 
             
            	size_t *sizes = NULL;
         | 
| 529 660 | 
             
            	VALUE value = Qundef;
         | 
| @@ -538,8 +669,9 @@ rb_mgc_load_buffers(VALUE object, VALUE arguments) | |
| 538 669 |  | 
| 539 670 | 
             
            	MAGIC_CHECK_ARRAY_EMPTY(arguments);
         | 
| 540 671 | 
             
            	MAGIC_CHECK_ARRAY_OF_STRINGS(arguments);
         | 
| 672 | 
            +
             | 
| 541 673 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 542 | 
            -
            	 | 
| 674 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 543 675 |  | 
| 544 676 | 
             
            	pointers = ALLOC_N(void *, count);
         | 
| 545 677 | 
             
            	if (!pointers) {
         | 
| @@ -560,35 +692,41 @@ rb_mgc_load_buffers(VALUE object, VALUE arguments) | |
| 560 692 | 
             
            		sizes[i] = (size_t)RSTRING_LEN(value);
         | 
| 561 693 | 
             
            	}
         | 
| 562 694 |  | 
| 563 | 
            -
            	ma.flags = magic_get_flags(object);
         | 
| 564 | 
            -
            	ma.type.buffers.count = count;
         | 
| 565 | 
            -
            	ma.type.buffers.pointers = pointers;
         | 
| 566 | 
            -
            	ma.type.buffers.sizes = sizes;
         | 
| 567 | 
            -
             | 
| 568 695 | 
             
            	magic_set_paths(object, RARRAY_EMPTY);
         | 
| 569 696 |  | 
| 570 | 
            -
            	 | 
| 571 | 
            -
             | 
| 697 | 
            +
            	mga = (rb_mgc_arguments_t) {
         | 
| 698 | 
            +
            		.magic_object = mgc,
         | 
| 699 | 
            +
            		.buffers = {
         | 
| 700 | 
            +
            			.count    = count,
         | 
| 701 | 
            +
            			.pointers = pointers,
         | 
| 702 | 
            +
            			.sizes    = sizes,
         | 
| 703 | 
            +
            		},
         | 
| 704 | 
            +
            		.flags = magic_get_flags(object),
         | 
| 705 | 
            +
            	};
         | 
| 706 | 
            +
             | 
| 707 | 
            +
            	MAGIC_SYNCHRONIZED(magic_load_buffers_internal, &mga);
         | 
| 708 | 
            +
            	if (mga.status < 0) {
         | 
| 572 709 | 
             
            		local_errno = errno;
         | 
| 573 710 | 
             
            		ruby_xfree(pointers);
         | 
| 574 711 | 
             
            		ruby_xfree(sizes);
         | 
| 575 712 | 
             
            		goto error;
         | 
| 576 713 | 
             
            	}
         | 
| 577 | 
            -
             | 
| 714 | 
            +
             | 
| 715 | 
            +
            	mgc->database_loaded = 1;
         | 
| 578 716 |  | 
| 579 717 | 
             
            	ruby_xfree(pointers);
         | 
| 580 718 | 
             
            	ruby_xfree(sizes);
         | 
| 581 719 |  | 
| 582 720 | 
             
            	return Qnil;
         | 
| 583 721 | 
             
            error:
         | 
| 584 | 
            -
            	 | 
| 722 | 
            +
            	mgc->database_loaded = 0;
         | 
| 585 723 |  | 
| 586 724 | 
             
            	if (local_errno == ENOMEM)
         | 
| 587 725 | 
             
            		MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
         | 
| 588 726 | 
             
            				    local_errno,
         | 
| 589 727 | 
             
            				    E_NOT_ENOUGH_MEMORY);
         | 
| 590 728 |  | 
| 591 | 
            -
            	MAGIC_LIBRARY_ERROR( | 
| 729 | 
            +
            	MAGIC_LIBRARY_ERROR(mgc);
         | 
| 592 730 | 
             
            }
         | 
| 593 731 |  | 
| 594 732 | 
             
            /*
         | 
| @@ -615,12 +753,12 @@ error: | |
| 615 753 | 
             
            VALUE
         | 
| 616 754 | 
             
            rb_mgc_load_p(VALUE object)
         | 
| 617 755 | 
             
            {
         | 
| 618 | 
            -
            	 | 
| 756 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 619 757 |  | 
| 620 758 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 621 | 
            -
            	MAGIC_OBJECT( | 
| 759 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 622 760 |  | 
| 623 | 
            -
            	return CBOOL2RVAL( | 
| 761 | 
            +
            	return CBOOL2RVAL(mgc->database_loaded);
         | 
| 624 762 | 
             
            }
         | 
| 625 763 |  | 
| 626 764 | 
             
            /*
         | 
| @@ -633,19 +771,25 @@ rb_mgc_load_p(VALUE object) | |
| 633 771 | 
             
            VALUE
         | 
| 634 772 | 
             
            rb_mgc_compile(VALUE object, VALUE value)
         | 
| 635 773 | 
             
            {
         | 
| 636 | 
            -
            	 | 
| 637 | 
            -
            	 | 
| 774 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 775 | 
            +
            	rb_mgc_arguments_t mga;
         | 
| 638 776 |  | 
| 639 777 | 
             
            	MAGIC_CHECK_STRING_TYPE(value);
         | 
| 778 | 
            +
             | 
| 640 779 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 641 | 
            -
            	 | 
| 780 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 642 781 |  | 
| 643 | 
            -
            	 | 
| 644 | 
            -
             | 
| 782 | 
            +
            	mga = (rb_mgc_arguments_t) {
         | 
| 783 | 
            +
            		.magic_object = mgc,
         | 
| 784 | 
            +
            		.file = {
         | 
| 785 | 
            +
            			.path = RVAL2CSTR(value),
         | 
| 786 | 
            +
            		},
         | 
| 787 | 
            +
            		.flags = magic_get_flags(object),
         | 
| 788 | 
            +
            	};
         | 
| 645 789 |  | 
| 646 | 
            -
            	MAGIC_SYNCHRONIZED(magic_compile_internal, & | 
| 647 | 
            -
            	if ( | 
| 648 | 
            -
            		MAGIC_LIBRARY_ERROR( | 
| 790 | 
            +
            	MAGIC_SYNCHRONIZED(magic_compile_internal, &mga);
         | 
| 791 | 
            +
            	if (mga.status < 0)
         | 
| 792 | 
            +
            		MAGIC_LIBRARY_ERROR(mgc);
         | 
| 649 793 |  | 
| 650 794 | 
             
            	return Qnil;
         | 
| 651 795 | 
             
            }
         | 
| @@ -660,18 +804,25 @@ rb_mgc_compile(VALUE object, VALUE value) | |
| 660 804 | 
             
            VALUE
         | 
| 661 805 | 
             
            rb_mgc_check(VALUE object, VALUE value)
         | 
| 662 806 | 
             
            {
         | 
| 663 | 
            -
            	 | 
| 664 | 
            -
            	 | 
| 807 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 808 | 
            +
            	rb_mgc_arguments_t mga;
         | 
| 665 809 |  | 
| 666 810 | 
             
            	MAGIC_CHECK_STRING_TYPE(value);
         | 
| 811 | 
            +
             | 
| 667 812 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 668 | 
            -
            	 | 
| 813 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 814 | 
            +
             | 
| 815 | 
            +
            	mga = (rb_mgc_arguments_t) {
         | 
| 816 | 
            +
            		.magic_object = mgc,
         | 
| 817 | 
            +
            		.file = {
         | 
| 818 | 
            +
            			.path = RVAL2CSTR(value),
         | 
| 819 | 
            +
            		},
         | 
| 820 | 
            +
            		.flags = magic_get_flags(object),
         | 
| 821 | 
            +
            	};
         | 
| 669 822 |  | 
| 670 | 
            -
            	 | 
| 671 | 
            -
            	ma.type.file.path = RVAL2CSTR(value);
         | 
| 823 | 
            +
            	MAGIC_SYNCHRONIZED(magic_check_internal, &mga);
         | 
| 672 824 |  | 
| 673 | 
            -
            	 | 
| 674 | 
            -
            	return ma.status < 0 ? Qfalse : Qtrue;
         | 
| 825 | 
            +
            	return mga.status < 0 ? Qfalse : Qtrue;
         | 
| 675 826 | 
             
            }
         | 
| 676 827 |  | 
| 677 828 | 
             
            /*
         | 
| @@ -684,8 +835,8 @@ rb_mgc_check(VALUE object, VALUE value) | |
| 684 835 | 
             
            VALUE
         | 
| 685 836 | 
             
            rb_mgc_file(VALUE object, VALUE value)
         | 
| 686 837 | 
             
            {
         | 
| 687 | 
            -
            	 | 
| 688 | 
            -
            	 | 
| 838 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 839 | 
            +
            	rb_mgc_arguments_t mga;
         | 
| 689 840 | 
             
            	const char *empty = "(null)";
         | 
| 690 841 |  | 
| 691 842 | 
             
            	UNUSED(empty);
         | 
| @@ -695,7 +846,7 @@ rb_mgc_file(VALUE object, VALUE value) | |
| 695 846 |  | 
| 696 847 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 697 848 | 
             
            	MAGIC_CHECK_LOADED(object);
         | 
| 698 | 
            -
            	 | 
| 849 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 699 850 |  | 
| 700 851 | 
             
            	if (rb_respond_to(value, rb_intern("to_io")))
         | 
| 701 852 | 
             
            		return rb_mgc_descriptor(object, value);
         | 
| @@ -704,12 +855,16 @@ rb_mgc_file(VALUE object, VALUE value) | |
| 704 855 | 
             
            	if (NIL_P(value))
         | 
| 705 856 | 
             
            		goto error;
         | 
| 706 857 |  | 
| 707 | 
            -
            	 | 
| 708 | 
            -
             | 
| 709 | 
            -
             | 
| 858 | 
            +
            	mga = (rb_mgc_arguments_t) {
         | 
| 859 | 
            +
            		.magic_object = mgc,
         | 
| 860 | 
            +
            		.file = {
         | 
| 861 | 
            +
            			.path = RVAL2CSTR(value),
         | 
| 862 | 
            +
            		},
         | 
| 863 | 
            +
            		.flags = magic_get_flags(object),
         | 
| 864 | 
            +
            	};
         | 
| 710 865 |  | 
| 711 | 
            -
            	MAGIC_SYNCHRONIZED(magic_file_internal, & | 
| 712 | 
            -
            	if ( | 
| 866 | 
            +
            	MAGIC_SYNCHRONIZED(magic_file_internal, &mga);
         | 
| 867 | 
            +
            	if (mga.status < 0 && !mga.result) {
         | 
| 713 868 | 
             
            		/*
         | 
| 714 869 | 
             
            		 * Handle the case when the "ERROR" flag is set regardless of the
         | 
| 715 870 | 
             
            		 * current version of the underlying Magic library.
         | 
| @@ -723,15 +878,15 @@ rb_mgc_file(VALUE object, VALUE value) | |
| 723 878 | 
             
            		 * This is an attempt to mitigate the problem and correct it to achieve
         | 
| 724 879 | 
             
            		 * the desired behavior as per the standards.
         | 
| 725 880 | 
             
            		 */
         | 
| 726 | 
            -
            		if ( | 
| 727 | 
            -
            			MAGIC_LIBRARY_ERROR( | 
| 881 | 
            +
            		if (mgc->stop_on_errors || (mga.flags & MAGIC_ERROR))
         | 
| 882 | 
            +
            			MAGIC_LIBRARY_ERROR(mgc);
         | 
| 728 883 |  | 
| 729 | 
            -
            		 | 
| 884 | 
            +
            		mga.result = magic_error_wrapper(mgc->cookie);
         | 
| 730 885 | 
             
            	}
         | 
| 731 | 
            -
            	if (! | 
| 886 | 
            +
            	if (!mga.result)
         | 
| 732 887 | 
             
            		MAGIC_GENERIC_ERROR(rb_mgc_eMagicError, EINVAL, E_UNKNOWN);
         | 
| 733 888 |  | 
| 734 | 
            -
            	assert( | 
| 889 | 
            +
            	assert(mga.result != NULL &&
         | 
| 735 890 | 
             
            	       "Must be a valid pointer to `const char' type");
         | 
| 736 891 |  | 
| 737 892 | 
             
            	/*
         | 
| @@ -740,10 +895,10 @@ rb_mgc_file(VALUE object, VALUE value) | |
| 740 895 | 
             
            	 * string instead. Often this would indicate that an older version of the
         | 
| 741 896 | 
             
            	 * Magic library is in use.
         | 
| 742 897 | 
             
            	 */
         | 
| 743 | 
            -
            	assert(strncmp( | 
| 898 | 
            +
            	assert(strncmp(mga.result, empty, strlen(empty)) != 0 &&
         | 
| 744 899 | 
             
            		       "Empty or invalid result");
         | 
| 745 900 |  | 
| 746 | 
            -
            	return magic_return(& | 
| 901 | 
            +
            	return magic_return(&mga);
         | 
| 747 902 | 
             
            error:
         | 
| 748 903 | 
             
            	MAGIC_ARGUMENT_TYPE_ERROR(value, "String or IO-like object");
         | 
| 749 904 | 
             
            }
         | 
| @@ -757,28 +912,34 @@ error: | |
| 757 912 | 
             
            VALUE
         | 
| 758 913 | 
             
            rb_mgc_buffer(VALUE object, VALUE value)
         | 
| 759 914 | 
             
            {
         | 
| 760 | 
            -
            	 | 
| 761 | 
            -
            	 | 
| 915 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 916 | 
            +
            	rb_mgc_arguments_t mga;
         | 
| 762 917 |  | 
| 763 918 | 
             
            	MAGIC_CHECK_STRING_TYPE(value);
         | 
| 919 | 
            +
             | 
| 764 920 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 765 921 | 
             
            	MAGIC_CHECK_LOADED(object);
         | 
| 766 | 
            -
            	 | 
| 922 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 767 923 |  | 
| 768 924 | 
             
            	StringValue(value);
         | 
| 769 925 |  | 
| 770 | 
            -
            	 | 
| 771 | 
            -
             | 
| 772 | 
            -
             | 
| 926 | 
            +
            	mga = (rb_mgc_arguments_t) {
         | 
| 927 | 
            +
            		.magic_object = mgc,
         | 
| 928 | 
            +
            		.buffers = {
         | 
| 929 | 
            +
            			.pointers = (void **)RSTRING_PTR(value),
         | 
| 930 | 
            +
            			.sizes    = (size_t *)RSTRING_LEN(value),
         | 
| 931 | 
            +
            		},
         | 
| 932 | 
            +
            		.flags = magic_get_flags(object),
         | 
| 933 | 
            +
            	};
         | 
| 773 934 |  | 
| 774 | 
            -
            	MAGIC_SYNCHRONIZED(magic_buffer_internal, & | 
| 775 | 
            -
            	if ( | 
| 776 | 
            -
            		MAGIC_LIBRARY_ERROR( | 
| 935 | 
            +
            	MAGIC_SYNCHRONIZED(magic_buffer_internal, &mga);
         | 
| 936 | 
            +
            	if (mga.status < 0)
         | 
| 937 | 
            +
            		MAGIC_LIBRARY_ERROR(mgc);
         | 
| 777 938 |  | 
| 778 | 
            -
            	assert( | 
| 939 | 
            +
            	assert(mga.result != NULL &&
         | 
| 779 940 | 
             
            	       "Must be a valid pointer to `const char' type");
         | 
| 780 941 |  | 
| 781 | 
            -
            	return magic_return(& | 
| 942 | 
            +
            	return magic_return(&mga);
         | 
| 782 943 | 
             
            }
         | 
| 783 944 |  | 
| 784 945 | 
             
            /*
         | 
| @@ -792,34 +953,40 @@ VALUE | |
| 792 953 | 
             
            rb_mgc_descriptor(VALUE object, VALUE value)
         | 
| 793 954 | 
             
            {
         | 
| 794 955 | 
             
            	int local_errno;
         | 
| 795 | 
            -
            	 | 
| 796 | 
            -
            	 | 
| 956 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 957 | 
            +
            	rb_mgc_arguments_t mga;
         | 
| 797 958 |  | 
| 798 959 | 
             
            	if (rb_respond_to(value, rb_intern("to_io")))
         | 
| 799 960 | 
             
            		value = INT2NUM(magic_fileno(value));
         | 
| 800 961 |  | 
| 801 962 | 
             
            	MAGIC_CHECK_INTEGER_TYPE(value);
         | 
| 963 | 
            +
             | 
| 802 964 | 
             
            	MAGIC_CHECK_OPEN(object);
         | 
| 803 965 | 
             
            	MAGIC_CHECK_LOADED(object);
         | 
| 804 | 
            -
            	 | 
| 966 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 805 967 |  | 
| 806 | 
            -
            	 | 
| 807 | 
            -
             | 
| 968 | 
            +
            	mga = (rb_mgc_arguments_t) {
         | 
| 969 | 
            +
            		.magic_object = mgc,
         | 
| 970 | 
            +
            		.file = {
         | 
| 971 | 
            +
            			.fd = NUM2INT(value),
         | 
| 972 | 
            +
            		},
         | 
| 973 | 
            +
            		.flags = magic_get_flags(object),
         | 
| 974 | 
            +
            	};
         | 
| 808 975 |  | 
| 809 | 
            -
            	MAGIC_SYNCHRONIZED(magic_descriptor_internal, & | 
| 976 | 
            +
            	MAGIC_SYNCHRONIZED(magic_descriptor_internal, &mga);
         | 
| 810 977 | 
             
            	local_errno = errno;
         | 
| 811 978 |  | 
| 812 | 
            -
            	if ( | 
| 979 | 
            +
            	if (mga.status < 0) {
         | 
| 813 980 | 
             
            		if (local_errno == EBADF)
         | 
| 814 981 | 
             
            			rb_raise(rb_eIOError, "Bad file descriptor");
         | 
| 815 982 |  | 
| 816 | 
            -
            		MAGIC_LIBRARY_ERROR( | 
| 983 | 
            +
            		MAGIC_LIBRARY_ERROR(mgc);
         | 
| 817 984 | 
             
            	}
         | 
| 818 985 |  | 
| 819 | 
            -
            	assert( | 
| 986 | 
            +
            	assert(mga.result != NULL &&
         | 
| 820 987 | 
             
            	       "Must be a valid pointer to `const char' type");
         | 
| 821 988 |  | 
| 822 | 
            -
            	return magic_return(& | 
| 989 | 
            +
            	return magic_return(&mga);
         | 
| 823 990 | 
             
            }
         | 
| 824 991 |  | 
| 825 992 | 
             
            /*
         | 
| @@ -841,59 +1008,69 @@ rb_mgc_version(RB_UNUSED_VAR(VALUE object)) | |
| 841 1008 | 
             
            static inline void*
         | 
| 842 1009 | 
             
            nogvl_magic_load(void *data)
         | 
| 843 1010 | 
             
            {
         | 
| 844 | 
            -
            	 | 
| 1011 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1012 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1013 | 
            +
             | 
| 1014 | 
            +
            	mga->status = magic_load_wrapper(cookie,
         | 
| 1015 | 
            +
            					 mga->file.path,
         | 
| 1016 | 
            +
            					 mga->flags);
         | 
| 845 1017 |  | 
| 846 | 
            -
            	ma->status = magic_load_wrapper(ma->cookie,
         | 
| 847 | 
            -
            					ma->type.file.path,
         | 
| 848 | 
            -
            					ma->flags);
         | 
| 849 1018 | 
             
            	return NULL;
         | 
| 850 1019 | 
             
            }
         | 
| 851 1020 |  | 
| 852 1021 | 
             
            static inline void*
         | 
| 853 1022 | 
             
            nogvl_magic_compile(void *data)
         | 
| 854 1023 | 
             
            {
         | 
| 855 | 
            -
            	 | 
| 1024 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1025 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1026 | 
            +
             | 
| 1027 | 
            +
            	mga->status = magic_compile_wrapper(cookie,
         | 
| 1028 | 
            +
            					    mga->file.path,
         | 
| 1029 | 
            +
            					    mga->flags);
         | 
| 856 1030 |  | 
| 857 | 
            -
            	ma->status = magic_compile_wrapper(ma->cookie,
         | 
| 858 | 
            -
            					   ma->type.file.path,
         | 
| 859 | 
            -
            					   ma->flags);
         | 
| 860 1031 | 
             
            	return NULL;
         | 
| 861 1032 | 
             
            }
         | 
| 862 1033 |  | 
| 863 1034 | 
             
            static inline void*
         | 
| 864 1035 | 
             
            nogvl_magic_check(void *data)
         | 
| 865 1036 | 
             
            {
         | 
| 866 | 
            -
            	 | 
| 1037 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1038 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1039 | 
            +
             | 
| 1040 | 
            +
            	mga->status = magic_check_wrapper(cookie,
         | 
| 1041 | 
            +
            					  mga->file.path,
         | 
| 1042 | 
            +
            					  mga->flags);
         | 
| 867 1043 |  | 
| 868 | 
            -
            	ma->status = magic_check_wrapper(ma->cookie,
         | 
| 869 | 
            -
            					 ma->type.file.path,
         | 
| 870 | 
            -
            					 ma->flags);
         | 
| 871 1044 | 
             
            	return NULL;
         | 
| 872 1045 | 
             
            }
         | 
| 873 1046 |  | 
| 874 1047 | 
             
            static inline void*
         | 
| 875 1048 | 
             
            nogvl_magic_file(void *data)
         | 
| 876 1049 | 
             
            {
         | 
| 877 | 
            -
            	 | 
| 1050 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1051 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 878 1052 |  | 
| 879 | 
            -
            	 | 
| 880 | 
            -
             | 
| 881 | 
            -
             | 
| 1053 | 
            +
            	mga->result = magic_file_wrapper(cookie,
         | 
| 1054 | 
            +
            					 mga->file.path,
         | 
| 1055 | 
            +
            					 mga->flags);
         | 
| 1056 | 
            +
             | 
| 1057 | 
            +
            	mga->status = !mga->result ? -1 : 0;
         | 
| 882 1058 |  | 
| 883 | 
            -
            	ma->status = !ma->result ? -1 : 0;
         | 
| 884 1059 | 
             
            	return NULL;
         | 
| 885 1060 | 
             
            }
         | 
| 886 1061 |  | 
| 887 1062 | 
             
            static inline void*
         | 
| 888 1063 | 
             
            nogvl_magic_descriptor(void *data)
         | 
| 889 1064 | 
             
            {
         | 
| 890 | 
            -
            	 | 
| 1065 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1066 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1067 | 
            +
             | 
| 1068 | 
            +
            	mga->result = magic_descriptor_wrapper(cookie,
         | 
| 1069 | 
            +
            					       mga->file.fd,
         | 
| 1070 | 
            +
            					       mga->flags);
         | 
| 891 1071 |  | 
| 892 | 
            -
            	 | 
| 893 | 
            -
            					      ma->type.file.fd,
         | 
| 894 | 
            -
            					      ma->flags);
         | 
| 1072 | 
            +
            	mga->status = !mga->result ? -1 : 0;
         | 
| 895 1073 |  | 
| 896 | 
            -
            	ma->status = !ma->result ? -1 : 0;
         | 
| 897 1074 | 
             
            	return NULL;
         | 
| 898 1075 | 
             
            }
         | 
| 899 1076 |  | 
| @@ -901,12 +1078,15 @@ static inline VALUE | |
| 901 1078 | 
             
            magic_get_parameter_internal(void *data)
         | 
| 902 1079 | 
             
            {
         | 
| 903 1080 | 
             
            	size_t value;
         | 
| 904 | 
            -
            	 | 
| 1081 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1082 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1083 | 
            +
             | 
| 1084 | 
            +
            	mga->status = magic_getparam_wrapper(cookie,
         | 
| 1085 | 
            +
            					     mga->parameter.tag,
         | 
| 1086 | 
            +
            					     &value);
         | 
| 1087 | 
            +
             | 
| 1088 | 
            +
            	mga->parameter.value = value;
         | 
| 905 1089 |  | 
| 906 | 
            -
            	ma->status = magic_getparam_wrapper(ma->cookie,
         | 
| 907 | 
            -
            					    ma->type.parameter.tag,
         | 
| 908 | 
            -
            					    &value);
         | 
| 909 | 
            -
            	ma->type.parameter.value = value;
         | 
| 910 1090 | 
             
            	return (VALUE)NULL;
         | 
| 911 1091 | 
             
            }
         | 
| 912 1092 |  | 
| @@ -914,30 +1094,44 @@ static inline VALUE | |
| 914 1094 | 
             
            magic_set_parameter_internal(void *data)
         | 
| 915 1095 | 
             
            {
         | 
| 916 1096 | 
             
            	size_t value;
         | 
| 917 | 
            -
            	 | 
| 1097 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1098 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1099 | 
            +
             | 
| 1100 | 
            +
            	value = mga->parameter.value;
         | 
| 1101 | 
            +
             | 
| 1102 | 
            +
            	mga->status = magic_setparam_wrapper(cookie,
         | 
| 1103 | 
            +
            					     mga->parameter.tag,
         | 
| 1104 | 
            +
            					     &value);
         | 
| 918 1105 |  | 
| 919 | 
            -
            	value = ma->type.parameter.value;
         | 
| 920 | 
            -
            	ma->status = magic_setparam_wrapper(ma->cookie,
         | 
| 921 | 
            -
            					    ma->type.parameter.tag,
         | 
| 922 | 
            -
            					    &value);
         | 
| 923 1106 | 
             
            	return (VALUE)NULL;
         | 
| 924 1107 | 
             
            }
         | 
| 925 1108 |  | 
| 926 1109 | 
             
            static inline VALUE
         | 
| 927 1110 | 
             
            magic_get_flags_internal(void *data)
         | 
| 928 1111 | 
             
            {
         | 
| 929 | 
            -
            	 | 
| 1112 | 
            +
            	int flags;
         | 
| 1113 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1114 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1115 | 
            +
             | 
| 1116 | 
            +
            	mga->status = 0;
         | 
| 1117 | 
            +
             | 
| 1118 | 
            +
            	flags = magic_getflags_wrapper(cookie);
         | 
| 1119 | 
            +
            	if (flags < 0)
         | 
| 1120 | 
            +
            		mga->status = -1;
         | 
| 1121 | 
            +
            	else
         | 
| 1122 | 
            +
            		mga->flags = flags;
         | 
| 930 1123 |  | 
| 931 | 
            -
            	ma->flags = magic_getflags_wrapper(ma->cookie);
         | 
| 932 1124 | 
             
            	return (VALUE)NULL;
         | 
| 933 1125 | 
             
            }
         | 
| 934 1126 |  | 
| 935 1127 | 
             
            static inline VALUE
         | 
| 936 1128 | 
             
            magic_set_flags_internal(void *data)
         | 
| 937 1129 | 
             
            {
         | 
| 938 | 
            -
            	 | 
| 1130 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1131 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1132 | 
            +
             | 
| 1133 | 
            +
            	mga->status = magic_setflags_wrapper(cookie, mga->flags);
         | 
| 939 1134 |  | 
| 940 | 
            -
            	ma->status = magic_setflags_wrapper(ma->cookie, ma->flags);
         | 
| 941 1135 | 
             
            	return (VALUE)NULL;
         | 
| 942 1136 | 
             
            }
         | 
| 943 1137 |  | 
| @@ -945,18 +1139,21 @@ static inline VALUE | |
| 945 1139 | 
             
            magic_close_internal(void *data)
         | 
| 946 1140 | 
             
            {
         | 
| 947 1141 | 
             
            	magic_library_close(data);
         | 
| 1142 | 
            +
             | 
| 948 1143 | 
             
            	return Qnil;
         | 
| 949 1144 | 
             
            }
         | 
| 950 1145 |  | 
| 951 1146 | 
             
            static inline VALUE
         | 
| 952 1147 | 
             
            magic_load_internal(void *data)
         | 
| 953 1148 | 
             
            {
         | 
| 954 | 
            -
            	 | 
| 955 | 
            -
            	 | 
| 1149 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1150 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1151 | 
            +
            	int old_flags = mga->flags;
         | 
| 956 1152 |  | 
| 957 | 
            -
            	NOGVL(nogvl_magic_load,  | 
| 958 | 
            -
             | 
| 959 | 
            -
             | 
| 1153 | 
            +
            	NOGVL(nogvl_magic_load, mga);
         | 
| 1154 | 
            +
             | 
| 1155 | 
            +
            	if (MAGIC_STATUS_CHECK(mga->status < 0))
         | 
| 1156 | 
            +
            		magic_setflags_wrapper(cookie, old_flags);
         | 
| 960 1157 |  | 
| 961 1158 | 
             
            	return (VALUE)NULL;
         | 
| 962 1159 | 
             
            }
         | 
| @@ -964,25 +1161,29 @@ magic_load_internal(void *data) | |
| 964 1161 | 
             
            static inline VALUE
         | 
| 965 1162 | 
             
            magic_load_buffers_internal(void *data)
         | 
| 966 1163 | 
             
            {
         | 
| 967 | 
            -
            	 | 
| 1164 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1165 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1166 | 
            +
             | 
| 1167 | 
            +
            	mga->status = magic_load_buffers_wrapper(cookie,
         | 
| 1168 | 
            +
            						 mga->buffers.pointers,
         | 
| 1169 | 
            +
            						 mga->buffers.sizes,
         | 
| 1170 | 
            +
            						 mga->buffers.count,
         | 
| 1171 | 
            +
            						 mga->flags);
         | 
| 968 1172 |  | 
| 969 | 
            -
            	ma->status = magic_load_buffers_wrapper(ma->cookie,
         | 
| 970 | 
            -
            						ma->type.buffers.pointers,
         | 
| 971 | 
            -
            						ma->type.buffers.sizes,
         | 
| 972 | 
            -
            						ma->type.buffers.count,
         | 
| 973 | 
            -
            						ma->flags);
         | 
| 974 1173 | 
             
            	return (VALUE)NULL;
         | 
| 975 1174 | 
             
            }
         | 
| 976 1175 |  | 
| 977 1176 | 
             
            static inline VALUE
         | 
| 978 1177 | 
             
            magic_compile_internal(void *data)
         | 
| 979 1178 | 
             
            {
         | 
| 980 | 
            -
            	 | 
| 981 | 
            -
            	 | 
| 1179 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1180 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1181 | 
            +
            	int old_flags = mga->flags;
         | 
| 1182 | 
            +
             | 
| 1183 | 
            +
            	NOGVL(nogvl_magic_compile, mga);
         | 
| 982 1184 |  | 
| 983 | 
            -
            	 | 
| 984 | 
            -
             | 
| 985 | 
            -
            		magic_setflags_wrapper(ma->cookie, old_flags);
         | 
| 1185 | 
            +
            	if (MAGIC_STATUS_CHECK(mga->status < 0))
         | 
| 1186 | 
            +
            		magic_setflags_wrapper(cookie, old_flags);
         | 
| 986 1187 |  | 
| 987 1188 | 
             
            	return (VALUE)NULL;
         | 
| 988 1189 | 
             
            }
         | 
| @@ -990,12 +1191,14 @@ magic_compile_internal(void *data) | |
| 990 1191 | 
             
            static inline VALUE
         | 
| 991 1192 | 
             
            magic_check_internal(void *data)
         | 
| 992 1193 | 
             
            {
         | 
| 993 | 
            -
            	 | 
| 994 | 
            -
            	 | 
| 1194 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1195 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1196 | 
            +
            	int old_flags = mga->flags;
         | 
| 995 1197 |  | 
| 996 | 
            -
            	NOGVL(nogvl_magic_check,  | 
| 997 | 
            -
             | 
| 998 | 
            -
             | 
| 1198 | 
            +
            	NOGVL(nogvl_magic_check, mga);
         | 
| 1199 | 
            +
             | 
| 1200 | 
            +
            	if (MAGIC_STATUS_CHECK(mga->status < 0))
         | 
| 1201 | 
            +
            		magic_setflags_wrapper(cookie, old_flags);
         | 
| 999 1202 |  | 
| 1000 1203 | 
             
            	return (VALUE)NULL;
         | 
| 1001 1204 | 
             
            }
         | 
| @@ -1003,23 +1206,26 @@ magic_check_internal(void *data) | |
| 1003 1206 | 
             
            static VALUE
         | 
| 1004 1207 | 
             
            magic_file_internal(void *data)
         | 
| 1005 1208 | 
             
            {
         | 
| 1006 | 
            -
            	magic_arguments_t *ma = data;
         | 
| 1007 | 
            -
            	int old_flags = ma->flags;
         | 
| 1008 | 
            -
            	int restore_flags;
         | 
| 1009 1209 | 
             
            	int local_errno;
         | 
| 1210 | 
            +
            	int restore_flags = 0;
         | 
| 1211 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1212 | 
            +
            	rb_mgc_object_t *mgc = mga->magic_object;
         | 
| 1213 | 
            +
            	magic_t cookie = mgc->cookie;
         | 
| 1214 | 
            +
            	int old_flags = mga->flags;
         | 
| 1010 1215 |  | 
| 1011 | 
            -
            	if ( | 
| 1012 | 
            -
            		 | 
| 1216 | 
            +
            	if (mgc->stop_on_errors)
         | 
| 1217 | 
            +
            		mga->flags |= MAGIC_ERROR;
         | 
| 1013 1218 |  | 
| 1014 | 
            -
            	if ( | 
| 1015 | 
            -
            		 | 
| 1219 | 
            +
            	if (mga->flags & MAGIC_CONTINUE)
         | 
| 1220 | 
            +
            		mga->flags |= MAGIC_RAW;
         | 
| 1016 1221 |  | 
| 1017 | 
            -
            	 | 
| 1222 | 
            +
            	if (old_flags != mga->flags)
         | 
| 1223 | 
            +
            		restore_flags = 1;
         | 
| 1018 1224 |  | 
| 1019 1225 | 
             
            	if (restore_flags)
         | 
| 1020 | 
            -
            		magic_setflags_wrapper( | 
| 1226 | 
            +
            		magic_setflags_wrapper(cookie, mga->flags);
         | 
| 1021 1227 |  | 
| 1022 | 
            -
            	NOGVL(nogvl_magic_file,  | 
| 1228 | 
            +
            	NOGVL(nogvl_magic_file, mga);
         | 
| 1023 1229 | 
             
            	local_errno = errno;
         | 
| 1024 1230 | 
             
            	/*
         | 
| 1025 1231 | 
             
            	 * The Magic library often does not correctly report errors,
         | 
| @@ -1028,11 +1234,11 @@ magic_file_internal(void *data) | |
| 1028 1234 | 
             
            	 * Magic library itself, and if that does not work, then from
         | 
| 1029 1235 | 
             
            	 * the saved errno value.
         | 
| 1030 1236 | 
             
            	 */
         | 
| 1031 | 
            -
            	if (magic_errno_wrapper( | 
| 1032 | 
            -
            		 | 
| 1237 | 
            +
            	if (magic_errno_wrapper(cookie) || local_errno)
         | 
| 1238 | 
            +
            		mga->status = -1;
         | 
| 1033 1239 |  | 
| 1034 1240 | 
             
            	if (restore_flags)
         | 
| 1035 | 
            -
            		magic_setflags_wrapper( | 
| 1241 | 
            +
            		magic_setflags_wrapper(cookie, old_flags);
         | 
| 1036 1242 |  | 
| 1037 1243 | 
             
            	return (VALUE)NULL;
         | 
| 1038 1244 | 
             
            }
         | 
| @@ -1040,27 +1246,29 @@ magic_file_internal(void *data) | |
| 1040 1246 | 
             
            static VALUE
         | 
| 1041 1247 | 
             
            magic_buffer_internal(void *data)
         | 
| 1042 1248 | 
             
            {
         | 
| 1043 | 
            -
            	 | 
| 1044 | 
            -
            	 | 
| 1045 | 
            -
            	 | 
| 1249 | 
            +
            	int restore_flags = 0;
         | 
| 1250 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1251 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1252 | 
            +
            	int old_flags = mga->flags;
         | 
| 1046 1253 |  | 
| 1047 | 
            -
            	if ( | 
| 1048 | 
            -
            		 | 
| 1254 | 
            +
            	if (mga->flags & MAGIC_CONTINUE)
         | 
| 1255 | 
            +
            		mga->flags |= MAGIC_RAW;
         | 
| 1049 1256 |  | 
| 1050 | 
            -
            	 | 
| 1257 | 
            +
            	if (old_flags != mga->flags)
         | 
| 1258 | 
            +
            		restore_flags = 1;
         | 
| 1051 1259 |  | 
| 1052 1260 | 
             
            	if (restore_flags)
         | 
| 1053 | 
            -
            		magic_setflags_wrapper( | 
| 1261 | 
            +
            		magic_setflags_wrapper(cookie, mga->flags);
         | 
| 1054 1262 |  | 
| 1055 | 
            -
            	 | 
| 1056 | 
            -
             | 
| 1057 | 
            -
             | 
| 1058 | 
            -
             | 
| 1263 | 
            +
            	mga->result = magic_buffer_wrapper(cookie,
         | 
| 1264 | 
            +
            					   (const void *)mga->buffers.pointers,
         | 
| 1265 | 
            +
            					   (size_t)mga->buffers.sizes,
         | 
| 1266 | 
            +
            					   mga->flags);
         | 
| 1059 1267 |  | 
| 1060 | 
            -
            	 | 
| 1268 | 
            +
            	mga->status = !mga->result ? -1 : 0;
         | 
| 1061 1269 |  | 
| 1062 1270 | 
             
            	if (restore_flags)
         | 
| 1063 | 
            -
            		magic_setflags_wrapper( | 
| 1271 | 
            +
            		magic_setflags_wrapper(cookie, old_flags);
         | 
| 1064 1272 |  | 
| 1065 1273 | 
             
            	return (VALUE)NULL;
         | 
| 1066 1274 | 
             
            }
         | 
| @@ -1068,22 +1276,24 @@ magic_buffer_internal(void *data) | |
| 1068 1276 | 
             
            static VALUE
         | 
| 1069 1277 | 
             
            magic_descriptor_internal(void *data)
         | 
| 1070 1278 | 
             
            {
         | 
| 1071 | 
            -
            	 | 
| 1072 | 
            -
            	 | 
| 1073 | 
            -
            	 | 
| 1279 | 
            +
            	int restore_flags = 0;
         | 
| 1280 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1281 | 
            +
            	magic_t cookie = mga->magic_object->cookie;
         | 
| 1282 | 
            +
            	int old_flags = mga->flags;
         | 
| 1074 1283 |  | 
| 1075 | 
            -
            	if ( | 
| 1076 | 
            -
            		 | 
| 1284 | 
            +
            	if (mga->flags & MAGIC_CONTINUE)
         | 
| 1285 | 
            +
            		mga->flags |= MAGIC_RAW;
         | 
| 1077 1286 |  | 
| 1078 | 
            -
            	 | 
| 1287 | 
            +
            	if (old_flags != mga->flags)
         | 
| 1288 | 
            +
            		restore_flags = 1;
         | 
| 1079 1289 |  | 
| 1080 1290 | 
             
            	if (restore_flags)
         | 
| 1081 | 
            -
            		magic_setflags_wrapper( | 
| 1291 | 
            +
            		magic_setflags_wrapper(cookie, mga->flags);
         | 
| 1082 1292 |  | 
| 1083 | 
            -
            	NOGVL(nogvl_magic_descriptor,  | 
| 1293 | 
            +
            	NOGVL(nogvl_magic_descriptor, mga);
         | 
| 1084 1294 |  | 
| 1085 1295 | 
             
            	if (restore_flags)
         | 
| 1086 | 
            -
            		magic_setflags_wrapper( | 
| 1296 | 
            +
            		magic_setflags_wrapper(cookie, old_flags);
         | 
| 1087 1297 |  | 
| 1088 1298 | 
             
            	return (VALUE)NULL;
         | 
| 1089 1299 | 
             
            }
         | 
| @@ -1105,129 +1315,129 @@ magic_library_open(void) | |
| 1105 1315 | 
             
            static inline void
         | 
| 1106 1316 | 
             
            magic_library_close(void *data)
         | 
| 1107 1317 | 
             
            {
         | 
| 1108 | 
            -
            	 | 
| 1318 | 
            +
            	rb_mgc_object_t *mgc = data;
         | 
| 1109 1319 |  | 
| 1110 | 
            -
            	assert( | 
| 1111 | 
            -
            	       "Must be a valid pointer to ` | 
| 1320 | 
            +
            	assert(mgc != NULL &&
         | 
| 1321 | 
            +
            	       "Must be a valid pointer to `rb_mgc_object_t' type");
         | 
| 1112 1322 |  | 
| 1113 | 
            -
            	if ( | 
| 1114 | 
            -
            		magic_close_wrapper( | 
| 1323 | 
            +
            	if (mgc->cookie)
         | 
| 1324 | 
            +
            		magic_close_wrapper(mgc->cookie);
         | 
| 1115 1325 |  | 
| 1116 | 
            -
            	 | 
| 1326 | 
            +
            	mgc->cookie = NULL;
         | 
| 1117 1327 | 
             
            }
         | 
| 1118 1328 |  | 
| 1119 1329 | 
             
            static VALUE
         | 
| 1120 1330 | 
             
            magic_allocate(VALUE klass)
         | 
| 1121 1331 | 
             
            {
         | 
| 1122 1332 | 
             
            	int local_errno;
         | 
| 1123 | 
            -
            	 | 
| 1333 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 1124 1334 |  | 
| 1125 | 
            -
            	 | 
| 1335 | 
            +
            	mgc = RB_ALLOC(rb_mgc_object_t);
         | 
| 1126 1336 | 
             
            	local_errno = ENOMEM;
         | 
| 1127 1337 |  | 
| 1128 | 
            -
            	if (! | 
| 1338 | 
            +
            	if (!mgc) {
         | 
| 1129 1339 | 
             
            		errno = local_errno;
         | 
| 1130 1340 | 
             
            		MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
         | 
| 1131 1341 | 
             
            				    local_errno,
         | 
| 1132 1342 | 
             
            				    E_NOT_ENOUGH_MEMORY);
         | 
| 1133 1343 | 
             
            	}
         | 
| 1134 1344 |  | 
| 1135 | 
            -
            	 | 
| 1136 | 
            -
            	 | 
| 1137 | 
            -
            	 | 
| 1138 | 
            -
            	 | 
| 1345 | 
            +
            	mgc->cookie = NULL;
         | 
| 1346 | 
            +
            	mgc->mutex = Qundef;
         | 
| 1347 | 
            +
            	mgc->database_loaded = 0;
         | 
| 1348 | 
            +
            	mgc->stop_on_errors = 0;
         | 
| 1139 1349 |  | 
| 1140 | 
            -
            	 | 
| 1350 | 
            +
            	mgc->cookie = magic_library_open();
         | 
| 1141 1351 | 
             
            	local_errno = errno;
         | 
| 1142 1352 |  | 
| 1143 | 
            -
            	if (! | 
| 1144 | 
            -
            		ruby_xfree( | 
| 1145 | 
            -
            		 | 
| 1353 | 
            +
            	if (!mgc->cookie) {
         | 
| 1354 | 
            +
            		ruby_xfree(mgc);
         | 
| 1355 | 
            +
            		mgc = NULL;
         | 
| 1146 1356 | 
             
            		errno = local_errno;
         | 
| 1147 1357 | 
             
            		MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
         | 
| 1148 1358 | 
             
            				    local_errno,
         | 
| 1149 1359 | 
             
            				    E_MAGIC_LIBRARY_INITIALIZE);
         | 
| 1150 1360 | 
             
            	}
         | 
| 1151 1361 |  | 
| 1152 | 
            -
            	return TypedData_Wrap_Struct(klass, & | 
| 1362 | 
            +
            	return TypedData_Wrap_Struct(klass, &rb_mgc_type, mgc);
         | 
| 1153 1363 | 
             
            }
         | 
| 1154 1364 |  | 
| 1155 1365 | 
             
            static inline void
         | 
| 1156 1366 | 
             
            magic_mark(void *data)
         | 
| 1157 1367 | 
             
            {
         | 
| 1158 | 
            -
            	 | 
| 1368 | 
            +
            	rb_mgc_object_t *mgc = data;
         | 
| 1159 1369 |  | 
| 1160 | 
            -
            	assert( | 
| 1161 | 
            -
            	       "Must be a valid pointer to ` | 
| 1370 | 
            +
            	assert(mgc != NULL &&
         | 
| 1371 | 
            +
            	       "Must be a valid pointer to `rb_mgc_object_t' type");
         | 
| 1162 1372 |  | 
| 1163 | 
            -
            	MAGIC_GC_MARK( | 
| 1373 | 
            +
            	MAGIC_GC_MARK(mgc->mutex);
         | 
| 1164 1374 | 
             
            }
         | 
| 1165 1375 |  | 
| 1166 1376 | 
             
            static inline void
         | 
| 1167 1377 | 
             
            magic_free(void *data)
         | 
| 1168 1378 | 
             
            {
         | 
| 1169 | 
            -
            	 | 
| 1379 | 
            +
            	rb_mgc_object_t *mgc = data;
         | 
| 1170 1380 |  | 
| 1171 | 
            -
            	assert( | 
| 1172 | 
            -
            	       "Must be a valid pointer to ` | 
| 1381 | 
            +
            	assert(mgc != NULL &&
         | 
| 1382 | 
            +
            	       "Must be a valid pointer to `rb_mgc_object_t' type");
         | 
| 1173 1383 |  | 
| 1174 | 
            -
            	if ( | 
| 1384 | 
            +
            	if (mgc->cookie)
         | 
| 1175 1385 | 
             
            		magic_library_close(data);
         | 
| 1176 1386 |  | 
| 1177 | 
            -
            	 | 
| 1178 | 
            -
            	 | 
| 1387 | 
            +
            	mgc->cookie = NULL;
         | 
| 1388 | 
            +
            	mgc->mutex = Qundef;
         | 
| 1179 1389 |  | 
| 1180 | 
            -
            	ruby_xfree( | 
| 1390 | 
            +
            	ruby_xfree(mgc);
         | 
| 1181 1391 | 
             
            }
         | 
| 1182 1392 |  | 
| 1183 1393 | 
             
            static inline size_t
         | 
| 1184 1394 | 
             
            magic_size(const void *data)
         | 
| 1185 1395 | 
             
            {
         | 
| 1186 | 
            -
            	const  | 
| 1396 | 
            +
            	const rb_mgc_object_t *mgc = data;
         | 
| 1187 1397 |  | 
| 1188 | 
            -
            	assert( | 
| 1189 | 
            -
            	       "Must be a valid pointer to ` | 
| 1398 | 
            +
            	assert(mgc != NULL &&
         | 
| 1399 | 
            +
            	       "Must be a valid pointer to `rb_mgc_object_t' type");
         | 
| 1190 1400 |  | 
| 1191 | 
            -
            	return sizeof(* | 
| 1401 | 
            +
            	return sizeof(*mgc);
         | 
| 1192 1402 | 
             
            }
         | 
| 1193 1403 |  | 
| 1194 1404 | 
             
            #if defined(HAVE_RUBY_GC_COMPACT)
         | 
| 1195 1405 | 
             
            static inline void
         | 
| 1196 1406 | 
             
            magic_compact(void *data)
         | 
| 1197 1407 | 
             
            {
         | 
| 1198 | 
            -
            	 | 
| 1408 | 
            +
            	rb_mgc_object_t *mgc = data;
         | 
| 1199 1409 |  | 
| 1200 | 
            -
            	assert( | 
| 1201 | 
            -
            	       "Must be a valid pointer to ` | 
| 1410 | 
            +
            	assert(mgc != NULL &&
         | 
| 1411 | 
            +
            	       "Must be a valid pointer to `rb_mgc_object_t' type");
         | 
| 1202 1412 |  | 
| 1203 | 
            -
            	 | 
| 1413 | 
            +
            	mgc->mutex = rb_gc_location(mgc->mutex);
         | 
| 1204 1414 | 
             
            }
         | 
| 1205 1415 | 
             
            #endif /* HAVE_RUBY_GC_COMPACT */
         | 
| 1206 1416 |  | 
| 1207 1417 | 
             
            static inline VALUE
         | 
| 1208 1418 | 
             
            magic_exception_wrapper(VALUE value)
         | 
| 1209 1419 | 
             
            {
         | 
| 1210 | 
            -
            	 | 
| 1420 | 
            +
            	rb_mgc_error_t *mge = (rb_mgc_error_t *)value;
         | 
| 1211 1421 |  | 
| 1212 | 
            -
            	return rb_exc_new2( | 
| 1422 | 
            +
            	return rb_exc_new2(mge->klass, mge->magic_error);
         | 
| 1213 1423 | 
             
            }
         | 
| 1214 1424 |  | 
| 1215 1425 | 
             
            static VALUE
         | 
| 1216 1426 | 
             
            magic_exception(void *data)
         | 
| 1217 1427 | 
             
            {
         | 
| 1218 | 
            -
            	magic_exception_t *e = data;
         | 
| 1219 1428 | 
             
            	int exception = 0;
         | 
| 1429 | 
            +
            	rb_mgc_error_t *mge = data;
         | 
| 1220 1430 | 
             
            	VALUE object = Qundef;
         | 
| 1221 1431 |  | 
| 1222 | 
            -
            	assert( | 
| 1223 | 
            -
            	       "Must be a valid pointer to ` | 
| 1432 | 
            +
            	assert(mge != NULL &&
         | 
| 1433 | 
            +
            	       "Must be a valid pointer to `rb_mgc_error_t' type");
         | 
| 1224 1434 |  | 
| 1225 | 
            -
            	object = rb_protect(magic_exception_wrapper, (VALUE) | 
| 1435 | 
            +
            	object = rb_protect(magic_exception_wrapper, (VALUE)mge, &exception);
         | 
| 1226 1436 |  | 
| 1227 1437 | 
             
            	if (exception)
         | 
| 1228 1438 | 
             
            		rb_jump_tag(exception);
         | 
| 1229 1439 |  | 
| 1230 | 
            -
            	rb_iv_set(object, "@errno", INT2NUM( | 
| 1440 | 
            +
            	rb_iv_set(object, "@errno", INT2NUM(mge->magic_errno));
         | 
| 1231 1441 | 
             
            	RB_GC_GUARD(object);
         | 
| 1232 1442 |  | 
| 1233 1443 | 
             
            	return object;
         | 
| @@ -1236,51 +1446,56 @@ magic_exception(void *data) | |
| 1236 1446 | 
             
            static inline VALUE
         | 
| 1237 1447 | 
             
            magic_generic_error(VALUE klass, int magic_errno, const char *magic_error)
         | 
| 1238 1448 | 
             
            {
         | 
| 1239 | 
            -
            	 | 
| 1449 | 
            +
            	rb_mgc_error_t mge;
         | 
| 1240 1450 |  | 
| 1241 | 
            -
            	 | 
| 1242 | 
            -
             | 
| 1243 | 
            -
             | 
| 1451 | 
            +
            	mge = (rb_mgc_error_t) {
         | 
| 1452 | 
            +
            		.klass       = klass,
         | 
| 1453 | 
            +
            		.magic_errno = magic_errno,
         | 
| 1454 | 
            +
            		.magic_error = magic_error,
         | 
| 1455 | 
            +
            	};
         | 
| 1244 1456 |  | 
| 1245 | 
            -
            	return magic_exception(& | 
| 1457 | 
            +
            	return magic_exception(&mge);
         | 
| 1246 1458 | 
             
            }
         | 
| 1247 1459 |  | 
| 1248 1460 | 
             
            static VALUE
         | 
| 1249 1461 | 
             
            magic_library_error(VALUE klass, void *data)
         | 
| 1250 1462 | 
             
            {
         | 
| 1251 | 
            -
            	 | 
| 1463 | 
            +
            	rb_mgc_error_t mge;
         | 
| 1252 1464 | 
             
            	const char *message = NULL;
         | 
| 1253 1465 | 
             
            	const char *empty = "(null)";
         | 
| 1254 1466 | 
             
            	magic_t cookie = data;
         | 
| 1255 1467 |  | 
| 1256 1468 | 
             
            	UNUSED(empty);
         | 
| 1257 1469 |  | 
| 1258 | 
            -
            	assert(cookie != NULL && | 
| 1470 | 
            +
            	assert(cookie != NULL &&
         | 
| 1259 1471 | 
             
            	       "Must be a valid pointer to `magic_t' type");
         | 
| 1260 1472 |  | 
| 1261 | 
            -
            	 | 
| 1262 | 
            -
             | 
| 1263 | 
            -
             | 
| 1473 | 
            +
            	mge = (rb_mgc_error_t) {
         | 
| 1474 | 
            +
            		.klass       = klass,
         | 
| 1475 | 
            +
            		.magic_errno = -1,
         | 
| 1476 | 
            +
            		.magic_error = MAGIC_ERRORS(E_UNKNOWN),
         | 
| 1477 | 
            +
            	};
         | 
| 1264 1478 |  | 
| 1265 1479 | 
             
            	message = magic_error_wrapper(cookie);
         | 
| 1266 1480 | 
             
            	if (message) {
         | 
| 1267 | 
            -
            		 | 
| 1268 | 
            -
            		 | 
| 1481 | 
            +
            		mge.magic_errno = magic_errno_wrapper(cookie);
         | 
| 1482 | 
            +
            		mge.magic_error = message;
         | 
| 1269 1483 | 
             
            	}
         | 
| 1270 1484 |  | 
| 1271 | 
            -
            	assert(strncmp( | 
| 1485 | 
            +
            	assert(strncmp(mge.magic_error, empty, strlen(empty)) != 0 &&
         | 
| 1272 1486 | 
             
            		       "Empty or invalid error message");
         | 
| 1273 1487 |  | 
| 1274 | 
            -
            	return magic_exception(& | 
| 1488 | 
            +
            	return magic_exception(&mge);
         | 
| 1275 1489 | 
             
            }
         | 
| 1276 1490 |  | 
| 1277 1491 | 
             
            VALUE
         | 
| 1278 1492 | 
             
            magic_lock(VALUE object, VALUE(*function)(ANYARGS), void *data)
         | 
| 1279 1493 | 
             
            {
         | 
| 1280 | 
            -
            	 | 
| 1494 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 1495 | 
            +
             | 
| 1496 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 1281 1497 |  | 
| 1282 | 
            -
            	 | 
| 1283 | 
            -
            	rb_funcall(mo->mutex, rb_intern("lock"), 0);
         | 
| 1498 | 
            +
            	rb_funcall(mgc->mutex, rb_intern("lock"), 0);
         | 
| 1284 1499 |  | 
| 1285 1500 | 
             
            	return rb_ensure(function, (VALUE)data, magic_unlock, object);
         | 
| 1286 1501 | 
             
            }
         | 
| @@ -1288,10 +1503,11 @@ magic_lock(VALUE object, VALUE(*function)(ANYARGS), void *data) | |
| 1288 1503 | 
             
            VALUE
         | 
| 1289 1504 | 
             
            magic_unlock(VALUE object)
         | 
| 1290 1505 | 
             
            {
         | 
| 1291 | 
            -
            	 | 
| 1506 | 
            +
            	rb_mgc_object_t *mgc;
         | 
| 1507 | 
            +
             | 
| 1508 | 
            +
            	MAGIC_OBJECT(object, mgc);
         | 
| 1292 1509 |  | 
| 1293 | 
            -
            	 | 
| 1294 | 
            -
            	rb_funcall(mo->mutex, rb_intern("unlock"), 0);
         | 
| 1510 | 
            +
            	rb_funcall(mgc->mutex, rb_intern("unlock"), 0);
         | 
| 1295 1511 |  | 
| 1296 1512 | 
             
            	return Qnil;
         | 
| 1297 1513 | 
             
            }
         | 
| @@ -1299,13 +1515,12 @@ magic_unlock(VALUE object) | |
| 1299 1515 | 
             
            static VALUE
         | 
| 1300 1516 | 
             
            magic_return(void *data)
         | 
| 1301 1517 | 
             
            {
         | 
| 1302 | 
            -
            	 | 
| 1518 | 
            +
            	rb_mgc_arguments_t *mga = data;
         | 
| 1303 1519 | 
             
            	const char *unknown = "???";
         | 
| 1304 1520 | 
             
            	VALUE separator = Qundef;
         | 
| 1305 | 
            -
            	VALUE array  | 
| 1306 | 
            -
            	VALUE string = Qundef;
         | 
| 1521 | 
            +
            	VALUE array, string;
         | 
| 1307 1522 |  | 
| 1308 | 
            -
            	string = CSTR2RVAL( | 
| 1523 | 
            +
            	string = CSTR2RVAL(mga->result);
         | 
| 1309 1524 | 
             
            	RB_GC_GUARD(string);
         | 
| 1310 1525 |  | 
| 1311 1526 | 
             
            	/*
         | 
| @@ -1313,15 +1528,15 @@ magic_return(void *data) | |
| 1313 1528 | 
             
            	 * when the CONTINUE flag is set causing all valid matches found by the
         | 
| 1314 1529 | 
             
            	 * Magic library to be returned.
         | 
| 1315 1530 | 
             
            	 */
         | 
| 1316 | 
            -
            	if ( | 
| 1531 | 
            +
            	if (mga->flags & MAGIC_CONTINUE)
         | 
| 1317 1532 | 
             
            		separator = CSTR2RVAL(MAGIC_CONTINUE_SEPARATOR);
         | 
| 1318 1533 |  | 
| 1319 | 
            -
            	if ( | 
| 1534 | 
            +
            	if (mga->flags & MAGIC_EXTENSION) {
         | 
| 1320 1535 | 
             
            		/*
         | 
| 1321 1536 | 
             
            		 * A possible I/O-related error has occurred, and there is very
         | 
| 1322 1537 | 
             
            		 * little sense processing the results, so return string as-is.
         | 
| 1323 1538 | 
             
            		 */
         | 
| 1324 | 
            -
            		if ( | 
| 1539 | 
            +
            		if (mga->status < 0)
         | 
| 1325 1540 | 
             
            			return string;
         | 
| 1326 1541 | 
             
            		/*
         | 
| 1327 1542 | 
             
            		 * A number of Magic flags that support primarily files e.g.,
         | 
| @@ -1330,19 +1545,25 @@ magic_return(void *data) | |
| 1330 1545 | 
             
            		 * return an empty string, to indicate lack of results, rather
         | 
| 1331 1546 | 
             
            		 * than a confusing string consisting of three questions marks.
         | 
| 1332 1547 | 
             
            		 */
         | 
| 1333 | 
            -
            		if (strncmp( | 
| 1548 | 
            +
            		if (strncmp(mga->result, unknown, strlen(unknown)) == 0)
         | 
| 1334 1549 | 
             
            			return CSTR2RVAL("");
         | 
| 1335 1550 |  | 
| 1336 1551 | 
             
            		separator = CSTR2RVAL(MAGIC_EXTENSION_SEPARATOR);
         | 
| 1337 1552 | 
             
            	}
         | 
| 1338 1553 |  | 
| 1339 | 
            -
            	 | 
| 1554 | 
            +
            	RB_GC_GUARD(separator);
         | 
| 1555 | 
            +
             | 
| 1556 | 
            +
            	if (mga->flags & (MAGIC_CONTINUE | MAGIC_EXTENSION)) {
         | 
| 1340 1557 | 
             
            		array = magic_split(string, separator);
         | 
| 1341 1558 | 
             
            		RB_GC_GUARD(array);
         | 
| 1342 | 
            -
             | 
| 1559 | 
            +
             | 
| 1560 | 
            +
            		if (RARRAY_LEN(array) > 1)
         | 
| 1561 | 
            +
            			return magic_strip_array(array);
         | 
| 1562 | 
            +
             | 
| 1563 | 
            +
            		string = magic_shift(array);
         | 
| 1343 1564 | 
             
            	}
         | 
| 1344 1565 |  | 
| 1345 | 
            -
            	return string;
         | 
| 1566 | 
            +
            	return magic_strip(string);
         | 
| 1346 1567 | 
             
            }
         | 
| 1347 1568 |  | 
| 1348 1569 | 
             
            static inline int
         | 
| @@ -1351,10 +1572,10 @@ magic_get_flags(VALUE object) | |
| 1351 1572 | 
             
            	return NUM2INT(rb_ivar_get(object, id_at_flags));
         | 
| 1352 1573 | 
             
            }
         | 
| 1353 1574 |  | 
| 1354 | 
            -
            static inline  | 
| 1355 | 
            -
            magic_set_flags(VALUE object,  | 
| 1575 | 
            +
            static inline void
         | 
| 1576 | 
            +
            magic_set_flags(VALUE object, int flags)
         | 
| 1356 1577 | 
             
            {
         | 
| 1357 | 
            -
            	 | 
| 1578 | 
            +
            	rb_ivar_set(object, id_at_flags, INT2NUM(flags));
         | 
| 1358 1579 | 
             
            }
         | 
| 1359 1580 |  | 
| 1360 1581 | 
             
            static inline VALUE
         | 
| @@ -1363,7 +1584,7 @@ magic_set_paths(VALUE object, VALUE value) | |
| 1363 1584 | 
             
            	return rb_ivar_set(object, id_at_paths, value);
         | 
| 1364 1585 | 
             
            }
         | 
| 1365 1586 |  | 
| 1366 | 
            -
            static const rb_data_type_t  | 
| 1587 | 
            +
            static const rb_data_type_t rb_mgc_type = {
         | 
| 1367 1588 | 
             
            	.wrap_struct_name = "magic",
         | 
| 1368 1589 | 
             
            	.function = {
         | 
| 1369 1590 | 
             
            		.dmark	  = magic_mark,
         |