home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD1.bin / useful / comm / tcp / amitcp / src / util / ls / list.c next >
Encoding:
C/C++ Source or Header  |  1994-02-24  |  6.5 KB  |  253 lines

  1. RCS_ID_C "$Id: list.c,v 1.11 1993/09/17 07:54:01 ppessi Exp $";
  2. /*
  3.  * list.c - build file list 
  4.  *
  5.  * Author: ppessi <Pekka.Pessi@hut.fi>
  6.  *
  7.  * Copyright (c) 1992, 1993 Pekka Pessi
  8.  *
  9.  * Last modified: Fri Sep 17 07:15:11 1993 ppessi
  10.  *
  11.  */
  12.  
  13. #include "ls.h"
  14. #include <dos/dosasl.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <limits.h>
  18.  
  19. static struct ExAllList *
  20. balloc(struct ExAllList * list)
  21. {
  22.   struct ExAllList * car = malloc(EXLISTSIZE);
  23.   if (car) {
  24.     car -> El_Next = list;
  25.   } 
  26. #ifndef NOMYDEBUG 
  27.   FPrintf(Stderr, "Balloc: %p -> %p\n", car, list);
  28. #endif
  29.   return car;
  30. }
  31.  
  32. void
  33. bfree(volatile struct ExAllList * list)
  34. {
  35.   while (list) {
  36.     volatile struct ExAllList * car = list;
  37.     list = car->El_Next;
  38.     free((struct ExAllList *)car);
  39.   }
  40. }
  41.  
  42. /* Filter to exlude .#? and icons (but Emacs info files, too) */
  43. static UBYTE filter_normal[] = 
  44. { P_NOT, P_ORSTART, P_ANY, '.', 'I', 'N', 'F', 'O', 
  45.          P_ORNEXT,  '.', P_ANY, P_OREND, P_NOTEND, '\0' }; 
  46. /* Filter to exclude icons */
  47. static UBYTE filter_dotted[] = 
  48. { P_NOT, P_ORSTART, P_ANY, '.', 'I', 'N', 'F', 'O', P_OREND, P_NOTEND, '\0' }; 
  49.  
  50. /*
  51.  * Fill in an emulated ExAllData structure 
  52.  */
  53. static struct ExAllData *
  54. fill_ead(struct ExAllData *next, struct FileInfoBlock *fib, 
  55.     UBYTE *name, UWORD namelen)
  56. {
  57.   next->ed_Next = NULL;
  58.   next->ed_Name = (UBYTE *)(next+1);
  59.   next->ed_Type = fib->fib_DirEntryType;
  60.   next->ed_Size = fib->fib_Size;
  61.   next->ed_Prot = fib->fib_Protection;
  62.   next->ed_Days = fib->fib_Date.ds_Days;
  63.   next->ed_Mins = fib->fib_Date.ds_Minute;
  64.   next->ed_Ticks = fib->fib_Date.ds_Tick;
  65.   next->ed_Comment = NULL;
  66. #ifdef FIBB_OTR_READ /* DOSVERSION >= 39 */
  67. #define FIB_OWNERUID(fib)  (fib->fib_OwnerUID)
  68. #define FIB_OWNERGID(fib)  (fib->fib_OwnerGID)
  69. #else
  70. #define FIB_OWNERUID(fib) ((WORD *)(fib->fib_Reserved))[0]
  71. #define FIB_OWNERGID(fib) ((WORD *)(fib->fib_Reserved))[1]
  72. #endif
  73.   next->ed_OwnerUID = FIB_OWNERUID(fib); /* V39 */
  74.   next->ed_OwnerGID = FIB_OWNERGID(fib); /* V39 */
  75.   /* NONSTANDARD */
  76.   next->ed_Key = fib->fib_DiskKey; 
  77.   next->ed_Blocks = fib->fib_NumBlocks; 
  78.  
  79.   strcpy(next->ed_Name, name);
  80.   next = (struct ExAllData *)(next->ed_Name + namelen + 1);
  81.   /* pad to next long word */
  82.   return (struct ExAllData *)
  83.     ((UBYTE *)next + ((4 - (3 & (unsigned int)next)) & 3));
  84. }
  85.  
  86. LONG 
  87. myExAll(BPTR lock, struct ExAllData *buffer, long size, long data,
  88.        struct ExAllControl *control)
  89. {
  90.   struct FileInfoBlock *fib;
  91.   struct ExAllData *prev = NULL;
  92.  
  93.   control->eac_Entries = 0;
  94.  
  95.   if (data <= ED_COMMENT) 
  96.     return ExAll(lock, buffer, size, data, control);
  97.   
  98.   if (!control->eac_LastKey) {
  99.     fib = AllocDosObject(DOS_FIB, (struct TagItem *)NULL);
  100.     control->eac_LastKey = (ULONG)fib;
  101.     if (!Examine(lock, fib) || !ExNext(lock, fib)) {
  102.       control->eac_LastKey = NULL;
  103.       FreeDosObject(DOS_FIB, fib); /* does not touch IoErr */
  104.       return DOSFALSE;
  105.     }
  106.   } else {
  107.     fib = (struct FileInfoBlock *)control->eac_LastKey;
  108.   }
  109.  
  110.   do {
  111.     LONG nlen;
  112.     if (control->eac_MatchString &&
  113.     !MatchPatternNoCase(control->eac_MatchString, fib->fib_FileName)) {
  114.       if (IoErr() == 0) continue;
  115.     }
  116.     nlen = strlen(fib->fib_FileName);
  117.     if (nlen + sizeof(*buffer) > size) return DOSTRUE;
  118.     if (prev)
  119.       prev->ed_Next = buffer;
  120.     control->eac_Entries++;
  121.     buffer = fill_ead(prev = buffer, fib, fib->fib_FileName, nlen);
  122.     size -= (UBYTE *)buffer - (UBYTE *)prev;
  123.   } while (ExNext(lock, fib));
  124.  
  125.   control->eac_LastKey = NULL;
  126.   FreeDosObject(DOS_FIB, fib);
  127.   SetIoErr(ERROR_NO_MORE_ENTRIES);
  128.   return DOSFALSE;
  129. }
  130.  
  131. /*
  132.  * listdir builds a ExAllList from directory name
  133.  */
  134. struct ExAllList *
  135. listdir(char *name, struct options options)
  136. {
  137.   struct ExAllList *newbuffer, *buffers;
  138.   struct ExAllControl *cntrl;
  139.   BPTR mylock;
  140.   int entries = 0;
  141.  
  142.   long data = 
  143.     options.longformat ? ED_OWNER : 
  144.       (options.inode || options.kilos ? ED_BLK : ED_DATE);
  145.  
  146.   newbuffer = buffers = balloc(NULL);
  147.   if (!buffers)
  148.     return NULL;
  149.  
  150.   cntrl = (struct ExAllControl *) 
  151.     AllocDosObject(DOS_EXALLCONTROL, (struct TagItem *)NULL);
  152.   if (!cntrl) {
  153.     bfree(buffers);
  154.     return NULL;
  155.   }
  156.  
  157.   cntrl -> eac_LastKey = 0;
  158.   cntrl -> eac_MatchString = 
  159.     (options.all ? 
  160.      NULL : (options.dotted ? 
  161.          filter_dotted : filter_normal));
  162.   cntrl -> eac_MatchFunc = NULL;
  163.  
  164.   /* read whole directory */
  165.   if (mylock = Lock((UBYTE *)name, SHARED_LOCK)) {
  166.     LONG again;
  167.  
  168.     do {
  169.       again = myExAll(mylock, &(newbuffer->El_Data), EXDATASIZE, data, cntrl);
  170.       entries += cntrl->eac_Entries; 
  171.       if (again && cntrl->eac_Entries > 0 && 
  172.       buffers && (buffers = balloc(newbuffer))) {
  173.     newbuffer = buffers;
  174.       } 
  175.       /* We loop until myExAll tells to stop */
  176.     } while (again);
  177.     if (IoErr() != ERROR_NO_MORE_ENTRIES)
  178.       buffers = NULL;
  179.     UnLock(mylock);
  180.   } else {
  181.     LONG code = IoErr();
  182.     if (code) PrintFault(code, name);
  183.   }
  184.  
  185.   if (buffers) {
  186.     buffers->El_Number = entries;
  187.   } else {
  188.     bfree(newbuffer);
  189.   }
  190.  
  191.   FreeDosObject(DOS_EXALLCONTROL, cntrl);
  192.   return buffers;
  193. }
  194.  
  195. /*
  196.  * listpatterns builds an ExAllList from all command line arguments
  197.  */
  198. struct ExAllList *
  199.   listpatterns(int patc, char **patv, struct options options)
  200. {
  201.   struct ExAllList *fbuffers = NULL;
  202.   struct ExAllData *prev, *next;
  203.   long entries = 0, left = 0, code;
  204.   UBYTE *pat;
  205.   struct AnchorPath *anchor = malloc(sizeof(struct AnchorPath) + MAXPATHLEN);
  206.   
  207.   if (!anchor) exit(RETURN_FAIL);
  208.  
  209.   anchor->ap_BreakBits = NULL;
  210.   anchor->ap_Flags = APF_DODOT;
  211.   anchor->ap_Strlen = MAXPATHLEN;
  212.   
  213.   for (; patc > 0; patv++, patc--) {
  214.     pat = *patv;
  215.     if (*pat == '.' && (*++pat == '.' || *pat == '/')) ++pat;
  216.     if (code = MatchFirst(pat, anchor)) {
  217.       PrintFault(code, *patv);
  218.       continue;
  219.     } else do {
  220.       int namelen = strlen(anchor->ap_Buf);
  221. #ifndef NOMYDEBUG 
  222.       FPrintf(Stderr, "Adding file %s at %p\n", anchor->ap_Buf, next);
  223. #endif
  224.       if (sizeof(struct ExAllData) + namelen > left) {
  225.     /* Allocate new buffer for entry */
  226.     if (!(fbuffers = balloc(fbuffers))) {
  227.       MatchEnd(anchor);
  228.       exit(RETURN_FAIL);
  229.     }
  230.     left = EXDATASIZE; 
  231.     next = &(fbuffers->El_Data);
  232.       } else {
  233.     prev->ed_Next = next;    /* Initialized by the if clause! */
  234.       }
  235.       next = fill_ead(prev = next, &(anchor->ap_Info), anchor->ap_Buf, namelen);
  236.       left -= (UBYTE *) next - (UBYTE *) prev;
  237.       fbuffers->El_Number = ++entries;
  238. #ifndef NOMYDEBUG 
  239.       FPrintf(Stderr, "Next at %p\n", next);
  240. #endif
  241.     } while (!MatchNext(anchor));
  242.     MatchEnd(anchor);
  243.   }
  244.   free(anchor);
  245.  
  246.   if (entries == 0) {
  247.     bfree(fbuffers);
  248.     fbuffers = NULL;
  249.   }
  250.  
  251.   return fbuffers;
  252. }
  253.