|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.