github.com/jurelou/go-magic@v0.0.0-20230518182705-f2995a311800/functions.c (about)

     1  #if defined(__cplusplus)
     2  extern "C" {
     3  #endif
     4  
     5  #include "functions.h"
     6  
     7  int check_fd(int fd);
     8  static int safe_dup(int fd);
     9  static int safe_close(int fd);
    10  static int safe_cloexec(int fd);
    11  int override_error_output(void *data);
    12  int restore_error_output(void *data);
    13  
    14  inline int
    15  check_fd(int fd)
    16  {
    17  	errno = 0;
    18  	if (fd < 0 || (fcntl(fd, F_GETFD) < 0 && errno == EBADF)) {
    19  		errno = EBADF;
    20  		return -EBADF;
    21  	}
    22  
    23  	return 0;
    24  }
    25  
    26  static int
    27  safe_dup(int fd)
    28  {
    29  	int new_fd;
    30  	int local_errno;
    31  	int flags = F_DUPFD;
    32  
    33  #if defined(HAVE_F_DUPFD_CLOEXEC)
    34  	flags = F_DUPFD_CLOEXEC;
    35  #endif
    36  
    37  	new_fd = fcntl(fd, flags, fileno(stderr) + 1);
    38  	if (new_fd < 0 && errno == EINVAL) {
    39  		new_fd = dup(fd);
    40  		if (new_fd < 0) {
    41  			local_errno = errno;
    42  			goto error;
    43  		}
    44  	}
    45  	if (safe_cloexec(new_fd) < 0) {
    46  		local_errno = errno;
    47  		goto error;
    48  	}
    49  
    50  	return new_fd;
    51  error:
    52  	errno = local_errno;
    53  	return -1;
    54  }
    55  
    56  static int
    57  safe_close(int fd)
    58  {
    59  	int rv;
    60  #if defined(HAVE_POSIX_CLOSE_RESTART)
    61  	rv = posix_close(fd, 0);
    62  #else
    63  	rv = close(fd);
    64  	if (rv < 0 && errno == EINTR)
    65  		errno = EINPROGRESS;
    66  #endif
    67  
    68  	return rv;
    69  }
    70  
    71  static inline int
    72  safe_cloexec(int fd)
    73  {
    74  	int local_errno;
    75  	int flags = fcntl(fd, F_GETFD);
    76  
    77  	if (flags < 0) {
    78  		local_errno = errno;
    79  		goto error;
    80  	}
    81  	if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
    82  		local_errno = errno;
    83  		goto error;
    84  	}
    85  
    86  	return 0;
    87  error:
    88  	errno = local_errno;
    89  	return -1;
    90  }
    91  
    92  int
    93  override_error_output(void *data)
    94  {
    95  	int local_errno;
    96  	mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
    97  	save_t *s = data;
    98  
    99  #if defined(HAVE_O_CLOEXEC)
   100  	mode |= O_CLOEXEC;
   101  #endif
   102  
   103  	assert(s != NULL && \
   104  	       "Must be a valid pointer to `save_t' type");
   105  
   106  	s->file.old_fd = -1;
   107  	s->file.new_fd = -1;
   108  	s->status = -1;
   109  
   110  	fflush(stderr);
   111  	fgetpos(stderr, &s->file.position);
   112  
   113  	s->file.old_fd = safe_dup(fileno(stderr));
   114  	if (s->file.old_fd < 0) {
   115  		local_errno = errno;
   116  		goto error;
   117  	}
   118  
   119  	s->file.new_fd = open("/dev/null", O_WRONLY | O_APPEND, mode);
   120  	if (s->file.new_fd < 0) {
   121  		local_errno = errno;
   122  
   123  		if (dup2(s->file.old_fd, fileno(stderr)) < 0) {
   124  			local_errno = errno;
   125  			goto error;
   126  		}
   127  
   128  		safe_close(s->file.old_fd);
   129  		goto error;
   130  	}
   131  	if (safe_cloexec(s->file.new_fd) < 0) {
   132  		local_errno = errno;
   133  		goto error;
   134  	}
   135  	if (dup2(s->file.new_fd, fileno(stderr)) < 0) {
   136  		local_errno = errno;
   137  		goto error;
   138  	}
   139  
   140  	safe_close(s->file.new_fd);
   141  
   142  	return 0;
   143  error:
   144  	s->status = local_errno;
   145  	errno = s->status;
   146  	return -1;
   147  }
   148  
   149  int
   150  restore_error_output(void *data)
   151  {
   152  	int local_errno;
   153  	save_t *s = data;
   154  
   155  	assert(s != NULL && \
   156  	       "Must be a valid pointer to `save_t' type");
   157  
   158  	if (s->file.old_fd < 0 && s->status != 0)
   159  		return -1;
   160  
   161  	fflush(stderr);
   162  
   163  	if (dup2(s->file.old_fd, fileno(stderr)) < 0) {
   164  		local_errno = errno;
   165  		goto error;
   166  	}
   167  
   168  	safe_close(s->file.old_fd);
   169  	clearerr(stderr);
   170  	fsetpos(stderr, &s->file.position);
   171  
   172  	if (setvbuf(stderr, NULL, _IONBF, 0) != 0) {
   173  		local_errno = errno;
   174  		goto error;
   175  	}
   176  
   177  	return 0;
   178  error:
   179  	s->status = local_errno;
   180  	errno = s->status;
   181  	return -1;
   182  }
   183  
   184  inline magic_t
   185  magic_open_wrapper(int flags)
   186  {
   187  	return magic_open(flags);
   188  }
   189  
   190  inline void
   191  magic_close_wrapper(magic_t magic)
   192  {
   193  	magic_close(magic);
   194  }
   195  
   196  inline const char*
   197  magic_error_wrapper(magic_t magic)
   198  {
   199  	return magic_error(magic);
   200  }
   201  
   202  inline int
   203  magic_errno_wrapper(magic_t magic)
   204  {
   205  	return magic_errno(magic);
   206  }
   207  
   208  inline const char*
   209  magic_getpath_wrapper(void)
   210  {
   211  	return magic_getpath(NULL, 0);
   212  }
   213  
   214  inline int
   215  magic_getparam_wrapper(magic_t magic, int parameter, void *value)
   216  {
   217  	return magic_getparam(magic, parameter, value);
   218  }
   219  
   220  inline int
   221  magic_setparam_wrapper(magic_t magic, int parameter, const void *value)
   222  {
   223  	if (*(const int *)value < 0 || *(const size_t *)value > UINT_MAX) {
   224  		errno = EOVERFLOW;
   225  		return -EOVERFLOW;
   226  	}
   227  
   228  	if (parameter == MAGIC_PARAM_BYTES_MAX)
   229  		return magic_setparam(magic, parameter, value);
   230  
   231  	if (*(const size_t *)value > USHRT_MAX) {
   232  		errno = EOVERFLOW;
   233  		return -EOVERFLOW;
   234  	}
   235  
   236  	return magic_setparam(magic, parameter, value);
   237  }
   238  
   239  inline int
   240  magic_getflags_wrapper(magic_t magic)
   241  {
   242  #if defined(HAVE_MAGIC_GETFLAGS)
   243  	return magic_getflags(magic);
   244  #else
   245  	UNUSED(magic);
   246  	errno = ENOSYS;
   247  	return -ENOSYS;
   248  #endif
   249  }
   250  
   251  inline int
   252  magic_setflags_wrapper(magic_t magic, int flags)
   253  {
   254  	if (flags < 0 || flags > 0xfffffff) {
   255  		errno = EINVAL;
   256  		return -EINVAL;
   257  	}
   258  
   259  	return magic_setflags(magic, flags);
   260  }
   261  
   262  inline int
   263  magic_load_wrapper(magic_t magic, const char *magic_file, int flags)
   264  {
   265  	int rv;
   266  	MAGIC_FUNCTION(magic_load, rv, flags, magic, magic_file);
   267  	return rv;
   268  }
   269  
   270  inline int
   271  magic_load_buffers_wrapper(magic_t magic, void **buffers, size_t *sizes, size_t count, int flags)
   272  {
   273  	int rv;
   274  	MAGIC_FUNCTION(magic_load_buffers, rv, flags, magic, buffers, sizes, count);
   275  	return rv;
   276  }
   277  
   278  inline int
   279  magic_compile_wrapper(magic_t magic, const char *magic_file, int flags)
   280  {
   281  	int rv;
   282  	MAGIC_FUNCTION(magic_compile, rv, flags, magic, magic_file);
   283  	return rv;
   284  }
   285  
   286  inline int
   287  magic_check_wrapper(magic_t magic, const char *magic_file, int flags)
   288  {
   289  	int rv;
   290  	MAGIC_FUNCTION(magic_check, rv, flags, magic, magic_file);
   291  	return rv;
   292  }
   293  
   294  inline const char*
   295  magic_file_wrapper(magic_t magic, const char* filename, int flags)
   296  {
   297  	const char *cstring;
   298  	MAGIC_FUNCTION(magic_file, cstring, flags, magic, filename);
   299  	return cstring;
   300  }
   301  
   302  inline const char*
   303  magic_buffer_wrapper(magic_t magic, const void *buffer, size_t size, int flags)
   304  {
   305  	const char *cstring;
   306  	MAGIC_FUNCTION(magic_buffer, cstring, flags, magic, buffer, size);
   307  	return cstring;
   308  }
   309  
   310  inline const char*
   311  magic_descriptor_wrapper(magic_t magic, int fd, int flags)
   312  {
   313  	int local_errno;
   314  	const char *cstring;
   315  
   316  	if (check_fd(fd) < 0) {
   317  		local_errno = errno;
   318  		goto error;
   319  	}
   320  
   321  	MAGIC_FUNCTION(magic_descriptor, cstring, flags, magic, fd);
   322  	return cstring;
   323  
   324  error:
   325  	errno = local_errno;
   326  	return NULL;
   327  }
   328  
   329  inline int
   330  magic_version_wrapper(void)
   331  {
   332  	return magic_version();
   333  }
   334  
   335  #if defined(__cplusplus)
   336  }
   337  #endif