• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * File test program for CUPS.
3  *
4  * Copyright 2007-2018 by Apple Inc.
5  * Copyright 1997-2007 by Easy Software Products.
6  *
7  * These coded instructions, statements, and computer programs are the
8  * property of Apple Inc. and are protected by Federal copyright
9  * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
10  * which should have been included with this file.  If this file is
11  * missing or damaged, see the license at "http://www.cups.org/".
12  *
13  * This file is subject to the Apple OS-Developed Software exception.
14  */
15 
16 /*
17  * Include necessary headers...
18  */
19 
20 #include "string-private.h"
21 #include "debug-private.h"
22 #include "file.h"
23 #include <stdlib.h>
24 #include <time.h>
25 #ifdef _WIN32
26 #  include <io.h>
27 #else
28 #  include <unistd.h>
29 #endif /* _WIN32 */
30 #include <fcntl.h>
31 
32 
33 /*
34  * Local functions...
35  */
36 
37 static int	count_lines(cups_file_t *fp);
38 static int	random_tests(void);
39 static int	read_write_tests(int compression);
40 
41 
42 /*
43  * 'main()' - Main entry.
44  */
45 
46 int					/* O - Exit status */
main(int argc,char * argv[])47 main(int  argc,				/* I - Number of command-line arguments */
48      char *argv[])			/* I - Command-line arguments */
49 {
50   int		status;			/* Exit status */
51   char		filename[1024];		/* Filename buffer */
52   cups_file_t	*fp;			/* File pointer */
53 #ifndef _WIN32
54   int		fds[2];			/* Open file descriptors */
55   cups_file_t	*fdfile;		/* File opened with cupsFileOpenFd() */
56 #endif /* !_WIN32 */
57   int		count;			/* Number of lines in file */
58 
59 
60   if (argc == 1)
61   {
62    /*
63     * Do uncompressed file tests...
64     */
65 
66     status = read_write_tests(0);
67 
68 #ifdef HAVE_LIBZ
69    /*
70     * Do compressed file tests...
71     */
72 
73     putchar('\n');
74 
75     status += read_write_tests(1);
76 #endif /* HAVE_LIBZ */
77 
78    /*
79     * Do uncompressed random I/O tests...
80     */
81 
82     status += random_tests();
83 
84 #ifndef _WIN32
85    /*
86     * Test fdopen and close without reading...
87     */
88 
89     pipe(fds);
90     close(fds[1]);
91 
92     fputs("\ncupsFileOpenFd(fd, \"r\"): ", stdout);
93     fflush(stdout);
94 
95     if ((fdfile = cupsFileOpenFd(fds[0], "r")) == NULL)
96     {
97       puts("FAIL");
98       status ++;
99     }
100     else
101     {
102      /*
103       * Able to open file, now close without reading.  If we don't return
104       * before the alarm fires, that is a failure and we will crash on the
105       * alarm signal...
106       */
107 
108       puts("PASS");
109       fputs("cupsFileClose(no read): ", stdout);
110       fflush(stdout);
111 
112       alarm(5);
113       cupsFileClose(fdfile);
114       alarm(0);
115 
116       puts("PASS");
117     }
118 #endif /* !_WIN32 */
119 
120    /*
121     * Count lines in psglyphs, rewind, then count again.
122     */
123 
124     fputs("\ncupsFileOpen(\"../data/media.defs\", \"r\"): ", stdout);
125 
126     if ((fp = cupsFileOpen("../data/media.defs", "r")) == NULL)
127     {
128       puts("FAIL");
129       status ++;
130     }
131     else
132     {
133       puts("PASS");
134       fputs("cupsFileGets: ", stdout);
135 
136       if ((count = count_lines(fp)) != 201)
137       {
138         printf("FAIL (got %d lines, expected 201)\n", count);
139 	status ++;
140       }
141       else
142       {
143         puts("PASS");
144 	fputs("cupsFileRewind: ", stdout);
145 
146 	if (cupsFileRewind(fp) != 0)
147 	{
148 	  puts("FAIL");
149 	  status ++;
150 	}
151 	else
152 	{
153 	  puts("PASS");
154 	  fputs("cupsFileGets: ", stdout);
155 
156 	  if ((count = count_lines(fp)) != 201)
157 	  {
158 	    printf("FAIL (got %d lines, expected 201)\n", count);
159 	    status ++;
160 	  }
161 	  else
162 	    puts("PASS");
163         }
164       }
165 
166       cupsFileClose(fp);
167     }
168 
169    /*
170     * Test path functions...
171     */
172 
173     fputs("\ncupsFileFind: ", stdout);
174 #ifdef _WIN32
175     if (cupsFileFind("notepad.exe", "C:/WINDOWS", 1, filename, sizeof(filename)) &&
176 	cupsFileFind("notepad.exe", "C:/WINDOWS;C:/WINDOWS/SYSTEM32", 1, filename, sizeof(filename)))
177 #else
178     if (cupsFileFind("cat", "/bin", 1, filename, sizeof(filename)) &&
179 	cupsFileFind("cat", "/bin:/usr/bin", 1, filename, sizeof(filename)))
180 #endif /* _WIN32 */
181       printf("PASS (%s)\n", filename);
182     else
183     {
184       puts("FAIL");
185       status ++;
186     }
187 
188    /*
189     * Summarize the results and return...
190     */
191 
192     if (!status)
193       puts("\nALL TESTS PASSED!");
194     else
195       printf("\n%d TEST(S) FAILED!\n", status);
196   }
197   else
198   {
199    /*
200     * Cat the filename on the command-line...
201     */
202 
203     char	line[8192];		/* Line from file */
204 
205     if ((fp = cupsFileOpen(argv[1], "r")) == NULL)
206     {
207       perror(argv[1]);
208       status = 1;
209     }
210     else if (argc == 2)
211     {
212       status = 0;
213 
214       while (cupsFileGets(fp, line, sizeof(line)))
215         puts(line);
216 
217       if (!cupsFileEOF(fp))
218         perror(argv[1]);
219 
220       cupsFileClose(fp);
221     }
222     else
223     {
224       status = 0;
225       ssize_t bytes;
226 
227       while ((bytes = cupsFileRead(fp, line, sizeof(line))) > 0)
228         printf("%s: %d bytes\n", argv[1], (int)bytes);
229 
230       if (cupsFileEOF(fp))
231         printf("%s: EOF\n", argv[1]);
232       else
233         perror(argv[1]);
234 
235       cupsFileClose(fp);
236     }
237   }
238 
239   return (status);
240 }
241 
242 
243 /*
244  * 'count_lines()' - Count the number of lines in a file.
245  */
246 
247 static int				/* O - Number of lines */
count_lines(cups_file_t * fp)248 count_lines(cups_file_t *fp)		/* I - File to read from */
249 {
250   int	count;				/* Number of lines */
251   char	line[1024];			/* Line buffer */
252 
253 
254   for (count = 0; cupsFileGets(fp, line, sizeof(line)); count ++);
255 
256   return (count);
257 }
258 
259 
260 /*
261  * 'random_tests()' - Do random access tests.
262  */
263 
264 static int				/* O - Status */
random_tests(void)265 random_tests(void)
266 {
267   int		status,			/* Status of tests */
268 		pass,			/* Current pass */
269 		count,			/* Number of records read */
270 		record,			/* Current record */
271 		num_records;		/* Number of records */
272   off_t		pos;			/* Position in file */
273   ssize_t	expected;		/* Expected position in file */
274   cups_file_t	*fp;			/* File */
275   char		buffer[512];		/* Data buffer */
276 
277 
278  /*
279   * Run 4 passes, each time appending to a data file and then reopening the
280   * file for reading to validate random records in the file.
281   */
282 
283   for (status = 0, pass = 0; pass < 4; pass ++)
284   {
285    /*
286     * cupsFileOpen(append)
287     */
288 
289     printf("\ncupsFileOpen(append %d): ", pass);
290 
291     if ((fp = cupsFileOpen("testfile.dat", "a")) == NULL)
292     {
293       printf("FAIL (%s)\n", strerror(errno));
294       status ++;
295       break;
296     }
297     else
298       puts("PASS");
299 
300    /*
301     * cupsFileTell()
302     */
303 
304     expected = 256 * (ssize_t)sizeof(buffer) * pass;
305 
306     fputs("cupsFileTell(): ", stdout);
307     if ((pos = cupsFileTell(fp)) != (off_t)expected)
308     {
309       printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n",
310 	     CUPS_LLCAST pos, CUPS_LLCAST expected);
311       status ++;
312       break;
313     }
314     else
315       puts("PASS");
316 
317    /*
318     * cupsFileWrite()
319     */
320 
321     fputs("cupsFileWrite(256 512-byte records): ", stdout);
322     for (record = 0; record < 256; record ++)
323     {
324       memset(buffer, record, sizeof(buffer));
325       if (cupsFileWrite(fp, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer))
326         break;
327     }
328 
329     if (record < 256)
330     {
331       printf("FAIL (%d: %s)\n", record, strerror(errno));
332       status ++;
333       break;
334     }
335     else
336       puts("PASS");
337 
338    /*
339     * cupsFileTell()
340     */
341 
342     expected += 256 * (ssize_t)sizeof(buffer);
343 
344     fputs("cupsFileTell(): ", stdout);
345     if ((pos = cupsFileTell(fp)) != (off_t)expected)
346     {
347       printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n",
348              CUPS_LLCAST pos, CUPS_LLCAST expected);
349       status ++;
350       break;
351     }
352     else
353       puts("PASS");
354 
355     cupsFileClose(fp);
356 
357    /*
358     * cupsFileOpen(read)
359     */
360 
361     printf("\ncupsFileOpen(read %d): ", pass);
362 
363     if ((fp = cupsFileOpen("testfile.dat", "r")) == NULL)
364     {
365       printf("FAIL (%s)\n", strerror(errno));
366       status ++;
367       break;
368     }
369     else
370       puts("PASS");
371 
372    /*
373     * cupsFileSeek, cupsFileRead
374     */
375 
376     fputs("cupsFileSeek(), cupsFileRead(): ", stdout);
377 
378     for (num_records = (pass + 1) * 256, count = (pass + 1) * 256, record = ((int)CUPS_RAND() & 65535) % num_records;
379          count > 0;
380 	 count --, record = (record + ((int)CUPS_RAND() & 31) - 16 + num_records) % num_records)
381     {
382      /*
383       * The last record is always the first...
384       */
385 
386       if (count == 1)
387         record = 0;
388 
389      /*
390       * Try reading the data for the specified record, and validate the
391       * contents...
392       */
393 
394       expected = (ssize_t)sizeof(buffer) * record;
395 
396       if ((pos = cupsFileSeek(fp, expected)) != expected)
397       {
398         printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n",
399 	       CUPS_LLCAST pos, CUPS_LLCAST expected);
400         status ++;
401 	break;
402       }
403       else
404       {
405 	if (cupsFileRead(fp, buffer, sizeof(buffer)) != sizeof(buffer))
406 	{
407 	  printf("FAIL (%s)\n", strerror(errno));
408 	  status ++;
409 	  break;
410 	}
411 	else if ((buffer[0] & 255) != (record & 255) ||
412 	         memcmp(buffer, buffer + 1, sizeof(buffer) - 1))
413 	{
414 	  printf("FAIL (Bad Data - %d instead of %d)\n", buffer[0] & 255,
415 	         record & 255);
416 	  status ++;
417 	  break;
418 	}
419       }
420     }
421 
422     if (count == 0)
423       puts("PASS");
424 
425     cupsFileClose(fp);
426   }
427 
428  /*
429   * Remove the test file...
430   */
431 
432   unlink("testfile.dat");
433 
434  /*
435   * Return the test status...
436   */
437 
438   return (status);
439 }
440 
441 
442 /*
443  * 'read_write_tests()' - Perform read/write tests.
444  */
445 
446 static int				/* O - Status */
read_write_tests(int compression)447 read_write_tests(int compression)	/* I - Use compression? */
448 {
449   int		i;			/* Looping var */
450   cups_file_t	*fp;			/* File */
451   int		status;			/* Exit status */
452   char		line[1024],		/* Line from file */
453 		*value;			/* Directive value from line */
454   int		linenum;		/* Line number */
455   unsigned char	readbuf[8192],		/* Read buffer */
456 		writebuf[8192];		/* Write buffer */
457   int		byte;			/* Byte from file */
458   ssize_t	bytes;			/* Number of bytes read/written */
459   off_t		length;			/* Length of file */
460   static const char *partial_line = "partial line";
461 					/* Partial line */
462 
463 
464  /*
465   * No errors so far...
466   */
467 
468   status = 0;
469 
470  /*
471   * Initialize the write buffer with random data...
472   */
473 
474   CUPS_SRAND((unsigned)time(NULL));
475 
476   for (i = 0; i < (int)sizeof(writebuf); i ++)
477     writebuf[i] = (unsigned char)CUPS_RAND();
478 
479  /*
480   * cupsFileOpen(write)
481   */
482 
483   printf("cupsFileOpen(write%s): ", compression ? " compressed" : "");
484 
485   fp = cupsFileOpen(compression ? "testfile.dat.gz" : "testfile.dat",
486                     compression ? "w9" : "w");
487   if (fp)
488   {
489     puts("PASS");
490 
491    /*
492     * cupsFileCompression()
493     */
494 
495     fputs("cupsFileCompression(): ", stdout);
496 
497     if (cupsFileCompression(fp) == compression)
498       puts("PASS");
499     else
500     {
501       printf("FAIL (Got %d, expected %d)\n", cupsFileCompression(fp),
502              compression);
503       status ++;
504     }
505 
506    /*
507     * cupsFilePuts()
508     */
509 
510     fputs("cupsFilePuts(): ", stdout);
511 
512     if (cupsFilePuts(fp, "# Hello, World\n") > 0)
513       puts("PASS");
514     else
515     {
516       printf("FAIL (%s)\n", strerror(errno));
517       status ++;
518     }
519 
520    /*
521     * cupsFilePrintf()
522     */
523 
524     fputs("cupsFilePrintf(): ", stdout);
525 
526     for (i = 0; i < 1000; i ++)
527       if (cupsFilePrintf(fp, "TestLine %03d\n", i) < 0)
528         break;
529 
530     if (i >= 1000)
531       puts("PASS");
532     else
533     {
534       printf("FAIL (%s)\n", strerror(errno));
535       status ++;
536     }
537 
538    /*
539     * cupsFilePutChar()
540     */
541 
542     fputs("cupsFilePutChar(): ", stdout);
543 
544     for (i = 0; i < 256; i ++)
545       if (cupsFilePutChar(fp, i) < 0)
546         break;
547 
548     if (i >= 256)
549       puts("PASS");
550     else
551     {
552       printf("FAIL (%s)\n", strerror(errno));
553       status ++;
554     }
555 
556    /*
557     * cupsFileWrite()
558     */
559 
560     fputs("cupsFileWrite(): ", stdout);
561 
562     for (i = 0; i < 10000; i ++)
563       if (cupsFileWrite(fp, (char *)writebuf, sizeof(writebuf)) < 0)
564         break;
565 
566     if (i >= 10000)
567       puts("PASS");
568     else
569     {
570       printf("FAIL (%s)\n", strerror(errno));
571       status ++;
572     }
573 
574    /*
575     * cupsFilePuts() with partial line...
576     */
577 
578     fputs("cupsFilePuts(\"partial line\"): ", stdout);
579 
580     if (cupsFilePuts(fp, partial_line) > 0)
581       puts("PASS");
582     else
583     {
584       printf("FAIL (%s)\n", strerror(errno));
585       status ++;
586     }
587 
588    /*
589     * cupsFileTell()
590     */
591 
592     fputs("cupsFileTell(): ", stdout);
593 
594     if ((length = cupsFileTell(fp)) == 81933283)
595       puts("PASS");
596     else
597     {
598       printf("FAIL (" CUPS_LLFMT " instead of 81933283)\n", CUPS_LLCAST length);
599       status ++;
600     }
601 
602    /*
603     * cupsFileClose()
604     */
605 
606     fputs("cupsFileClose(): ", stdout);
607 
608     if (!cupsFileClose(fp))
609       puts("PASS");
610     else
611     {
612       printf("FAIL (%s)\n", strerror(errno));
613       status ++;
614     }
615   }
616   else
617   {
618     printf("FAIL (%s)\n", strerror(errno));
619     status ++;
620   }
621 
622  /*
623   * cupsFileOpen(read)
624   */
625 
626   fputs("\ncupsFileOpen(read): ", stdout);
627 
628   fp = cupsFileOpen(compression ? "testfile.dat.gz" : "testfile.dat", "r");
629   if (fp)
630   {
631     puts("PASS");
632 
633    /*
634     * cupsFileGets()
635     */
636 
637     fputs("cupsFileGets(): ", stdout);
638 
639     if (cupsFileGets(fp, line, sizeof(line)))
640     {
641       if (line[0] == '#')
642         puts("PASS");
643       else
644       {
645         printf("FAIL (Got line \"%s\", expected comment line)\n", line);
646 	status ++;
647       }
648     }
649     else
650     {
651       printf("FAIL (%s)\n", strerror(errno));
652       status ++;
653     }
654 
655    /*
656     * cupsFileCompression()
657     */
658 
659     fputs("cupsFileCompression(): ", stdout);
660 
661     if (cupsFileCompression(fp) == compression)
662       puts("PASS");
663     else
664     {
665       printf("FAIL (Got %d, expected %d)\n", cupsFileCompression(fp),
666              compression);
667       status ++;
668     }
669 
670    /*
671     * cupsFileGetConf()
672     */
673 
674     linenum = 1;
675 
676     fputs("cupsFileGetConf(): ", stdout);
677 
678     for (i = 0, value = NULL; i < 1000; i ++)
679       if (!cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
680         break;
681       else if (_cups_strcasecmp(line, "TestLine") || !value || atoi(value) != i ||
682                linenum != (i + 2))
683         break;
684 
685     if (i >= 1000)
686       puts("PASS");
687     else if (line[0])
688     {
689       printf("FAIL (Line %d, directive \"%s\", value \"%s\")\n", linenum,
690              line, value ? value : "(null)");
691       status ++;
692     }
693     else
694     {
695       printf("FAIL (%s)\n", strerror(errno));
696       status ++;
697     }
698 
699    /*
700     * cupsFileGetChar()
701     */
702 
703     fputs("cupsFileGetChar(): ", stdout);
704 
705     for (i = 0, byte = 0; i < 256; i ++)
706       if ((byte = cupsFileGetChar(fp)) != i)
707         break;
708 
709     if (i >= 256)
710       puts("PASS");
711     else if (byte >= 0)
712     {
713       printf("FAIL (Got %d, expected %d)\n", byte, i);
714       status ++;
715     }
716     else
717     {
718       printf("FAIL (%s)\n", strerror(errno));
719       status ++;
720     }
721 
722    /*
723     * cupsFileRead()
724     */
725 
726     fputs("cupsFileRead(): ", stdout);
727 
728     for (i = 0, bytes = 0; i < 10000; i ++)
729       if ((bytes = cupsFileRead(fp, (char *)readbuf, sizeof(readbuf))) < 0)
730         break;
731       else if (memcmp(readbuf, writebuf, sizeof(readbuf)))
732         break;
733 
734     if (i >= 10000)
735       puts("PASS");
736     else if (bytes > 0)
737     {
738       printf("FAIL (Pass %d, ", i);
739 
740       for (i = 0; i < (int)sizeof(readbuf); i ++)
741         if (readbuf[i] != writebuf[i])
742 	  break;
743 
744       printf("match failed at offset %d - got %02X, expected %02X)\n",
745              i, readbuf[i], writebuf[i]);
746     }
747     else
748     {
749       printf("FAIL (%s)\n", strerror(errno));
750       status ++;
751     }
752 
753    /*
754     * cupsFileGetChar() with partial line...
755     */
756 
757     fputs("cupsFileGetChar(partial line): ", stdout);
758 
759     for (i = 0; i < (int)strlen(partial_line); i ++)
760       if ((byte = cupsFileGetChar(fp)) < 0)
761         break;
762       else if (byte != partial_line[i])
763         break;
764 
765     if (!partial_line[i])
766       puts("PASS");
767     else
768     {
769       printf("FAIL (got '%c', expected '%c')\n", byte, partial_line[i]);
770       status ++;
771     }
772 
773    /*
774     * cupsFileTell()
775     */
776 
777     fputs("cupsFileTell(): ", stdout);
778 
779     if ((length = cupsFileTell(fp)) == 81933283)
780       puts("PASS");
781     else
782     {
783       printf("FAIL (" CUPS_LLFMT " instead of 81933283)\n", CUPS_LLCAST length);
784       status ++;
785     }
786 
787    /*
788     * cupsFileClose()
789     */
790 
791     fputs("cupsFileClose(): ", stdout);
792 
793     if (!cupsFileClose(fp))
794       puts("PASS");
795     else
796     {
797       printf("FAIL (%s)\n", strerror(errno));
798       status ++;
799     }
800   }
801   else
802   {
803     printf("FAIL (%s)\n", strerror(errno));
804     status ++;
805   }
806 
807  /*
808   * Remove the test file...
809   */
810 
811   if (!status)
812     unlink(compression ? "testfile.dat.gz" : "testfile.dat");
813 
814  /*
815   * Return the test status...
816   */
817 
818   return (status);
819 }
820