1ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik/* timepng.c
2ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik *
3ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik * Copyright (c) 2013 John Cunningham Bowler
4ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik *
5ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik * Last changed in libpng 1.6.1 [March 28, 2013]
6ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik *
7ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik * This code is released under the libpng license.
8ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik * For conditions of distribution and use, see the disclaimer
9ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik * and license in png.h
10ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik *
11ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik * Load an arbitrary number of PNG files (from the command line, or, if there
12ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik * are no arguments on the command line, from stdin) then run a time test by
13ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik * reading each file by row.  The test does nothing with the read result and
14ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik * does no transforms.  The only output is a time as a floating point number of
15ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik * seconds with 9 decimal digits.
16ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik */
17ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#define _POSIX_C_SOURCE 199309L /* for clock_gettime */
18ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
19ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#include <stdlib.h>
20ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#include <stdio.h>
21ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#include <string.h>
22ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
23ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#include <time.h>
24ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
25ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
26ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#  include <config.h>
27ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#endif
28ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
29ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik/* Define the following to use this test against your installed libpng, rather
30ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik * than the one being built here:
31ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik */
32ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#ifdef PNG_FREESTANDING_TESTS
33ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#  include <png.h>
34ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#else
35ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#  include "../../png.h"
36ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#endif
37ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
38ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craikstatic int read_png(FILE *fp)
39ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik{
40ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
41ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   png_infop info_ptr = NULL;
42ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   png_bytep row = NULL, display = NULL;
43ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
44ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   if (png_ptr == NULL)
45ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      return 0;
46ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
47ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   if (setjmp(png_jmpbuf(png_ptr)))
48ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   {
49ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
50ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      if (row != NULL) free(row);
51ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      if (display != NULL) free(display);
52ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      return 0;
53ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   }
54ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
55ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   png_init_io(png_ptr, fp);
56ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
57ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   info_ptr = png_create_info_struct(png_ptr);
58ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   if (info_ptr == NULL)
59ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      png_error(png_ptr, "OOM allocating info structure");
60ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
61ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   png_read_info(png_ptr, info_ptr);
62ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
63ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   {
64ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
65ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
66ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      row = malloc(rowbytes);
67ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      display = malloc(rowbytes);
68ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
69ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      if (row == NULL || display == NULL)
70ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         png_error(png_ptr, "OOM allocating row buffers");
71ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
72ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      {
73ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
74ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         int passes = png_set_interlace_handling(png_ptr);
75ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         int pass;
76ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
77ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         png_start_read_image(png_ptr);
78ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
79ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         for (pass = 0; pass < passes; ++pass)
80ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         {
81ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            png_uint_32 y = height;
82ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
83ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            /* NOTE: this trashes the row each time; interlace handling won't
84ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik             * work, but this avoids memory thrashing for speed testing.
85ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik             */
86ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            while (y-- > 0)
87ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               png_read_row(png_ptr, row, display);
88ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         }
89ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      }
90ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   }
91ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
92ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   /* Make sure to read to the end of the file: */
93ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   png_read_end(png_ptr, info_ptr);
94ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
95ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   free(row);
96ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   free(display);
97ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   return 1;
98ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik}
99ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
100ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craikstatic int mytime(struct timespec *t)
101ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik{
102ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   /* Do the timing using clock_gettime and the per-process timer. */
103ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   if (!clock_gettime(CLOCK_PROCESS_CPUTIME_ID, t))
104ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      return 1;
105ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
106ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   perror("CLOCK_PROCESS_CPUTIME_ID");
107ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   fprintf(stderr, "timepng: could not get the time\n");
108ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   return 0;
109ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik}
110ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
111ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craikstatic int perform_one_test(FILE *fp, int nfiles)
112ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik{
113ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   int i;
114ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   struct timespec before, after;
115ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
116ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   /* Clear out all errors: */
117ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   rewind(fp);
118ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
119ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   if (mytime(&before))
120ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   {
121ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      for (i=0; i<nfiles; ++i)
122ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      {
123ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         if (read_png(fp))
124ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         {
125ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            if (ferror(fp))
126ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            {
127ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               perror("temporary file");
128ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               fprintf(stderr, "file %d: error reading PNG data\n", i);
129ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               return 0;
130ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            }
131ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         }
132ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
133ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         else
134ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         {
135ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            perror("temporary file");
136ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            fprintf(stderr, "file %d: error from libpng\n", i);
137ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            return 0;
138ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         }
139ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      }
140ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   }
141ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
142ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   else
143ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      return 0;
144ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
145ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   if (mytime(&after))
146ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   {
147ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      /* Work out the time difference and print it - this is the only output,
148ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik       * so flush it immediately.
149ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik       */
150ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      unsigned long s = after.tv_sec - before.tv_sec;
151ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      long ns = after.tv_nsec - before.tv_nsec;
152ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
153ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      if (ns < 0)
154ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      {
155ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         --s;
156ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         ns += 1000000000;
157ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
158ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         if (ns < 0)
159ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         {
160ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            fprintf(stderr, "timepng: bad clock from kernel\n");
161ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            return 0;
162ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         }
163ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      }
164ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
165ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      printf("%lu.%.9ld\n", s, ns);
166ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      fflush(stdout);
167ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      if (ferror(stdout))
168ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      {
169ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         fprintf(stderr, "timepng: error writing output\n");
170ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         return 0;
171ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      }
172ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
173ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      /* Successful return */
174ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      return 1;
175ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   }
176ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
177ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   else
178ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      return 0;
179ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik}
180ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
181ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craikstatic int add_one_file(FILE *fp, char *name)
182ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik{
183ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   FILE *ip = fopen(name, "rb");
184ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
185ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   if (ip != NULL)
186ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   {
187ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      int ch;
188ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      for (;;)
189ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      {
190ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         ch = getc(ip);
191ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         if (ch == EOF) break;
192ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         putc(ch, fp);
193ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      }
194ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
195ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      if (ferror(ip))
196ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      {
197ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         perror(name);
198ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         fprintf(stderr, "%s: read error\n", name);
199ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         return 0;
200ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      }
201ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
202ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      (void)fclose(ip);
203ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
204ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      if (ferror(fp))
205ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      {
206ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         perror("temporary file");
207ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         fprintf(stderr, "temporary file write error\n");
208ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         return 0;
209ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      }
210ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   }
211ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
212ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   else
213ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   {
214ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      perror(name);
215ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      fprintf(stderr, "%s: open failed\n", name);
216ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      return 0;
217ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   }
218ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
219ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   return 1;
220ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik}
221ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
222ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craikint main(int argc, char **argv)
223ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik{
224ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   int ok = 0;
225ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   FILE *fp = tmpfile();
226ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
227ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   if (fp != NULL)
228ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   {
229ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      int err = 0;
230ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      int nfiles = 0;
231ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
232ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      if (argc > 1)
233ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      {
234ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         int i;
235ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
236ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         for (i=1; i<argc; ++i)
237ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         {
238ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            if (add_one_file(fp, argv[i]))
239ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               ++nfiles;
240ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
241ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            else
242ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            {
243ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               err = 1;
244ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               break;
245ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            }
246ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         }
247ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      }
248ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
249ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      else
250ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      {
251ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         char filename[FILENAME_MAX+1];
252ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
253ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         while (fgets(filename, FILENAME_MAX+1, stdin))
254ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         {
255ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            size_t len = strlen(filename);
256ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
257ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            if (filename[len-1] == '\n')
258ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            {
259ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               filename[len-1] = 0;
260ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               if (add_one_file(fp, filename))
261ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik                  ++nfiles;
262ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
263ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               else
264ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               {
265ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik                  err = 1;
266ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik                  break;
267ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               }
268ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            }
269ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
270ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            else
271ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            {
272ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               fprintf(stderr, "timepng: truncated file name ...%s\n",
273ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik                  filename+len-32);
274ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               err = 1;
275ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik               break;
276ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            }
277ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         }
278ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
279ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         if (ferror(stdin))
280ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         {
281ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            fprintf(stderr, "timepng: stdin: read error\n");
282ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            err = 1;
283ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         }
284ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      }
285ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
286ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      if (!err)
287ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      {
288ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         if (nfiles > 0)
289ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            ok = perform_one_test(fp, nfiles);
290ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
291ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik         else
292ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik            fprintf(stderr, "usage: timepng {files} or ls files | timepng\n");
293ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      }
294ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
295ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      (void)fclose(fp);
296ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   }
297ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
298ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   else
299ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik      fprintf(stderr, "timepng: could not open temporary file\n");
300ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik
301ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   /* Exit code 0 on success. */
302ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik   return ok == 0;
303ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik}
304