/* :ts=8 bk=0 * Filesystem routines (or, How To Find A File The Hard Way) */ #include #include #include "things.h" extern struct IOExtTD *diskreq; extern ULONG diskchangecount, *diskbuffer; findfile (name) /* Traverse the filesystem the hard way */ char *name; { register int err; register char *b, *e; char str[80]; strcpy (str, name); if (b = index (str, ':')) /* Ignore device names */ b++; else b = str; while (*b == '/') /* Ignore leading slashes */ b++; if (!*b) { /* Don't do anything if string is empty */ notice ("Badly formed filename."); return (0); } e = b; MotorOn (); GetSector (ROOTBLOCK); /* All paths are relative to the root */ while (e) { if (!*b) { notice ("Badly formed filename."); return (0); } if (e = index (b, '/')) *e = '\0'; if ((err = traverse (b, hash (b))) < 0) { switch (err) { case -1: notice ("Badly formed path."); break; case -2: notice ("File not found."); break; } return (0); } if (e) { skip: b = e+1; while (*b == '/') b++; } } drawfile (); MotorOff (); return (1); } traverse (str, hash) /* Indirect through the disk blocks */ char *str; int hash; { register int block; register char *file = (char *) &diskbuffer [NAME]; if (diskbuffer [TYPE] == T_SHORT && diskbuffer [SECONDARY_TYPE] == ST_FILE) /* Can't indirect out of a file */ return (-1); strupper (str); block = diskbuffer [hash]; for ever { if (!block) return (-2); /* No such file */ GetSector ((long) block); /* Force null termination in case BCPL doesn't do it */ file [*file + 1] = '\0'; strupper (file+1); /* Force to all upper case */ if (!strcmp (str, file+1)) /* Is this it? */ break; /* This ain't it; traverse hash chain */ block = diskbuffer [HASHCHAIN]; } return (1); } drawfile () /* Draw file's allocated sectors */ { register int i; /* * File control blocks are marked with pen 1, data blocks with pen 2. */ marksector (diskbuffer [HEADER_KEY], 1); if (diskbuffer [TYPE] == T_SHORT && diskbuffer [SECONDARY_TYPE] == ST_FILE) for ever { for (i=FH_BLOCKLIST; i>=FH_ENDLIST; i--) if (diskbuffer [i]) marksector (diskbuffer [i], 2); if (diskbuffer [EXTENSION]) { marksector (diskbuffer [EXTENSION], 1); GetSector (diskbuffer [EXTENSION]); } else break; } } strupper (str) register char *str; { while (*str) { *str = toupper (*str); str++; } } /* * The following routines were stolen from an RKM example by Bob Peck and * hacked up a bit. */ GetSector (sector) long sector; { LONG offset = sector * BLOCKSIZE; diskreq -> iotd_Req.io_Length = BLOCKSIZE; diskreq -> iotd_Req.io_Data = (APTR) diskbuffer; /* show where to put the data when read */ diskreq -> iotd_Req.io_Command = ETD_READ; /* check that disk not changed before reading */ diskreq -> iotd_Count = diskchangecount; /* convert from cylinder, head, sector to byte-offset value to get * right one (as dos and everyone else sees it)...*/ /* driver reads one CYLINDER at a time (head does not move for * 22 sequential sector reads, or better-put, head doesnt move for * 2 sequential full track reads.) */ diskreq -> iotd_Req.io_Offset = offset; DoIO (diskreq); return (0); } MotorOn() { /* TURN ON DISK MOTOR ... old motor state is returned in io_Actual */ diskreq -> iotd_Req.io_Length = 1; /* this says motor is to be turned on */ diskreq -> iotd_Req.io_Command = TD_MOTOR; /* do something with the motor */ DoIO (diskreq); return (0); } MotorOff() { diskreq -> iotd_Req.io_Length = 0; /* says that motor is to be turned on */ diskreq -> iotd_Req.io_Command = TD_MOTOR; /* do something with the motor */ DoIO (diskreq); return (0); } /* * The following code segment was thrown at the USENET by Neil Katin. * Thanks, Neil. */ hash (str) unsigned char *str; { int res; unsigned char *sp; unsigned c; res = strlen (str); for (sp = str; *sp; sp++) { c = *sp; if (c >= 'a' && c <= 'z') c = c - 'a' + 'A'; res = ((res * 13 + c) & 0x7ff); } return (res % 72 + DIR_HASHTAB); }