/src/libvips/libvips/iofuncs/source.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* A byte source/sink .. it can be a pipe, file descriptor, memory area, |
2 | | * socket, node.js stream, etc. |
3 | | * |
4 | | * 19/6/14 |
5 | | * |
6 | | * 3/2/20 |
7 | | * - add vips_pipe_read_limit_set() |
8 | | * 3/10/20 |
9 | | * - improve behaviour with read and seek on pipes |
10 | | * 26/11/20 |
11 | | * - use _setmode() on win to force binary read for previously opened |
12 | | * descriptors |
13 | | * 8/10/21 |
14 | | * - fix named pipes |
15 | | * 10/5/22 |
16 | | * - add vips_source_new_from_target() |
17 | | */ |
18 | | |
19 | | /* |
20 | | |
21 | | This file is part of VIPS. |
22 | | |
23 | | VIPS is free software; you can redistribute it and/or modify |
24 | | it under the terms of the GNU Lesser General Public License as published by |
25 | | the Free Software Foundation; either version 2 of the License, or |
26 | | (at your option) any later version. |
27 | | |
28 | | This program is distributed in the hope that it will be useful, |
29 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
30 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
31 | | GNU Lesser General Public License for more details. |
32 | | |
33 | | You should have received a copy of the GNU Lesser General Public License |
34 | | along with this program; if not, write to the Free Software |
35 | | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
36 | | 02110-1301 USA |
37 | | |
38 | | */ |
39 | | |
40 | | /* |
41 | | |
42 | | These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk |
43 | | |
44 | | */ |
45 | | |
46 | | /* |
47 | | #define TEST_SANITY |
48 | | #define VIPS_DEBUG |
49 | | #define DEBUG_MINIMISE |
50 | | */ |
51 | | |
52 | | #ifdef HAVE_CONFIG_H |
53 | | #include <config.h> |
54 | | #endif /*HAVE_CONFIG_H*/ |
55 | | #include <glib/gi18n-lib.h> |
56 | | |
57 | | #include <stdio.h> |
58 | | #include <stdlib.h> |
59 | | #ifdef HAVE_UNISTD_H |
60 | | #include <unistd.h> |
61 | | #endif /*HAVE_UNISTD_H*/ |
62 | | #include <string.h> |
63 | | #include <errno.h> |
64 | | #include <sys/types.h> |
65 | | #include <sys/stat.h> |
66 | | #include <fcntl.h> |
67 | | |
68 | | #include <vips/vips.h> |
69 | | |
70 | | #ifdef G_OS_WIN32 |
71 | | #include <io.h> |
72 | | #endif /*G_OS_WIN32*/ |
73 | | |
74 | | #include <vips/debug.h> |
75 | | #include <vips/internal.h> |
76 | | |
77 | 0 | #define MODE_READ CLOEXEC(BINARYIZE(O_RDONLY)) |
78 | | |
79 | | /* -1 on a pipe isn't actually unbounded. Have a limit to prevent |
80 | | * huge sources accidentally filling memory. |
81 | | * |
82 | | * This can be configured with vips_pipe_read_limit_set(). |
83 | | */ |
84 | | static gint64 vips__pipe_read_limit = 1024 * 1024 * 1024; |
85 | | |
86 | | /** |
87 | | * vips_pipe_read_limit_set: |
88 | | * @limit: maximum number of bytes to buffer from a pipe |
89 | | * |
90 | | * If a source does not support mmap or seek and the source is |
91 | | * used with a loader that can only work from memory, then the data will be |
92 | | * automatically read into memory to EOF before the loader starts. This can |
93 | | * produce high memory use if the descriptor represents a large object. |
94 | | * |
95 | | * Use vips_pipe_read_limit_set() to limit the size of object that |
96 | | * will be read in this way. The default is 1GB. |
97 | | * |
98 | | * Set a value of -1 to mean no limit. |
99 | | * |
100 | | * See also: `--vips-pipe-read-limit` and the environment variable |
101 | | * `VIPS_PIPE_READ_LIMIT`. |
102 | | */ |
103 | | void |
104 | | vips_pipe_read_limit_set(gint64 limit) |
105 | 0 | { |
106 | 0 | vips__pipe_read_limit = limit; |
107 | 0 | } |
108 | | |
109 | | G_DEFINE_TYPE(VipsSource, vips_source, VIPS_TYPE_CONNECTION); |
110 | | |
111 | | /* Does this source support seek. You must unminimise before calling this. |
112 | | */ |
113 | | static int |
114 | | vips_source_test_seek(VipsSource *source) |
115 | 2.78M | { |
116 | 2.78M | if (!source->have_tested_seek) { |
117 | 148k | VipsSourceClass *class = VIPS_SOURCE_GET_CLASS(source); |
118 | | |
119 | 148k | source->have_tested_seek = TRUE; |
120 | | |
121 | 148k | VIPS_DEBUG_MSG("vips_source_can_seek: testing seek ..\n"); |
122 | | |
123 | | /* Can we seek this input? |
124 | | * |
125 | | * We need to call the method directly rather than via |
126 | | * vips_source_seek() etc. or we might trigger seek emulation. |
127 | | */ |
128 | 148k | if (source->data || |
129 | 148k | class->seek(source, 0, SEEK_CUR) != -1) { |
130 | 148k | gint64 length; |
131 | | |
132 | 148k | VIPS_DEBUG_MSG(" seekable source\n"); |
133 | | |
134 | | /* We should be able to get the length of seekable |
135 | | * objects. |
136 | | */ |
137 | 148k | if ((length = vips_source_length(source)) == -1) |
138 | 0 | return -1; |
139 | | |
140 | 148k | source->length = length; |
141 | | |
142 | | /* If we can seek, we won't need to save header bytes. |
143 | | */ |
144 | 148k | VIPS_FREEF(g_byte_array_unref, source->header_bytes); |
145 | 148k | } |
146 | 0 | else { |
147 | | /* Not seekable. This must be some kind of pipe. |
148 | | */ |
149 | 0 | VIPS_DEBUG_MSG(" not seekable\n"); |
150 | 0 | source->is_pipe = TRUE; |
151 | 0 | } |
152 | 148k | } |
153 | | |
154 | 2.78M | return 0; |
155 | 2.78M | } |
156 | | |
157 | | /* We can't test for seekability or length during _build, since the read and |
158 | | * seek signal handlers might not have been connected yet. Instead, we test |
159 | | * when we first need to know. |
160 | | */ |
161 | | static int |
162 | | vips_source_test_features(VipsSource *source) |
163 | 2.78M | { |
164 | 2.78M | if (vips_source_unminimise(source) || |
165 | 2.78M | vips_source_test_seek(source)) |
166 | 0 | return -1; |
167 | | |
168 | 2.78M | return 0; |
169 | 2.78M | } |
170 | | |
171 | | #ifdef TEST_SANITY |
172 | | static void |
173 | | vips_source_sanity(VipsSource *source) |
174 | | { |
175 | | if (source->data) { |
176 | | /* A memory buffer. Not a pipe (can map and seek). |
177 | | */ |
178 | | g_assert(!source->is_pipe); |
179 | | |
180 | | /* Read position must lie within the buffer. |
181 | | */ |
182 | | g_assert(source->read_position >= 0); |
183 | | g_assert(source->read_position <= source->length); |
184 | | |
185 | | /* After we're done with the header, the sniff buffer should |
186 | | * be gone. |
187 | | */ |
188 | | g_assert(!source->decode || |
189 | | !source->sniff); |
190 | | |
191 | | /* Have length. |
192 | | */ |
193 | | g_assert(source->length != -1); |
194 | | } |
195 | | else if (source->is_pipe) { |
196 | | /* Something like a descriptor we can't seek. It might not have |
197 | | * ->descriptor valid, that could be held in a subclass. |
198 | | */ |
199 | | |
200 | | if (source->decode) { |
201 | | /* Reading pixel data. |
202 | | */ |
203 | | g_assert(!source->header_bytes); |
204 | | g_assert(!source->sniff); |
205 | | } |
206 | | else { |
207 | | /* Reading header data. |
208 | | */ |
209 | | g_assert(source->header_bytes); |
210 | | g_assert(source->read_position >= 0); |
211 | | g_assert(source->read_position <= source->header_bytes->len); |
212 | | } |
213 | | |
214 | | /* No length available. |
215 | | */ |
216 | | g_assert(source->length == -1); |
217 | | } |
218 | | else { |
219 | | /* Something like a descriptor we can seek. It might not have |
220 | | * ->descriptor valid, that could be held in a subclass. |
221 | | */ |
222 | | |
223 | | /* After we're done with the header, the sniff buffer should |
224 | | * be gone. |
225 | | */ |
226 | | if (source->decode) |
227 | | g_assert(!source->sniff); |
228 | | |
229 | | /* Once we've tested seek, the read position must lie within |
230 | | * the file. |
231 | | */ |
232 | | if (source->have_tested_seek) { |
233 | | g_assert(source->length != -1); |
234 | | g_assert(source->read_position >= 0); |
235 | | g_assert(source->read_position <= source->length); |
236 | | } |
237 | | } |
238 | | } |
239 | | #endif /*TEST_SANITY*/ |
240 | | |
241 | | #ifdef TEST_SANITY |
242 | | #define SANITY(S) vips_source_sanity(S) |
243 | | #warning "sanity tests on in source.c" |
244 | | #else /*!TEST_SANITY*/ |
245 | | #define SANITY(S) |
246 | | #endif /*TEST_SANITY*/ |
247 | | |
248 | | static void |
249 | | vips_source_finalize(GObject *gobject) |
250 | 148k | { |
251 | 148k | VipsSource *source = VIPS_SOURCE(gobject); |
252 | | |
253 | | #ifdef DEBUG_MINIMISE |
254 | | printf("vips_source_finalize: %p\n", source); |
255 | | #endif /*DEBUG_MINIMISE*/ |
256 | | |
257 | 148k | VIPS_FREEF(g_byte_array_unref, source->header_bytes); |
258 | 148k | VIPS_FREEF(g_byte_array_unref, source->sniff); |
259 | 148k | if (source->mmap_baseaddr) { |
260 | 0 | vips__munmap(source->mmap_baseaddr, source->mmap_length); |
261 | 0 | source->mmap_baseaddr = NULL; |
262 | 0 | } |
263 | | |
264 | 148k | G_OBJECT_CLASS(vips_source_parent_class)->finalize(gobject); |
265 | 148k | } |
266 | | |
267 | | static int |
268 | | vips_source_build(VipsObject *object) |
269 | 148k | { |
270 | 148k | VipsConnection *connection = VIPS_CONNECTION(object); |
271 | 148k | VipsSource *source = VIPS_SOURCE(object); |
272 | | |
273 | 148k | VIPS_DEBUG_MSG("vips_source_build: %p\n", source); |
274 | | |
275 | 148k | if (VIPS_OBJECT_CLASS(vips_source_parent_class)->build(object)) |
276 | 0 | return -1; |
277 | | |
278 | 148k | if (vips_object_argument_isset(object, "filename") && |
279 | 148k | vips_object_argument_isset(object, "descriptor")) { |
280 | 0 | vips_error(vips_connection_nick(connection), |
281 | 0 | "%s", _("don't set 'filename' and 'descriptor'")); |
282 | 0 | return -1; |
283 | 0 | } |
284 | | |
285 | | /* unminimise will open the filename. |
286 | | */ |
287 | 148k | if (vips_object_argument_isset(object, "filename") && |
288 | 148k | vips_source_unminimise(source)) |
289 | 0 | return -1; |
290 | | |
291 | 148k | if (vips_object_argument_isset(object, "descriptor")) { |
292 | 0 | connection->descriptor = dup(connection->descriptor); |
293 | 0 | connection->close_descriptor = connection->descriptor; |
294 | |
|
295 | | #ifdef G_OS_WIN32 |
296 | | /* Windows will create eg. stdin and stdout in text mode. |
297 | | * We always read in binary mode. |
298 | | */ |
299 | | _setmode(connection->descriptor, _O_BINARY); |
300 | | #endif /*G_OS_WIN32*/ |
301 | 0 | } |
302 | | |
303 | 148k | if (vips_object_argument_isset(object, "blob")) { |
304 | 148k | size_t length; |
305 | | |
306 | 148k | if (!(source->data = vips_blob_get(source->blob, &length))) |
307 | 0 | return -1; |
308 | | |
309 | 148k | source->length = VIPS_MIN(length, G_MAXSSIZE); |
310 | 148k | } |
311 | | |
312 | 148k | return 0; |
313 | 148k | } |
314 | | |
315 | | static gint64 |
316 | | vips_source_read_real(VipsSource *source, void *data, size_t length) |
317 | 0 | { |
318 | 0 | VipsConnection *connection = VIPS_CONNECTION(source); |
319 | |
|
320 | 0 | gint64 bytes_read; |
321 | |
|
322 | 0 | VIPS_DEBUG_MSG("vips_source_read_real:\n"); |
323 | |
|
324 | 0 | do { |
325 | 0 | bytes_read = read(connection->descriptor, data, length); |
326 | 0 | } while (bytes_read < 0 && errno == EINTR); |
327 | |
|
328 | 0 | return bytes_read; |
329 | 0 | } |
330 | | |
331 | | static gint64 |
332 | | vips_source_seek_real(VipsSource *source, gint64 offset, int whence) |
333 | 0 | { |
334 | 0 | VipsConnection *connection = VIPS_CONNECTION(source); |
335 | |
|
336 | 0 | VIPS_DEBUG_MSG("vips_source_seek_real:\n"); |
337 | | |
338 | | /* Like _read_real(), we must not set a vips_error. We need to use the |
339 | | * vips__seek() wrapper so we can seek long files on Windows. |
340 | | */ |
341 | 0 | if (connection->descriptor != -1) |
342 | 0 | return vips__seek_no_error(connection->descriptor, offset, whence); |
343 | | |
344 | 0 | return -1; |
345 | 0 | } |
346 | | |
347 | | static void |
348 | | vips_source_class_init(VipsSourceClass *class) |
349 | 1 | { |
350 | 1 | GObjectClass *gobject_class = G_OBJECT_CLASS(class); |
351 | 1 | VipsObjectClass *object_class = VIPS_OBJECT_CLASS(class); |
352 | | |
353 | 1 | gobject_class->finalize = vips_source_finalize; |
354 | 1 | gobject_class->set_property = vips_object_set_property; |
355 | 1 | gobject_class->get_property = vips_object_get_property; |
356 | | |
357 | 1 | object_class->nickname = "source"; |
358 | 1 | object_class->description = _("input source"); |
359 | | |
360 | 1 | object_class->build = vips_source_build; |
361 | | |
362 | 1 | class->read = vips_source_read_real; |
363 | 1 | class->seek = vips_source_seek_real; |
364 | | |
365 | 1 | VIPS_ARG_BOXED(class, "blob", 3, |
366 | 1 | _("Blob"), |
367 | 1 | _("Blob to load from"), |
368 | 1 | VIPS_ARGUMENT_OPTIONAL_INPUT, |
369 | 1 | G_STRUCT_OFFSET(VipsSource, blob), |
370 | 1 | VIPS_TYPE_BLOB); |
371 | 1 | } |
372 | | |
373 | | static void |
374 | | vips_source_init(VipsSource *source) |
375 | 148k | { |
376 | 148k | source->length = -1; |
377 | 148k | source->sniff = g_byte_array_new(); |
378 | 148k | source->header_bytes = g_byte_array_new(); |
379 | 148k | } |
380 | | |
381 | | /** |
382 | | * vips_source_new_from_descriptor: |
383 | | * @descriptor: read from this file descriptor |
384 | | * |
385 | | * Create an source attached to a file descriptor. @descriptor is |
386 | | * closed with close() when source is finalized. |
387 | | * |
388 | | * Returns: a new source. |
389 | | */ |
390 | | VipsSource * |
391 | | vips_source_new_from_descriptor(int descriptor) |
392 | 0 | { |
393 | 0 | VipsSource *source; |
394 | |
|
395 | 0 | VIPS_DEBUG_MSG("vips_source_new_from_descriptor: %d\n", |
396 | 0 | descriptor); |
397 | |
|
398 | 0 | source = VIPS_SOURCE(g_object_new(VIPS_TYPE_SOURCE, |
399 | 0 | "descriptor", descriptor, |
400 | 0 | NULL)); |
401 | |
|
402 | 0 | if (vips_object_build(VIPS_OBJECT(source))) { |
403 | 0 | VIPS_UNREF(source); |
404 | 0 | return NULL; |
405 | 0 | } |
406 | | |
407 | 0 | SANITY(source); |
408 | |
|
409 | 0 | return source; |
410 | 0 | } |
411 | | |
412 | | /** |
413 | | * vips_source_new_from_file: |
414 | | * @descriptor: read from this filename |
415 | | * |
416 | | * Create an source attached to a file. |
417 | | * |
418 | | * If this descriptor does not support mmap and the source is |
419 | | * used with a loader that can only work from memory, then the data will be |
420 | | * automatically read into memory to EOF before the loader starts. This can |
421 | | * produce high memory use if the descriptor represents a large object. |
422 | | * |
423 | | * Use vips_pipe_read_limit_set() to limit the size of object that |
424 | | * will be read in this way. The default is 1GB. |
425 | | * |
426 | | * Returns: a new source. |
427 | | */ |
428 | | VipsSource * |
429 | | vips_source_new_from_file(const char *filename) |
430 | 0 | { |
431 | 0 | VipsSource *source; |
432 | |
|
433 | 0 | VIPS_DEBUG_MSG("vips_source_new_from_file: %s\n", |
434 | 0 | filename); |
435 | |
|
436 | 0 | source = VIPS_SOURCE(g_object_new(VIPS_TYPE_SOURCE, |
437 | 0 | "filename", filename, |
438 | 0 | NULL)); |
439 | |
|
440 | 0 | if (vips_object_build(VIPS_OBJECT(source))) { |
441 | 0 | VIPS_UNREF(source); |
442 | 0 | return NULL; |
443 | 0 | } |
444 | | |
445 | 0 | SANITY(source); |
446 | |
|
447 | 0 | return source; |
448 | 0 | } |
449 | | |
450 | | /** |
451 | | * vips_source_new_from_blob: |
452 | | * @blob: memory area to load |
453 | | * |
454 | | * Create a source attached to an area of memory. |
455 | | * |
456 | | * Returns: a new source. |
457 | | */ |
458 | | VipsSource * |
459 | | vips_source_new_from_blob(VipsBlob *blob) |
460 | 148k | { |
461 | 148k | VipsSource *source; |
462 | | |
463 | 148k | VIPS_DEBUG_MSG("vips_source_new_from_blob: %p\n", blob); |
464 | | |
465 | 148k | source = VIPS_SOURCE(g_object_new(VIPS_TYPE_SOURCE, |
466 | 148k | "blob", blob, |
467 | 148k | NULL)); |
468 | | |
469 | 148k | if (vips_object_build(VIPS_OBJECT(source))) { |
470 | 0 | VIPS_UNREF(source); |
471 | 0 | return NULL; |
472 | 0 | } |
473 | | |
474 | 148k | SANITY(source); |
475 | | |
476 | 148k | return source; |
477 | 148k | } |
478 | | |
479 | | /** |
480 | | * vips_source_new_from_target: |
481 | | * @target: build the source from this target |
482 | | * |
483 | | * Create a source from a temp target that has been written to. |
484 | | * |
485 | | * Returns: a new source. |
486 | | */ |
487 | | VipsSource * |
488 | | vips_source_new_from_target(VipsTarget *target) |
489 | 0 | { |
490 | 0 | VipsConnection *connection = VIPS_CONNECTION(target); |
491 | |
|
492 | 0 | VipsSource *source; |
493 | |
|
494 | 0 | VIPS_DEBUG_MSG("vips_source_new_from_target: %p\n", target); |
495 | | |
496 | | /* Flush output buffer, move memory into the blob, etc. |
497 | | */ |
498 | 0 | if (vips_target_end(target)) |
499 | 0 | return NULL; |
500 | | |
501 | 0 | if (connection->descriptor > 0) |
502 | 0 | source = vips_source_new_from_descriptor(connection->descriptor); |
503 | 0 | else if (target->memory) { |
504 | 0 | VipsBlob *blob; |
505 | |
|
506 | 0 | g_object_get(target, "blob", &blob, NULL); |
507 | 0 | source = vips_source_new_from_blob(blob); |
508 | 0 | vips_area_unref(VIPS_AREA(blob)); |
509 | 0 | } |
510 | 0 | else { |
511 | 0 | vips_error(vips_connection_nick(connection), |
512 | 0 | "%s", _("unimplemented target")); |
513 | 0 | return NULL; |
514 | 0 | } |
515 | | |
516 | 0 | return source; |
517 | 0 | } |
518 | | |
519 | | /** |
520 | | * vips_source_new_from_memory: |
521 | | * @data: memory area to load |
522 | | * @length: size of memory area |
523 | | * |
524 | | * Create a source attached to an area of memory. |
525 | | * |
526 | | * You must not free @data while the source is active. |
527 | | * |
528 | | * Returns: a new source. |
529 | | */ |
530 | | VipsSource * |
531 | | vips_source_new_from_memory(const void *data, size_t length) |
532 | 148k | { |
533 | 148k | VipsSource *source; |
534 | 148k | VipsBlob *blob; |
535 | | |
536 | 148k | VIPS_DEBUG_MSG("vips_source_new_from_buffer: %p, length = %zd\n", |
537 | 148k | data, length); |
538 | | |
539 | | /* We don't take a copy of the data or free it. |
540 | | */ |
541 | 148k | blob = vips_blob_new(NULL, data, length); |
542 | | |
543 | 148k | source = vips_source_new_from_blob(blob); |
544 | | |
545 | 148k | vips_area_unref(VIPS_AREA(blob)); |
546 | | |
547 | 148k | SANITY(source); |
548 | | |
549 | 148k | return source; |
550 | 148k | } |
551 | | |
552 | | /** |
553 | | * vips_source_new_from_options: |
554 | | * @options: option string |
555 | | * |
556 | | * Create a source from an option string. |
557 | | * |
558 | | * Returns: a new source. |
559 | | */ |
560 | | VipsSource * |
561 | | vips_source_new_from_options(const char *options) |
562 | 0 | { |
563 | 0 | VipsSource *source; |
564 | |
|
565 | 0 | VIPS_DEBUG_MSG("vips_source_new_from_options: %s\n", options); |
566 | |
|
567 | 0 | source = VIPS_SOURCE(g_object_new(VIPS_TYPE_SOURCE, NULL)); |
568 | |
|
569 | 0 | if (vips_object_set_from_string(VIPS_OBJECT(source), options) || |
570 | 0 | vips_object_build(VIPS_OBJECT(source))) { |
571 | 0 | VIPS_UNREF(source); |
572 | 0 | return NULL; |
573 | 0 | } |
574 | | |
575 | 0 | SANITY(source); |
576 | |
|
577 | 0 | return source; |
578 | 0 | } |
579 | | |
580 | | /** |
581 | | * vips_source_minimise: |
582 | | * @source: source to operate on |
583 | | * |
584 | | * Minimise the source. As many resources as can be safely removed are |
585 | | * removed. Use vips_source_unminimise() to restore the source if you wish to |
586 | | * use it again. |
587 | | * |
588 | | * Loaders should call this in response to the minimise signal on their output |
589 | | * image. |
590 | | */ |
591 | | void |
592 | | vips_source_minimise(VipsSource *source) |
593 | 72.3k | { |
594 | 72.3k | VipsConnection *connection = VIPS_CONNECTION(source); |
595 | | |
596 | 72.3k | SANITY(source); |
597 | | |
598 | 72.3k | (void) vips_source_test_features(source); |
599 | | |
600 | 72.3k | if (connection->filename && |
601 | 72.3k | connection->descriptor != -1 && |
602 | 72.3k | connection->tracked_descriptor == connection->descriptor && |
603 | 72.3k | !source->is_pipe) { |
604 | | #ifdef DEBUG_MINIMISE |
605 | | printf("vips_source_minimise: %p %s\n", |
606 | | source, |
607 | | vips_connection_nick(VIPS_CONNECTION(source))); |
608 | | #endif /*DEBUG_MINIMISE*/ |
609 | |
|
610 | 0 | vips_tracked_close(connection->tracked_descriptor); |
611 | 0 | connection->tracked_descriptor = -1; |
612 | 0 | connection->descriptor = -1; |
613 | 0 | } |
614 | | |
615 | 72.3k | SANITY(source); |
616 | 72.3k | } |
617 | | |
618 | | /** |
619 | | * vips_source_unminimise: |
620 | | * @source: source to operate on |
621 | | * |
622 | | * Restore the source after minimisation. This is called at the start |
623 | | * of every source method, so loaders should not usually need this. |
624 | | * |
625 | | * See also: vips_source_minimise(). |
626 | | * |
627 | | * Returns: 0 on success, or -1 on error. |
628 | | */ |
629 | | int |
630 | | vips_source_unminimise(VipsSource *source) |
631 | 4.92M | { |
632 | 4.92M | VipsConnection *connection = VIPS_CONNECTION(source); |
633 | | |
634 | 4.92M | if (connection->descriptor == -1 && |
635 | 4.92M | connection->tracked_descriptor == -1 && |
636 | 4.92M | connection->filename) { |
637 | 0 | int fd; |
638 | |
|
639 | | #ifdef DEBUG_MINIMISE |
640 | | printf("vips_source_unminimise: %p %s\n", |
641 | | source, |
642 | | vips_connection_nick(VIPS_CONNECTION(source))); |
643 | | #endif /*DEBUG_MINIMISE*/ |
644 | |
|
645 | 0 | if ((fd = vips_tracked_open(connection->filename, |
646 | 0 | MODE_READ, 0)) == -1) { |
647 | 0 | vips_error_system(errno, |
648 | 0 | vips_connection_nick(connection), |
649 | 0 | "%s", _("unable to open for read")); |
650 | 0 | return -1; |
651 | 0 | } |
652 | | |
653 | 0 | connection->tracked_descriptor = fd; |
654 | 0 | connection->descriptor = fd; |
655 | |
|
656 | 0 | if (vips_source_test_seek(source)) |
657 | 0 | return -1; |
658 | | |
659 | | /* It might be a named pipe. |
660 | | */ |
661 | 0 | if (!source->is_pipe) { |
662 | 0 | VIPS_DEBUG_MSG("vips_source_unminimise: restoring " |
663 | 0 | "read position %" G_GINT64_FORMAT "\n", |
664 | 0 | source->read_position); |
665 | 0 | if (vips__seek(connection->descriptor, |
666 | 0 | source->read_position, SEEK_SET) == -1) |
667 | 0 | return -1; |
668 | 0 | } |
669 | 0 | } |
670 | | |
671 | 4.92M | return 0; |
672 | 4.92M | } |
673 | | |
674 | | /** |
675 | | * vips_source_decode: |
676 | | * @source: source to operate on |
677 | | * |
678 | | * Signal the end of header read and the start of the pixel decode phase. |
679 | | * After this, you can no longer seek on this source. |
680 | | * |
681 | | * Loaders should call this at the end of header read. |
682 | | * |
683 | | * See also: vips_source_unminimise(). |
684 | | * |
685 | | * Returns: 0 on success, -1 on error. |
686 | | */ |
687 | | int |
688 | | vips_source_decode(VipsSource *source) |
689 | 6.02k | { |
690 | 6.02k | VIPS_DEBUG_MSG("vips_source_decode:\n"); |
691 | | |
692 | 6.02k | SANITY(source); |
693 | | |
694 | 6.02k | if (!source->decode) { |
695 | 6.02k | source->decode = TRUE; |
696 | | |
697 | 6.02k | VIPS_FREEF(g_byte_array_unref, source->sniff); |
698 | | |
699 | | /* Now decode is set, header_bytes will be freed once it's |
700 | | * exhausted, see vips_source_read(). |
701 | | */ |
702 | 6.02k | } |
703 | | |
704 | 6.02k | vips_source_minimise(source); |
705 | | |
706 | 6.02k | SANITY(source); |
707 | | |
708 | 6.02k | return 0; |
709 | 6.02k | } |
710 | | |
711 | | #ifdef VIPS_DEBUG |
712 | | static void |
713 | | vips_source_print(VipsSource *source) |
714 | | { |
715 | | printf("vips_source_print: %p\n", source); |
716 | | printf(" source->read_position = %zd\n", source->read_position); |
717 | | printf(" source->is_pipe = %d\n", source->is_pipe); |
718 | | printf(" source->length = %zd\n", source->length); |
719 | | printf(" source->data = %p\n", source->data); |
720 | | printf(" source->header_bytes = %p\n", source->header_bytes); |
721 | | if (source->header_bytes) |
722 | | printf(" source->header_bytes->len = %d\n", |
723 | | source->header_bytes->len); |
724 | | printf(" source->sniff = %p\n", source->sniff); |
725 | | if (source->sniff) |
726 | | printf(" source->sniff->len = %d\n", source->sniff->len); |
727 | | } |
728 | | #endif /*VIPS_DEBUG*/ |
729 | | |
730 | | /** |
731 | | * vips_source_read: |
732 | | * @source: source to operate on |
733 | | * @buffer: store bytes here |
734 | | * @length: length of @buffer in bytes |
735 | | * |
736 | | * Read up to @length bytes from @source and store the bytes in @buffer. |
737 | | * Return the number of bytes actually read. If all bytes have been read from |
738 | | * the file, return 0. |
739 | | * |
740 | | * Arguments exactly as read(2). |
741 | | * |
742 | | * Returns: the number of bytes read, 0 on end of file, -1 on error. |
743 | | */ |
744 | | gint64 |
745 | | vips_source_read(VipsSource *source, void *buffer, size_t length) |
746 | 771k | { |
747 | 771k | VipsSourceClass *class = VIPS_SOURCE_GET_CLASS(source); |
748 | | |
749 | 771k | gint64 total_read; |
750 | | |
751 | 771k | VIPS_DEBUG_MSG("vips_source_read:\n"); |
752 | | |
753 | 771k | SANITY(source); |
754 | | |
755 | 771k | if (vips_source_unminimise(source) || |
756 | 771k | vips_source_test_features(source)) |
757 | 0 | return -1; |
758 | | |
759 | 771k | total_read = 0; |
760 | | |
761 | 771k | if (source->data) { |
762 | | /* The whole thing is in memory somehow. |
763 | | */ |
764 | 771k | gint64 available = VIPS_MIN(length, |
765 | 771k | source->length - source->read_position); |
766 | | |
767 | 771k | VIPS_DEBUG_MSG(" %zd bytes from memory\n", available); |
768 | 771k | memcpy(buffer, |
769 | 771k | (char *) source->data + source->read_position, available); |
770 | 771k | source->read_position += available; |
771 | 771k | total_read += available; |
772 | 771k | } |
773 | 0 | else { |
774 | | /* Some kind of filesystem or custom source. |
775 | | * |
776 | | * Get what we can from header_bytes. We may need to read |
777 | | * some more after this. |
778 | | */ |
779 | 0 | if (source->header_bytes && |
780 | 0 | source->read_position < source->header_bytes->len) { |
781 | 0 | gint64 available = VIPS_MIN(length, |
782 | 0 | source->header_bytes->len - source->read_position); |
783 | |
|
784 | 0 | VIPS_DEBUG_MSG(" %zd bytes from cache\n", available); |
785 | 0 | memcpy(buffer, |
786 | 0 | source->header_bytes->data + source->read_position, available); |
787 | 0 | source->read_position += available; |
788 | 0 | buffer = (char *) buffer + available; |
789 | 0 | length -= available; |
790 | 0 | total_read += available; |
791 | 0 | } |
792 | | |
793 | | /* We're in pixel decode mode and we've exhausted the header |
794 | | * cache. We can safely junk it. |
795 | | */ |
796 | 0 | if (source->decode && |
797 | 0 | source->header_bytes && |
798 | 0 | source->read_position >= source->header_bytes->len) |
799 | 0 | VIPS_FREEF(g_byte_array_unref, source->header_bytes); |
800 | | |
801 | | /* Any more bytes requested? Call the read() vfunc. |
802 | | */ |
803 | 0 | if (length > 0) { |
804 | 0 | gint64 bytes_read; |
805 | |
|
806 | 0 | VIPS_DEBUG_MSG(" calling class->read()\n"); |
807 | 0 | bytes_read = class->read(source, buffer, length); |
808 | 0 | VIPS_DEBUG_MSG(" %zd bytes from read()\n", bytes_read); |
809 | 0 | if (bytes_read == -1) { |
810 | 0 | vips_error_system(errno, |
811 | 0 | vips_connection_nick(VIPS_CONNECTION(source)), |
812 | 0 | "%s", _("read error")); |
813 | 0 | return -1; |
814 | 0 | } |
815 | | |
816 | | /* We need to save bytes if we're in header mode and |
817 | | * we can't seek or map. |
818 | | */ |
819 | 0 | if (source->header_bytes && |
820 | 0 | source->is_pipe && |
821 | 0 | !source->decode && |
822 | 0 | bytes_read > 0) |
823 | 0 | g_byte_array_append(source->header_bytes, buffer, bytes_read); |
824 | |
|
825 | 0 | source->read_position += bytes_read; |
826 | 0 | total_read += bytes_read; |
827 | 0 | } |
828 | 0 | } |
829 | | |
830 | 771k | VIPS_DEBUG_MSG(" %zd bytes total\n", total_read); |
831 | | |
832 | 771k | SANITY(source); |
833 | | |
834 | 771k | return total_read; |
835 | 771k | } |
836 | | |
837 | | /* Read to a position. |
838 | | * |
839 | | * target == -1 means read to end of source -- useful for forcing a pipe into |
840 | | * memory, for example. This will always set length to the pipe length. |
841 | | * |
842 | | * If we hit EOF and we're buffering, set length on the pipe and turn it into |
843 | | * a memory source. |
844 | | * |
845 | | * read_position is left somewhere indeterminate. |
846 | | */ |
847 | | static int |
848 | | vips_source_pipe_read_to_position(VipsSource *source, gint64 target) |
849 | 0 | { |
850 | 0 | const char *nick = vips_connection_nick(VIPS_CONNECTION(source)); |
851 | |
|
852 | 0 | unsigned char buffer[4096]; |
853 | | |
854 | | /* This is only useful for pipes (sources where we don't know the |
855 | | * length). |
856 | | */ |
857 | 0 | g_assert(source->length == -1); |
858 | 0 | g_assert(source->is_pipe); |
859 | |
|
860 | 0 | while (target == -1 || |
861 | 0 | source->read_position < target) { |
862 | 0 | gint64 bytes_read; |
863 | |
|
864 | 0 | bytes_read = vips_source_read(source, buffer, 4096); |
865 | 0 | if (bytes_read == -1) |
866 | 0 | return -1; |
867 | | |
868 | 0 | if (bytes_read == 0) { |
869 | | /* No more bytes available, we must be at EOF. |
870 | | */ |
871 | 0 | source->length = source->read_position; |
872 | | |
873 | | /* Have we been buffering the whole thing? We can |
874 | | * become a memory source. |
875 | | */ |
876 | 0 | if (source->header_bytes) { |
877 | 0 | source->data = source->header_bytes->data; |
878 | 0 | source->is_pipe = FALSE; |
879 | | |
880 | | /* TODO ... we could close more fds here. |
881 | | */ |
882 | 0 | vips_source_minimise(source); |
883 | 0 | } |
884 | |
|
885 | 0 | break; |
886 | 0 | } |
887 | | |
888 | 0 | if (vips__pipe_read_limit != -1 && |
889 | 0 | source->read_position > vips__pipe_read_limit) { |
890 | 0 | vips_error(nick, "%s", _("pipe too long")); |
891 | 0 | return -1; |
892 | 0 | } |
893 | 0 | } |
894 | | |
895 | 0 | return 0; |
896 | 0 | } |
897 | | |
898 | | /* Convert a seekable source that can't be mapped (eg. a custom input with a |
899 | | * seek method) into a memory source. |
900 | | */ |
901 | | static int |
902 | | vips_source_read_to_memory(VipsSource *source) |
903 | 0 | { |
904 | 0 | GByteArray *byte_array; |
905 | 0 | gint64 read_position; |
906 | 0 | unsigned char *q; |
907 | |
|
908 | 0 | VIPS_DEBUG_MSG("vips_source_read_to_memory:\n"); |
909 | |
|
910 | 0 | g_assert(!source->is_pipe); |
911 | 0 | g_assert(!source->blob); |
912 | 0 | g_assert(!source->header_bytes); |
913 | 0 | g_assert(source->length >= 0); |
914 | |
|
915 | 0 | if (vips_source_rewind(source)) |
916 | 0 | return -1; |
917 | | |
918 | | /* We know the length, so we can size the buffer correctly and read |
919 | | * directly to it. |
920 | | */ |
921 | 0 | byte_array = g_byte_array_new(); |
922 | 0 | g_byte_array_set_size(byte_array, source->length); |
923 | |
|
924 | 0 | read_position = 0; |
925 | 0 | q = byte_array->data; |
926 | 0 | while (read_position < source->length) { |
927 | 0 | gint64 bytes_read; |
928 | |
|
929 | 0 | bytes_read = vips_source_read(source, q, |
930 | 0 | VIPS_MAX(4096, source->length - read_position)); |
931 | 0 | if (bytes_read == -1) { |
932 | 0 | VIPS_FREEF(g_byte_array_unref, byte_array); |
933 | 0 | return -1; |
934 | 0 | } |
935 | 0 | if (bytes_read == 0) |
936 | 0 | break; |
937 | | |
938 | 0 | read_position += bytes_read; |
939 | 0 | q += bytes_read; |
940 | 0 | } |
941 | | |
942 | | /* Steal the byte_array pointer and turn into a memory source. |
943 | | * |
944 | | * We save byte_array in the header_bytes field to get it freed when |
945 | | * we are freed. |
946 | | */ |
947 | 0 | source->data = byte_array->data; |
948 | 0 | source->is_pipe = FALSE; |
949 | 0 | source->header_bytes = byte_array; |
950 | |
|
951 | 0 | vips_source_minimise(source); |
952 | |
|
953 | 0 | return 0; |
954 | 0 | } |
955 | | |
956 | | static int |
957 | | vips_source_descriptor_to_memory(VipsSource *source) |
958 | 0 | { |
959 | 0 | VipsConnection *connection = VIPS_CONNECTION(source); |
960 | |
|
961 | 0 | VIPS_DEBUG_MSG("vips_source_descriptor_to_memory:\n"); |
962 | |
|
963 | 0 | g_assert(!source->blob); |
964 | 0 | g_assert(!source->mmap_baseaddr); |
965 | |
|
966 | 0 | if (!(source->mmap_baseaddr = vips__mmap(connection->descriptor, |
967 | 0 | FALSE, source->length, 0))) |
968 | 0 | return -1; |
969 | | |
970 | | /* And it's now a memory source. |
971 | | */ |
972 | 0 | source->data = source->mmap_baseaddr; |
973 | 0 | source->mmap_length = source->length; |
974 | |
|
975 | 0 | return 0; |
976 | 0 | } |
977 | | |
978 | | /** |
979 | | * vips_source_is_mappable: |
980 | | * @source: source to operate on |
981 | | * |
982 | | * Some sources can be efficiently mapped into memory. |
983 | | * You can still use vips_source_map() if this function returns %FALSE, |
984 | | * but it will be slow. |
985 | | * |
986 | | * Returns: %TRUE if the source can be efficiently mapped into memory. |
987 | | */ |
988 | | gboolean |
989 | | vips_source_is_mappable(VipsSource *source) |
990 | 12.4k | { |
991 | 12.4k | if (vips_source_unminimise(source) || |
992 | 12.4k | vips_source_test_features(source)) |
993 | 0 | return -1; |
994 | | |
995 | | /* Already a memory object, or there's a filename we can map, or |
996 | | * there's a seekable descriptor. |
997 | | */ |
998 | 12.4k | return source->data || |
999 | 12.4k | VIPS_CONNECTION(source)->filename || |
1000 | 12.4k | (!source->is_pipe && |
1001 | 0 | VIPS_CONNECTION(source)->descriptor != -1); |
1002 | 12.4k | } |
1003 | | |
1004 | | /** |
1005 | | * vips_source_is_file: |
1006 | | * @source: source to operate on |
1007 | | * |
1008 | | * Test if this source is a simple file with support for seek. Named pipes, |
1009 | | * for example, will fail this test. If TRUE, you can use |
1010 | | * vips_connection_filename() to find the filename. |
1011 | | * |
1012 | | * Use this to add basic source support for older loaders which can only work |
1013 | | * on files. |
1014 | | * |
1015 | | * Returns: %TRUE if the source is a simple file. |
1016 | | */ |
1017 | | gboolean |
1018 | | vips_source_is_file(VipsSource *source) |
1019 | 0 | { |
1020 | 0 | if (vips_source_unminimise(source) || |
1021 | 0 | vips_source_test_features(source)) |
1022 | 0 | return -1; |
1023 | | |
1024 | | /* There's a filename, and it supports seek. |
1025 | | */ |
1026 | 0 | return VIPS_CONNECTION(source)->filename && |
1027 | 0 | !source->is_pipe; |
1028 | 0 | } |
1029 | | |
1030 | | /** |
1031 | | * vips_source_map: |
1032 | | * @source: source to operate on |
1033 | | * @length_out: return the file length here, or NULL |
1034 | | * |
1035 | | * Map the source entirely into memory and return a pointer to the |
1036 | | * start. If @length_out is non-NULL, the source size is written to it. |
1037 | | * |
1038 | | * This operation can take a long time. Use vips_source_is_mappable() to |
1039 | | * check if a source can be mapped efficiently. |
1040 | | * |
1041 | | * The pointer is valid for as long as @source is alive. |
1042 | | * |
1043 | | * Returns: a pointer to the start of the file contents, or NULL on error. |
1044 | | */ |
1045 | | const void * |
1046 | | vips_source_map(VipsSource *source, size_t *length_out) |
1047 | 15.4k | { |
1048 | 15.4k | VIPS_DEBUG_MSG("vips_source_map:\n"); |
1049 | | |
1050 | 15.4k | SANITY(source); |
1051 | | |
1052 | 15.4k | if (vips_source_unminimise(source) || |
1053 | 15.4k | vips_source_test_features(source)) |
1054 | 0 | return NULL; |
1055 | | |
1056 | | /* Try to map the file into memory, if possible. Some filesystems have |
1057 | | * mmap disabled, so we don't give up if this fails. |
1058 | | */ |
1059 | 15.4k | if (!source->data && |
1060 | 15.4k | vips_source_is_mappable(source)) |
1061 | 0 | (void) vips_source_descriptor_to_memory(source); |
1062 | | |
1063 | | /* If it's not a pipe, we can rewind, get the length, and read the |
1064 | | * whole thing. |
1065 | | */ |
1066 | 15.4k | if (!source->data && |
1067 | 15.4k | !source->is_pipe && |
1068 | 15.4k | vips_source_read_to_memory(source)) |
1069 | 0 | return NULL; |
1070 | | |
1071 | | /* We don't know the length and must read and assemble in chunks. |
1072 | | */ |
1073 | 15.4k | if (source->is_pipe && |
1074 | 15.4k | vips_source_pipe_read_to_position(source, -1)) |
1075 | 0 | return NULL; |
1076 | | |
1077 | 15.4k | if (length_out) |
1078 | 15.4k | *length_out = source->length; |
1079 | | |
1080 | 15.4k | SANITY(source); |
1081 | | |
1082 | 15.4k | return source->data; |
1083 | 15.4k | } |
1084 | | |
1085 | | static int |
1086 | | vips_source_map_cb(void *a, VipsArea *area) |
1087 | 0 | { |
1088 | 0 | GObject *gobject = G_OBJECT(area->client); |
1089 | |
|
1090 | 0 | VIPS_UNREF(gobject); |
1091 | |
|
1092 | 0 | return 0; |
1093 | 0 | } |
1094 | | |
1095 | | /** |
1096 | | * vips_source_map_blob: |
1097 | | * @source: source to operate on |
1098 | | * |
1099 | | * Just like vips_source_map(), but return a #VipsBlob containing the |
1100 | | * pointer. @source will stay alive as long as the result is alive. |
1101 | | * |
1102 | | * Returns: a new #VipsBlob containing the data, or NULL on error. |
1103 | | */ |
1104 | | VipsBlob * |
1105 | | vips_source_map_blob(VipsSource *source) |
1106 | 0 | { |
1107 | 0 | const void *buf; |
1108 | 0 | size_t len; |
1109 | 0 | VipsBlob *blob; |
1110 | |
|
1111 | 0 | if (!(buf = vips_source_map(source, &len)) || |
1112 | 0 | !(blob = vips_blob_new((VipsCallbackFn) vips_source_map_cb, buf, len))) |
1113 | 0 | return NULL; |
1114 | | |
1115 | | /* The source must stay alive until the blob is done. |
1116 | | */ |
1117 | 0 | g_object_ref(source); |
1118 | 0 | VIPS_AREA(blob)->client = source; |
1119 | |
|
1120 | 0 | return blob; |
1121 | 0 | } |
1122 | | |
1123 | | /** |
1124 | | * vips_source_seek: |
1125 | | * @source: source to operate on |
1126 | | * @offset: seek by this offset |
1127 | | * @whence: seek relative to this point |
1128 | | * |
1129 | | * Move the file read position. You can't call this after pixel decode starts. |
1130 | | * The arguments are exactly as lseek(2). |
1131 | | * |
1132 | | * Returns: the new file position, or -1 on error. |
1133 | | */ |
1134 | | gint64 |
1135 | | vips_source_seek(VipsSource *source, gint64 offset, int whence) |
1136 | 1.34M | { |
1137 | 1.34M | const char *nick = vips_connection_nick(VIPS_CONNECTION(source)); |
1138 | 1.34M | VipsSourceClass *class = VIPS_SOURCE_GET_CLASS(source); |
1139 | | |
1140 | 1.34M | gint64 new_pos; |
1141 | | |
1142 | 1.34M | VIPS_DEBUG_MSG( |
1143 | 1.34M | "vips_source_seek: offset = %" G_GINT64_FORMAT ", whence = %d\n", |
1144 | 1.34M | offset, whence); |
1145 | | |
1146 | 1.34M | if (vips_source_unminimise(source) || |
1147 | 1.34M | vips_source_test_features(source)) |
1148 | 0 | return -1; |
1149 | | |
1150 | 1.34M | if (source->data) { |
1151 | 1.34M | switch (whence) { |
1152 | 845k | case SEEK_SET: |
1153 | 845k | new_pos = offset; |
1154 | 845k | break; |
1155 | | |
1156 | 304k | case SEEK_CUR: |
1157 | 304k | new_pos = source->read_position + offset; |
1158 | 304k | break; |
1159 | | |
1160 | 197k | case SEEK_END: |
1161 | 197k | new_pos = source->length + offset; |
1162 | 197k | break; |
1163 | | |
1164 | 0 | default: |
1165 | 0 | vips_error(nick, "%s", _("bad 'whence'")); |
1166 | 0 | return -1; |
1167 | 1.34M | } |
1168 | 1.34M | } |
1169 | 0 | else if (source->is_pipe) { |
1170 | 0 | switch (whence) { |
1171 | 0 | case SEEK_SET: |
1172 | 0 | new_pos = offset; |
1173 | 0 | break; |
1174 | | |
1175 | 0 | case SEEK_CUR: |
1176 | 0 | new_pos = source->read_position + offset; |
1177 | 0 | break; |
1178 | | |
1179 | 0 | case SEEK_END: |
1180 | | /* We have to read the whole source into memory to get |
1181 | | * the length. |
1182 | | */ |
1183 | 0 | if (vips_source_pipe_read_to_position(source, -1)) |
1184 | 0 | return -1; |
1185 | | |
1186 | 0 | new_pos = source->length + offset; |
1187 | 0 | break; |
1188 | | |
1189 | 0 | default: |
1190 | 0 | vips_error(nick, "%s", _("bad 'whence'")); |
1191 | 0 | return -1; |
1192 | 0 | } |
1193 | 0 | } |
1194 | 0 | else { |
1195 | 0 | if ((new_pos = class->seek(source, offset, whence)) == -1) |
1196 | 0 | return -1; |
1197 | 0 | } |
1198 | | |
1199 | | /* For pipes, we have to fake seek by reading to that point. This |
1200 | | * might hit EOF and turn the pipe into a memory source. |
1201 | | */ |
1202 | 1.34M | if (source->is_pipe && |
1203 | 1.34M | vips_source_pipe_read_to_position(source, new_pos)) |
1204 | 0 | return -1; |
1205 | | |
1206 | | /* Don't allow out of range seeks. |
1207 | | */ |
1208 | 1.34M | if (new_pos < 0 || |
1209 | 1.34M | (source->length != -1 && new_pos > source->length)) { |
1210 | 124k | vips_error(nick, |
1211 | 124k | _("bad seek to %" G_GINT64_FORMAT), new_pos); |
1212 | 124k | return -1; |
1213 | 124k | } |
1214 | | |
1215 | 1.22M | source->read_position = new_pos; |
1216 | | |
1217 | 1.22M | VIPS_DEBUG_MSG(" new_pos = %" G_GINT64_FORMAT "\n", new_pos); |
1218 | | |
1219 | 1.22M | return new_pos; |
1220 | 1.34M | } |
1221 | | |
1222 | | /** |
1223 | | * vips_source_rewind: |
1224 | | * @source: source to operate on |
1225 | | * |
1226 | | * Rewind the source to the start. |
1227 | | * |
1228 | | * You can't always do this after the pixel decode phase starts -- for |
1229 | | * example, pipe-like sources can't be rewound. |
1230 | | * |
1231 | | * Returns: 0 on success, or -1 on error. |
1232 | | */ |
1233 | | int |
1234 | | vips_source_rewind(VipsSource *source) |
1235 | 161k | { |
1236 | 161k | VIPS_DEBUG_MSG("vips_source_rewind:\n"); |
1237 | | |
1238 | 161k | SANITY(source); |
1239 | | |
1240 | 161k | if (vips_source_test_features(source) || |
1241 | 161k | vips_source_seek(source, 0, SEEK_SET) != 0) |
1242 | 0 | return -1; |
1243 | | |
1244 | | /* Back into sniff + header decode state. |
1245 | | */ |
1246 | 161k | source->decode = FALSE; |
1247 | 161k | if (!source->sniff) |
1248 | 0 | source->sniff = g_byte_array_new(); |
1249 | | |
1250 | 161k | SANITY(source); |
1251 | | |
1252 | 161k | return 0; |
1253 | 161k | } |
1254 | | |
1255 | | /** |
1256 | | * vips_source_length: |
1257 | | * @source: source to operate on |
1258 | | * |
1259 | | * Return the length in bytes of the source. Unseekable sources, for |
1260 | | * example pipes, will have to be read entirely into memory before the length |
1261 | | * can be found, so this operation can take a long time. |
1262 | | * |
1263 | | * Returns: number of bytes in source, or -1 on error. |
1264 | | */ |
1265 | | gint64 |
1266 | | vips_source_length(VipsSource *source) |
1267 | 197k | { |
1268 | 197k | gint64 length; |
1269 | 197k | gint64 read_position; |
1270 | | |
1271 | 197k | VIPS_DEBUG_MSG("vips_source_length:\n"); |
1272 | | |
1273 | 197k | if (vips_source_test_features(source)) |
1274 | 0 | return -1; |
1275 | | |
1276 | 197k | read_position = vips_source_seek(source, 0, SEEK_CUR); |
1277 | 197k | length = vips_source_seek(source, 0, SEEK_END); |
1278 | 197k | vips_source_seek(source, read_position, SEEK_SET); |
1279 | | |
1280 | 197k | return length; |
1281 | 197k | } |
1282 | | |
1283 | | /** |
1284 | | * vips_source_sniff_at_most: |
1285 | | * @source: peek this source |
1286 | | * @data: return a pointer to the bytes read here |
1287 | | * @length: max number of bytes to read |
1288 | | * |
1289 | | * Attempt to sniff at most @length bytes from the start of the source. A |
1290 | | * pointer to the bytes is returned in @data. The number of bytes actually |
1291 | | * read is returned -- it may be less than @length if the file is shorter than |
1292 | | * @length. A negative number indicates a read error. |
1293 | | * |
1294 | | * Returns: number of bytes read, or -1 on error. |
1295 | | */ |
1296 | | gint64 |
1297 | | vips_source_sniff_at_most(VipsSource *source, |
1298 | | unsigned char **data, size_t length) |
1299 | 102k | { |
1300 | 102k | unsigned char *q; |
1301 | 102k | gint64 read_position; |
1302 | | |
1303 | 102k | VIPS_DEBUG_MSG("vips_source_sniff_at_most: %zd bytes\n", length); |
1304 | | |
1305 | 102k | SANITY(source); |
1306 | | |
1307 | 102k | if (vips_source_test_features(source) || |
1308 | 102k | vips_source_rewind(source)) |
1309 | 0 | return -1; |
1310 | | |
1311 | 102k | g_byte_array_set_size(source->sniff, length); |
1312 | | |
1313 | 102k | read_position = 0; |
1314 | 102k | q = source->sniff->data; |
1315 | 205k | while (read_position < length) { |
1316 | 103k | gint64 bytes_read; |
1317 | | |
1318 | 103k | bytes_read = vips_source_read(source, q, length - read_position); |
1319 | 103k | if (bytes_read == -1) |
1320 | 0 | return -1; |
1321 | 103k | if (bytes_read == 0) |
1322 | 1.18k | break; |
1323 | | |
1324 | 102k | read_position += bytes_read; |
1325 | 102k | q += bytes_read; |
1326 | 102k | } |
1327 | | |
1328 | 102k | SANITY(source); |
1329 | | |
1330 | 102k | *data = source->sniff->data; |
1331 | | |
1332 | 102k | return read_position; |
1333 | 102k | } |
1334 | | |
1335 | | /** |
1336 | | * vips_source_sniff: |
1337 | | * @source: sniff this source |
1338 | | * @length: number of bytes to sniff |
1339 | | * |
1340 | | * Return a pointer to the first few bytes of the file. If the file is too |
1341 | | * short, return NULL. |
1342 | | * |
1343 | | * Returns: a pointer to the bytes at the start of the file, or NULL on error. |
1344 | | */ |
1345 | | unsigned char * |
1346 | | vips_source_sniff(VipsSource *source, size_t length) |
1347 | 102k | { |
1348 | 102k | unsigned char *data; |
1349 | 102k | gint64 bytes_read; |
1350 | | |
1351 | 102k | if (vips_source_test_features(source)) |
1352 | 0 | return NULL; |
1353 | | |
1354 | 102k | bytes_read = vips_source_sniff_at_most(source, &data, length); |
1355 | 102k | if (bytes_read == -1) |
1356 | 0 | return NULL; |
1357 | 102k | if (bytes_read < length) |
1358 | 1.18k | return NULL; |
1359 | | |
1360 | 101k | return data; |
1361 | 102k | } |