home *** CD-ROM | disk | FTP | other *** search
- RCS_ID_C "$Id: list.c,v 1.11 1993/09/17 07:54:01 ppessi Exp $";
- /*
- * list.c - build file list
- *
- * Author: ppessi <Pekka.Pessi@hut.fi>
- *
- * Copyright (c) 1992, 1993 Pekka Pessi
- *
- * Last modified: Fri Sep 17 07:15:11 1993 ppessi
- *
- */
-
- #include "ls.h"
- #include <dos/dosasl.h>
- #include <stdlib.h>
- #include <string.h>
- #include <limits.h>
-
- static struct ExAllList *
- balloc(struct ExAllList * list)
- {
- struct ExAllList * car = malloc(EXLISTSIZE);
- if (car) {
- car -> El_Next = list;
- }
- #ifndef NOMYDEBUG
- FPrintf(Stderr, "Balloc: %p -> %p\n", car, list);
- #endif
- return car;
- }
-
- void
- bfree(volatile struct ExAllList * list)
- {
- while (list) {
- volatile struct ExAllList * car = list;
- list = car->El_Next;
- free((struct ExAllList *)car);
- }
- }
-
- /* Filter to exlude .#? and icons (but Emacs info files, too) */
- static UBYTE filter_normal[] =
- { P_NOT, P_ORSTART, P_ANY, '.', 'I', 'N', 'F', 'O',
- P_ORNEXT, '.', P_ANY, P_OREND, P_NOTEND, '\0' };
- /* Filter to exclude icons */
- static UBYTE filter_dotted[] =
- { P_NOT, P_ORSTART, P_ANY, '.', 'I', 'N', 'F', 'O', P_OREND, P_NOTEND, '\0' };
-
- /*
- * Fill in an emulated ExAllData structure
- */
- static struct ExAllData *
- fill_ead(struct ExAllData *next, struct FileInfoBlock *fib,
- UBYTE *name, UWORD namelen)
- {
- next->ed_Next = NULL;
- next->ed_Name = (UBYTE *)(next+1);
- next->ed_Type = fib->fib_DirEntryType;
- next->ed_Size = fib->fib_Size;
- next->ed_Prot = fib->fib_Protection;
- next->ed_Days = fib->fib_Date.ds_Days;
- next->ed_Mins = fib->fib_Date.ds_Minute;
- next->ed_Ticks = fib->fib_Date.ds_Tick;
- next->ed_Comment = NULL;
- #ifdef FIBB_OTR_READ /* DOSVERSION >= 39 */
- #define FIB_OWNERUID(fib) (fib->fib_OwnerUID)
- #define FIB_OWNERGID(fib) (fib->fib_OwnerGID)
- #else
- #define FIB_OWNERUID(fib) ((WORD *)(fib->fib_Reserved))[0]
- #define FIB_OWNERGID(fib) ((WORD *)(fib->fib_Reserved))[1]
- #endif
- next->ed_OwnerUID = FIB_OWNERUID(fib); /* V39 */
- next->ed_OwnerGID = FIB_OWNERGID(fib); /* V39 */
- /* NONSTANDARD */
- next->ed_Key = fib->fib_DiskKey;
- next->ed_Blocks = fib->fib_NumBlocks;
-
- strcpy(next->ed_Name, name);
- next = (struct ExAllData *)(next->ed_Name + namelen + 1);
- /* pad to next long word */
- return (struct ExAllData *)
- ((UBYTE *)next + ((4 - (3 & (unsigned int)next)) & 3));
- }
-
- LONG
- myExAll(BPTR lock, struct ExAllData *buffer, long size, long data,
- struct ExAllControl *control)
- {
- struct FileInfoBlock *fib;
- struct ExAllData *prev = NULL;
-
- control->eac_Entries = 0;
-
- if (data <= ED_COMMENT)
- return ExAll(lock, buffer, size, data, control);
-
- if (!control->eac_LastKey) {
- fib = AllocDosObject(DOS_FIB, (struct TagItem *)NULL);
- control->eac_LastKey = (ULONG)fib;
- if (!Examine(lock, fib) || !ExNext(lock, fib)) {
- control->eac_LastKey = NULL;
- FreeDosObject(DOS_FIB, fib); /* does not touch IoErr */
- return DOSFALSE;
- }
- } else {
- fib = (struct FileInfoBlock *)control->eac_LastKey;
- }
-
- do {
- LONG nlen;
- if (control->eac_MatchString &&
- !MatchPatternNoCase(control->eac_MatchString, fib->fib_FileName)) {
- if (IoErr() == 0) continue;
- }
- nlen = strlen(fib->fib_FileName);
- if (nlen + sizeof(*buffer) > size) return DOSTRUE;
- if (prev)
- prev->ed_Next = buffer;
- control->eac_Entries++;
- buffer = fill_ead(prev = buffer, fib, fib->fib_FileName, nlen);
- size -= (UBYTE *)buffer - (UBYTE *)prev;
- } while (ExNext(lock, fib));
-
- control->eac_LastKey = NULL;
- FreeDosObject(DOS_FIB, fib);
- SetIoErr(ERROR_NO_MORE_ENTRIES);
- return DOSFALSE;
- }
-
- /*
- * listdir builds a ExAllList from directory name
- */
- struct ExAllList *
- listdir(char *name, struct options options)
- {
- struct ExAllList *newbuffer, *buffers;
- struct ExAllControl *cntrl;
- BPTR mylock;
- int entries = 0;
-
- long data =
- options.longformat ? ED_OWNER :
- (options.inode || options.kilos ? ED_BLK : ED_DATE);
-
- newbuffer = buffers = balloc(NULL);
- if (!buffers)
- return NULL;
-
- cntrl = (struct ExAllControl *)
- AllocDosObject(DOS_EXALLCONTROL, (struct TagItem *)NULL);
- if (!cntrl) {
- bfree(buffers);
- return NULL;
- }
-
- cntrl -> eac_LastKey = 0;
- cntrl -> eac_MatchString =
- (options.all ?
- NULL : (options.dotted ?
- filter_dotted : filter_normal));
- cntrl -> eac_MatchFunc = NULL;
-
- /* read whole directory */
- if (mylock = Lock((UBYTE *)name, SHARED_LOCK)) {
- LONG again;
-
- do {
- again = myExAll(mylock, &(newbuffer->El_Data), EXDATASIZE, data, cntrl);
- entries += cntrl->eac_Entries;
- if (again && cntrl->eac_Entries > 0 &&
- buffers && (buffers = balloc(newbuffer))) {
- newbuffer = buffers;
- }
- /* We loop until myExAll tells to stop */
- } while (again);
- if (IoErr() != ERROR_NO_MORE_ENTRIES)
- buffers = NULL;
- UnLock(mylock);
- } else {
- LONG code = IoErr();
- if (code) PrintFault(code, name);
- }
-
- if (buffers) {
- buffers->El_Number = entries;
- } else {
- bfree(newbuffer);
- }
-
- FreeDosObject(DOS_EXALLCONTROL, cntrl);
- return buffers;
- }
-
- /*
- * listpatterns builds an ExAllList from all command line arguments
- */
- struct ExAllList *
- listpatterns(int patc, char **patv, struct options options)
- {
- struct ExAllList *fbuffers = NULL;
- struct ExAllData *prev, *next;
- long entries = 0, left = 0, code;
- UBYTE *pat;
- struct AnchorPath *anchor = malloc(sizeof(struct AnchorPath) + MAXPATHLEN);
-
- if (!anchor) exit(RETURN_FAIL);
-
- anchor->ap_BreakBits = NULL;
- anchor->ap_Flags = APF_DODOT;
- anchor->ap_Strlen = MAXPATHLEN;
-
- for (; patc > 0; patv++, patc--) {
- pat = *patv;
- if (*pat == '.' && (*++pat == '.' || *pat == '/')) ++pat;
- if (code = MatchFirst(pat, anchor)) {
- PrintFault(code, *patv);
- continue;
- } else do {
- int namelen = strlen(anchor->ap_Buf);
- #ifndef NOMYDEBUG
- FPrintf(Stderr, "Adding file %s at %p\n", anchor->ap_Buf, next);
- #endif
- if (sizeof(struct ExAllData) + namelen > left) {
- /* Allocate new buffer for entry */
- if (!(fbuffers = balloc(fbuffers))) {
- MatchEnd(anchor);
- exit(RETURN_FAIL);
- }
- left = EXDATASIZE;
- next = &(fbuffers->El_Data);
- } else {
- prev->ed_Next = next; /* Initialized by the if clause! */
- }
- next = fill_ead(prev = next, &(anchor->ap_Info), anchor->ap_Buf, namelen);
- left -= (UBYTE *) next - (UBYTE *) prev;
- fbuffers->El_Number = ++entries;
- #ifndef NOMYDEBUG
- FPrintf(Stderr, "Next at %p\n", next);
- #endif
- } while (!MatchNext(anchor));
- MatchEnd(anchor);
- }
- free(anchor);
-
- if (entries == 0) {
- bfree(fbuffers);
- fbuffers = NULL;
- }
-
- return fbuffers;
- }
-