workbench/classes/zune: Compile fixed for AROS m68k
[AROS.git] / workbench / c / List.c
blob53e0ab5ce2e4071b67e5c491975020abba99787c
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 List the contents of a directory.
6 */
7 /*****************************************************************************
9 NAME
11 List
13 FORMAT
15 List [(dir | pattern | filename)] [ PAT (pattern)] [KEYS] [DATES]
16 [NODATES] [TO (name)] [SUB (string)] [SINCE (date)] [UPTO (date)]
17 [QUICK] [BLOCK] [NOHEAD] [FILES] [DIRS] [LFORMAT (string)] [ALL]
19 TEMPLATE
21 DIR/M,P=PAT/K,KEYS/S,DATES/S,NODATES/S,TO/K,SUB/K,SINCE/K,UPTO/K,QUICK/S,BLOCK/S,NOHEAD/S,FILES/S,DIRS/S,LFORMAT/K,ALL/S
23 LOCATION
27 FUNCTION
29 Lists detailed information about the files and directories in the
30 current directory or in the directory specified by DIR.
32 The information for each file or directory is presented on a separate
33 line, containing the following information:
35 name
36 size (in bytes)
37 protection bits
38 date and time
40 INPUTS
42 DIR -- The directory to list. If left out, the current
43 directory will be listed.
44 PAT -- Display only files matching 'string'
45 KEYS -- Display the block number of each file or directory
46 DATES -- Display the creation date of files and directories
47 NODATES -- Don't display dates
48 TO (name) -- Write the listing to a file instead of stdout
49 SUB (string) -- Display only files, a substring of which matches
50 the substring 'string'
51 SINCE (date) -- Display only files newer than 'date'
52 UPTO (date) -- Display only files older than 'date'
53 QUICK -- Display only the names of files
54 BLOCK -- File sizes are in blocks of 512 bytes
55 NOHEAD -- Don't print any header information
56 FILES -- Display files only
57 DIRS -- Display directories only
58 LFORMAT -- Specify the list output in printf-style
59 ALL -- List the contents of directories recursively
61 The following attributes of the LFORMAT strings are available
63 %A -- file attributes
64 %B -- size of file in blocks rather than bytes
65 %C -- file comment
66 %D -- creation date
67 %E -- file extension
68 %F -- volume name
69 %K -- file key block number
70 %L -- size of file in bytes
71 %M -- file name without extension
72 %N -- file name
73 %P -- file path
74 %S -- superceded by %N and %P; obsolete
75 %T -- creation time
77 RESULT
79 Standard DOS return codes.
81 EXAMPLE
83 1> List C:
84 Directory "C:" on Wednesday 12-Dec-99
85 AddBuffers 444 --p-rwed 02-Sep-99 11:51:31
86 Assign 3220 --p-rwed 02-Sep-99 11:51:31
87 Avail 728 --p-rwed 02-Sep-99 11:51:31
88 Copy 3652 --p-rwed 02-Sep-99 11:51:31
89 Delete 1972 --p-rwed 02-Sep-99 11:51:31
90 Execute 4432 --p-rwed 02-Sep-99 11:51:31
91 List 5108 --p-rwed 02-Sep-99 11:51:31
92 Installer 109956 ----rwed 02-Sep-99 11:51:31
93 Which 1068 --p-rwed 02-Sep-99 11:51:31
94 9 files - 274 blocks used
96 BUGS
98 SEE ALSO
102 INTERNALS
104 ******************************************************************************/
106 #define DEBUG 0
107 #include <aros/debug.h>
109 #include <clib/macros.h>
110 #include <exec/memory.h>
111 #include <proto/exec.h>
112 #include <dos/datetime.h>
113 #include <dos/dos.h>
114 #include <dos/exall.h>
115 #include <dos/dosasl.h>
116 #include <dos/datetime.h>
117 #include <proto/dos.h>
118 #include <proto/alib.h>
119 #include <utility/tagitem.h>
121 #include <stdio.h>
122 #include <string.h>
123 #include <ctype.h>
124 #include <stdlib.h>
125 #include <memory.h>
127 const TEXT version[] = "$VER: List 41.7 (18.08.2010)\n";
129 #define ARG_TEMPLATE "DIR/M,P=PAT/K,KEYS/S,DATES/S,NODATES/S,TO/K,SUB/K,SINCE/K,UPTO/K,QUICK/S,BLOCK/S,NOHEAD/S,FILES/S,DIRS/S,LFORMAT/K,ALL/S"
131 struct DirNode
133 struct MinNode node;
134 char *dirname;
138 typedef struct _Statistics
140 ULONG nFiles;
141 ULONG nDirs;
142 ULONG nBlocks;
143 } Statistics;
146 enum
148 ARG_DIR = 0,
149 ARG_PAT,
150 ARG_KEYS,
151 ARG_DATES,
152 ARG_NODATES,
153 ARG_TO,
154 ARG_SUB,
155 ARG_SINCE,
156 ARG_UPTO,
157 ARG_QUICK,
158 ARG_BLOCK,
159 ARG_NOHEAD,
160 ARG_FILES,
161 ARG_DIRS,
162 ARG_LFORMAT,
163 ARG_ALL,
164 NOOFARGS
167 #define MAX_PATH_LEN 1024
169 #define BLOCKSIZE 512
171 int printDirHeader(STRPTR dirname, BOOL noHead)
173 struct DateTime dt;
175 char datestr[LEN_DATSTRING];
176 char dow[LEN_DATSTRING];
178 if (!noHead)
180 DateStamp((struct DateStamp *)&dt);
181 dt.dat_Format = FORMAT_DEF;
182 dt.dat_Flags = 0;
183 dt.dat_StrDay = dow;
184 dt.dat_StrDate = datestr;
185 dt.dat_StrTime = NULL;
186 DateToStr(&dt);
188 Printf("Directory \"%s\" on %s %s:\n", dirname, dow, datestr);
191 return RETURN_OK;
195 /* Possible printf-type switches
197 %A -- file attributes
198 %B -- size of file in blocks rather than bytes
199 %C -- file comment
200 %D -- file date
201 %E -- file extension
202 %F -- volume name
203 %K -- file key block number
204 %L -- size of file in bytes
205 %M -- file name without extension
206 %N -- file name
207 %P -- file path
208 %S -- file name or file path
209 %T -- creation date
212 struct lfstruct
214 struct AnchorPath *ap;
215 BOOL isdir;
216 STRPTR date;
217 STRPTR time;
218 STRPTR flags;
219 STRPTR filename;
220 STRPTR comment;
221 ULONG size;
222 ULONG key;
226 #define roundUp(x, bSize) ((x + bSize - 1)/bSize)
228 int printLformat(STRPTR format, struct lfstruct *lf)
230 STRPTR filename = FilePart(lf->filename);
231 STRPTR temp = format;
232 LONG substitutePath = 0;
233 char c;
236 Whether the path or the filename is substituted for an occurrence
237 of %S depends on how many occurrences are in the LFORMAT line, and
238 their order, as follows:
240 Occurrences of %S 1st 2nd 3rd 4th
241 1 filename
242 2 path filename
243 3 path filename filename
244 4 path filename path filename
247 while ( ( substitutePath < 4 ) && ( '\0' != (c = *temp++) ) )
249 if ( '%' == c )
250 if ( 'S' == toupper(*temp++) )
251 substitutePath++;
253 if ( substitutePath == 3 )
254 substitutePath = 2;
256 while ('\0' != (c = *format++))
258 if ('%' == c)
260 switch (toupper(*format++))
262 /* File comment */
263 case 'C':
264 Printf(lf->comment);
265 break;
267 /* Creation date */
268 case 'D':
269 Printf(lf->date);
270 break;
272 /* Creation time */
273 case 'T':
274 Printf(lf->time);
275 break;
277 /* File size in blocks of BLOCKSIZE bytes */
278 case 'B':
279 if (lf->isdir)
281 Printf("Dir");
283 else
285 ULONG tmp = roundUp(lf->size, BLOCKSIZE);
287 /* File is 0 bytes? */
288 if (tmp == 0)
290 Printf("empty");
292 else
294 Printf("%lu", tmp);
298 break;
300 /* Path incl. volume name*/
301 case 'F':
303 UBYTE buf[256];
305 if (NameFromLock(lf->ap->ap_Current->an_Lock, buf, 256))
307 int len;
309 Printf(buf);
311 len = strlen(buf);
312 if ((len > 0) && (buf[len - 1] != ':') && (buf[len - 1] != '/'))
314 Printf("/");
319 break;
321 /* File attributes (flags) */
322 case 'A':
323 Printf(lf->flags);
324 break;
326 /* Disk block key */
327 case 'K':
328 Printf("[%ld]", lf->key);
329 break;
331 /* File size */
332 case 'L':
333 if (lf->isdir)
335 Printf("Dir");
337 else
339 if (lf->size == 0)
341 Printf("empty");
343 else
345 Printf("%lu", lf->size);
349 break;
351 /* File name without extension */
352 case 'M':
354 STRPTR lastPoint = strrchr(filename, '.');
356 if (lastPoint != NULL)
358 *lastPoint = 0;
361 Printf(filename);
363 /* Resurrect filename in case we should print it once
364 more */
365 if (lastPoint != NULL)
367 *lastPoint = '.';
371 break;
373 /* Filename or Path name */
374 case 'S':
375 D(bug("[List] substitutePath = %d\n", substitutePath));
376 if ( (--substitutePath == 3) || (substitutePath == 1) )
378 STRPTR end = FilePart(lf->filename);
379 UBYTE token = *end;
381 *end = '\0';
383 Printf(lf->filename);
385 /* Restore pathname */
386 *end = token;
388 break;
390 /* Fall through */
391 case 'N':
392 Printf(filename);
393 break;
395 /* File extension */
396 case 'E':
398 STRPTR extension = strrchr(filename, '.');
400 if (extension != NULL)
402 Printf(extension);
406 break;
408 /* Path name, but without volume */
409 case 'P':
411 STRPTR end = FilePart(lf->filename);
412 UBYTE token = *end;
414 *end = 0;
416 Printf(lf->filename);
418 /* Restore pathname */
419 *end = token;
422 break;
424 case 0:
425 return 0;
426 break;
428 default:
429 Printf("%%%lc", *format);
430 break;
433 else
435 Printf("%lc", c);
439 return 0;
443 int printFileData(struct AnchorPath *ap,
444 BOOL showFiles, BOOL showDirs, STRPTR parsedPattern,
445 ULONG *files, ULONG *dirs, ULONG *nBlocks, STRPTR lFormat,
446 BOOL quick, BOOL dates, BOOL noDates, BOOL block,
447 struct DateStamp *sinceDate, struct DateStamp *uptoDate,
448 BOOL doSince, BOOL doUpto, STRPTR subpatternStr,
449 BOOL keys)
451 STRPTR filename = ap->ap_Buf;
452 BOOL isDir = (ap->ap_Info.fib_DirEntryType >= 0);
453 struct DateStamp *ds = &ap->ap_Info.fib_Date;
454 ULONG protection = ap->ap_Info.fib_Protection;
455 ULONG size = ap->ap_Info.fib_Size;
456 STRPTR filenote = ap->ap_Info.fib_Comment;
457 LONG diskKey = ap->ap_Info.fib_DiskKey;
459 int error = RETURN_OK;
461 UBYTE date[LEN_DATSTRING];
462 UBYTE time[LEN_DATSTRING];
463 UBYTE flags[8];
465 struct DateTime dt;
467 /* Do the file match the time interval we are looking for?
468 (ARG_SINCE and ARG_UPTO) -- any combination of these may be
469 specified */
470 if ((doSince && (CompareDates(sinceDate, ds) < 0)) ||
471 (doUpto && (CompareDates(uptoDate, ds) > 0)))
473 return 0;
476 /* Does the filename match a certain pattern? (ARG_PAT) */
477 if (parsedPattern != NULL &&
478 !MatchPatternNoCase(parsedPattern, FilePart(filename)))
480 return 0;
483 /* Does a substring of the filename match a certain pattern? (ARG_SUB) */
484 if (subpatternStr != NULL &&
485 !MatchPatternNoCase(subpatternStr, FilePart(filename)))
487 return 0;
490 CopyMem(ds, &dt.dat_Stamp, sizeof(struct DateStamp));
491 dt.dat_Format = FORMAT_DOS;
492 dt.dat_Flags = DTF_SUBST;
493 dt.dat_StrDay = NULL;
494 dt.dat_StrDate = date;
495 dt.dat_StrTime = time;
496 DateToStr(&dt); /* returns 0 if invalid */
498 /* Convert the protection bits to a string */
499 flags[0] = protection & FIBF_SCRIPT ? 's' : '-';
500 flags[1] = protection & FIBF_PURE ? 'p' : '-';
501 flags[2] = protection & FIBF_ARCHIVE ? 'a' : '-';
503 /* The following flags are high-active! */
504 flags[3] = protection & FIBF_READ ? '-' : 'r';
505 flags[4] = protection & FIBF_WRITE ? '-' : 'w';
506 flags[5] = protection & FIBF_EXECUTE ? '-' : 'e';
507 flags[6] = protection & FIBF_DELETE ? '-' : 'd';
508 flags[7] = 0x00;
510 if (isDir)
512 if (showDirs)
514 ++*dirs;
515 ++*nBlocks; /* dir entry uses 1 block on AROS, 2 on OS31) */
517 if (lFormat != NULL)
519 struct lfstruct lf = { ap, isDir, date, time, flags, filename,
520 filenote, size, diskKey};
522 printLformat(lFormat, &lf);
523 Printf("\n");
525 else
527 D(bug("Found file %s\n", filename));
529 Printf("%-25s ", FilePart(filename));
531 if (!quick)
533 Printf(" <Dir> %7s ", flags);
536 if (!noDates && (!quick || dates))
538 Printf("%-11s %s", date, time);
541 Printf("\n");
545 else if (showFiles)
547 ++*files;
548 *nBlocks += roundUp(size, BLOCKSIZE);
550 if (lFormat != NULL)
552 struct lfstruct lf = { ap, isDir, date, time, flags, filename,
553 filenote, size, diskKey };
555 printLformat(lFormat, &lf);
556 Printf("\n");
558 else
560 Printf("%-25s ", FilePart(filename));
562 if (!quick)
564 if(keys)
566 char key[16];
567 int fill;
568 int i; /* Loop variable */
570 sprintf(key, "%ld", diskKey);
571 fill = 7 - strlen(key) - 2;
573 for (i = 0; i < fill; i++)
575 Printf(" ");
578 Printf("[%ld] ", diskKey);
580 else
582 if (0 != size)
584 Printf("%7ld ",
585 block ? roundUp(size, BLOCKSIZE) : size);
587 else
589 Printf(" empty ");
593 Printf("%7s ", flags);
596 if (!noDates && (!quick || dates))
598 Printf("%-11s %s", date, time);
601 if (!quick && (*filenote != 0))
603 Printf("\n: %s", filenote);
606 Printf("\n");
610 return error;
614 /* Print directory summary information */
615 void printSummary(CONST_STRPTR dirname, int files, int dirs, int nBlocks,
616 BOOL noHead, BOOL PrintEmpty)
618 if (noHead)
619 return;
621 if (files || dirs)
623 if (files > 1)
624 Printf("%ld files - ", files);
625 else if (files > 0)
626 PutStr("1 file - ");
628 if (dirs > 1)
629 Printf("%ld directories - ", dirs);
630 else if (dirs > 0)
631 PutStr("1 directory - ");
633 if (nBlocks > 1)
634 Printf("%ld blocks used\n", nBlocks);
635 else if (nBlocks > 0)
636 PutStr("1 block used\n");
638 else if (PrintEmpty)
639 Printf("Directory \"%s\" is empty\n", dirname);
643 int listFile(CONST_STRPTR filename, BOOL showFiles, BOOL showDirs,
644 STRPTR parsedPattern, BOOL noHead, STRPTR lFormat, BOOL quick,
645 BOOL dates, BOOL noDates, BOOL block, struct DateStamp *sinceDate,
646 struct DateStamp *uptoDate, BOOL doSince, BOOL doUpto,
647 STRPTR subpatternStr, BOOL all, BOOL keys, Statistics *stats)
649 struct AnchorPath *ap;
650 struct List DirList, FreeDirNodeList;
651 struct DirNode *dirnode, *prev_dirnode = NULL;
653 ULONG files = 0;
654 ULONG dirs = 0;
655 ULONG nBlocks = 0;
656 ULONG error;
658 NewList(&DirList);
659 NewList(&FreeDirNodeList);
663 ap = AllocVec(sizeof(struct AnchorPath) + MAX_PATH_LEN, MEMF_CLEAR);
665 if (ap == NULL)
667 return RETURN_ERROR;
670 ap->ap_Strlen = MAX_PATH_LEN;
672 error = MatchFirst(filename, ap);
674 /* Explicitely named directory and not a pattern? --> enter dir */
676 if (0 == error)
678 if (!(ap->ap_Flags & APF_ITSWILD))
680 if (ap->ap_Info.fib_DirEntryType >= 0)
682 //error = printDirHeader(filename, noHead);
683 ap->ap_Flags |= APF_DODIR;
685 if (0 == error)
687 error = MatchNext(ap);
693 if (0 == error)
695 BOOL first = TRUE;
697 ap->ap_BreakBits = SIGBREAKF_CTRL_C;
698 if (FilePart(ap->ap_Buf) == ap->ap_Buf)
700 ap->ap_Flags &= ~APF_DirChanged;
706 ** There's something to show.
708 if (!(ap->ap_Flags & APF_DIDDIR))
710 if (ap->ap_Flags & APF_DirChanged)
712 STRPTR p;
713 UBYTE c;
715 if (!first) printSummary(filename, files, dirs, nBlocks, noHead, TRUE);
717 /* Update global statistics for (possiblr) ALL option */
718 stats->nFiles += files;
719 stats->nDirs += dirs;
720 stats->nBlocks += nBlocks;
722 files = 0;
723 dirs = 0;
724 nBlocks = 0;
726 p = PathPart(ap->ap_Buf);
727 c = *p;
728 *p = 0;
730 error = printDirHeader(ap->ap_Buf, noHead);
732 *p = c;
736 error = printFileData(ap,
737 showFiles,
738 showDirs,
739 parsedPattern,
740 &files,
741 &dirs,
742 &nBlocks,
743 lFormat,
744 quick,
745 dates,
746 noDates,
747 block,
748 sinceDate,
749 uptoDate,
750 doSince,
751 doUpto,
752 subpatternStr,
753 keys);
755 if (all && (ap->ap_Info.fib_DirEntryType >= 0))
757 if ((dirnode = malloc(sizeof(struct DirNode))))
759 if ((dirnode->dirname = strdup(ap->ap_Buf)))
761 Insert(&DirList, (struct Node *)dirnode,
762 (struct Node *)prev_dirnode);
764 prev_dirnode = dirnode;
766 else
768 free(dirnode);
774 error = MatchNext(ap);
776 first = FALSE;
778 } while (0 == error);
781 MatchEnd(ap);
783 FreeVec(ap);
785 if (error == ERROR_BREAK)
787 PrintFault(error, NULL);
790 if (error == ERROR_NO_MORE_ENTRIES)
792 error = 0;
795 if ((error == 0) || (error == ERROR_BREAK))
797 BOOL printEmpty = !(ap->ap_Flags & APF_ITSWILD);
798 printSummary(filename, files, dirs, nBlocks, noHead, printEmpty);
801 /* Update global statistics for (possiblr) ALL option */
802 stats->nFiles += files;
803 stats->nDirs += dirs;
804 stats->nBlocks += nBlocks;
806 files = 0;
807 dirs = 0;
808 nBlocks = 0;
811 if (error) break;
813 dirnode = (struct DirNode *)RemHead(&DirList);
815 if (dirnode != NULL)
817 filename = dirnode->dirname;
819 prev_dirnode = NULL;
821 /* do not free() dirnode, as we reference dirnode->dirname! */
823 AddTail(&FreeDirNodeList, (struct Node *)dirnode);
825 } while (dirnode);
827 while ((dirnode = (struct DirNode *)RemHead(&FreeDirNodeList)))
829 free(dirnode->dirname);
830 free(dirnode);
833 return error;
837 int __nocommandline;
839 int main(void)
841 IPTR args[NOOFARGS] =
843 (IPTR) NULL, // ARG_DIR
844 (IPTR) NULL, // ARG_PAT
845 FALSE, // ARG_KEYS
846 FALSE, // ARG_DATES
847 FALSE, // ARG_NODATES
848 (IPTR) NULL, // ARG_TO
849 (IPTR) NULL, // ARG_SUB
850 (IPTR) NULL, // ARG_SINCE
851 (IPTR) NULL, // ARG_UPTO
852 FALSE, // ARG_QUICK
853 FALSE, // ARG_BLOCK
854 FALSE, // ARG_NOHEAD
855 FALSE, // ARG_FILES
856 FALSE, // ARG_DIRS
857 FALSE, // ARG_LFORMAT
858 FALSE // ARG_ALL
860 static CONST_STRPTR default_directories[] = {(CONST_STRPTR)"", 0};
861 struct RDArgs *rda;
863 LONG error = RETURN_OK;
864 STRPTR parsedPattern = NULL;
865 STRPTR subpatternStr = NULL;
866 BPTR oldOutput = BNULL;
868 Statistics stats = { 0, 0, 0 };
870 rda = ReadArgs(ARG_TEMPLATE, args, NULL);
872 if (rda != NULL)
874 CONST_STRPTR *directories = (CONST_STRPTR *)args[ARG_DIR];
875 STRPTR lFormat = (STRPTR)args[ARG_LFORMAT];
876 STRPTR pattern = (STRPTR)args[ARG_PAT];
877 STRPTR toFile = (STRPTR)args[ARG_TO];
878 STRPTR subStr = (STRPTR)args[ARG_SUB];
879 STRPTR since = (STRPTR)args[ARG_SINCE];
880 STRPTR upto = (STRPTR)args[ARG_UPTO];
881 BOOL files = (BOOL)args[ARG_FILES];
882 BOOL dirs = (BOOL)args[ARG_DIRS];
883 BOOL noDates = (BOOL)args[ARG_NODATES];
884 BOOL dates = (BOOL)args[ARG_DATES];
885 BOOL quick = (BOOL)args[ARG_QUICK];
886 BOOL noHead = (BOOL)args[ARG_NOHEAD];
887 BOOL block = (BOOL)args[ARG_BLOCK];
888 BOOL all = (BOOL)args[ARG_ALL];
889 BOOL keys = (BOOL)args[ARG_KEYS];
891 struct DateTime sinceDatetime;
892 struct DateTime uptoDatetime;
894 ULONG i; /* Loop variable */
896 if (since != NULL)
898 sinceDatetime.dat_StrDate = since;
899 sinceDatetime.dat_StrTime = NULL;
900 sinceDatetime.dat_Format = FORMAT_DEF;
901 sinceDatetime.dat_Flags = 0;
902 if (StrToDate(&sinceDatetime) == DOSFALSE)
904 FreeArgs(rda);
905 Printf("*** Illegal 'SINCE' parameter\n");
907 return RETURN_FAIL;
911 if (upto != NULL)
913 uptoDatetime.dat_StrDate = upto;
914 uptoDatetime.dat_StrTime = NULL;
915 uptoDatetime.dat_Format = FORMAT_DEF;
916 uptoDatetime.dat_Flags = 0;
918 if (StrToDate(&uptoDatetime) == DOSFALSE)
920 FreeArgs(rda);
921 Printf("*** Illegal 'UPTO' parameter\n");
923 return RETURN_FAIL;
927 if (subStr != NULL)
929 STRPTR subStrWithPat;
930 ULONG length = (strlen(subStr) + sizeof("#?#?"))*2 + 2;
932 subStrWithPat = AllocVec(length, MEMF_ANY);
934 if (subStrWithPat == NULL)
936 FreeArgs(rda);
937 PrintFault(IoErr(), "List");
939 return RETURN_FAIL;
942 strcpy(subStrWithPat, "#?");
943 strcat(subStrWithPat, subStr);
944 strcat(subStrWithPat, "#?");
946 subpatternStr = AllocVec(length, MEMF_ANY);
948 if (subpatternStr == NULL ||
949 ParsePatternNoCase(subStrWithPat, subpatternStr, length) == -1)
951 FreeVec(subStrWithPat);
952 FreeArgs(rda);
953 PrintFault(IoErr(), "List");
955 return RETURN_FAIL;
958 FreeVec(subStrWithPat);
962 if (pattern != NULL)
964 ULONG length = strlen(pattern)*2 + 2;
966 parsedPattern = AllocVec(length, MEMF_ANY);
968 if (parsedPattern == NULL ||
969 ParsePatternNoCase(pattern, parsedPattern, length) == -1)
971 FreeVec(subpatternStr);
972 FreeArgs(rda);
974 return RETURN_FAIL;
978 if (toFile != NULL)
980 BPTR file = Open(toFile, MODE_NEWFILE);
982 if (file == BNULL)
984 FreeVec(subpatternStr);
985 FreeVec(parsedPattern);
986 FreeArgs(rda);
987 PrintFault(IoErr(), "List");
989 return RETURN_FAIL;
991 oldOutput = SelectOutput(file);
994 if (!files && !dirs)
996 files = TRUE;
997 dirs = TRUE;
1000 /* if (!dates && !noDates)
1002 dates = TRUE;
1005 if (lFormat)
1007 noHead = TRUE;
1010 if ((directories == NULL) || (*directories == NULL))
1012 directories = default_directories;
1015 for (i = 0; directories[i] != NULL; i++)
1017 error = listFile(directories[i], files, dirs, parsedPattern,
1018 noHead, lFormat, quick, dates, noDates,
1019 block, &sinceDatetime.dat_Stamp,
1020 &uptoDatetime.dat_Stamp, since != NULL,
1021 upto != NULL, subpatternStr, all, keys,
1022 &stats);
1024 if (error != RETURN_OK)
1026 break;
1029 // Printf("\n");
1032 FreeArgs(rda);
1034 else
1036 error = IoErr();;
1039 if ((BOOL)args[ARG_NOHEAD] == FALSE &&
1040 (BOOL)args[ARG_LFORMAT] == FALSE &&
1041 (BOOL)args[ARG_ALL] &&
1042 (stats.nFiles || stats.nDirs))
1044 Printf("\nTOTAL: %ld files - %ld directories - %ld blocks used\n",
1045 stats.nFiles, stats.nDirs, stats.nBlocks);
1049 if (error != RETURN_OK)
1051 if (error == ERROR_BREAK)
1053 error = RETURN_WARN;
1055 else
1057 PrintFault(error, "List");
1058 error = RETURN_FAIL;
1062 if (parsedPattern != NULL)
1064 FreeVec(parsedPattern);
1067 if (subpatternStr != NULL)
1069 FreeVec(subpatternStr);
1072 if (oldOutput != BNULL)
1074 Close(SelectOutput(oldOutput));
1077 return error;