- Allow menu highlight colour to be configured through an ARGB hex value in
[AROS.git] / workbench / c / List.c
blob23c8dedca6bbbbf9542e53e4d6927deb8e83a169
1 /*
2 Copyright © 1995-2011, 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 <proto/utility.h>
120 #include <utility/tagitem.h>
122 const TEXT version[] = "$VER: List 41.8 (05.11.2011)\n";
124 #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"
126 struct DirNode
128 struct MinNode node;
129 char *dirname;
133 typedef struct _Statistics
135 ULONG nFiles;
136 ULONG nDirs;
137 UQUAD nBlocks;
138 } Statistics;
141 enum
143 ARG_DIR = 0,
144 ARG_PAT,
145 ARG_KEYS,
146 ARG_DATES,
147 ARG_NODATES,
148 ARG_TO,
149 ARG_SUB,
150 ARG_SINCE,
151 ARG_UPTO,
152 ARG_QUICK,
153 ARG_BLOCK,
154 ARG_NOHEAD,
155 ARG_FILES,
156 ARG_DIRS,
157 ARG_LFORMAT,
158 ARG_ALL,
159 NOOFARGS
162 #define MAX_PATH_LEN 1024
164 #define BLOCKSIZE 512
166 int printDirHeader(STRPTR dirname, BOOL noHead)
168 struct DateTime dt;
170 char datestr[LEN_DATSTRING];
171 char dow[LEN_DATSTRING];
173 if (!noHead)
175 DateStamp((struct DateStamp *)&dt);
176 dt.dat_Format = FORMAT_DEF;
177 dt.dat_Flags = 0;
178 dt.dat_StrDay = dow;
179 dt.dat_StrDate = datestr;
180 dt.dat_StrTime = NULL;
181 DateToStr(&dt);
183 Printf("Directory \"%s\" on %s %s:\n", dirname, dow, datestr);
186 return RETURN_OK;
190 /* Possible printf-type switches
192 %A -- file attributes
193 %B -- size of file in blocks rather than bytes
194 %C -- file comment
195 %D -- file date
196 %E -- file extension
197 %F -- volume name
198 %K -- file key block number
199 %L -- size of file in bytes
200 %M -- file name without extension
201 %N -- file name
202 %P -- file path
203 %S -- file name or file path
204 %T -- creation date
207 struct lfstruct
209 struct AnchorPath *ap;
210 BOOL isdir;
211 STRPTR date;
212 STRPTR time;
213 STRPTR flags;
214 STRPTR filename;
215 STRPTR comment;
216 UQUAD size;
217 ULONG key;
221 #define roundUp(x, bSize) ((x + bSize - 1)/bSize)
223 int printLformat(STRPTR format, struct lfstruct *lf)
225 STRPTR filename = FilePart(lf->filename);
226 STRPTR temp = format;
227 LONG substitutePath = 0;
228 char c;
231 Whether the path or the filename is substituted for an occurrence
232 of %S depends on how many occurrences are in the LFORMAT line, and
233 their order, as follows:
235 Occurrences of %S 1st 2nd 3rd 4th
236 1 filename
237 2 path filename
238 3 path filename filename
239 4 path filename path filename
242 while ( ( substitutePath < 4 ) && ( '\0' != (c = *temp++) ) )
244 if ( '%' == c )
245 if ( 'S' == ToUpper(*temp++) )
246 substitutePath++;
248 if ( substitutePath == 3 )
249 substitutePath = 2;
251 while ('\0' != (c = *format++))
253 if ('%' == c)
255 switch (ToUpper(*format++))
257 /* File comment */
258 case 'C':
259 Printf(lf->comment);
260 break;
262 /* Creation date */
263 case 'D':
264 Printf(lf->date);
265 break;
267 /* Creation time */
268 case 'T':
269 Printf(lf->time);
270 break;
272 /* File size in blocks of BLOCKSIZE bytes */
273 case 'B':
274 if (lf->isdir)
276 Printf("Dir");
278 else
280 ULONG tmp = roundUp(lf->size, BLOCKSIZE);
282 /* File is 0 bytes? */
283 if (tmp == 0)
285 Printf("empty");
287 else
289 Printf("%lu", tmp);
293 break;
295 /* Path incl. volume name*/
296 case 'F':
298 UBYTE buf[256];
300 if (NameFromLock(lf->ap->ap_Current->an_Lock, buf, 256))
302 int len;
304 Printf(buf);
306 len = strlen(buf);
307 if ((len > 0) && (buf[len - 1] != ':') && (buf[len - 1] != '/'))
309 Printf("/");
314 break;
316 /* File attributes (flags) */
317 case 'A':
318 Printf(lf->flags);
319 break;
321 /* Disk block key */
322 case 'K':
323 Printf("[%ld]", lf->key);
324 break;
326 /* File size */
327 case 'L':
328 if (lf->isdir)
330 Printf("Dir");
332 else
334 if (lf->size == 0)
336 Printf("empty");
338 else
340 UQUAD filesize = lf->size;
342 char buf[256];
343 buf[255] = '\0';
345 char *bufpos = &buf[254];
349 bufpos[0] = '0' + (filesize % 10);
350 filesize /= 10;
351 bufpos--;
352 } while (filesize);
354 Printf("%s", &bufpos[1]);
358 break;
360 /* File name without extension */
361 case 'M':
363 STRPTR lastPoint = strrchr(filename, '.');
365 if (lastPoint != NULL)
367 *lastPoint = 0;
370 Printf(filename);
372 /* Resurrect filename in case we should print it once
373 more */
374 if (lastPoint != NULL)
376 *lastPoint = '.';
380 break;
382 /* Filename or Path name */
383 case 'S':
384 D(bug("[List] substitutePath = %d\n", substitutePath));
385 if ( (--substitutePath == 3) || (substitutePath == 1) )
387 STRPTR end = FilePart(lf->filename);
388 UBYTE token = *end;
390 *end = '\0';
392 Printf(lf->filename);
394 /* Restore pathname */
395 *end = token;
397 break;
399 /* Fall through */
400 case 'N':
401 Printf(filename);
402 break;
404 /* File extension */
405 case 'E':
407 STRPTR extension = strrchr(filename, '.');
409 if (extension != NULL)
411 Printf(extension);
415 break;
417 /* Path name, but without volume */
418 case 'P':
420 STRPTR end = FilePart(lf->filename);
421 UBYTE token = *end;
423 *end = 0;
425 Printf(lf->filename);
427 /* Restore pathname */
428 *end = token;
431 break;
433 case 0:
434 return 0;
435 break;
437 default:
438 Printf("%%%lc", *format);
439 break;
442 else
444 Printf("%lc", c);
448 return 0;
452 int printFileData(struct AnchorPath *ap,
453 BOOL showFiles, BOOL showDirs, STRPTR parsedPattern,
454 ULONG *files, ULONG *dirs, ULONG *nBlocks, STRPTR lFormat,
455 BOOL quick, BOOL dates, BOOL noDates, BOOL block,
456 struct DateStamp *sinceDate, struct DateStamp *uptoDate,
457 BOOL doSince, BOOL doUpto, STRPTR subpatternStr,
458 BOOL keys)
460 STRPTR filename = ap->ap_Buf;
461 BOOL isDir = (ap->ap_Info.fib_DirEntryType >= 0);
462 struct DateStamp *ds = &ap->ap_Info.fib_Date;
463 ULONG protection = ap->ap_Info.fib_Protection;
464 UQUAD size = ap->ap_Info.fib_Size;
465 STRPTR filenote = ap->ap_Info.fib_Comment;
466 LONG diskKey = ap->ap_Info.fib_DiskKey;
468 int error = 0;
470 UBYTE date[LEN_DATSTRING];
471 UBYTE time[LEN_DATSTRING];
472 UBYTE flags[8];
474 struct DateTime dt;
476 #if defined(ACTION_GET_FILE_SIZE64)
477 if (ap->ap_Info.fib_Size >= 0x7FFFFFFF)
479 BPTR flock = BNULL;
480 flock = Lock(filename, ACCESS_READ);
482 if (flock)
484 UQUAD *size_ptr = (UQUAD *)DoPkt(((struct FileLock *)flock)->fl_Task, ACTION_GET_FILE_SIZE64, (IPTR)flock, 0, 0, 0, 0);
485 if (size_ptr)
487 size = *size_ptr;
489 UnLock(flock);
492 #endif
493 /* Do the file match the time interval we are looking for?
494 (ARG_SINCE and ARG_UPTO) -- any combination of these may be
495 specified */
496 if ((doSince && (CompareDates(sinceDate, ds) < 0)) ||
497 (doUpto && (CompareDates(uptoDate, ds) > 0)))
499 return 0;
502 /* Does the filename match a certain pattern? (ARG_PAT) */
503 if (parsedPattern != NULL &&
504 !MatchPatternNoCase(parsedPattern, FilePart(filename)))
506 return 0;
509 /* Does a substring of the filename match a certain pattern? (ARG_SUB) */
510 if (subpatternStr != NULL &&
511 !MatchPatternNoCase(subpatternStr, FilePart(filename)))
513 return 0;
516 CopyMem(ds, &dt.dat_Stamp, sizeof(struct DateStamp));
517 dt.dat_Format = FORMAT_DOS;
518 dt.dat_Flags = DTF_SUBST;
519 dt.dat_StrDay = NULL;
520 dt.dat_StrDate = date;
521 dt.dat_StrTime = time;
522 DateToStr(&dt); /* returns 0 if invalid */
524 /* Convert the protection bits to a string */
525 flags[0] = protection & FIBF_SCRIPT ? 's' : '-';
526 flags[1] = protection & FIBF_PURE ? 'p' : '-';
527 flags[2] = protection & FIBF_ARCHIVE ? 'a' : '-';
529 /* The following flags are high-active! */
530 flags[3] = protection & FIBF_READ ? '-' : 'r';
531 flags[4] = protection & FIBF_WRITE ? '-' : 'w';
532 flags[5] = protection & FIBF_EXECUTE ? '-' : 'e';
533 flags[6] = protection & FIBF_DELETE ? '-' : 'd';
534 flags[7] = 0x00;
536 if (isDir)
538 if (showDirs)
540 ++*dirs;
541 ++*nBlocks; /* dir entry uses 1 block on AROS, 2 on OS31) */
543 if (lFormat != NULL)
545 struct lfstruct lf = { ap, isDir, date, time, flags, filename,
546 filenote, size, diskKey};
548 printLformat(lFormat, &lf);
549 Printf("\n");
551 else
553 D(bug("Found file %s\n", filename));
555 Printf("%-25s ", FilePart(filename));
557 if (!quick)
559 Printf(" <Dir> %7s ", flags);
562 if (!noDates && (!quick || dates))
564 Printf("%-11s %s", date, time);
567 Printf("\n");
571 else if (showFiles)
573 ++*files;
574 *nBlocks += roundUp(size, BLOCKSIZE);
576 if (lFormat != NULL)
578 struct lfstruct lf = { ap, isDir, date, time, flags, filename,
579 filenote, size, diskKey };
581 printLformat(lFormat, &lf);
582 Printf("\n");
584 else
586 Printf("%-25s ", FilePart(filename));
588 if (!quick)
590 if(keys)
592 char key[16];
593 int fill;
594 int i; /* Loop variable */
596 __sprintf(key, "%ld", (long)diskKey);
597 fill = 7 - strlen(key) - 2;
599 for (i = 0; i < fill; i++)
601 Printf(" ");
604 Printf("[%ld] ", diskKey);
606 else
608 if (0 != size)
610 UQUAD filesize = block ? roundUp(size, BLOCKSIZE) : size;
612 char buf[256];
613 buf[255] = '\0';
615 char *bufpos = &buf[254];
619 bufpos[0] = '0' + (filesize % 10);
620 filesize /= 10;
621 bufpos--;
622 } while (filesize);
624 Printf("%s", &bufpos[1]);
626 else
628 Printf(" empty ");
632 Printf("%7s ", flags);
635 if (!noDates && (!quick || dates))
637 Printf("%-11s %s", date, time);
640 if (!quick && (*filenote != 0))
642 Printf("\n: %s", filenote);
645 Printf("\n");
649 return error;
653 /* Print directory summary information */
654 void printSummary(CONST_STRPTR dirname, int files, int dirs, int nBlocks,
655 BOOL noHead, BOOL PrintEmpty)
658 if (noHead) return;
660 if (files || dirs)
663 if (files > 1)
664 Printf("%ld files", files);
665 else if (files > 0)
666 PutStr("1 file");
668 if( files && (dirs || nBlocks) ) PutStr(" - ");
670 if (dirs > 1)
671 Printf("%ld directories", dirs);
672 else if (dirs > 0)
673 PutStr("1 directory");
675 if( dirs && nBlocks ) PutStr(" - ");
677 if (nBlocks > 1)
678 Printf("%ld blocks used\n", nBlocks);
679 else if (nBlocks > 0)
680 PutStr("1 block used\n");
681 else PutStr("\n");
684 else if (PrintEmpty)
685 Printf("Directory \"%s\" is empty\n", dirname);
689 int listFile(CONST_STRPTR filename, BOOL showFiles, BOOL showDirs,
690 STRPTR parsedPattern, BOOL noHead, STRPTR lFormat, BOOL quick,
691 BOOL dates, BOOL noDates, BOOL block, struct DateStamp *sinceDate,
692 struct DateStamp *uptoDate, BOOL doSince, BOOL doUpto,
693 STRPTR subpatternStr, BOOL all, BOOL keys, Statistics *stats)
695 struct AnchorPath *ap;
696 struct List DirList, FreeDirNodeList;
697 struct DirNode *dirnode, *prev_dirnode = NULL;
699 ULONG files = 0;
700 ULONG dirs = 0;
701 ULONG nBlocks = 0;
702 LONG error;
704 NewList(&DirList);
705 NewList(&FreeDirNodeList);
709 ap = AllocVec(sizeof(struct AnchorPath) + MAX_PATH_LEN, MEMF_CLEAR);
711 if (ap == NULL)
713 return 0;
716 ap->ap_Strlen = MAX_PATH_LEN;
718 error = MatchFirst(filename, ap);
720 /* Explicitly named directory and not a pattern? --> enter dir */
722 if (0 == error)
724 if (!(ap->ap_Flags & APF_ITSWILD))
726 if (ap->ap_Info.fib_DirEntryType >= 0)
728 //error = printDirHeader(filename, noHead);
729 ap->ap_Flags |= APF_DODIR;
731 if (0 == error)
733 error = MatchNext(ap);
739 if (0 == error)
741 BOOL first = TRUE;
743 ap->ap_BreakBits = SIGBREAKF_CTRL_C;
744 if (FilePart(ap->ap_Buf) == ap->ap_Buf)
746 ap->ap_Flags &= ~APF_DirChanged;
752 ** There's something to show.
754 if (!(ap->ap_Flags & APF_DIDDIR))
756 if (ap->ap_Flags & APF_DirChanged)
758 STRPTR p;
759 UBYTE c;
761 if (!first) printSummary(filename, files, dirs, nBlocks, noHead, TRUE);
763 /* Update global statistics for (possible) ALL option */
764 stats->nFiles += files;
765 stats->nDirs += dirs;
766 stats->nBlocks += nBlocks;
768 files = 0;
769 dirs = 0;
770 nBlocks = 0;
772 p = PathPart(ap->ap_Buf);
773 c = *p;
774 *p = 0;
776 error = printDirHeader(ap->ap_Buf, noHead);
778 *p = c;
782 error = printFileData(ap,
783 showFiles,
784 showDirs,
785 parsedPattern,
786 &files,
787 &dirs,
788 &nBlocks,
789 lFormat,
790 quick,
791 dates,
792 noDates,
793 block,
794 sinceDate,
795 uptoDate,
796 doSince,
797 doUpto,
798 subpatternStr,
799 keys);
801 if (all && (ap->ap_Info.fib_DirEntryType >= 0))
803 if ((dirnode = AllocMem(sizeof(struct DirNode), MEMF_ANY)))
805 if ((dirnode->dirname = StrDup(ap->ap_Buf)))
807 Insert(&DirList, (struct Node *)dirnode,
808 (struct Node *)prev_dirnode);
810 prev_dirnode = dirnode;
812 else
814 FreeMem(dirnode, sizeof(struct DirNode));
820 error = MatchNext(ap);
822 first = FALSE;
824 } while (0 == error);
827 MatchEnd(ap);
829 FreeVec(ap);
831 if (error == ERROR_BREAK)
833 PrintFault(error, NULL);
836 if (error == ERROR_NO_MORE_ENTRIES)
838 error = 0;
841 if ((error == 0) || (error == ERROR_BREAK))
843 BOOL printEmpty = !(ap->ap_Flags & APF_ITSWILD);
844 printSummary(filename, files, dirs, nBlocks, noHead, printEmpty);
847 /* Update global statistics for (possible) ALL option */
848 stats->nFiles += files;
849 stats->nDirs += dirs;
850 stats->nBlocks += nBlocks;
852 files = 0;
853 dirs = 0;
854 nBlocks = 0;
857 if (error) break;
859 dirnode = (struct DirNode *)RemHead(&DirList);
861 if (dirnode != NULL)
863 filename = dirnode->dirname;
865 prev_dirnode = NULL;
867 /* do not free() dirnode, as we reference dirnode->dirname! */
869 AddTail(&FreeDirNodeList, (struct Node *)dirnode);
871 } while (dirnode);
873 while ((dirnode = (struct DirNode *)RemHead(&FreeDirNodeList)))
875 FreeVec(dirnode->dirname);
876 FreeMem(dirnode, sizeof(struct DirNode));
879 return error;
883 int __nocommandline;
885 int main(void)
887 IPTR args[NOOFARGS] =
889 (IPTR) NULL, // ARG_DIR
890 (IPTR) NULL, // ARG_PAT
891 FALSE, // ARG_KEYS
892 FALSE, // ARG_DATES
893 FALSE, // ARG_NODATES
894 (IPTR) NULL, // ARG_TO
895 (IPTR) NULL, // ARG_SUB
896 (IPTR) NULL, // ARG_SINCE
897 (IPTR) NULL, // ARG_UPTO
898 FALSE, // ARG_QUICK
899 FALSE, // ARG_BLOCK
900 FALSE, // ARG_NOHEAD
901 FALSE, // ARG_FILES
902 FALSE, // ARG_DIRS
903 FALSE, // ARG_LFORMAT
904 FALSE // ARG_ALL
906 static CONST_STRPTR default_directories[] = {(CONST_STRPTR)"", 0};
907 struct RDArgs *rda;
909 LONG result = RETURN_OK;
910 LONG error = 0;
911 STRPTR parsedPattern = NULL;
912 STRPTR subpatternStr = NULL;
913 BPTR oldOutput = BNULL;
915 Statistics stats = { 0, 0, 0 };
917 rda = ReadArgs(ARG_TEMPLATE, args, NULL);
919 if (rda != NULL)
921 CONST_STRPTR *directories = (CONST_STRPTR *)args[ARG_DIR];
922 STRPTR lFormat = (STRPTR)args[ARG_LFORMAT];
923 STRPTR pattern = (STRPTR)args[ARG_PAT];
924 STRPTR toFile = (STRPTR)args[ARG_TO];
925 STRPTR subStr = (STRPTR)args[ARG_SUB];
926 STRPTR since = (STRPTR)args[ARG_SINCE];
927 STRPTR upto = (STRPTR)args[ARG_UPTO];
928 BOOL files = (BOOL)args[ARG_FILES];
929 BOOL dirs = (BOOL)args[ARG_DIRS];
930 BOOL noDates = (BOOL)args[ARG_NODATES];
931 BOOL dates = (BOOL)args[ARG_DATES];
932 BOOL quick = (BOOL)args[ARG_QUICK];
933 BOOL noHead = (BOOL)args[ARG_NOHEAD];
934 BOOL block = (BOOL)args[ARG_BLOCK];
935 BOOL all = (BOOL)args[ARG_ALL];
936 BOOL keys = (BOOL)args[ARG_KEYS];
938 struct DateTime sinceDatetime;
939 struct DateTime uptoDatetime;
941 ULONG i; /* Loop variable */
943 if (since != NULL)
945 sinceDatetime.dat_StrDate = since;
946 sinceDatetime.dat_StrTime = NULL;
947 sinceDatetime.dat_Format = FORMAT_DEF;
948 sinceDatetime.dat_Flags = 0;
949 if (StrToDate(&sinceDatetime) == DOSFALSE)
951 FreeArgs(rda);
952 Printf("*** Illegal 'SINCE' parameter\n");
954 return RETURN_FAIL;
958 if (upto != NULL)
960 uptoDatetime.dat_StrDate = upto;
961 uptoDatetime.dat_StrTime = NULL;
962 uptoDatetime.dat_Format = FORMAT_DEF;
963 uptoDatetime.dat_Flags = 0;
965 if (StrToDate(&uptoDatetime) == DOSFALSE)
967 FreeArgs(rda);
968 Printf("*** Illegal 'UPTO' parameter\n");
970 return RETURN_FAIL;
974 if (subStr != NULL)
976 STRPTR subStrWithPat;
977 ULONG length = (strlen(subStr) + sizeof("#?#?"))*2 + 2;
979 subStrWithPat = AllocVec(length, MEMF_ANY);
981 if (subStrWithPat == NULL)
983 FreeArgs(rda);
984 PrintFault(IoErr(), "List");
986 return RETURN_FAIL;
989 strcpy(subStrWithPat, "#?");
990 strcat(subStrWithPat, subStr);
991 strcat(subStrWithPat, "#?");
993 subpatternStr = AllocVec(length, MEMF_ANY);
995 if (subpatternStr == NULL ||
996 ParsePatternNoCase(subStrWithPat, subpatternStr, length) == -1)
998 FreeVec(subStrWithPat);
999 FreeArgs(rda);
1000 PrintFault(IoErr(), "List");
1002 return RETURN_FAIL;
1005 FreeVec(subStrWithPat);
1009 if (pattern != NULL)
1011 ULONG length = strlen(pattern)*2 + 2;
1013 parsedPattern = AllocVec(length, MEMF_ANY);
1015 if (parsedPattern == NULL ||
1016 ParsePatternNoCase(pattern, parsedPattern, length) == -1)
1018 FreeVec(subpatternStr);
1019 FreeArgs(rda);
1021 return RETURN_FAIL;
1025 if (toFile != NULL)
1027 BPTR file = Open(toFile, MODE_NEWFILE);
1029 if (file == BNULL)
1031 FreeVec(subpatternStr);
1032 FreeVec(parsedPattern);
1033 FreeArgs(rda);
1034 PrintFault(IoErr(), "List");
1036 return RETURN_FAIL;
1038 oldOutput = SelectOutput(file);
1041 if (!files && !dirs)
1043 files = TRUE;
1044 dirs = TRUE;
1047 /* if (!dates && !noDates)
1049 dates = TRUE;
1052 if (lFormat)
1054 noHead = TRUE;
1057 if ((directories == NULL) || (*directories == NULL))
1059 directories = default_directories;
1062 for (i = 0; directories[i] != NULL; i++)
1064 error = listFile(directories[i], files, dirs, parsedPattern,
1065 noHead, lFormat, quick, dates, noDates,
1066 block, &sinceDatetime.dat_Stamp,
1067 &uptoDatetime.dat_Stamp, since != NULL,
1068 upto != NULL, subpatternStr, all, keys,
1069 &stats);
1071 if (error != 0)
1073 break;
1076 // Printf("\n");
1079 FreeArgs(rda);
1081 else
1083 error = IoErr();
1086 if ((BOOL)args[ARG_NOHEAD] == FALSE &&
1087 (BOOL)args[ARG_LFORMAT] == FALSE &&
1088 (BOOL)args[ARG_ALL] &&
1089 (stats.nFiles || stats.nDirs))
1091 Printf("\nTOTAL: %ld files - %ld directories - %ld blocks used\n",
1092 stats.nFiles, stats.nDirs, stats.nBlocks);
1096 if (error != 0)
1098 if (error == ERROR_BREAK)
1100 result = RETURN_WARN;
1102 else
1104 PrintFault(error, "List");
1105 result = RETURN_FAIL;
1109 if (parsedPattern != NULL)
1111 FreeVec(parsedPattern);
1114 if (subpatternStr != NULL)
1116 FreeVec(subpatternStr);
1119 if (oldOutput != BNULL)
1121 Close(SelectOutput(oldOutput));
1124 return result;