ruby-magic 0.2.0 → 0.3.0

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.
@@ -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 : */