📄 rt11fslib.c
字号:
switch (function) { case FIODISKINIT: return (rt11FsVolInit (pFd->rfd_vdptr)); case FIODIRENTRY: return (rt11FsDirEntry (pFd->rfd_vdptr, (REQ_DIR_ENTRY *)arg)); case FIORENAME: return (rt11FsRename (pFd, (char *)arg)); case FIOSEEK: return (rt11FsSeek (pFd, arg)); case FIOWHERE: return (rt11FsWhere (pFd)); case FIOFLUSH: return (rt11FsFlush (pFd)); case FIONREAD: if ((where = rt11FsWhere (pFd)) == ERROR) return (ERROR); *((int *) arg) = pFd->rfd_endptr - where; return (OK); case FIODISKCHANGE: rt11FsReadyChange (pFd->rfd_vdptr); return (OK); case FIOSQUEEZE: return (rt11FsSqueeze (pFd->rfd_vdptr)); case FIOREADDIR: return (rt11FsDirRead (pFd, (DIR *) arg)); case FIOFSTATGET: return (rt11FsFileStatGet (pFd, (struct stat *) arg)); case FIOGETFL: *((int *) arg) = pFd->rfd_mode; return (OK); default: /* Call device driver function */ return ((* pFd->rfd_vdptr->vd_pBlkDev->bd_ioctl) (pFd->rfd_vdptr->vd_pBlkDev, function, arg)); } }/********************************************************************************* rt11FsMkfs - initialize a device and create an rt11Fs file system** This routine provides a quick method of creating an rt11Fs file system on* a device. It is used instead of the two-step procedure of calling* rt11FsDevInit() followed by an ioctl() call with an FIODISKINIT function* code.** This routine provides defaults for the rt11Fs parameters expected by* rt11FsDevInit(). The directory size is set to RT_FILES_FOR_2_BLOCK_SEG* (defined in rt11FsLib.h). No standard disk format is assumed; this* allows the use of rt11Fs on block devices with an odd number of sectors per* track. The <changeNoWarn> parameter is defined as FALSE, * indicating that the disk will not be replaced without rt11FsReadyChange() * being called first.** If different values are needed for any of these parameters, the routine* rt11FsDevInit() must be used instead of this routine, followed by a* request for disk initialization using the ioctl() function FIODISKINIT.** RETURNS: A pointer to an rt11Fs volume descriptor (RT_VOL_DESC),* or NULL if there is an error.** SEE ALSO: rt11FsDevInit()*/RT_VOL_DESC *rt11FsMkfs ( char *volName, /* volume name to use */ BLK_DEV *pBlkDev /* pointer to block device struct */ ) { FAST RT_VOL_DESC *vdptr; /* pointer to RT-11 volume descriptor */ vdptr = rt11FsDevInit (volName, /* name */ pBlkDev, /* device to use */ FALSE, /* no std RT11 format */ RT_FILES_FOR_2_BLOCK_SEG, /* dir size */ FALSE); /* no changeNoWarn */ if (vdptr == NULL) return (NULL); if (rt11FsVolInit (vdptr) != OK) return (NULL); return (vdptr); }/********************************************************************************* rt11FsNameR50 - convert ASCII string to radix-50 RT-11 name** This routine converts the specified ASCII string to an RT-11 name.* The <string> must be of the form "ffffff.ttt" and be null terminated.** If characters are in <string> that don't exist in the radix-50 world,* undefined things will happen.*/LOCAL void rt11FsNameR50 ( char *string, /* pointer to ASCII string to convert */ RT_NAME *pName /* pointer where to return RT-11 radix-50 name struct */ ) { char tstring [RT_NAME_LEN]; FAST char *dot; /* get local copy of string and make sure it's terminated */ (void) strncpy (tstring, string, RT_NAME_LEN - 1); tstring [RT_NAME_LEN - 1] = EOS; /* find the dot, if any; convert extension; and replace dot w/EOS */ dot = index (tstring, '.'); if (dot == 0) pName->nm_type = 0; else { *dot = EOS; pName->nm_type = rt11FsR50out (dot + 1); } /* convert name part 1 then part 2 if more */ pName->nm_name1 = rt11FsR50out (tstring); if (strlen (tstring) <= 3) pName->nm_name2 = 0; else pName->nm_name2 = rt11FsR50out (tstring + 3); }/********************************************************************************* rt11FsR50out - convert up to 3 ASCII characters to radix-50** RETURNS: radix-50 equivalent of first 3 chars of <string>.*/LOCAL int rt11FsR50out ( FAST char *string /* string to convert */ ) { unsigned int r50 = 0; int r; int i; char ch; for (i = 0; i < 3; i++) { if (*string == EOS) r = 0; else { ch = *string; if (isupper (ch)) ch = tolower (ch); r = (char *) index (rad50, ch) - rad50; string++; } r50 = (r50 * 050) + r; } return (r50); }/********************************************************************************* rt11FsNameString - convert radix-50 RT-11 name to ASCII string** This routine converts the specified RT-11 <name> into an ASCII string* of the form "ffffff.ttt" and null terminated.*/LOCAL void rt11FsNameString ( RT_NAME name, /* RT-11 radix-50 name structure */ FAST char *string /* pointer to receive ASCII string */ ) { FAST char *pStr; /* index into string */ rt11FsR50in (name.nm_name1, string); rt11FsR50in (name.nm_name2, string + 3); for (pStr = string; (pStr < (string + 6)) && (*pStr != ' '); ++pStr) ; /* prepare to overwrite trailing blanks */ *pStr++ = '.'; rt11FsR50in (name.nm_type, pStr); *(pStr + 3) = EOS; }/********************************************************************************* rt11FsR50in - convert radix-50 to 3 ASCII characters*/LOCAL void rt11FsR50in ( unsigned int r50, /* radix-50 number to convert */ char *string /* where to put resulting string */ ) { FAST int i; for (i = 2; i >= 0; i--) { string [i] = rad50 [r50 % 050]; r50 /= 050; } }/********************************************************************************* rt11FsOpen - open a file on an RT-11 volume** This routine opens the file <name> with the specified <mode>.* The volume directory is searched, and if the file is found* an RT-11 file descriptor is initialized for it.** The directory currently in memory for the volume is used unless there* has been a ready change (rt11FsReadyChange()) or this is the very first* open. If that is the case, the directory will be read from the disk* automatically.** A null file <name> is treated specially, to open an entire disk.* In this case, no attempt is made to access the disk directory, so that* even un-initialized disks may be accessed.** RETURNS:* A pointer to the RT-11 file descriptor, or* ERROR if the volume not available or* no RT-11 file descriptors are available or* there is no such file.*/LOCAL RT_FILE_DESC *rt11FsOpen ( RT_VOL_DESC *vdptr, /* pointer to volume descriptor */ char *name, /* RT-11 filename (ffffff.ttt) */ int mode /* file mode (O_RDONLY/O_WRONLY/O_RDWR) */ ) { int start; int entryNum; FAST RT_FILE_DESC *pFd; /* file descriptor pointer */ /* Call driver check-status routine, if any */ if (vdptr->vd_pBlkDev->bd_statusChk != NULL) { if ((* vdptr->vd_pBlkDev->bd_statusChk) (vdptr->vd_pBlkDev) != OK) { return ((RT_FILE_DESC *) ERROR); } } /* Set up for re-mount if no disk change notification */ if (vdptr->vd_changeNoWarn == TRUE) rt11FsReadyChange (vdptr); /* get a free file descriptor */ pFd = rt11FsGetFd (); /* file descriptor pointer */ if (pFd == NULL) return ((RT_FILE_DESC *) ERROR); /* check for O_CREAT and O_TRUNC mode */ if ((mode & O_CREAT) || (mode & O_TRUNC)) { /*XXX O_CREAT and O_TRUNC are masked off because several rt11FsLib * routines use rt11FsVolMode() to check the mode of a file by * arithmetic comparison instead of by boolean comparison of * specific bits. */ mode &= ~O_CREAT; /* create the file if it does not exist or O_TRUNC is set */ if ((mode & O_TRUNC) || (rt11FsFindEntry (vdptr, name, &start) == ERROR)) { mode &= ~O_TRUNC; rt11FsFreeFd (pFd); return (rt11FsCreate (vdptr, name, mode)); } } /* check for open of raw device (null filename) */ if (name [0] == EOS) { /* check that volume is available */ semTake (vdptr->vd_semId, WAIT_FOREVER); if (rt11FsCheckVol (vdptr, FALSE) != OK) { semGive (vdptr->vd_semId); rt11FsFreeFd (pFd); errnoSet (S_rt11FsLib_VOLUME_NOT_AVAILABLE); return ((RT_FILE_DESC *) ERROR); } if (rt11FsVolMode (vdptr) < mode) { semGive (vdptr->vd_semId); rt11FsFreeFd (pFd); errnoSet (S_ioLib_WRITE_PROTECTED); return ((RT_FILE_DESC *) ERROR); } semGive (vdptr->vd_semId); /* null name is special indicator for "raw" disk; * fabricate a bogus directory entry covering entire volume */ start = 0; pFd->rfd_dir_entry.de_status = DES_BOGUS; pFd->rfd_dir_entry.de_date = rt11FsDate (rt11FsYear, rt11FsMonth, rt11FsDay); pFd->rfd_dir_entry.de_nblocks = vdptr->vd_nblocks; rt11FsNameR50 ("device.raw", &pFd->rfd_dir_entry.de_name); } else { /* check that volume is available */ semTake (vdptr->vd_semId, WAIT_FOREVER); if ((rt11FsCheckVol (vdptr, TRUE) != OK) || (vdptr->vd_status != OK)) { semGive (vdptr->vd_semId); rt11FsFreeFd (pFd); errnoSet (S_rt11FsLib_VOLUME_NOT_AVAILABLE); return ((RT_FILE_DESC *) ERROR); } if (rt11FsVolMode (vdptr) < mode) { semGive (vdptr->vd_semId); rt11FsFreeFd (pFd); errnoSet (S_ioLib_WRITE_PROTECTED); return ((RT_FILE_DESC *) ERROR); } /* find specified file name in directory */ if ((entryNum = rt11FsFindEntry (vdptr, name, &start)) == ERROR) { semGive (vdptr->vd_semId); /* release volume */ rt11FsFreeFd (pFd); return ((RT_FILE_DESC *) ERROR); } rt11FsGetEntry (vdptr, entryNum, &pFd->rfd_dir_entry); semGive (vdptr->vd_semId); /* release volume */ } /* initialize file descriptor */ pFd->rfd_mode = mode; pFd->rfd_vdptr = vdptr; pFd->rfd_start = start; pFd->rfd_curptr = NONE; pFd->rfd_newptr = 0; pFd->rfd_endptr = pFd->rfd_dir_entry.de_nblocks * RT_BYTES_PER_BLOCK; pFd->rfd_modified = FALSE; return (pFd); }/********************************************************************************* rt11FsPutEntry - put directory entry of RT-11 file** This routines puts the specified directory entry of the specified* volume. The first entry is #0.** Posession of the volume descriptor's semaphor
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -