Annotation of MiNT/src/tosfs.c, revision 1.1.1.6

1.1       root        1: /*
                      2: 
1.1.1.3   root        3: Copyright 1991,1992 Eric R. Smith.
                      4: 
1.1.1.5   root        5: Copyright 1992,1993,1994 Atari Corporation.
1.1.1.3   root        6: 
                      7: All rights reserved.
1.1       root        8: 
                      9: */
                     10: 
                     11: 
                     12: 
                     13: /* a VERY simple tosfs.c 
                     14: 
                     15:  * this one is extremely brain-damaged, but will serve OK for a
                     16: 
                     17:  * skeleton in which to put a "real" tosfs.c
                     18: 
                     19:  */
                     20: 
                     21: 
                     22: 
                     23: #include "mint.h"
                     24: 
                     25: 
                     26: 
1.1.1.3   root       27: /* if NEWWAY is defined, tosfs uses the new dup_cookie/release_cookie
                     28: 
                     29:  * protocol to keep track of file cookies, instead of the old
                     30: 
                     31:  * method of "timing"
                     32: 
                     33:  */
                     34: 
                     35: /* #define NEWWAY */
                     36: 
                     37: #if 0
                     38: 
                     39: #define COOKIE_DB(x) DEBUG(x)
                     40: 
                     41: #else
                     42: 
                     43: #define COOKIE_DB(x)
                     44: 
                     45: #endif
                     46: 
                     47: 
                     48: 
                     49: /* if RO_FASCISM is defined, the read/write modes are enforced. This is
                     50: 
                     51:  * a Good Thing, not fascist at all. Ask Allan Pratt why he chose
                     52: 
                     53:  * that name sometime.
                     54: 
                     55:  */
                     56: 
                     57: #define RO_FASCISM
                     58: 
                     59: 
                     60: 
                     61: /* temporary code for debugging Falcon media change bug */
                     62: 
                     63: #if 0
                     64: 
                     65: #define MEDIA_DB(x) DEBUG(x)
                     66: 
                     67: #else
                     68: 
                     69: #define MEDIA_DB(x)
                     70: 
                     71: #endif
                     72: 
                     73: 
                     74: 
1.1       root       75: /* search mask for anything OTHER THAN a volume label */
                     76: 
                     77: #define FILEORDIR 0x37
                     78: 
                     79: 
                     80: 
                     81: char tmpbuf[PATH_MAX+1];
                     82: 
                     83: 
                     84: 
1.1.1.2   root       85: static long    ARGS_ON_STACK tos_root  P_((int drv, fcookie *fc));
1.1       root       86: 
1.1.1.2   root       87: static long    ARGS_ON_STACK tos_lookup        P_((fcookie *dir, const char *name, fcookie *fc));
1.1       root       88: 
1.1.1.2   root       89: static long    ARGS_ON_STACK tos_getxattr      P_((fcookie *fc, XATTR *xattr));
1.1       root       90: 
1.1.1.2   root       91: static long    ARGS_ON_STACK tos_chattr        P_((fcookie *fc, int attrib));
1.1       root       92: 
1.1.1.2   root       93: static long    ARGS_ON_STACK tos_chown P_((fcookie *fc, int uid, int gid));
1.1       root       94: 
1.1.1.2   root       95: static long    ARGS_ON_STACK tos_chmode        P_((fcookie *fc, unsigned mode));
1.1       root       96: 
1.1.1.2   root       97: static long    ARGS_ON_STACK tos_mkdir P_((fcookie *dir, const char *name, unsigned mode));
1.1       root       98: 
1.1.1.2   root       99: static long    ARGS_ON_STACK tos_rmdir P_((fcookie *dir, const char *name));
1.1       root      100: 
1.1.1.2   root      101: static long    ARGS_ON_STACK tos_remove        P_((fcookie *dir, const char *name));
1.1       root      102: 
1.1.1.3   root      103: static long    ARGS_ON_STACK tos_getname       P_((fcookie *root, fcookie *dir,
                    104: 
                    105:                                                    char *pathname, int size));
1.1       root      106: 
1.1.1.2   root      107: static long    ARGS_ON_STACK tos_rename        P_((fcookie *olddir, char *oldname,
1.1       root      108: 
                    109:                                    fcookie *newdir, const char *newname));
                    110: 
1.1.1.2   root      111: static long    ARGS_ON_STACK tos_opendir       P_((DIR *dirh, int flags));
1.1       root      112: 
1.1.1.2   root      113: static long    ARGS_ON_STACK tos_readdir       P_((DIR *dirh, char *nm, int nmlen, fcookie *));
1.1       root      114: 
1.1.1.2   root      115: static long    ARGS_ON_STACK tos_rewinddir     P_((DIR *dirh));
1.1       root      116: 
1.1.1.2   root      117: static long    ARGS_ON_STACK tos_closedir      P_((DIR *dirh));
1.1       root      118: 
1.1.1.2   root      119: static long    ARGS_ON_STACK tos_pathconf      P_((fcookie *dir, int which));
1.1       root      120: 
1.1.1.2   root      121: static long    ARGS_ON_STACK tos_dfree P_((fcookie *dir, long *buf));
1.1       root      122: 
1.1.1.2   root      123: static long    ARGS_ON_STACK tos_writelabel    P_((fcookie *dir, const char *name));
1.1       root      124: 
1.1.1.2   root      125: static long    ARGS_ON_STACK tos_readlabel     P_((fcookie *dir, char *name, int namelen));
1.1       root      126: 
                    127: 
                    128: 
1.1.1.2   root      129: static long    ARGS_ON_STACK tos_creat P_((fcookie *dir, const char *name, unsigned mode,
1.1       root      130: 
                    131:                                    int attrib, fcookie *fc));
                    132: 
1.1.1.2   root      133: static DEVDRV *        ARGS_ON_STACK tos_getdev        P_((fcookie *fc, long *devsp));
1.1       root      134: 
1.1.1.2   root      135: static long    ARGS_ON_STACK tos_open  P_((FILEPTR *f));
1.1       root      136: 
1.1.1.2   root      137: static long    ARGS_ON_STACK tos_write P_((FILEPTR *f, const char *buf, long bytes));
1.1       root      138: 
1.1.1.2   root      139: static long    ARGS_ON_STACK tos_read  P_((FILEPTR *f, char *buf, long bytes));
1.1       root      140: 
1.1.1.2   root      141: static long    ARGS_ON_STACK tos_lseek P_((FILEPTR *f, long where, int whence));
1.1       root      142: 
1.1.1.2   root      143: static long    ARGS_ON_STACK tos_ioctl P_((FILEPTR *f, int mode, void *buf));
1.1       root      144: 
1.1.1.2   root      145: static long    ARGS_ON_STACK tos_datime        P_((FILEPTR *f, short *time, int rwflag));
1.1       root      146: 
1.1.1.2   root      147: static long    ARGS_ON_STACK tos_close P_((FILEPTR *f, int pid));
1.1       root      148: 
1.1.1.2   root      149: static long    ARGS_ON_STACK tos_dskchng       P_((int drv));
1.1       root      150: 
                    151: 
                    152: 
1.1.1.3   root      153: #ifdef NEWWAY
                    154: 
                    155: static long    ARGS_ON_STACK tos_release P_((fcookie *fc));
                    156: 
                    157: static long    ARGS_ON_STACK tos_dupcookie P_((fcookie *dst, fcookie *src));
                    158: 
                    159: #endif
                    160: 
                    161: 
                    162: 
1.1       root      163: /* some routines from biosfs.c */
                    164: 
1.1.1.2   root      165: extern long    ARGS_ON_STACK null_select       P_((FILEPTR *f, long p, int mode));
1.1       root      166: 
1.1.1.2   root      167: extern void    ARGS_ON_STACK null_unselect     P_((FILEPTR *f, long p, int mode));
1.1       root      168: 
                    169: 
                    170: 
                    171: DEVDRV tos_device = {
                    172: 
                    173:        tos_open, tos_write, tos_read, tos_lseek, tos_ioctl, tos_datime,
                    174: 
                    175:        tos_close, null_select, null_unselect
                    176: 
                    177: };
                    178: 
                    179: 
                    180: 
                    181: FILESYS tos_filesys = {
                    182: 
                    183:        (FILESYS *)0,
                    184: 
1.1.1.3   root      185:        FS_KNOPARSE | FS_NOXBIT | FS_LONGPATH,
1.1       root      186: 
                    187:        tos_root,
                    188: 
                    189:        tos_lookup, tos_creat, tos_getdev, tos_getxattr,
                    190: 
                    191:        tos_chattr, tos_chown, tos_chmode,
                    192: 
                    193:        tos_mkdir, tos_rmdir, tos_remove, tos_getname, tos_rename,
                    194: 
                    195:        tos_opendir, tos_readdir, tos_rewinddir, tos_closedir,
                    196: 
                    197:        tos_pathconf, tos_dfree, tos_writelabel, tos_readlabel,
                    198: 
1.1.1.3   root      199:        nosymlink, noreadlink, nohardlink, nofscntl, tos_dskchng,
                    200: 
                    201: #ifdef NEWWAY
                    202: 
                    203:        tos_release, tos_dupcookie
                    204: 
                    205: #else
                    206: 
                    207:        0, 0
                    208: 
                    209: #endif
1.1       root      210: 
                    211: };
                    212: 
                    213: 
                    214: 
                    215: /* some utility functions and variables: see end of file */
                    216: 
                    217: static DTABUF  *lastdta;       /* last DTA buffer we asked TOS about */
                    218: 
                    219: static DTABUF  foo;
                    220: 
                    221: static void do_setdta P_((DTABUF *dta));
                    222: 
                    223: static int executable_extension P_((char *));
                    224: 
                    225: 
                    226: 
                    227: /* this array keeps track of which drives have been changed */
                    228: 
                    229: /* a nonzero entry means that the corresponding drive has been changed,
                    230: 
                    231:  * but GEMDOS doesn't know it yet
                    232: 
                    233:  */
                    234: 
                    235: static char drvchanged[NUM_DRIVES];
                    236: 
                    237: 
                    238: 
                    239: /* force TOS to see a media change */
                    240: 
                    241: static void force_mediach P_((int drv));
                    242: 
1.1.1.2   root      243: static long ARGS_ON_STACK Newgetbpb P_((int));
1.1       root      244: 
1.1.1.2   root      245: static long ARGS_ON_STACK Newmediach P_((int));
1.1       root      246: 
1.1.1.2   root      247: static long ARGS_ON_STACK Newrwabs P_((int, void *, int, int, int, long));
1.1       root      248: 
                    249: 
                    250: 
1.1.1.3   root      251: #ifdef NEWWAY
                    252: 
                    253: #define NUM_INDICES 64
                    254: 
                    255: #else
                    256: 
1.1       root      257: #define NUM_INDICES 128
                    258: 
                    259: #define MIN_AGE 8
                    260: 
1.1.1.3   root      261: #endif
                    262: 
1.1       root      263: 
                    264: 
                    265: struct tindex {
                    266: 
                    267:        char *name;             /* full path name */
                    268: 
                    269:        FILEPTR *open;          /* fileptrs for this file; OR
                    270: 
                    271:                                 * count of number of open directories
                    272: 
                    273:                                 */
                    274: 
                    275:        LOCK *locks;            /* locks on this file */
                    276: 
                    277: /* file status */
                    278: 
                    279:        long  size;
                    280: 
                    281:        short time;
                    282: 
                    283:        short date;
                    284: 
                    285:        short attr;
                    286: 
                    287:        short valid;            /* 1 if the above status is still valid */
                    288: 
1.1.1.3   root      289: #ifdef NEWWAY
                    290: 
                    291:        short links;            /* how many times index is in use */
                    292: 
                    293: #else
                    294: 
1.1       root      295:        short stamp;            /* age of this index, for garbage collection */
                    296: 
1.1.1.3   root      297: #endif
                    298: 
1.1       root      299: } gl_ti[NUM_INDICES];
                    300: 
                    301: 
                    302: 
                    303: /* temporary index for files found by readdir */
                    304: 
                    305: static struct tindex tmpindex;
                    306: 
                    307: static char tmpiname[PATH_MAX];
                    308: 
                    309: 
                    310: 
                    311: static struct tindex *tstrindex P_((char *s));
                    312: 
                    313: static int tfullpath P_((char *result, struct tindex *base, const char *name));
                    314: 
                    315: static struct tindex *garbage_collect P_((void));
                    316: 
                    317: 
                    318: 
1.1.1.3   root      319: #ifndef NEWWAY
                    320: 
1.1       root      321: static short tclock;           /* #calls to tfullpath since last garbage
                    322: 
                    323:                                   collection */
                    324: 
1.1.1.3   root      325: #endif
                    326: 
1.1       root      327: 
                    328: 
1.1.1.6 ! root      329: 
        !           330: 
        !           331: #define ROOTPERMS 32
        !           332: 
        !           333: #ifdef ROOTPERMS
        !           334: 
        !           335: /* jr: save access permissions, owner and group for root directories.
        !           336: 
        !           337:    ROOTPERMS is the number of supported drives; 'mode' has ROOTPERMSET
        !           338: 
        !           339:    if it has been set  */
        !           340: 
        !           341: 
        !           342: 
        !           343: struct tosrootperm {
        !           344: 
        !           345:        ushort uid, gid, mode;
        !           346: 
        !           347: } root_perms[ROOTPERMS];
        !           348: 
        !           349: 
        !           350: 
        !           351: #define ROOTPERMSET    0x8000
        !           352: 
        !           353: #endif
        !           354: 
        !           355: 
        !           356: 
        !           357: /* jr: external table, set up by getbpb in bios.c */
        !           358: 
        !           359: extern unsigned short clsizb[];
        !           360: 
        !           361: 
        !           362: 
        !           363: #define INODE_PER_CRC
        !           364: 
        !           365: 
        !           366: 
        !           367: #ifdef INODE_PER_CRC
        !           368: 
        !           369: 
        !           370: 
        !           371: /* jr: use crc algorithm described in P1003.2, D11.2 with crctab as in
        !           372: 
        !           373:    GNU-cksum. Slightly modified to return 0 for the root (instead of ~0) */
        !           374: 
        !           375: 
        !           376: 
        !           377: static unsigned long crctab[] = { /* CRC polynomial 0xedb88320 */
        !           378: 
        !           379: 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
        !           380: 
        !           381: 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
        !           382: 
        !           383: 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
        !           384: 
        !           385: 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
        !           386: 
        !           387: 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
        !           388: 
        !           389: 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
        !           390: 
        !           391: 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
        !           392: 
        !           393: 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
        !           394: 
        !           395: 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
        !           396: 
        !           397: 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
        !           398: 
        !           399: 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
        !           400: 
        !           401: 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
        !           402: 
        !           403: 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
        !           404: 
        !           405: 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
        !           406: 
        !           407: 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
        !           408: 
        !           409: 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
        !           410: 
        !           411: 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
        !           412: 
        !           413: 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
        !           414: 
        !           415: 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
        !           416: 
        !           417: 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
        !           418: 
        !           419: 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
        !           420: 
        !           421: 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
        !           422: 
        !           423: 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
        !           424: 
        !           425: 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
        !           426: 
        !           427: 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
        !           428: 
        !           429: 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
        !           430: 
        !           431: 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
        !           432: 
        !           433: 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
        !           434: 
        !           435: 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
        !           436: 
        !           437: 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
        !           438: 
        !           439: 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
        !           440: 
        !           441: 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
        !           442: 
        !           443: };
        !           444: 
        !           445: 
        !           446: 
        !           447: #define UPDC32(octet, crc) (((crc) << 8) ^ crctab[((crc) >> 24) ^ (octet)])
        !           448: 
        !           449: 
        !           450: 
        !           451: static unsigned long
        !           452: 
        !           453: filename_crc (const char *filename)
        !           454: 
        !           455: {
        !           456: 
        !           457:        unsigned long s = 0;
        !           458: 
        !           459:        unsigned int n = 0;
        !           460: 
        !           461:        
        !           462: 
        !           463:        /* skip x: */
        !           464: 
        !           465:        filename += 2;
        !           466: 
        !           467:        
        !           468: 
        !           469:        while (*filename) {
        !           470: 
        !           471:                s = UPDC32 (*filename++, s);
        !           472: 
        !           473:                n++;
        !           474: 
        !           475:        }
        !           476: 
        !           477: 
        !           478: 
        !           479:        while (n != 0) {
        !           480: 
        !           481:                s = UPDC32 (n & 0377, s);
        !           482: 
        !           483:                n >>= 8;
        !           484: 
        !           485:        }
        !           486: 
        !           487:        
        !           488: 
        !           489:        return s;
        !           490: 
        !           491: }
        !           492: 
        !           493: 
        !           494: 
        !           495: #endif
        !           496: 
        !           497: 
        !           498: 
        !           499: 
        !           500: 
1.1       root      501: /* some extra flags for the attr field */
                    502: 
                    503: 
                    504: 
                    505: /*
                    506: 
                    507:  * is a string the name of a file with executable extension?
                    508: 
                    509:  */
                    510: 
                    511: #define FA_EXEC 0x4000
                    512: 
                    513: /*
                    514: 
                    515:  * should the file be deleted when it is closed?
                    516: 
                    517:  */
                    518: 
                    519: #define FA_DELETE 0x2000
                    520: 
                    521: 
                    522: 
                    523: /*
                    524: 
                    525:  * NOTE: call executable_extension only on a DTA name returned from
                    526: 
1.1.1.3   root      527:  * Fsfirst(), not on an arbitrary path, for two reasons: (1) it
                    528: 
                    529:  * expects only upper case, and (2) it looks only for the 1st extension,
                    530: 
                    531:  * so a folder with a '.' in its name would confuse it.
1.1       root      532: 
                    533:  */
                    534: 
                    535: 
                    536: 
                    537: static int
                    538: 
                    539: executable_extension(s)
                    540: 
                    541:        char *s;
                    542: 
                    543: {
                    544: 
                    545:        while (*s && *s != '.') s++;
                    546: 
                    547:        if (!*s) return 0;
                    548: 
                    549:        s++;
                    550: 
                    551:        if (s[0] == 'T') {
                    552: 
                    553:                return (s[1] == 'T' && s[2] == 'P') ||
                    554: 
                    555:                       (s[1] == 'O' && s[2] == 'S');
                    556: 
                    557:        }
                    558: 
                    559:        if (s[0] == 'P')
                    560: 
                    561:                return s[1] == 'R' && s[2] == 'G';
                    562: 
                    563:        if (s[0] == 'A')
                    564: 
                    565:                return s[1] == 'P' && s[2] == 'P';
                    566: 
                    567:        if (s[0] == 'G')
                    568: 
                    569:                return s[1] == 'T' && s[2] == 'P';
                    570: 
                    571:        return 0;
                    572: 
                    573: }
                    574: 
                    575: 
                    576: 
                    577: /*
                    578: 
                    579:  * Look in the table of tos indices to see if an index corresponding
                    580: 
                    581:  * to this file name already exists. If so, mark it as being used
                    582: 
                    583:  * and return it. If not, find an empty slot and make an index for
                    584: 
                    585:  * this string. If no empty slots exist, garbage collect and
                    586: 
                    587:  * try again.
                    588: 
                    589:  *
                    590: 
                    591:  * This routine is pretty dumb; we really should use a hash table
                    592: 
                    593:  * of some sort
                    594: 
                    595:  */
                    596: 
                    597: 
                    598: 
                    599: static struct tindex *tstrindex(s)
                    600: 
                    601:        char *s;
                    602: 
                    603: {
                    604: 
                    605:        int i;
                    606: 
                    607:        char *r;
                    608: 
                    609:        struct tindex *t, *free = 0;
                    610: 
                    611: 
                    612: 
                    613:        assert(s != 0);
                    614: 
                    615:        t = gl_ti;
                    616: 
                    617:        for (i = 0; i < NUM_INDICES; i++, t++) {
                    618: 
                    619:                if (t->name && !stricmp(t->name, s)) {
                    620: 
1.1.1.3   root      621: #ifndef NEWWAY
                    622: 
1.1       root      623:                        t->stamp = tclock;      /* update use time */
                    624: 
1.1.1.3   root      625: #endif
                    626: 
1.1       root      627:                        return t;
                    628: 
                    629:                }
                    630: 
                    631:                else if (!t->name && !free)
                    632: 
                    633:                        free = t;
                    634: 
                    635:        }
                    636: 
                    637:        if (!free) {
                    638: 
                    639:                free = garbage_collect();
                    640: 
                    641:        }
                    642: 
1.1.1.3   root      643: #ifdef NEWWAY
                    644: 
                    645:        if (!free) {
                    646: 
                    647:                FORCE("tosfs: all slots in use!!");
                    648: 
                    649:                FORCE("Links\tName");
                    650: 
                    651:                t = gl_ti;
                    652: 
                    653:                for (i = 0; i < NUM_INDICES; i++,t++) {
                    654: 
                    655:                        FORCE("%d\t%s", t->links, t->name);
                    656: 
                    657:                }
                    658: 
                    659:                FATAL("tosfs: unable to get a file name index");
                    660: 
                    661:        }
                    662: 
                    663: #else
                    664: 
1.1       root      665:        if (!free) {
                    666: 
                    667:                FATAL("tosfs: unable to get a file name index");
                    668: 
                    669:        }
                    670: 
1.1.1.3   root      671: #endif
                    672: 
1.1       root      673:        r = kmalloc((long)strlen(s)+1);
                    674: 
                    675:        if (!r) {
                    676: 
                    677:                FATAL("tosfs: unable to allocate space for a file name");
                    678: 
                    679:        }
                    680: 
                    681:        strcpy(r, s);
                    682: 
                    683:        free->name = r;
                    684: 
1.1.1.3   root      685: #ifdef NEWWAY
                    686: 
                    687:        free->links = 0;
                    688: 
                    689: #else
                    690: 
1.1       root      691:        free->stamp = tclock;
                    692: 
1.1.1.3   root      693: #endif
                    694: 
1.1       root      695:        free->open = 0;
                    696: 
                    697:        free->locks = 0;
                    698: 
                    699: 
                    700: 
                    701: /* check to see if this file was recently returned by opendir() */
                    702: 
1.1.1.3   root      703: #ifndef NEWWAY
                    704: 
1.1       root      705:        if (tmpindex.valid && tclock - tmpindex.stamp < MIN_AGE &&
                    706: 
                    707:            !stricmp(free->name, tmpindex.name)) {
                    708: 
                    709:                free->size = tmpindex.size;
                    710: 
                    711:                free->time = tmpindex.time;
                    712: 
                    713:                free->date = tmpindex.date;
                    714: 
                    715:                free->attr = tmpindex.attr;
                    716: 
                    717:                free->valid = 1;
                    718: 
                    719:                tmpindex.valid = 0;
                    720: 
                    721:        } else
                    722: 
1.1.1.3   root      723: #endif
                    724: 
1.1.1.6 ! root      725:        {
        !           726: 
1.1       root      727:                free->valid = 0;
                    728: 
1.1.1.6 ! root      729:                free->attr = 0;
        !           730: 
        !           731:        }
        !           732: 
1.1       root      733:        return free;
                    734: 
                    735: }
                    736: 
                    737: 
                    738: 
                    739: /*
                    740: 
                    741:  * garbage collection routine: for any TOS index older than MIN_AGE,
                    742: 
                    743:  * check through all current processes to see if it's in use. If
                    744: 
                    745:  * not, free the corresponding string.
                    746: 
                    747:  * Returns: a pointer to a newly freed index, or NULL.
                    748: 
                    749:  */
                    750: 
                    751: 
                    752: 
                    753: /* it's unlikely that the kernel would need to hold onto a file cookie
                    754: 
                    755:    for longer than this many calls to tstrindex() without first
                    756: 
                    757:    saving the cookie in a directory or file pointer
                    758: 
                    759:  */
                    760: 
                    761: 
                    762: 
                    763: static struct tindex *
                    764: 
                    765: garbage_collect()
                    766: 
                    767: {
                    768: 
                    769:        struct tindex *free, *t;
                    770: 
1.1.1.3   root      771:        int i;
                    772: 
                    773: #ifndef NEWWAY
                    774: 
1.1       root      775:        fcookie *fc, *gc;
                    776: 
                    777:        PROC *p;
                    778: 
1.1.1.3   root      779:        int j;
1.1       root      780: 
                    781:        int age;
                    782: 
1.1.1.3   root      783: #endif
                    784: 
1.1       root      785: 
                    786: 
                    787:        free = 0;
                    788: 
                    789:        t = gl_ti;
                    790: 
                    791:        for (i = 0; i < NUM_INDICES; i++,t++) {
                    792: 
                    793:                if (!t->name) continue;
                    794: 
1.1.1.3   root      795: #ifdef NEWWAY
                    796: 
                    797:                if (t->links == 0) {
                    798: 
                    799:                        kfree(t->name);
                    800: 
                    801:                        t->name = 0;
                    802: 
                    803:                        if (!free) free = t;
                    804: 
                    805:                }
                    806: 
                    807: #else
                    808: 
1.1       root      809:                age = tclock - t->stamp;
                    810: 
                    811:                t->stamp = 0;
                    812: 
                    813:                assert(age >= 0);
                    814: 
                    815:                if (age > MIN_AGE) {
                    816: 
                    817:                /* see if any process is using this index */
                    818: 
                    819:                        if (t->open)
                    820: 
                    821:                                goto found_index;
                    822: 
                    823:                        for (p = proclist; p; p = p->gl_next) {
                    824: 
                    825:                                fc = p->curdir;
                    826: 
                    827:                                gc = p->root;
                    828: 
                    829:                                for (j = 0; j < NUM_DRIVES; j++,fc++,gc++) {
                    830: 
                    831:                                        if (( fc->fs == &tos_filesys &&
                    832: 
                    833:                                              fc->index == (long)t ) ||
                    834: 
                    835:                                            ( gc->fs == &tos_filesys &&
                    836: 
                    837:                                              gc->index == (long)t ) )
                    838: 
                    839:                                                goto found_index;
                    840: 
                    841:                                }
                    842: 
                    843:                        }
                    844: 
                    845:                /* here, we couldn't find the index in use by any proc. */
                    846: 
                    847:                        kfree(t->name);
                    848: 
                    849:                        t->name = 0;
                    850: 
                    851:                        if (!free)
                    852: 
                    853:                                free = t;
                    854: 
                    855:                found_index:
                    856: 
                    857:                        ;
                    858: 
                    859:                } else {
                    860: 
                    861:        /* make sure that future garbage collections might look at this file */
                    862: 
                    863:                        t->stamp = -age;
                    864: 
                    865:                }
                    866: 
1.1.1.3   root      867: #endif
                    868: 
1.1       root      869:        }
                    870: 
                    871: 
                    872: 
1.1.1.3   root      873: #ifndef NEWWAY
                    874: 
1.1       root      875:        tclock = 0;     /* reset the clock */
                    876: 
                    877:        tmpindex.valid = 0; /* expire the temporary Fsfirst buffer */
                    878: 
1.1.1.3   root      879: #endif
                    880: 
1.1       root      881:        return free;
                    882: 
                    883: }
                    884: 
                    885: 
                    886: 
                    887: #define DIRSEP(c) ((c) == '\\')
                    888: 
                    889: 
                    890: 
                    891: static int
                    892: 
                    893: tfullpath(result, basei, path)
                    894: 
                    895:        char *result;
                    896: 
                    897:        struct tindex *basei;
                    898: 
                    899:        const char *path;
                    900: 
                    901: {
                    902: 
                    903: #define TNMTEMP 32
                    904: 
                    905:        char *n, name[TNMTEMP+1];
                    906: 
                    907:        int namelen, pathlen;
                    908: 
                    909:        char *base = basei->name;
                    910: 
                    911:        int r = 0;
                    912: 
                    913: 
                    914: 
1.1.1.3   root      915: #ifndef NEWWAY
                    916: 
1.1       root      917:        basei->stamp = ++tclock;
                    918: 
                    919:        if (tclock > 10000) {
                    920: 
                    921:        /* garbage collect every so often whether we need it or not */
                    922: 
                    923:                (void)garbage_collect();
                    924: 
                    925:        }
                    926: 
1.1.1.3   root      927: #endif
                    928: 
1.1       root      929:        if (!*path) {
                    930: 
                    931:                strncpy(result, base, PATH_MAX-1);
                    932: 
                    933:                return r;
                    934: 
                    935:        }
                    936: 
                    937: 
                    938: 
                    939:        strncpy(result, base, PATH_MAX-1);
                    940: 
                    941: 
                    942: 
                    943:        pathlen = strlen(result);
                    944: 
                    945: 
                    946: 
                    947: /* now path is relative to what's currently in "result" */
                    948: 
                    949: 
                    950: 
                    951:        while(*path) {
                    952: 
                    953: /* get next name in path */
                    954: 
                    955:                n = name; namelen = 0;
                    956: 
                    957:                while (*path && !DIRSEP(*path)) {
                    958: 
                    959: /* BUG: we really should to the translation to DOS 8.3
                    960: 
                    961:  * format *here*, so that really long names are truncated
                    962: 
                    963:  * correctly.
                    964: 
                    965:  */
                    966: 
                    967:                        if (namelen < TNMTEMP) {
                    968: 
                    969:                                *n++ = toupper(*path); path++; namelen++;
                    970: 
                    971:                        }
                    972: 
                    973:                        else
                    974: 
                    975:                                path++;
                    976: 
                    977:                }
                    978: 
1.1.1.2   root      979:                *n = 0;
1.1       root      980: 
                    981:                while (DIRSEP(*path)) path++;
                    982: 
                    983: /* check for "." and ".." */
                    984: 
                    985:                if (!strcmp(name, ".")) continue;
                    986: 
                    987:                if (!strcmp(name, "..")) {
                    988: 
                    989:                        n = strrchr(result, '\\');
                    990: 
                    991:                        if (n) {
                    992: 
                    993:                                *n = 0;
                    994: 
1.1.1.2   root      995:                                pathlen = (int)(n - result);
1.1       root      996: 
                    997:                        }
                    998: 
                    999:                        else r = EMOUNT;
                   1000: 
                   1001:                        continue;
                   1002: 
                   1003:                }
                   1004: 
                   1005:                if (pathlen + namelen < PATH_MAX - 1) {
                   1006: 
                   1007:                        strcat(result, "\\");
                   1008: 
                   1009:                        pathlen++;
                   1010: 
                   1011: 
                   1012: 
                   1013:        /* make sure the name is restricted to DOS 8.3 format */
                   1014: 
                   1015:                        for (base = result; *base; base++)
                   1016: 
                   1017:                                ;
                   1018: 
                   1019:                        n = name;
                   1020: 
                   1021:                        namelen = 0;
                   1022: 
                   1023:                        while (*n && *n != '.' && namelen++ < 8) {
                   1024: 
                   1025:                                *base++ = *n++;
                   1026: 
                   1027:                                pathlen++;
                   1028: 
                   1029:                        }
                   1030: 
                   1031:                        while (*n && *n != '.') n++;
                   1032: 
                   1033:                        if (*n == '.' && *(n+1) != 0) {
                   1034: 
                   1035:                                *base++ = *n++;
                   1036: 
                   1037:                                pathlen++;
                   1038: 
                   1039:                                namelen = 0;
                   1040: 
                   1041:                                while (*n && namelen++ < 3) {
                   1042: 
                   1043:                                        *base++ = *n++;
                   1044: 
                   1045:                                        pathlen++;
                   1046: 
                   1047:                                }
                   1048: 
                   1049:                        }
                   1050: 
                   1051:                        *base = 0;
                   1052: 
                   1053:                }
                   1054: 
                   1055:        }
                   1056: 
                   1057:        return r;
                   1058: 
                   1059: }
                   1060: 
                   1061: 
                   1062: 
1.1.1.2   root     1063: static long ARGS_ON_STACK 
1.1       root     1064: 
                   1065: tos_root(drv, fc)
                   1066: 
                   1067:        int drv;
                   1068: 
                   1069:        fcookie *fc;
                   1070: 
                   1071: {
                   1072: 
                   1073:        struct tindex *ti;
                   1074: 
                   1075: 
                   1076: 
                   1077:        ksprintf(tmpbuf, "%c:", drv+'A');
                   1078: 
                   1079:        fc->fs = &tos_filesys;
                   1080: 
                   1081:        fc->dev = drv;
                   1082: 
                   1083:        ti = tstrindex(tmpbuf);
                   1084: 
                   1085:        ti->size = ti->date = ti->time = 0;
                   1086: 
                   1087:        ti->attr = FA_DIR;
                   1088: 
                   1089:        ti->valid = 1;
                   1090: 
                   1091:        fc->index = (long)ti;
                   1092: 
                   1093: 
                   1094: 
                   1095: /* if the drive has changed, make sure GEMDOS knows it! */
                   1096: 
                   1097:        if (drvchanged[drv]) {
                   1098: 
                   1099:                force_mediach(drv);
                   1100: 
                   1101:        }
                   1102: 
1.1.1.3   root     1103: #ifdef NEWWAY
                   1104: 
                   1105:        ti->links++;
                   1106: 
                   1107: #endif
                   1108: 
1.1       root     1109:        return 0;
                   1110: 
                   1111: }
                   1112: 
                   1113: 
                   1114: 
1.1.1.2   root     1115: static long ARGS_ON_STACK 
1.1       root     1116: 
                   1117: tos_lookup(dir, name, fc)
                   1118: 
                   1119:        fcookie *dir;
                   1120: 
                   1121:        const char *name;
                   1122: 
                   1123:        fcookie *fc;
                   1124: 
                   1125: {
                   1126: 
                   1127:        long r;
                   1128: 
                   1129:        struct tindex *ti = (struct tindex *)dir->index;
                   1130: 
                   1131: 
                   1132: 
                   1133:        r = tfullpath(tmpbuf, ti, name);
                   1134: 
                   1135: 
                   1136: 
                   1137: /* if the name is empty or otherwise trivial, just return the directory */
                   1138: 
                   1139:        if (!strcmp(ti->name, tmpbuf)) {
                   1140: 
                   1141:                *fc = *dir;
                   1142: 
1.1.1.3   root     1143: #ifdef NEWWAY
                   1144: 
                   1145:                ti->links++;
                   1146: 
                   1147:                COOKIE_DB(("tos_lookup: %s now has %d links", ti->name, ti->links));
                   1148: 
                   1149: #endif 
                   1150: 
1.1       root     1151:                return r;
                   1152: 
                   1153:        }
                   1154: 
                   1155: 
                   1156: 
                   1157: /* is there already an index for this file?? If so, is it up to date?? */
                   1158: 
                   1159:        ti = tstrindex(tmpbuf);
                   1160: 
                   1161:        if (!ti->valid) {
                   1162: 
                   1163:                if (tmpbuf[1] == ':' && tmpbuf[2] == 0) {
                   1164: 
                   1165:                        /* a root directory -- lookup always succeeds */
                   1166: 
                   1167:                        foo.dta_size = 0;
                   1168: 
                   1169:                        foo.dta_date = foo.dta_time = 0;
                   1170: 
                   1171:                        foo.dta_attrib = FA_DIR;
                   1172: 
                   1173:                        foo.dta_name[0] = 0;
                   1174: 
                   1175:                } else {
                   1176: 
                   1177:                        do_setdta(&foo);
                   1178: 
                   1179:                        r = Fsfirst(tmpbuf, FILEORDIR);
                   1180: 
                   1181:                        if (r) {
                   1182: 
1.1.1.2   root     1183: DEBUG(("tos_lookup: Fsfirst(%s) returned %ld", tmpbuf, r));
1.1       root     1184: 
                   1185:                                return r;
                   1186: 
                   1187:                        }
                   1188: 
                   1189:                }
                   1190: 
                   1191:                ti->size = foo.dta_size;
                   1192: 
                   1193:                ti->date = foo.dta_date;
                   1194: 
                   1195:                ti->time = foo.dta_time;
                   1196: 
1.1.1.6 ! root     1197:                ti->attr = foo.dta_attrib | (ti->attr & FA_DELETE);
1.1       root     1198: 
                   1199:                if (executable_extension(foo.dta_name))
                   1200: 
                   1201:                        ti->attr |= FA_EXEC;
                   1202: 
                   1203:                ti->valid = 1;
                   1204: 
                   1205:        }
                   1206: 
                   1207:        fc->fs = &tos_filesys;
                   1208: 
                   1209:        fc->index = (long)ti;
                   1210: 
                   1211:        fc->dev = dir->dev;
                   1212: 
1.1.1.3   root     1213: #ifdef NEWWAY
                   1214: 
                   1215:        ti->links++;
                   1216: 
                   1217:        COOKIE_DB(("tos_lookup: %s now has %d links", ti->name, ti->links));
                   1218: 
                   1219: #endif
                   1220: 
1.1       root     1221:        return r;
                   1222: 
                   1223: }
                   1224: 
                   1225: 
                   1226: 
1.1.1.2   root     1227: static long ARGS_ON_STACK 
1.1       root     1228: 
                   1229: tos_getxattr(fc, xattr)
                   1230: 
                   1231:        fcookie *fc;
                   1232: 
                   1233:        XATTR *xattr;
                   1234: 
                   1235: {
                   1236: 
                   1237:        struct tindex *ti = (struct tindex *)fc->index;
                   1238: 
                   1239:        long r;
                   1240: 
1.1.1.6 ! root     1241: #ifndef INODE_PER_CRC
        !          1242: 
1.1       root     1243:        static long junkindex = 0;
                   1244: 
1.1.1.6 ! root     1245: #endif
        !          1246: 
        !          1247: #ifdef ROOTPERMS
        !          1248: 
        !          1249:        struct tosrootperm *tp = NULL;
1.1       root     1250: 
1.1.1.6 ! root     1251:        
        !          1252: 
        !          1253:        if (fc->dev < ROOTPERMS) tp = &root_perms[fc->dev];
        !          1254: 
        !          1255: #endif
        !          1256: 
        !          1257: 
        !          1258: 
        !          1259: #ifdef INODE_PER_CRC
        !          1260: 
        !          1261:        xattr->index = filename_crc (ti->name);
        !          1262: 
        !          1263: #else
1.1       root     1264: 
                   1265:        xattr->index = junkindex++;
                   1266: 
1.1.1.6 ! root     1267: #endif
        !          1268: 
        !          1269: 
        !          1270: 
1.1       root     1271:        xattr->dev = fc->dev;
                   1272: 
1.1.1.5   root     1273:        xattr->rdev = fc->dev;
                   1274: 
1.1       root     1275:        xattr->nlink = 1;
                   1276: 
1.1.1.6 ! root     1277: 
        !          1278: 
1.1       root     1279:        xattr->uid = xattr->gid = 0;
                   1280: 
                   1281: 
                   1282: 
1.1.1.6 ! root     1283: #ifdef ROOTPERMS
        !          1284: 
        !          1285:        if (tp) {
        !          1286: 
        !          1287:                xattr->uid = tp->uid;
        !          1288: 
        !          1289:                xattr->gid = tp->gid;
        !          1290: 
        !          1291:        }
        !          1292: 
        !          1293: #endif
        !          1294: 
        !          1295: 
        !          1296: 
1.1.1.3   root     1297: #ifndef NEWWAY
                   1298: 
1.1       root     1299:        ti->stamp = ++tclock;
                   1300: 
1.1.1.3   root     1301: #endif
                   1302: 
                   1303: 
                   1304: 
1.1       root     1305:        if (!ti->valid) {
                   1306: 
                   1307:                do_setdta(&foo);
                   1308: 
                   1309:                if (ti->name[2] == 0) {         /* a root directory */
                   1310: 
                   1311: /* actually, this can also happen if a program tries to open a file
                   1312: 
                   1313:  * with an empty name... so we should fail gracefully
                   1314: 
                   1315:  */
                   1316: 
1.1.1.3   root     1317:                        ti->attr = FA_DIR;
                   1318: 
                   1319:                        ti->size = 0;
                   1320: 
                   1321:                        ti->date = ti->time = 0;
                   1322: 
1.1       root     1323:                        goto around;
                   1324: 
                   1325:                }
                   1326: 
                   1327:        
                   1328: 
                   1329:                r = Fsfirst(ti->name, FILEORDIR);
                   1330: 
1.1.1.3   root     1331:                if (r) {
                   1332: 
                   1333:                        DEBUG(("tosfs: search error %ld on [%s]", r, ti->name));
1.1       root     1334: 
1.1.1.3   root     1335:                        return r;
                   1336: 
                   1337:                }
1.1       root     1338: 
                   1339:                ti->size = foo.dta_size;
                   1340: 
                   1341:                ti->date = foo.dta_date;
                   1342: 
                   1343:                ti->time = foo.dta_time;
                   1344: 
1.1.1.6 ! root     1345:                ti->attr = foo.dta_attrib | (ti->attr & FA_DELETE);
1.1       root     1346: 
                   1347:                if (executable_extension(foo.dta_name))
                   1348: 
                   1349:                        ti->attr |= FA_EXEC;
                   1350: 
                   1351: around:
                   1352: 
                   1353:                ti->valid = 1;
                   1354: 
                   1355:        }
                   1356: 
                   1357:        xattr->size = ti->size;
                   1358: 
                   1359: 
                   1360: 
1.1.1.6 ! root     1361:        /* jr: if cluster size unknown, do a getbpb once */
        !          1362: 
        !          1363:        if (fc->dev < 32 && ! clsizb[fc->dev])
        !          1364: 
        !          1365:                getbpb (fc->dev);
        !          1366: 
        !          1367: 
1.1       root     1368: 
                   1369:        xattr->blksize = 1024;
                   1370: 
1.1.1.6 ! root     1371:        if (fc->dev < 32 && clsizb[fc->dev])
        !          1372: 
        !          1373:                xattr->blksize = clsizb[fc->dev];
        !          1374: 
        !          1375:        
        !          1376: 
        !          1377:        xattr->nblocks = (xattr->size + xattr->blksize - 1) / xattr->blksize;
1.1       root     1378: 
                   1379:        xattr->mdate = xattr->cdate = xattr->adate = ti->date;
                   1380: 
                   1381:        xattr->mtime = xattr->ctime = xattr->atime = ti->time;
                   1382: 
                   1383:        xattr->mode = (ti->attr & FA_DIR) ? (S_IFDIR | DEFAULT_DIRMODE) :
                   1384: 
                   1385:                         (S_IFREG | DEFAULT_MODE);
                   1386: 
                   1387: 
                   1388: 
1.1.1.5   root     1389: /* TOS files have permissions rwxrwx--- */
                   1390: 
                   1391:        xattr->mode &= ~(S_IROTH|S_IWOTH|S_IXOTH);
                   1392: 
                   1393: 
                   1394: 
1.1.1.6 ! root     1395: #ifdef ROOTPERMS
        !          1396: 
        !          1397:        /* when root permissions are set, use them. For regular files,
        !          1398: 
        !          1399:        unmask x bits */
        !          1400: 
        !          1401: 
        !          1402: 
        !          1403:        if (tp && (tp->mode & ROOTPERMSET)) {
        !          1404: 
        !          1405:                xattr->mode &= ~DEFAULT_DIRMODE;
        !          1406: 
        !          1407:                xattr->mode |= (tp->mode & DEFAULT_DIRMODE);
        !          1408: 
        !          1409: 
        !          1410: 
        !          1411:                if (! (ti->attr & FA_DIR))
        !          1412: 
        !          1413:                        xattr->mode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
        !          1414: 
        !          1415:        }
        !          1416: 
        !          1417: #endif
        !          1418: 
        !          1419: 
        !          1420: 
1.1       root     1421:        if (ti->attr & FA_RDONLY) {
                   1422: 
                   1423:                xattr->mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
                   1424: 
                   1425:        }
                   1426: 
                   1427: 
                   1428: 
                   1429:        if (ti->attr & FA_EXEC) {
                   1430: 
                   1431:                xattr->mode |= (S_IXUSR|S_IXGRP|S_IXOTH);
                   1432: 
                   1433:        }
                   1434: 
1.1.1.6 ! root     1435: 
        !          1436: 
1.1       root     1437:        xattr->attr = ti->attr & 0xff;
                   1438: 
                   1439:        return 0;
                   1440: 
                   1441: }
                   1442: 
                   1443: 
                   1444: 
1.1.1.2   root     1445: static long ARGS_ON_STACK
1.1       root     1446: 
                   1447: tos_chattr(fc, attrib)
                   1448: 
                   1449:        fcookie *fc;
                   1450: 
                   1451:        int attrib;
                   1452: 
                   1453: {
                   1454: 
                   1455:        struct tindex *ti = (struct tindex *)fc->index;
                   1456: 
                   1457: 
                   1458: 
                   1459:        if (ti->attr & FA_DIR) {
                   1460: 
1.1.1.2   root     1461:                DEBUG(("error: attempt to change attributes of a directory"));
1.1       root     1462: 
                   1463:                return EACCDN;
                   1464: 
                   1465:        }
                   1466: 
                   1467:        ti->valid = 0;
                   1468: 
                   1469:        (void)tfullpath(tmpbuf, ti, "");
                   1470: 
                   1471:        return Fattrib(tmpbuf, 1, attrib);
                   1472: 
                   1473: }
                   1474: 
                   1475: 
                   1476: 
1.1.1.2   root     1477: static long ARGS_ON_STACK 
1.1       root     1478: 
                   1479: tos_chown(dir, uid, gid)
                   1480: 
                   1481:        fcookie *dir;
                   1482: 
                   1483:        int uid, gid;
                   1484: 
                   1485: {
                   1486: 
1.1.1.6 ! root     1487: #ifdef ROOTPERMS
        !          1488: 
        !          1489:        struct tindex *ti = (struct tindex *)dir->index;
        !          1490: 
        !          1491: 
        !          1492: 
        !          1493:        if (dir->dev < ROOTPERMS)
        !          1494: 
        !          1495:                if (ti->name[2] == '\0')        /* root? */
        !          1496: 
        !          1497:                {
        !          1498: 
        !          1499:                        root_perms[dir->dev].uid = uid;
        !          1500: 
        !          1501:                        root_perms[dir->dev].gid = gid;
        !          1502: 
        !          1503:                        return 0;       
        !          1504: 
        !          1505:                }
        !          1506: 
        !          1507:        
        !          1508: 
        !          1509:        return EINVFN;
        !          1510: 
        !          1511:        
        !          1512: 
        !          1513: #else
        !          1514: 
1.1.1.2   root     1515:        UNUSED(dir); UNUSED(uid); UNUSED(gid);
                   1516: 
1.1       root     1517:        return EINVFN;
                   1518: 
1.1.1.6 ! root     1519: #endif
        !          1520: 
1.1       root     1521: }
                   1522: 
                   1523: 
                   1524: 
1.1.1.2   root     1525: static long ARGS_ON_STACK 
1.1       root     1526: 
                   1527: tos_chmode(fc, mode)
                   1528: 
                   1529:        fcookie *fc;
                   1530: 
                   1531:        unsigned mode;
                   1532: 
                   1533: {
                   1534: 
                   1535:        int oldattr, newattr;
                   1536: 
                   1537:        long r;
                   1538: 
                   1539:        struct tindex *ti = (struct tindex *)fc->index;
                   1540: 
                   1541: 
                   1542: 
1.1.1.6 ! root     1543: #ifdef ROOTPERMS
        !          1544: 
        !          1545:        if (fc->dev < ROOTPERMS) {
        !          1546: 
        !          1547:                if (ti->name[2] == '\0') {
        !          1548: 
        !          1549:                        /* root? */
        !          1550: 
        !          1551:                        root_perms[fc->dev].mode = ROOTPERMSET | mode;
        !          1552: 
        !          1553:                        return 0;
        !          1554: 
        !          1555:                }
        !          1556: 
        !          1557:        }
        !          1558: 
        !          1559: #endif
        !          1560: 
        !          1561: 
        !          1562: 
1.1       root     1563:        oldattr = Fattrib(ti->name, 0, 0);
                   1564: 
                   1565:        if (oldattr < 0)
                   1566: 
                   1567:                return oldattr;
                   1568: 
                   1569: 
                   1570: 
                   1571:        ti->valid = 0;
                   1572: 
                   1573: 
                   1574: 
                   1575:        if (!(mode & S_IWUSR))
                   1576: 
                   1577:                newattr = oldattr | FA_RDONLY;
                   1578: 
                   1579:        else
                   1580: 
                   1581:                newattr = oldattr & ~FA_RDONLY;
                   1582: 
                   1583:        if (newattr != oldattr)
                   1584: 
                   1585:                r = Fattrib(ti->name, 1, newattr);
                   1586: 
                   1587:        else
                   1588: 
                   1589:                r = 0;
                   1590: 
                   1591:        return (r < 0) ? r : 0;
                   1592: 
                   1593: }
                   1594: 
                   1595: 
                   1596: 
1.1.1.2   root     1597: static long ARGS_ON_STACK 
1.1       root     1598: 
                   1599: tos_mkdir(dir, name, mode)
                   1600: 
                   1601:        fcookie *dir;
                   1602: 
                   1603:        const char *name;
                   1604: 
                   1605:        unsigned mode;          /* ignored under TOS */
                   1606: 
                   1607: {
                   1608: 
1.1.1.2   root     1609:        UNUSED(mode);
                   1610: 
                   1611: 
                   1612: 
1.1       root     1613:        (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
                   1614: 
                   1615:        tmpindex.valid = 0;
                   1616: 
                   1617: 
                   1618: 
                   1619:        return Dcreate(tmpbuf);
                   1620: 
                   1621: }
                   1622: 
                   1623: 
                   1624: 
1.1.1.2   root     1625: static long ARGS_ON_STACK 
1.1       root     1626: 
                   1627: tos_rmdir(dir, name)
                   1628: 
                   1629:        fcookie *dir;
                   1630: 
                   1631:        const char *name;
                   1632: 
                   1633: {
                   1634: 
                   1635:        struct tindex *ti;
                   1636: 
                   1637: 
                   1638: 
                   1639:        (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
                   1640: 
                   1641:        ti = tstrindex(tmpbuf);
                   1642: 
                   1643:        ti->valid = 0;
                   1644: 
                   1645: 
                   1646: 
                   1647:        return Ddelete(tmpbuf);
                   1648: 
                   1649: }
                   1650: 
                   1651: 
                   1652: 
1.1.1.2   root     1653: static long ARGS_ON_STACK 
1.1       root     1654: 
                   1655: tos_remove(dir, name)
                   1656: 
                   1657:        fcookie *dir;
                   1658: 
                   1659:        const char *name;
                   1660: 
                   1661: {
                   1662: 
                   1663:        struct tindex *ti;
                   1664: 
                   1665: 
                   1666: 
                   1667:        (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
                   1668: 
                   1669: 
                   1670: 
                   1671:        ti = tstrindex(tmpbuf);
                   1672: 
                   1673:        if (ti->open) {
                   1674: 
1.1.1.2   root     1675:                DEBUG(("tos_remove: file is open, will be deleted later"));
1.1       root     1676: 
                   1677:                if (ti->attr & FA_RDONLY)
                   1678: 
                   1679:                        return EACCDN;
                   1680: 
                   1681:                ti->attr |= FA_DELETE;
                   1682: 
                   1683:                return 0;
                   1684: 
                   1685:        }
                   1686: 
                   1687:        ti->valid = 0;
                   1688: 
                   1689:        return Fdelete(tmpbuf);
                   1690: 
                   1691: }
                   1692: 
                   1693: 
                   1694: 
1.1.1.2   root     1695: static long ARGS_ON_STACK 
1.1       root     1696: 
1.1.1.3   root     1697: tos_getname(root, dir, pathname, size)
1.1       root     1698: 
                   1699:        fcookie *root, *dir;
                   1700: 
                   1701:        char *pathname;
                   1702: 
1.1.1.3   root     1703:        int size;
                   1704: 
1.1       root     1705: {
                   1706: 
1.1.1.2   root     1707:        char *rootnam = ((struct tindex *)root->index)->name;
                   1708: 
                   1709:        char *dirnam = ((struct tindex *)dir->index)->name;
                   1710: 
                   1711:        int i;
                   1712: 
1.1       root     1713: 
                   1714: 
1.1.1.2   root     1715:        i = strlen(rootnam);
1.1       root     1716: 
1.1.1.3   root     1717:        if (strlen(dirnam) < i) {
                   1718: 
                   1719:                DEBUG(("tos_getname: root is longer than path"));
1.1       root     1720: 
1.1.1.3   root     1721:                return EINTRN;
1.1       root     1722: 
1.1.1.3   root     1723:        }
1.1.1.2   root     1724: 
1.1.1.3   root     1725:        if (strlen(dirnam+i) < size) {
                   1726: 
                   1727:                strcpy(pathname, dirnam + i);
1.1.1.2   root     1728: 
                   1729: /*
                   1730: 
                   1731:  * BUG: must be a better way to decide upper/lower case
                   1732: 
                   1733:  */
                   1734: 
                   1735:                if (curproc->domain == DOM_MINT)
                   1736: 
                   1737:                        strlwr(pathname);
                   1738: 
1.1.1.3   root     1739:                return 0;
1.1       root     1740: 
1.1.1.3   root     1741:        } else {
                   1742: 
                   1743:                DEBUG(("tosfs: name too long"));
                   1744: 
                   1745:                return ERANGE;
                   1746: 
                   1747:        }
1.1       root     1748: 
                   1749: }
                   1750: 
                   1751: 
                   1752: 
1.1.1.2   root     1753: static long ARGS_ON_STACK 
1.1       root     1754: 
                   1755: tos_rename(olddir, oldname, newdir, newname)
                   1756: 
                   1757:        fcookie *olddir;
                   1758: 
                   1759:        char *oldname;
                   1760: 
                   1761:        fcookie *newdir;
                   1762: 
                   1763:        const char *newname;
                   1764: 
                   1765: {
                   1766: 
                   1767:        char newbuf[128];
                   1768: 
                   1769:        struct tindex *ti;
                   1770: 
                   1771:        long r;
                   1772: 
                   1773: 
                   1774: 
                   1775:        (void)tfullpath(tmpbuf, (struct tindex *)olddir->index, oldname);
                   1776: 
                   1777:        (void)tfullpath(newbuf, (struct tindex *)newdir->index, newname);
                   1778: 
                   1779:        r = Frename(0, tmpbuf, newbuf);
                   1780: 
                   1781:        if (r == 0) {
                   1782: 
                   1783:                ti = tstrindex(tmpbuf);
                   1784: 
                   1785:                kfree(ti->name);
                   1786: 
                   1787:                ti->name = kmalloc((long)strlen(newbuf)+1);
                   1788: 
                   1789:                if (!ti->name) {
                   1790: 
                   1791:                        FATAL("tosfs: unable to allocate space for a name");
                   1792: 
                   1793:                }
                   1794: 
                   1795:                strcpy(ti->name, newbuf);
                   1796: 
                   1797:                ti->valid = 0;
                   1798: 
                   1799:        }
                   1800: 
                   1801:        return r;
                   1802: 
                   1803: }
                   1804: 
                   1805: 
                   1806: 
                   1807: #define DIR_FLAG(x)    (x->fsstuff[0])
                   1808: 
                   1809: #define STARTSEARCH    0       /* opendir() was just called */
                   1810: 
                   1811: #define INSEARCH       1       /* readdir() has been called at least once */
                   1812: 
                   1813: #define NMFILE         2       /* no more files to read */
                   1814: 
                   1815: 
                   1816: 
                   1817: #define DIR_DTA(x)     ((DTABUF *)(x->fsstuff + 2))
                   1818: 
                   1819: #define DIR_NAME(x)    (x->fsstuff + 32)
                   1820: 
                   1821: 
                   1822: 
                   1823: /*
                   1824: 
                   1825:  * The directory functions are a bit tricky. What we do is have
                   1826: 
                   1827:  * opendir() do Fsfirst; the first readdir() picks up this name,
                   1828: 
                   1829:  * subsequent readdir()'s have to do Fsnext
                   1830: 
                   1831:  */
                   1832: 
                   1833: 
                   1834: 
1.1.1.2   root     1835: static long ARGS_ON_STACK 
1.1       root     1836: 
                   1837: tos_opendir(dirh, flags)
                   1838: 
                   1839:        DIR *dirh;
                   1840: 
                   1841:        int flags;
                   1842: 
                   1843: {
                   1844: 
                   1845:        long r;
                   1846: 
                   1847:        struct tindex *t = (struct tindex *)dirh->fc.index;
                   1848: 
                   1849: 
                   1850: 
1.1.1.2   root     1851:        UNUSED(flags);
                   1852: 
                   1853: 
                   1854: 
1.1       root     1855:        (void)tfullpath(tmpbuf, t, "*.*");
                   1856: 
                   1857: 
                   1858: 
                   1859:        do_setdta(DIR_DTA(dirh));
                   1860: 
                   1861: 
                   1862: 
                   1863:        r = Fsfirst(tmpbuf, FILEORDIR);
                   1864: 
                   1865: 
                   1866: 
                   1867:        if (r == 0) {
                   1868: 
                   1869:                t->open++;
                   1870: 
                   1871:                DIR_FLAG(dirh) = STARTSEARCH;
                   1872: 
                   1873:                return 0;
                   1874: 
                   1875:        } else if (r == EFILNF) {
                   1876: 
                   1877:                t->open++;
                   1878: 
                   1879:                DIR_FLAG(dirh) = NMFILE;
                   1880: 
                   1881:                return 0;
                   1882: 
                   1883:        }
                   1884: 
                   1885:        return r;
                   1886: 
                   1887: }
                   1888: 
                   1889: 
                   1890: 
1.1.1.2   root     1891: static long ARGS_ON_STACK 
1.1       root     1892: 
                   1893: tos_readdir(dirh, name, namelen, fc)
                   1894: 
                   1895:        DIR *dirh;
                   1896: 
                   1897:        char *name;
                   1898: 
                   1899:        int namelen;
                   1900: 
                   1901:        fcookie *fc;
                   1902: 
                   1903: {
                   1904: 
                   1905:        static long index = 0;
                   1906: 
                   1907:        long ret;
                   1908: 
                   1909:        int giveindex = dirh->flags == 0;
                   1910: 
                   1911:        struct tindex *ti;
                   1912: 
                   1913:        DTABUF *dta = DIR_DTA(dirh);
                   1914: 
                   1915: 
                   1916: 
                   1917: again:
                   1918: 
                   1919:        if (DIR_FLAG(dirh) == NMFILE)
                   1920: 
                   1921:                return ENMFIL;
                   1922: 
                   1923: 
                   1924: 
                   1925:        if (DIR_FLAG(dirh) == STARTSEARCH) {
                   1926: 
                   1927:                DIR_FLAG(dirh) = INSEARCH;
                   1928: 
                   1929:        } else {
                   1930: 
                   1931:                assert(DIR_FLAG(dirh) == INSEARCH);
                   1932: 
                   1933:                do_setdta(dta);
                   1934: 
                   1935:                ret = Fsnext();
                   1936: 
                   1937:                if (ret) {
                   1938: 
                   1939:                        DIR_FLAG(dirh) = NMFILE;
                   1940: 
                   1941:                        return ret;
                   1942: 
                   1943:                }
                   1944: 
                   1945:        }
                   1946: 
                   1947: 
                   1948: 
                   1949: /* don't return volume labels from readdir */
                   1950: 
                   1951:        if (dta->dta_attrib == FA_LABEL) goto again;
                   1952: 
                   1953: 
                   1954: 
                   1955:        fc->fs = &tos_filesys;
                   1956: 
                   1957:        fc->dev = dirh->fc.dev;
                   1958: 
                   1959: 
                   1960: 
                   1961:        (void)tfullpath(tmpiname, (struct tindex *)dirh->fc.index, DIR_NAME(dirh));
                   1962: 
                   1963: 
                   1964: 
                   1965:        ti = &tmpindex;
                   1966: 
                   1967:        ti->name = tmpiname;
                   1968: 
                   1969:        ti->valid = 1;
                   1970: 
                   1971:        ti->size = dta->dta_size;
                   1972: 
                   1973:        ti->date = dta->dta_date;
                   1974: 
                   1975:        ti->time = dta->dta_time;
                   1976: 
                   1977:        ti->attr = dta->dta_attrib;
                   1978: 
1.1.1.3   root     1979: #ifndef NEWWAY
                   1980: 
1.1       root     1981:        ti->stamp = tclock;
                   1982: 
1.1.1.3   root     1983: #endif
                   1984: 
1.1       root     1985:        if (executable_extension(dta->dta_name))
                   1986: 
                   1987:                ti->attr |= FA_EXEC;
                   1988: 
                   1989:        fc->index = (long)ti;
                   1990: 
                   1991: 
                   1992: 
                   1993:        if (giveindex) {
                   1994: 
1.1.1.2   root     1995:                namelen -= (int) sizeof(long);
1.1       root     1996: 
                   1997:                if (namelen <= 0) return ERANGE;
                   1998: 
                   1999:                *((long *)name) = index++;
                   2000: 
                   2001:                name += sizeof(long);
                   2002: 
                   2003:        }
                   2004: 
                   2005:        strncpy(name, DIR_NAME(dirh), namelen-1);
                   2006: 
                   2007:        name[namelen-1] = 0;
                   2008: 
1.1.1.3   root     2009: 
                   2010: 
                   2011: /* BUG: we really should do the "strlwr" operation only
                   2012: 
                   2013:  * for Dreaddir (i.e. if giveindex == 0) but
                   2014: 
                   2015:  * unfortunately some old programs rely on the behaviour
                   2016: 
                   2017:  * below
                   2018: 
                   2019:  */
                   2020: 
                   2021:        if (curproc->domain == DOM_MINT) {
1.1       root     2022: 
                   2023:                strlwr(name);
                   2024: 
                   2025:        }
                   2026: 
                   2027:        if (strlen(DIR_NAME(dirh)) >= namelen)
                   2028: 
                   2029:                return ENAMETOOLONG;
                   2030: 
1.1.1.3   root     2031: #ifdef NEWWAY
1.1       root     2032: 
1.1.1.3   root     2033:        ti->links++;
                   2034: 
                   2035:        COOKIE_DB(("tos_readdir: %s now has %d links", ti->name, ti->links));
                   2036: 
                   2037: #endif
                   2038: 
                   2039:        return 0;
1.1       root     2040: 
                   2041: }
                   2042: 
                   2043: 
                   2044: 
1.1.1.2   root     2045: static long ARGS_ON_STACK 
1.1       root     2046: 
                   2047: tos_rewinddir(dirh)
                   2048: 
                   2049:        DIR *dirh;
                   2050: 
                   2051: {
                   2052: 
                   2053:        struct tindex *ti = (struct tindex *)dirh->fc.index;
                   2054: 
                   2055:        long r;
                   2056: 
                   2057: 
                   2058: 
                   2059:        (void)tfullpath(tmpbuf, ti, "*.*");
                   2060: 
                   2061:        do_setdta(DIR_DTA(dirh));
                   2062: 
                   2063:        r = Fsfirst(tmpbuf, FILEORDIR);
                   2064: 
                   2065:        if (r == 0) {
                   2066: 
                   2067:                DIR_FLAG(dirh) = STARTSEARCH;
                   2068: 
                   2069:        } else {
                   2070: 
                   2071:                DIR_FLAG(dirh) = NMFILE;
                   2072: 
                   2073:        }
                   2074: 
                   2075:        return r;
                   2076: 
                   2077: }
                   2078: 
                   2079: 
                   2080: 
1.1.1.2   root     2081: static long ARGS_ON_STACK 
1.1       root     2082: 
                   2083: tos_closedir(dirh)
                   2084: 
                   2085:        DIR *dirh;
                   2086: 
                   2087: {
                   2088: 
                   2089:        struct tindex *t = (struct tindex *)dirh->fc.index;
                   2090: 
                   2091: 
                   2092: 
1.1.1.2   root     2093:        if (t->open == 0) {
                   2094: 
                   2095:                FATAL("t->open == 0: directory == %s", t->name);
                   2096: 
                   2097:        }
1.1       root     2098: 
                   2099:        --t->open;
                   2100: 
                   2101:        DIR_FLAG(dirh) = NMFILE;
                   2102: 
                   2103:        return 0;
                   2104: 
                   2105: }
                   2106: 
                   2107: 
                   2108: 
1.1.1.2   root     2109: static long ARGS_ON_STACK 
1.1       root     2110: 
                   2111: tos_pathconf(dir, which)
                   2112: 
                   2113:        fcookie *dir;
                   2114: 
                   2115:        int which;
                   2116: 
                   2117: {
                   2118: 
1.1.1.2   root     2119:        UNUSED(dir);
                   2120: 
                   2121: 
                   2122: 
1.1       root     2123:        switch(which) {
                   2124: 
                   2125:        case -1:
                   2126: 
                   2127:                return DP_MAXREQ;
                   2128: 
                   2129:        case DP_IOPEN:
                   2130: 
                   2131:                return 60;      /* we can only keep about this many open */
                   2132: 
                   2133:        case DP_MAXLINKS:
                   2134: 
                   2135:                 return 1;      /* no hard links */
                   2136: 
                   2137:        case DP_PATHMAX:
                   2138: 
                   2139:                return PATH_MAX;
                   2140: 
                   2141:        case DP_NAMEMAX:
                   2142: 
                   2143:                return 8+3+1;
                   2144: 
                   2145:        case DP_ATOMIC:
                   2146: 
                   2147:                return 512;     /* we can write at least a sector atomically */
                   2148: 
                   2149:        case DP_TRUNC:
                   2150: 
                   2151:                return DP_DOSTRUNC;     /* DOS style file names */
                   2152: 
                   2153:        case DP_CASE:
                   2154: 
                   2155:                return DP_CASECONV;     /* names converted to upper case */
                   2156: 
1.1.1.6 ! root     2157:        case DP_MODEATTR:
        !          2158: 
        !          2159:                return FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_LABEL|FA_CHANGED|
        !          2160: 
        !          2161: #ifdef ROOTPERMS
        !          2162: 
        !          2163:                                0666L << 8|
        !          2164: 
        !          2165: #endif
        !          2166: 
        !          2167:                                DP_FT_DIR|DP_FT_REG;
        !          2168: 
        !          2169:        case DP_XATTRFIELDS:
        !          2170: 
        !          2171:                return DP_DEV|DP_NLINK|DP_BLKSIZE|DP_SIZE|DP_NBLOCKS|DP_MTIME;
        !          2172: 
1.1       root     2173:        default:
                   2174: 
                   2175:                return EINVFN;
                   2176: 
                   2177:        }
                   2178: 
                   2179: }
                   2180: 
                   2181: 
                   2182: 
1.1.1.2   root     2183: long ARGS_ON_STACK 
1.1       root     2184: 
                   2185: tos_dfree(dir, buf)
                   2186: 
                   2187:        fcookie *dir;
                   2188: 
                   2189:        long *buf;
                   2190: 
                   2191: {
                   2192: 
                   2193:        return Dfree(buf, (dir->dev)+1);
                   2194: 
                   2195: }
                   2196: 
                   2197: 
                   2198: 
                   2199: /*
                   2200: 
                   2201:  * writelabel: creates a volume label
                   2202: 
                   2203:  * readlabel: reads a volume label
                   2204: 
                   2205:  * both of these are only guaranteed to work in the root directory
                   2206: 
                   2207:  */
                   2208: 
                   2209: 
                   2210: 
                   2211: /*
                   2212: 
                   2213:  * BUG: this should first delete any old labels, so that it will
                   2214: 
                   2215:  * work with TOS <1.4
                   2216: 
                   2217:  */
                   2218: 
                   2219: 
                   2220: 
1.1.1.2   root     2221: long ARGS_ON_STACK 
1.1       root     2222: 
                   2223: tos_writelabel(dir, name)
                   2224: 
                   2225:        fcookie *dir;
                   2226: 
                   2227:        const char *name;
                   2228: 
                   2229: {
                   2230: 
                   2231:        long r;
                   2232: 
                   2233:        struct tindex *ti;
                   2234: 
                   2235: 
                   2236: 
                   2237:        (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
                   2238: 
                   2239:        r = Fcreate(tmpbuf, FA_LABEL);
                   2240: 
                   2241:        if (r < 0) return r;
                   2242: 
1.1.1.2   root     2243:        (void)Fclose((int)r);
1.1       root     2244: 
                   2245:        ti = tstrindex(tmpbuf);
                   2246: 
                   2247:        ti->valid = 0;
                   2248: 
                   2249:        return 0;
                   2250: 
                   2251: }
                   2252: 
                   2253: 
                   2254: 
1.1.1.2   root     2255: long ARGS_ON_STACK 
1.1       root     2256: 
                   2257: tos_readlabel(dir, name, namelen)
                   2258: 
                   2259:        fcookie *dir;
                   2260: 
                   2261:        char *name;
                   2262: 
                   2263:        int namelen;
                   2264: 
                   2265: {
                   2266: 
                   2267:        long r;
                   2268: 
                   2269:        struct tindex *ti = (struct tindex *)dir->index;
                   2270: 
                   2271: 
                   2272: 
                   2273:        if (ti->name[2] != 0)           /* not a root directory? */
                   2274: 
                   2275:                return EFILNF;
                   2276: 
                   2277: 
                   2278: 
                   2279:        (void)tfullpath(tmpbuf, ti, "*.*");
                   2280: 
                   2281:        do_setdta(&foo);
                   2282: 
                   2283:        r = Fsfirst(tmpbuf, FA_LABEL);
                   2284: 
                   2285:        if (r)
                   2286: 
                   2287:                return r;
                   2288: 
                   2289:        strncpy(name, foo.dta_name, namelen-1);
                   2290: 
                   2291:        return (strlen(foo.dta_name) < namelen) ? 0 : ENAMETOOLONG;
                   2292: 
                   2293: }
                   2294: 
                   2295: 
                   2296: 
                   2297: /*
                   2298: 
                   2299:  * TOS creat: this doesn't actually create the file, rather it
                   2300: 
                   2301:  * sets up a (fake) index for the file that will be used by
                   2302: 
                   2303:  * the later tos_open call.
                   2304: 
                   2305:  */
                   2306: 
                   2307: 
                   2308: 
1.1.1.2   root     2309: static long ARGS_ON_STACK 
1.1       root     2310: 
                   2311: tos_creat(dir, name, mode, attrib, fc)
                   2312: 
                   2313:        fcookie *dir;
                   2314: 
                   2315:        const char *name;
                   2316: 
                   2317:        unsigned mode;
                   2318: 
                   2319:        int attrib;
                   2320: 
                   2321:        fcookie *fc;
                   2322: 
                   2323: {
                   2324: 
                   2325:        struct tindex *ti;
                   2326: 
1.1.1.2   root     2327:        UNUSED(mode);
                   2328: 
1.1       root     2329: 
                   2330: 
                   2331:        (void)tfullpath(tmpbuf, (struct tindex *)dir->index, name);
                   2332: 
                   2333: 
                   2334: 
                   2335:        ti = tstrindex(tmpbuf);
                   2336: 
                   2337:        ti->size = 0;
                   2338: 
                   2339:        ti->date = datestamp;
                   2340: 
                   2341:        ti->time = timestamp;
                   2342: 
                   2343:        ti->attr = attrib;
                   2344: 
                   2345:        ti->valid = 1;
                   2346: 
                   2347: 
                   2348: 
                   2349:        fc->fs = &tos_filesys;
                   2350: 
                   2351:        fc->index = (long)ti;
                   2352: 
                   2353:        fc->dev = dir->dev;
                   2354: 
1.1.1.3   root     2355: #ifdef NEWWAY
                   2356: 
                   2357:        ti->links++;
                   2358: 
                   2359:        COOKIE_DB(("tos_creat: %s now has %d links", ti->name, ti->links));
                   2360: 
                   2361: #endif
                   2362: 
1.1       root     2363:        return 0;
                   2364: 
                   2365: }
                   2366: 
                   2367:        
                   2368: 
                   2369: /*
                   2370: 
                   2371:  * TOS device driver
                   2372: 
                   2373:  */
                   2374: 
                   2375: 
                   2376: 
1.1.1.2   root     2377: static DEVDRV * ARGS_ON_STACK 
1.1       root     2378: 
                   2379: tos_getdev(fc, devsp)
                   2380: 
                   2381:        fcookie *fc;
                   2382: 
                   2383:        long *devsp;
                   2384: 
                   2385: {
                   2386: 
1.1.1.2   root     2387:        UNUSED(fc); UNUSED(devsp);
                   2388: 
1.1       root     2389:        return &tos_device;
                   2390: 
                   2391: }
                   2392: 
                   2393: 
                   2394: 
1.1.1.2   root     2395: static long ARGS_ON_STACK 
1.1       root     2396: 
                   2397: tos_open(f)
                   2398: 
                   2399:        FILEPTR *f;
                   2400: 
                   2401: {
                   2402: 
                   2403:        struct tindex *ti;
                   2404: 
                   2405:        int mode = f->flags;
                   2406: 
                   2407:        int tosmode;
                   2408: 
                   2409:        long r;
                   2410: 
                   2411:        extern int flk;         /* in main.c, set if _FLK cookie already present */
                   2412: 
                   2413: 
                   2414: 
                   2415:        ti = (struct tindex *)(f->fc.index);
                   2416: 
                   2417:        assert(ti != 0);
                   2418: 
                   2419: 
                   2420: 
1.1.1.3   root     2421: #ifndef NEWWAY
                   2422: 
1.1       root     2423:        ti->stamp = ++tclock;
                   2424: 
1.1.1.3   root     2425: #endif
                   2426: 
1.1       root     2427:        ti->valid = 0;
                   2428: 
                   2429: 
                   2430: 
1.1.1.3   root     2431: #ifndef RO_FASCISM
                   2432: 
1.1       root     2433: /* TEMPORARY HACK: change all modes to O_RDWR for files opened in
                   2434: 
                   2435:  * compatibility sharing mode. This is silly, but
                   2436: 
                   2437:  * allows broken TOS programs that write to read-only handles to continue
                   2438: 
                   2439:  * to work (it also helps file sharing, by making the realistic assumption
                   2440: 
                   2441:  * that any open TOS file can be written to). Eventually,
                   2442: 
                   2443:  * this should be tuneable by the user somehow.
                   2444: 
                   2445:  * ALSO: change O_COMPAT opens into O_DENYNONE; again, this may be temporary.
                   2446: 
                   2447:  */
                   2448: 
                   2449:        if ( (mode & O_SHMODE) == O_COMPAT ) {
                   2450: 
                   2451:                f->flags = (mode & ~(O_RWMODE|O_SHMODE)) | O_RDWR | O_DENYNONE;
                   2452: 
                   2453:        }
                   2454: 
1.1.1.3   root     2455: #endif
                   2456: 
1.1       root     2457: 
                   2458: 
                   2459: /* check to see that nobody has opened this file already in an
                   2460: 
                   2461:  * incompatible mode
                   2462: 
                   2463:  */
                   2464: 
                   2465:        if (denyshare(ti->open, f)) {
                   2466: 
1.1.1.2   root     2467:                TRACE(("tos_open: file sharing denied"));
1.1       root     2468: 
                   2469:                return EACCDN;
                   2470: 
                   2471:        }
                   2472: 
                   2473: 
                   2474: 
                   2475: /*
                   2476: 
                   2477:  * now open the file; if O_TRUNC was specified, actually
                   2478: 
                   2479:  * create the file anew.
                   2480: 
                   2481:  * BUG: O_TRUNC without O_CREAT doesn't work right. The kernel doesn't
                   2482: 
                   2483:  * use this mode, anyways
                   2484: 
                   2485:  */
                   2486: 
                   2487: 
                   2488: 
                   2489:        if (mode & O_TRUNC) {
                   2490: 
                   2491:                if (ti->open) {
                   2492: 
1.1.1.2   root     2493:                        DEBUG(("tos_open: attempt to truncate an open file"));
1.1       root     2494: 
                   2495:                        return EACCDN;
                   2496: 
                   2497:                }
                   2498: 
                   2499:                r = Fcreate(ti->name, ti->attr);
                   2500: 
                   2501:        } else {
                   2502: 
                   2503:                if (flk)
                   2504: 
                   2505:                        tosmode = mode & (O_RWMODE|O_SHMODE);
                   2506: 
                   2507:                else
                   2508: 
                   2509:                        tosmode = (mode & O_RWMODE);
                   2510: 
                   2511:                if (tosmode == O_EXEC) tosmode = O_RDONLY;
                   2512: 
                   2513: 
                   2514: 
                   2515:                r = Fopen(ti->name, tosmode );
                   2516: 
                   2517:                if (r == EFILNF && (mode & O_CREAT))
                   2518: 
                   2519:                        r = Fcreate(ti->name, ti->attr);
                   2520: 
                   2521:        }
                   2522: 
                   2523: 
                   2524: 
                   2525:        if (r < 0) {
                   2526: 
                   2527: /* get rid of the index for the file, since it doesn't exist */
                   2528: 
                   2529:                kfree(ti->name);
                   2530: 
                   2531:                ti->name = 0;
                   2532: 
                   2533:                ti->valid = 0;
                   2534: 
                   2535:                return r;
                   2536: 
                   2537:        }
                   2538: 
                   2539: 
                   2540: 
                   2541:        f->devinfo = r;
                   2542: 
                   2543: 
                   2544: 
                   2545:        f->next = ti->open;
                   2546: 
                   2547:        ti->open = f;
                   2548: 
                   2549:        return 0;
                   2550: 
                   2551: }
                   2552: 
                   2553: 
                   2554: 
1.1.1.2   root     2555: static long ARGS_ON_STACK 
1.1       root     2556: 
                   2557: tos_write(f, buf, bytes)
                   2558: 
                   2559:        FILEPTR *f; const char *buf; long bytes;
                   2560: 
                   2561: {
                   2562: 
                   2563:        struct tindex *ti = (struct tindex *)f->fc.index;
                   2564: 
                   2565: 
                   2566: 
                   2567:        ti->valid = 0;
                   2568: 
                   2569:        return Fwrite((int)f->devinfo, bytes, buf);
                   2570: 
                   2571: }
                   2572: 
                   2573: 
                   2574: 
1.1.1.2   root     2575: static long ARGS_ON_STACK 
1.1       root     2576: 
                   2577: tos_read(f, buf, bytes)
                   2578: 
                   2579:        FILEPTR *f; char *buf; long bytes;
                   2580: 
                   2581: {
                   2582: 
                   2583:        return Fread((int)f->devinfo, bytes, buf);
                   2584: 
                   2585: }
                   2586: 
                   2587: 
                   2588: 
1.1.1.2   root     2589: static long ARGS_ON_STACK 
1.1       root     2590: 
                   2591: tos_lseek(f, where, whence)
                   2592: 
                   2593:        FILEPTR *f; long where; int whence;
                   2594: 
                   2595: {
                   2596: 
                   2597:        long r;
                   2598: 
                   2599: 
                   2600: 
                   2601:        r = Fseek(where, (int)f->devinfo, whence);
                   2602: 
                   2603:        return r;
                   2604: 
                   2605: }
                   2606: 
                   2607: 
                   2608: 
1.1.1.2   root     2609: static long ARGS_ON_STACK 
1.1       root     2610: 
                   2611: tos_ioctl(f, mode, buf)
                   2612: 
                   2613:        FILEPTR *f; int mode; void *buf;
                   2614: 
                   2615: {
                   2616: 
                   2617:        LOCK t, *lck, **old;
                   2618: 
                   2619:        struct flock *fl;
                   2620: 
                   2621:        long r;
                   2622: 
                   2623:        struct tindex *ti;
                   2624: 
                   2625:        extern int flk;         /* set in main.c if _FLK already installed */
                   2626: 
                   2627: 
                   2628: 
1.1.1.6 ! root     2629:        switch(mode) {
        !          2630: 
        !          2631:        case FIONREAD:
        !          2632: 
        !          2633:                r = Fseek (0L, (int) f->devinfo, 1);
        !          2634: 
        !          2635:                if (r < 0) return r;
        !          2636: 
        !          2637:                *(long *) buf = Fseek (0L, (int) f->devinfo, 2) - r;
        !          2638: 
        !          2639:                (void) Fseek (r, (int) f->devinfo, 0);
        !          2640: 
        !          2641:                return 0;
        !          2642: 
        !          2643:        case FIONWRITE:
1.1       root     2644: 
                   2645:                *((long *)buf) = 1;
                   2646: 
                   2647:                return 0;
                   2648: 
1.1.1.6 ! root     2649:        case FIOEXCEPT:
1.1       root     2650: 
1.1.1.6 ! root     2651:                *((long *)buf) = 0;
        !          2652: 
        !          2653:                return 0;
        !          2654: 
        !          2655:        case F_SETLK:
        !          2656: 
        !          2657:        case F_SETLKW:
        !          2658: 
        !          2659:        case F_GETLK:
1.1       root     2660: 
                   2661:                fl = ((struct flock *)buf);
                   2662: 
                   2663:                t.l = *fl;
                   2664: 
                   2665:                switch(t.l.l_whence) {
                   2666: 
                   2667:                case 0:
                   2668: 
                   2669:                        break;
                   2670: 
                   2671:                case 1:         /* SEEK_CUR */
                   2672: 
                   2673:                        r = Fseek(0L, (int)f->devinfo, 1);
                   2674: 
                   2675:                        t.l.l_start += r;
                   2676: 
                   2677:                        break;
                   2678: 
                   2679:                case 2:
                   2680: 
                   2681:                        r = Fseek(0L, (int)f->devinfo, 1);
                   2682: 
                   2683:                        t.l.l_start = Fseek(t.l.l_start, (int)f->devinfo, 2);
                   2684: 
                   2685:                        (void)Fseek(r, (int)f->devinfo, 0);
                   2686: 
                   2687:                        break;
                   2688: 
                   2689:                default:
                   2690: 
1.1.1.2   root     2691:                        DEBUG(("Invalid value for l_whence"));
1.1       root     2692: 
                   2693:                        return EINVFN;
                   2694: 
                   2695:                }
                   2696: 
                   2697: /* BUG: can't lock a file starting at >2gigabytes from the beginning */
                   2698: 
                   2699:                if (t.l.l_start < 0) t.l.l_start = 0;
                   2700: 
                   2701:                t.l.l_whence = 0;
                   2702: 
                   2703:                ti = (struct tindex *)f->fc.index;
                   2704: 
                   2705: 
                   2706: 
                   2707:                if (mode == F_GETLK) {
                   2708: 
                   2709:                        lck = denylock(ti->locks, &t);
                   2710: 
                   2711:                        if (lck)
                   2712: 
                   2713:                                *fl = lck->l;
                   2714: 
                   2715:                        else
                   2716: 
                   2717:                                fl->l_type = F_UNLCK;
                   2718: 
                   2719:                        return 0;
                   2720: 
                   2721:                }
                   2722: 
                   2723: 
                   2724: 
                   2725:                if (t.l.l_type == F_UNLCK) {
                   2726: 
                   2727:                /* try to find the lock */
                   2728: 
                   2729:                        old = &ti->locks;
                   2730: 
                   2731:                        lck = *old;
                   2732: 
                   2733:                        while (lck) {
                   2734: 
                   2735:                                if (lck->l.l_pid == curproc->pid &&
                   2736: 
                   2737:                                    lck->l.l_start == t.l.l_start &&
                   2738: 
                   2739:                                    lck->l.l_len == t.l.l_len) {
                   2740: 
                   2741:                /* found it -- remove the lock */
                   2742: 
                   2743:                                        *old = lck->next;
                   2744: 
1.1.1.2   root     2745:                                        TRACE(("tosfs: unlocked %s: %ld + %ld",
1.1       root     2746: 
1.1.1.2   root     2747:                                                ti->name, t.l.l_start, t.l.l_len));
1.1       root     2748: 
                   2749:                                        if (flk)
                   2750: 
                   2751:                                            (void)Flock((int)f->devinfo, 1,
                   2752: 
                   2753:                                                        t.l.l_start, t.l.l_len);
                   2754: 
1.1.1.2   root     2755:                                /* wake up anyone waiting on the lock */
                   2756: 
                   2757:                                        wake(IO_Q, (long)lck);
                   2758: 
                   2759:                                        kfree(lck);
                   2760: 
1.1       root     2761:                                        break;
                   2762: 
                   2763:                                }
                   2764: 
                   2765:                                old = &lck->next;
                   2766: 
                   2767:                                lck = lck->next;
                   2768: 
                   2769:                        }
                   2770: 
                   2771:                        return lck ?  0 : ENSLOCK;
                   2772: 
                   2773:                }
                   2774: 
1.1.1.2   root     2775:                TRACE(("tosfs: lock %s: %ld + %ld", ti->name,
1.1       root     2776: 
1.1.1.2   root     2777:                        t.l.l_start, t.l.l_len));
1.1       root     2778: 
1.1.1.2   root     2779:                do {
1.1       root     2780: 
1.1.1.2   root     2781:                /* see if there's a conflicting lock */
1.1       root     2782: 
1.1.1.2   root     2783:                        while ((lck = denylock(ti->locks, &t)) != 0) {
1.1       root     2784: 
1.1.1.2   root     2785:                                DEBUG(("tosfs: lock conflicts with one held by %d",
1.1       root     2786: 
1.1.1.2   root     2787:                                        lck->l.l_pid));
1.1       root     2788: 
1.1.1.2   root     2789:                                if (mode == F_SETLKW) {
1.1       root     2790: 
1.1.1.2   root     2791:                                        sleep(IO_Q, (long)lck);         /* sleep a while */
                   2792: 
                   2793:                                }
1.1       root     2794: 
1.1.1.2   root     2795:                                else
1.1       root     2796: 
1.1.1.2   root     2797:                                        return ELOCKED;
1.1       root     2798: 
1.1.1.2   root     2799:                        }
1.1       root     2800: 
1.1.1.2   root     2801:                /* if not, add this lock to the list */
1.1       root     2802: 
1.1.1.2   root     2803:                        lck = kmalloc(SIZEOF(LOCK));
1.1       root     2804: 
1.1.1.2   root     2805:                        if (!lck) return ENSMEM;
1.1       root     2806: 
1.1.1.2   root     2807:                /* see if other _FLK code might object */
1.1       root     2808: 
1.1.1.2   root     2809:                        if (flk) {
1.1       root     2810: 
1.1.1.2   root     2811:                                r = Flock((int)f->devinfo, 0, t.l.l_start, t.l.l_len);
                   2812: 
                   2813:                                if (r) {
                   2814: 
                   2815:                                        kfree(lck);
                   2816: 
                   2817:                                        if (mode == F_SETLKW && r == ELOCKED) {
                   2818: 
                   2819:                                                yield();
                   2820: 
                   2821:                                                lck = NULL;
                   2822: 
                   2823:                                        }
                   2824: 
                   2825:                                        else
                   2826: 
                   2827:                                                return r;
                   2828: 
                   2829:                                }
1.1       root     2830: 
                   2831:                        }
                   2832: 
1.1.1.2   root     2833:                } while (!lck);
1.1       root     2834: 
                   2835:                lck->l = t.l;
                   2836: 
                   2837:                lck->l.l_pid = curproc->pid;
                   2838: 
                   2839:                lck->next = ti->locks;
                   2840: 
                   2841:                ti->locks = lck;
                   2842: 
                   2843:        /* mark the file as being locked */
                   2844: 
                   2845:                f->flags |= O_LOCK;
                   2846: 
                   2847:                return 0;
                   2848: 
                   2849:        }
                   2850: 
                   2851:        return EINVFN;
                   2852: 
                   2853: }
                   2854: 
                   2855: 
                   2856: 
1.1.1.2   root     2857: static long ARGS_ON_STACK 
1.1       root     2858: 
                   2859: tos_datime(f, timeptr, rwflag)
                   2860: 
                   2861:        FILEPTR *f;
                   2862: 
                   2863:        short *timeptr;
                   2864: 
                   2865:        int rwflag;
                   2866: 
                   2867: {
                   2868: 
                   2869:        if (rwflag) {
                   2870: 
                   2871:                struct tindex *ti = (struct tindex *)f->fc.index;
                   2872: 
                   2873:                ti->valid = 0;
                   2874: 
                   2875:        }
                   2876: 
                   2877:        return Fdatime(timeptr, (int)f->devinfo, rwflag);
                   2878: 
                   2879: }
                   2880: 
                   2881: 
                   2882: 
1.1.1.2   root     2883: static long ARGS_ON_STACK 
1.1       root     2884: 
                   2885: tos_close(f, pid)
                   2886: 
                   2887:        FILEPTR *f;
                   2888: 
                   2889:        int pid;
                   2890: 
                   2891: {
                   2892: 
                   2893:        LOCK *lck, **oldl;
                   2894: 
                   2895:        struct tindex *t;
                   2896: 
                   2897:        FILEPTR **old, *p;
                   2898: 
                   2899:        long r = 0;
                   2900: 
                   2901:        extern int flk;         /* set in main.c */
                   2902: 
                   2903: 
                   2904: 
                   2905:        t = (struct tindex *)(f->fc.index);
                   2906: 
                   2907: /* if this handle was locked, remove any locks held by the process
                   2908: 
                   2909:  */
                   2910: 
                   2911:        if (f->flags & O_LOCK) {
                   2912: 
1.1.1.2   root     2913:                TRACE(("tos_close: releasing locks (file mode: %x)", f->flags));
1.1       root     2914: 
                   2915:                oldl = &t->locks;
                   2916: 
                   2917:                lck = *oldl;
                   2918: 
                   2919:                while (lck) {
                   2920: 
                   2921:                        if (lck->l.l_pid == pid) {
                   2922: 
                   2923:                                *oldl = lck->next;
                   2924: 
                   2925:                                if (flk)
                   2926: 
                   2927:                                        (void)Flock((int)f->devinfo, 1,
                   2928: 
                   2929:                                                lck->l.l_start, lck->l.l_len);
                   2930: 
1.1.1.2   root     2931:                                wake(IO_Q, (long)lck);
                   2932: 
1.1       root     2933:                                kfree(lck);
                   2934: 
                   2935:                        } else {
                   2936: 
                   2937:                                oldl = &lck->next;
                   2938: 
                   2939:                        }
                   2940: 
                   2941:                        lck = *oldl;
                   2942: 
                   2943:                }
                   2944: 
                   2945:        }
                   2946: 
                   2947: 
                   2948: 
                   2949:        if (f->links <= 0) {
                   2950: 
                   2951: /* remove f from the list of open file pointers on this index */
                   2952: 
                   2953:                t->valid = 0;
                   2954: 
                   2955:                old = &t->open;
                   2956: 
                   2957:                p = t->open;
                   2958: 
                   2959:                while (p && p != f) {
                   2960: 
                   2961:                        old = &p->next;
                   2962: 
                   2963:                        p = p->next;
                   2964: 
                   2965:                }
                   2966: 
                   2967:                assert(p);
                   2968: 
                   2969:                *old = f->next;
                   2970: 
                   2971:                f->next = 0;
                   2972: 
                   2973:                r = Fclose((int)f->devinfo);
                   2974: 
                   2975: 
                   2976: 
                   2977: /* if the file was marked for deletion, delete it */
                   2978: 
                   2979:                if (!t->open) {
                   2980: 
                   2981:                        if (t->attr & FA_DELETE) {
                   2982: 
                   2983:                                (void)Fdelete(t->name);
                   2984: 
                   2985:                                t->name = 0;
                   2986: 
                   2987:                        }
                   2988: 
                   2989:                }
                   2990: 
                   2991:        }
                   2992: 
                   2993:        return r;
                   2994: 
                   2995: }
                   2996: 
                   2997: 
                   2998: 
                   2999: /*
                   3000: 
                   3001:  * check for disk change: called by the kernel if Mediach returns a
                   3002: 
                   3003:  * non-zero value
                   3004: 
                   3005:  */
                   3006: 
                   3007: 
                   3008: 
1.1.1.2   root     3009: long ARGS_ON_STACK 
1.1       root     3010: 
                   3011: tos_dskchng(drv)
                   3012: 
                   3013:        int drv;
                   3014: 
                   3015: {
                   3016: 
                   3017:        char dlet;
                   3018: 
                   3019:        int i;
                   3020: 
                   3021:        struct tindex *ti;
                   3022: 
1.1.1.3   root     3023:        FILEPTR *f, *nextf;
                   3024: 
1.1       root     3025: 
                   3026: 
                   3027:        dlet = 'A' + drv;
                   3028: 
1.1.1.3   root     3029: MEDIA_DB(("tos_dskchng(%c)", dlet));
                   3030: 
1.1       root     3031:        ti = gl_ti;
                   3032: 
                   3033:        for (i = 0; i < NUM_INDICES; i++, ti++) {
                   3034: 
1.1.1.2   root     3035:                if (ti->name && ti->name[0] == dlet) {
1.1       root     3036: 
1.1.1.4   root     3037: #ifdef NEWWAY
                   3038: 
                   3039:        /* only free the name if this index not used by any cookie */
                   3040: 
                   3041:                        if (ti->links != 0)
                   3042: 
                   3043:                                ti->valid = 0;
                   3044: 
                   3045:                        else
                   3046: 
                   3047: #endif /* NEWWAY */
1.1       root     3048: 
1.1.1.4   root     3049:                        {
1.1       root     3050: 
1.1.1.4   root     3051:                                kfree(ti->name);
1.1.1.3   root     3052: 
1.1.1.4   root     3053:                                ti->name = 0;
1.1.1.3   root     3054: 
1.1.1.4   root     3055:                        }
                   3056: 
                   3057:                        if (!(ti->attr & FA_DIR)) {
                   3058: 
                   3059:                                nextf = ti->open;
                   3060: 
                   3061:                                while ( (f = nextf) != 0 ) {
1.1.1.3   root     3062: 
1.1.1.4   root     3063:                                        nextf = f->next;
                   3064: 
                   3065:                                        f->next = 0;
                   3066: 
                   3067:                                }
1.1.1.3   root     3068: 
                   3069:                        }
                   3070: 
                   3071:                        ti->open = 0;
                   3072: 
                   3073:        /* if there are any cookies pointing at this name, they're not
                   3074: 
                   3075:         * valid any more, so we will *want* to get an error if they're
                   3076: 
                   3077:         * used.
                   3078: 
                   3079:         */
                   3080: 
1.1       root     3081:                }
                   3082: 
                   3083:        }
                   3084: 
1.1.1.2   root     3085:        tmpindex.valid = 0;
                   3086: 
1.1       root     3087: /*
                   3088: 
                   3089:  * OK, make sure that GEMDOS knows to look for a change if we
                   3090: 
                   3091:  * ever use this drive again.
                   3092: 
                   3093:  */
                   3094: 
                   3095:        drvchanged[drv] = 1;
                   3096: 
                   3097:        return 1;
                   3098: 
                   3099: }
                   3100: 
                   3101: 
                   3102: 
1.1.1.3   root     3103: #ifdef NEWWAY
                   3104: 
                   3105: /* release/copy file cookies; these functions exist to keep
                   3106: 
                   3107:  * track of whether or not the kernel is still using a file
                   3108: 
                   3109:  */
                   3110: 
                   3111: long
                   3112: 
                   3113: tos_release(fc)
                   3114: 
                   3115:        fcookie *fc;
                   3116: 
                   3117: {
                   3118: 
                   3119:        struct tindex *ti = (struct tindex *)fc->index;
                   3120: 
                   3121: 
                   3122: 
                   3123:        if (ti->links <= 0) {
                   3124: 
                   3125:                FATAL("tos_release: link count of `%s' is %d", ti->name, ti->links);
                   3126: 
                   3127:        }
                   3128: 
                   3129:        ti->links--;
                   3130: 
                   3131:        COOKIE_DB(("tos_release: %s now has %d links", ti->name, ti->links));
                   3132: 
                   3133:        return 0;
                   3134: 
                   3135: }
                   3136: 
                   3137: 
                   3138: 
                   3139: long
                   3140: 
                   3141: tos_dupcookie(dest, src)
                   3142: 
                   3143:        fcookie *dest, *src;
                   3144: 
                   3145: {
                   3146: 
                   3147:        struct tindex *ti = (struct tindex *)src->index;
                   3148: 
                   3149: 
                   3150: 
                   3151:        if (ti->links <= 0) {
                   3152: 
                   3153:                FATAL("tos_dupcookie: link count of %s is %d", ti->name, ti->links);
                   3154: 
                   3155:        }
                   3156: 
                   3157:        ti->links++;
                   3158: 
                   3159:        COOKIE_DB(("tos_dupcookie: %s now has %d links", ti->name, ti->links));
                   3160: 
                   3161:        *dest = *src;
                   3162: 
                   3163:        return 0;
                   3164: 
                   3165: }
                   3166: 
                   3167: #endif
                   3168: 
                   3169: 
                   3170: 
1.1       root     3171: /*
                   3172: 
                   3173:  * utility function: sets the TOS DTA, and also records what directory
                   3174: 
                   3175:  * this was in. This is just to save us a call into the kernel if the
                   3176: 
                   3177:  * correct DTA has already been set.
                   3178: 
                   3179:  */
                   3180: 
                   3181: 
                   3182: 
                   3183: static void
                   3184: 
                   3185: do_setdta(dta)
                   3186: 
                   3187:        DTABUF *dta;
                   3188: 
                   3189: {
                   3190: 
                   3191:        if (dta != lastdta) {
                   3192: 
                   3193:                Fsetdta(dta);
                   3194: 
                   3195:                lastdta = dta;
                   3196: 
                   3197:        }
                   3198: 
                   3199: }
                   3200: 
                   3201: 
                   3202: 
                   3203: /*
                   3204: 
                   3205:  * routines for forcing a media change on drive "drv"
                   3206: 
                   3207:  */
                   3208: 
                   3209: 
                   3210: 
                   3211: static int chdrv;
                   3212: 
                   3213: 
                   3214: 
                   3215: /* new Getbpb function: when this is called, all the other
                   3216: 
                   3217:  * vectors can be un-installed
                   3218: 
                   3219:  */
                   3220: 
                   3221: 
                   3222: 
1.1.1.2   root     3223: static long ARGS_ON_STACK (*Oldgetbpb) P_((int));
1.1       root     3224: 
1.1.1.2   root     3225: static long ARGS_ON_STACK (*Oldmediach) P_((int));
1.1       root     3226: 
1.1.1.2   root     3227: static long ARGS_ON_STACK (*Oldrwabs) P_((int, void *, int, int, int, long));
1.1       root     3228: 
                   3229: 
                   3230: 
1.1.1.2   root     3231: static long  ARGS_ON_STACK
1.1       root     3232: 
                   3233: Newgetbpb(d)
                   3234: 
                   3235:        int d;
                   3236: 
                   3237: {
                   3238: 
                   3239:        if (d == chdrv) {
                   3240: 
1.1.1.3   root     3241: MEDIA_DB(("Newgetbpb(%c)", d+'A'));
1.1       root     3242: 
1.1.1.3   root     3243: if (Oldgetbpb == Newgetbpb) {
1.1       root     3244: 
1.1.1.3   root     3245: MEDIA_DB(("AARGH!!! BAD BPBs"));
1.1       root     3246: 
1.1.1.3   root     3247: }
1.1.1.2   root     3248: 
1.1.1.3   root     3249:                *((Func *)0x472L) = Oldgetbpb;
1.1.1.2   root     3250: 
1.1.1.3   root     3251:                *((Func *)0x476L) = Oldrwabs;
                   3252: 
                   3253:                *((Func *)0x47eL) = Oldmediach;
1.1.1.2   root     3254: 
1.1       root     3255:        }
                   3256: 
                   3257:        return (*Oldgetbpb)(d);
                   3258: 
                   3259: }
                   3260: 
                   3261: 
                   3262: 
1.1.1.2   root     3263: static long ARGS_ON_STACK
1.1       root     3264: 
                   3265: Newmediach(d)
                   3266: 
                   3267:        int d;
                   3268: 
                   3269: {
                   3270: 
1.1.1.3   root     3271:        if (d == chdrv) {
                   3272: 
                   3273: MEDIA_DB(("Newmediach(%c)", d+'A'));
1.1       root     3274: 
                   3275:                return 2;
                   3276: 
1.1.1.3   root     3277:        }
                   3278: 
1.1       root     3279:        return (*Oldmediach)(d);
                   3280: 
                   3281: }
                   3282: 
                   3283: 
                   3284: 
1.1.1.2   root     3285: static long ARGS_ON_STACK
1.1       root     3286: 
1.1.1.6 ! root     3287: Newrwabs(mode, buf, num, recno, dev, l)
1.1       root     3288: 
1.1.1.6 ! root     3289:        int mode;
1.1       root     3290: 
                   3291:        void *buf;
                   3292: 
1.1.1.6 ! root     3293:        int num, recno, dev;
1.1       root     3294: 
                   3295:        long l;
                   3296: 
                   3297: {
                   3298: 
1.1.1.6 ! root     3299:        if (dev == chdrv) {
1.1.1.3   root     3300: 
                   3301: MEDIA_DB(("Newrwabs"));
1.1       root     3302: 
                   3303:                return E_CHNG;
                   3304: 
1.1.1.3   root     3305:        }
                   3306: 
1.1.1.6 ! root     3307:        return (*Oldrwabs)(mode, buf, num, recno, dev, l);
1.1       root     3308: 
                   3309: }
                   3310: 
                   3311: 
                   3312: 
                   3313: static void
                   3314: 
                   3315: force_mediach(d)
                   3316: 
                   3317:        int d;
                   3318: 
                   3319: {
                   3320: 
1.1.1.3   root     3321: #ifdef FSFIRST_MEDIACH
                   3322: 
1.1.1.2   root     3323:        static char fname[] = "X:\\*.*";
1.1       root     3324: 
1.1.1.3   root     3325: #else
1.1       root     3326: 
1.1.1.3   root     3327:        long r;
                   3328: 
                   3329:        static char fname[] = "X:\\X";
                   3330: 
                   3331: #endif
1.1       root     3332: 
1.1.1.2   root     3333:        TRACE(("tosfs: disk change drive %c", d+'A'));
1.1       root     3334: 
1.1.1.3   root     3335: MEDIA_DB(("forcing media change on %c", d+'A'));
                   3336: 
1.1       root     3337: 
                   3338: 
                   3339:        chdrv = d;
                   3340: 
                   3341:        Oldrwabs = *((Func *)0x476L);
                   3342: 
1.1.1.3   root     3343:        Oldgetbpb = *((Func *)0x472L);
1.1       root     3344: 
1.1.1.3   root     3345:        Oldmediach = *((Func *)0x47eL);
1.1       root     3346: 
                   3347: 
                   3348: 
1.1.1.3   root     3349:        if (Oldrwabs == Newrwabs || Oldgetbpb == Newgetbpb ||
1.1       root     3350: 
1.1.1.3   root     3351:            Oldmediach == Newmediach) {
1.1       root     3352: 
1.1.1.3   root     3353:                FORCE("tosfs: error in media change code");
                   3354: 
                   3355:        } else {
                   3356: 
                   3357:                *((Func *)0x476L) = Newrwabs;
1.1       root     3358: 
                   3359:                *((Func *)0x472L) = Newgetbpb;
                   3360: 
1.1.1.3   root     3361:                *((Func *)0x47eL) = Newmediach;
                   3362: 
1.1       root     3363:        }
                   3364: 
                   3365: 
                   3366: 
                   3367:        fname[0] = d + 'A';
                   3368: 
1.1.1.3   root     3369: MEDIA_DB(("calling GEMDOS"));
                   3370: 
                   3371: #ifdef FSFIRST_MEDIACH
                   3372: 
                   3373:        (void)Fsfirst(fname, 8);
                   3374: 
                   3375: #else  
                   3376: 
                   3377:        r = Fopen(fname, 0);
                   3378: 
                   3379:        if (r >= 0) Fclose((int)r);
                   3380: 
                   3381: #endif
                   3382: 
                   3383: MEDIA_DB(("done calling GEMDOS"));
1.1       root     3384: 
                   3385:        drvchanged[d] = 0;
                   3386: 
1.1.1.3   root     3387:        if ( *((Func *)0x476L) == Newrwabs ) {
                   3388: 
                   3389:                DEBUG(("WARNING: media change not performed correctly"));
                   3390: 
                   3391:                *((Func *)0x472L) = Oldgetbpb;
                   3392: 
                   3393:                *((Func *)0x476L) = Oldrwabs;
                   3394: 
                   3395:                *((Func *)0x47eL) = Oldmediach;
                   3396: 
                   3397:        }
                   3398: 
1.1       root     3399: }
                   3400: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.