ruby-magic 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,329 +1,344 @@
1
- /* :enddoc: */
2
-
3
- /*
4
- * functions.c
5
- *
6
- * Copyright 2013-2015 Krzysztof Wilczynski
7
- *
8
- * Licensed under the Apache License, Version 2.0 (the "License");
9
- * you may not use this file except in compliance with the License.
10
- * You may obtain a copy of the License at
11
- *
12
- * http://www.apache.org/licenses/LICENSE-2.0
13
- *
14
- * Unless required by applicable law or agreed to in writing, software
15
- * distributed under the License is distributed on an "AS IS" BASIS,
16
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
- * See the License for the specific language governing permissions and
18
- * limitations under the License.
19
- */
20
-
21
1
  #if defined(__cplusplus)
22
2
  extern "C" {
23
3
  #endif
24
4
 
25
5
  #include "functions.h"
26
6
 
27
- int suppress_error_output(void *data);
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);
28
12
  int restore_error_output(void *data);
29
13
 
30
- int override_current_locale(void *data);
31
- int restore_current_locale(void *data);
32
-
33
- int
34
- suppress_error_output(void *data)
14
+ inline int
15
+ check_fd(int fd)
35
16
  {
36
- int local_errno;
37
- mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
38
-
39
- save_t *s = data;
40
- assert(s != NULL && "Must be a valid pointer to `save_t' type");
17
+ errno = 0;
18
+ if (fd < 0 || (fcntl(fd, F_GETFD) < 0 && errno == EBADF)) {
19
+ errno = EBADF;
20
+ return -EBADF;
21
+ }
41
22
 
42
- s->data.file.old_fd = -1;
43
- s->data.file.new_fd = -1;
44
- s->status = -1;
45
-
46
- fflush(stderr);
47
- fgetpos(stderr, &s->data.file.position);
48
-
49
- s->data.file.old_fd = dup(fileno(stderr));
50
- if (s->data.file.old_fd < 0) {
51
- local_errno = errno;
52
- goto out;
53
- }
54
-
55
- s->data.file.new_fd = open("/dev/null", O_WRONLY | O_APPEND, mode);
56
- if (s->data.file.new_fd < 0) {
57
- local_errno = errno;
23
+ return 0;
24
+ }
58
25
 
59
- if (dup2(s->data.file.old_fd, fileno(stderr)) < 0) {
60
- local_errno = errno;
61
- goto out;
62
- }
26
+ static int
27
+ safe_dup(int fd)
28
+ {
29
+ int new_fd;
30
+ int local_errno;
31
+ int flags = F_DUPFD;
63
32
 
64
- close(s->data.file.old_fd);
65
- goto out;
66
- }
33
+ #if defined(HAVE_F_DUPFD_CLOEXEC)
34
+ flags = F_DUPFD_CLOEXEC;
35
+ #endif
67
36
 
68
- if (dup2(s->data.file.new_fd, fileno(stderr)) < 0) {
69
- local_errno = errno;
70
- goto out;
71
- }
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
+ }
72
55
 
73
- close(s->data.file.new_fd);
74
- return 0;
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
75
67
 
76
- out:
77
- s->status = local_errno;
78
- errno = s->status;
68
+ return rv;
69
+ }
79
70
 
80
- return -1;
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;
81
90
  }
82
91
 
83
92
  int
84
- restore_error_output(void *data)
93
+ override_error_output(void *data)
85
94
  {
86
- int local_errno;
87
-
88
- save_t *s = data;
89
- assert(s != NULL && "Must be a valid pointer to `save_t' type");
90
-
91
- if (s->data.file.old_fd < 0 && s->status != 0) {
92
- return -1;
93
- }
95
+ int local_errno;
96
+ mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
97
+ save_t *s = data;
94
98
 
95
- fflush(stderr);
96
-
97
- if (dup2(s->data.file.old_fd, fileno(stderr)) < 0) {
98
- local_errno = errno;
99
- goto out;
100
- }
101
-
102
- close(s->data.file.old_fd);
103
- clearerr(stderr);
104
- fsetpos(stderr, &s->data.file.position);
105
-
106
- if (setvbuf(stderr, NULL, _IONBF, 0) != 0) {
107
- local_errno = errno;
108
- goto out;
109
- }
110
-
111
- return 0;
112
-
113
- out:
114
- s->status = local_errno;
115
- errno = s->status;
99
+ #if defined(HAVE_O_CLOEXEC)
100
+ mode |= O_CLOEXEC;
101
+ #endif
116
102
 
117
- return -1;
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;
118
147
  }
119
148
 
120
149
  int
121
- override_current_locale(void *data)
150
+ restore_error_output(void *data)
122
151
  {
123
- #if !defined(HAVE_SAFE_LOCALE)
124
- char *current_locale = NULL;
125
- #endif
126
-
127
- save_t *s = data;
128
- assert(s != NULL && "Must be a valid pointer to `save_t' type");
129
-
130
- s->status = -1;
152
+ int local_errno;
153
+ save_t *s = data;
131
154
 
132
- #if defined(HAVE_SAFE_LOCALE)
133
- s->data.locale.old_locale = NULL;
134
- s->data.locale.new_locale = NULL;
155
+ assert(s != NULL && \
156
+ "Must be a valid pointer to `save_t' type");
135
157
 
136
- s->data.locale.new_locale = newlocale(LC_ALL_MASK, "C", NULL);
137
- if (s->data.locale.new_locale == (locale_t)0) {
138
- goto out;
139
- }
158
+ if (s->file.old_fd < 0 && s->status != 0)
159
+ return -1;
140
160
 
141
- assert(s->data.locale.new_locale != NULL && \
142
- "Must be a valid pointer to `locale_t' type");
161
+ fflush(stderr);
143
162
 
144
- s->data.locale.old_locale = uselocale(s->data.locale.new_locale);
145
- if (s->data.locale.old_locale == (locale_t)0) {
146
- goto out;
147
- }
163
+ if (dup2(s->file.old_fd, fileno(stderr)) < 0) {
164
+ local_errno = errno;
165
+ goto error;
166
+ }
148
167
 
149
- assert(s->data.locale.old_locale != NULL && \
150
- "Must be a valid pointer to `locale_t' type");
151
- #else
152
- s->data.locale.old_locale = NULL;
153
-
154
- current_locale = setlocale(LC_ALL, NULL);
155
- if (!current_locale) {
156
- goto out;
157
- }
158
-
159
- s->data.locale.old_locale = strndup(current_locale, strlen(current_locale));
160
- if (!s->data.locale.old_locale) {
161
- goto out;
162
- }
168
+ safe_close(s->file.old_fd);
169
+ clearerr(stderr);
170
+ fsetpos(stderr, &s->file.position);
163
171
 
164
- if (!setlocale(LC_ALL, "C")) {
165
- goto out;
166
- }
167
-
168
- assert(s->data.locale.old_locale != NULL && \
169
- "Must be a valid pointer to `char' type");
170
- #endif
171
- s->status = 0;
172
+ if (setvbuf(stderr, NULL, _IONBF, 0) != 0) {
173
+ local_errno = errno;
174
+ goto error;
175
+ }
172
176
 
173
- out:
174
- return s->status;
177
+ return 0;
178
+ error:
179
+ s->status = local_errno;
180
+ errno = s->status;
181
+ return -1;
175
182
  }
176
183
 
177
- int
178
- restore_current_locale(void *data)
184
+ inline magic_t
185
+ magic_open_wrapper(int flags)
179
186
  {
180
- save_t *s = data;
181
- assert(s != NULL && "Must be a valid pointer to `save_t' type");
182
-
183
- #if defined(HAVE_SAFE_LOCALE)
184
- if (!s->data.locale.new_locale && !s->data.locale.old_locale && s->status != 0) {
185
- return -1;
186
- }
187
+ return magic_open(flags);
188
+ }
187
189
 
188
- if (uselocale(s->data.locale.old_locale) == (locale_t)0) {
189
- goto out;
190
- }
190
+ inline void
191
+ magic_close_wrapper(magic_t magic)
192
+ {
193
+ magic_close(magic);
194
+ }
191
195
 
192
- assert(s->data.locale.new_locale != NULL && \
193
- "Must be a valid pointer to `locale_t' type");
196
+ inline const char*
197
+ magic_error_wrapper(magic_t magic)
198
+ {
199
+ return magic_error(magic);
200
+ }
194
201
 
195
- freelocale(s->data.locale.new_locale);
196
- #else
197
- if (!s->data.locale.old_locale && s->status != 0) {
198
- return -1;
199
- }
202
+ inline int
203
+ magic_errno_wrapper(magic_t magic)
204
+ {
205
+ return magic_errno(magic);
206
+ }
200
207
 
201
- if (!setlocale(LC_ALL, s->data.locale.old_locale)) {
202
- goto out;
203
- }
208
+ inline const char*
209
+ magic_getpath_wrapper(void)
210
+ {
211
+ return magic_getpath(NULL, 0);
212
+ }
204
213
 
205
- assert(s->data.locale.old_locale != NULL && \
206
- "Must be a valid pointer to `char' type");
214
+ inline int
215
+ magic_getparam_wrapper(magic_t magic, int parameter, void *value)
216
+ {
217
+ return magic_getparam(magic, parameter, value);
218
+ }
207
219
 
208
- free(s->data.locale.old_locale);
209
- #endif
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
+ }
210
227
 
211
- return 0;
228
+ if (parameter == MAGIC_PARAM_BYTES_MAX)
229
+ return magic_setparam(magic, parameter, value);
212
230
 
213
- out:
214
- s->status = -1;
215
- #if defined(HAVE_SAFE_LOCALE)
216
- s->data.locale.old_locale = NULL;
217
- s->data.locale.new_locale = NULL;
218
- #else
219
- s->data.locale.old_locale = NULL;
220
- #endif
231
+ if (*(const size_t *)value > USHRT_MAX) {
232
+ errno = EOVERFLOW;
233
+ return -EOVERFLOW;
234
+ }
221
235
 
222
- return -1;
236
+ return magic_setparam(magic, parameter, value);
223
237
  }
224
238
 
225
- inline const char*
226
- magic_getpath_wrapper(void)
239
+ inline int
240
+ magic_getflags_wrapper(magic_t magic)
227
241
  {
228
- return magic_getpath(NULL, 0);
242
+ #if defined(HAVE_MAGIC_GETFLAGS)
243
+ return magic_getflags(magic);
244
+ #else
245
+ UNUSED(magic);
246
+ errno = ENOSYS;
247
+ return -ENOSYS;
248
+ #endif
229
249
  }
230
250
 
231
251
  inline int
232
- magic_setflags_wrapper(struct magic_set *ms, int flags)
252
+ magic_setflags_wrapper(magic_t magic, int flags)
233
253
  {
234
- if (flags < MAGIC_NONE || flags > MAGIC_NO_CHECK_BUILTIN) {
235
- errno = EINVAL;
236
- return -EINVAL;
237
- }
254
+ if (flags < 0 || flags > 0xfffffff) {
255
+ errno = EINVAL;
256
+ return -EINVAL;
257
+ }
238
258
 
239
259
  #if !defined(HAVE_UTIME) && !defined(HAVE_UTIMES)
240
- if (flags & MAGIC_PRESERVE_ATIME) {
241
- errno = ENOSYS;
242
- return -ENOSYS;
243
- }
260
+ if (flags & MAGIC_PRESERVE_ATIME) {
261
+ errno = ENOSYS;
262
+ return -ENOSYS;
263
+ }
244
264
  #endif
245
265
 
246
- return magic_setflags(ms, flags);
266
+ return magic_setflags(magic, flags);
247
267
  }
248
268
 
249
269
  inline int
250
- magic_load_wrapper(struct magic_set *ms, const char *magicfile, int flags)
270
+ magic_load_wrapper(magic_t magic, const char *magic_file, int flags)
251
271
  {
252
- int rv;
253
-
254
- MAGIC_FUNCTION(magic_load, rv, flags, ms, magicfile);
255
-
256
- return rv;
272
+ int rv;
273
+ MAGIC_FUNCTION(magic_load, rv, flags, magic, magic_file);
274
+ return rv;
257
275
  }
258
276
 
259
277
  inline int
260
- magic_compile_wrapper(struct magic_set *ms, const char *magicfile, int flags)
278
+ magic_load_buffers_wrapper(magic_t magic, void **buffers, size_t *sizes, size_t count, int flags)
261
279
  {
262
- int rv;
263
-
264
- MAGIC_FUNCTION(magic_compile, rv, flags, ms, magicfile);
265
-
266
- return rv;
280
+ int rv;
281
+ MAGIC_FUNCTION(magic_load_buffers, rv, flags, magic, buffers, sizes, count);
282
+ return rv;
267
283
  }
268
284
 
269
285
  inline int
270
- magic_check_wrapper(struct magic_set *ms, const char *magicfile, int flags)
286
+ magic_compile_wrapper(magic_t magic, const char *magic_file, int flags)
271
287
  {
272
- int rv;
273
-
274
- MAGIC_FUNCTION(magic_check, rv, flags, ms, magicfile);
288
+ int rv;
289
+ MAGIC_FUNCTION(magic_compile, rv, flags, magic, magic_file);
290
+ return rv;
291
+ }
275
292
 
276
- return rv;
293
+ inline int
294
+ magic_check_wrapper(magic_t magic, const char *magic_file, int flags)
295
+ {
296
+ int rv;
297
+ MAGIC_FUNCTION(magic_check, rv, flags, magic, magic_file);
298
+ return rv;
277
299
  }
278
300
 
279
301
  inline const char*
280
- magic_file_wrapper(struct magic_set *ms, const char* filename, int flags)
302
+ magic_file_wrapper(magic_t magic, const char* filename, int flags)
281
303
  {
282
- const char *cstring;
283
-
284
- MAGIC_FUNCTION(magic_file, cstring, flags, ms, filename);
285
-
286
- return cstring;
304
+ const char *cstring;
305
+ MAGIC_FUNCTION(magic_file, cstring, flags, magic, filename);
306
+ return cstring;
287
307
  }
288
308
 
289
309
  inline const char*
290
- magic_buffer_wrapper(struct magic_set *ms, const void *buffer, size_t size, int flags)
310
+ magic_buffer_wrapper(magic_t magic, const void *buffer, size_t size, int flags)
291
311
  {
292
- const char *cstring;
293
-
294
- MAGIC_FUNCTION(magic_buffer, cstring, flags, ms, buffer, size);
295
-
296
- return cstring;
312
+ const char *cstring;
313
+ MAGIC_FUNCTION(magic_buffer, cstring, flags, magic, buffer, size);
314
+ return cstring;
297
315
  }
298
316
 
299
317
  inline const char*
300
- magic_descriptor_wrapper(struct magic_set *ms, int fd, int flags)
318
+ magic_descriptor_wrapper(magic_t magic, int fd, int flags)
301
319
  {
302
- const char *cstring;
320
+ int local_errno;
321
+ const char *cstring;
322
+
323
+ if (check_fd(fd) < 0) {
324
+ local_errno = errno;
325
+ goto error;
326
+ }
303
327
 
304
- MAGIC_FUNCTION(magic_descriptor, cstring, flags, ms, fd);
328
+ MAGIC_FUNCTION(magic_descriptor, cstring, flags, magic, fd);
329
+ return cstring;
305
330
 
306
- return cstring;
331
+ error:
332
+ errno = local_errno;
333
+ return NULL;
307
334
  }
308
335
 
309
336
  inline int
310
337
  magic_version_wrapper(void)
311
338
  {
312
- #if defined(HAVE_MAGIC_VERSION)
313
- return magic_version();
314
- #else
315
- # if defined(HAVE_WARNING)
316
- # warning "function `int magic_version(void)' not implemented"
317
- # else
318
- # pragma message("function `int magic_version(void)' not implemented")
319
- # endif
320
- errno = ENOSYS;
321
- return -ENOSYS;
322
- #endif
339
+ return magic_version();
323
340
  }
324
341
 
325
342
  #if defined(__cplusplus)
326
343
  }
327
344
  #endif
328
-
329
- /* vim: set ts=8 sw=4 sts=2 et : */