📄 rt11fslib.c
字号:
nameLen = strlen (pDir->dd_dirent.d_name); if (nameLen > 0) { pChar = (pDir->dd_dirent.d_name + nameLen - 1); while ((*pChar == ' ') || (*pChar == '.')) { *pChar = EOS; pChar--; } } pDir->dd_cookie = entryNum; /* copy updated entry number */ semGive (vdptr->vd_semId); return (OK); }/********************************************************************************* rt11FsFileStatGet - get file status info from directory entry** This routine is called via an ioctl() call, using the FIOFSTATGET* function code. The passed stat structure is filled, using data* obtained from the directory entry which describes the file.** RETURNS: OK (always).*/LOCAL STATUS rt11FsFileStatGet ( FAST RT_FILE_DESC *pFd, /* pointer to file descriptor */ FAST struct stat *pStat /* structure to fill with data */ ) { struct tm fileDate; bzero ((char *) pStat, sizeof (struct stat)); /* zero out stat struct */ /* Fill stat structure */ pStat->st_dev = (ULONG) pFd->rfd_vdptr; /* device ID = DEV_HDR addr */ pStat->st_ino = 0; /* no file serial number */ pStat->st_nlink = 1; /* always only one link */ pStat->st_uid = 0; /* no user ID */ pStat->st_gid = 0; /* no group ID */ pStat->st_rdev = 0; /* no special device ID */ pStat->st_size = (pFd->rfd_dir_entry.de_nblocks * RT_BYTES_PER_BLOCK); /* file size, in bytes */ pStat->st_blksize = 0; pStat->st_blocks = 0; pStat->st_attrib = 0; /* no file attribute byte */ /* * Fill in the timestamp fields */ bzero ((char *) &fileDate, sizeof (fileDate)); fileDate.tm_mday = (pFd->rfd_dir_entry.de_date >> 5) & 0x001f; /* Need to adjust if day == 0 ; ANSI days run 1-31, zero isn't valid */ if (fileDate.tm_mday == 0) fileDate.tm_mday = 1; fileDate.tm_mon = (pFd->rfd_dir_entry.de_date >> 10) & 0x000f; /* RT11 uses 1972 as the starting date, ANSI uses 1900; adjust by 72 yrs */ fileDate.tm_year = (pFd->rfd_dir_entry.de_date & 0x001f) + 72; /* Set access, change, and modify times all to the value for de_date */ pStat->st_atime = pStat->st_mtime = pStat->st_ctime = mktime (&fileDate); /* Set mode field (if whole volume opened, mark as directory) */ if (pFd->rfd_dir_entry.de_status == DES_BOGUS) pStat->st_mode = S_IFDIR; /* raw vol = dir */ else pStat->st_mode = S_IFREG; /* regular file */ pStat->st_mode |= (S_IRWXU | S_IRWXG | S_IRWXO); /* default privileges are * read-write-execute for all */ return (OK); }/********************************************************************************* rt11FsFindEntry - find a directory entry by name on an RT-11 volume** This routines searches for the directory entry of the specified file* <name> from the specified volume, if it exists.** Possession of the volume descriptor semaphore must have been secured* before this routine is called.** RETURNS:* Entry number if found, or* ERROR if file not found.*/LOCAL int rt11FsFindEntry ( FAST RT_VOL_DESC *vdptr, /* pointer to volume descriptor */ char *name, /* RT-11 filename (ffffff.ttt) */ int *pstart /* pointer where to return start block number */ ) { RT_DIR_ENTRY entry; RT_NAME name_r50; FAST int i; /* Ignore any leading "/" or "\"'s in file name */ while ((*name == '/') || (*name == '\\')) name++; /* search entire directory for active entry matching specified name. * keep track of start block by accumulating entry lengths. */ rt11FsNameR50 (name, &name_r50); *pstart = vdptr->vd_dir_seg->ds_start; for (i = 0; ; i++) { rt11FsGetEntry (vdptr, i, &entry); /* if this is the end of the directory, then file not found. */ if (entry.de_status == DES_END) { errnoSet (S_rt11FsLib_FILE_NOT_FOUND); return (ERROR); } /* check if this is the desired file */ if (((entry.de_status == DES_PERMANENT) || (entry.de_status == DES_TENTATIVE)) && (entry.de_name.nm_name1 == name_r50.nm_name1) && (entry.de_name.nm_name2 == name_r50.nm_name2) && (entry.de_name.nm_type == name_r50.nm_type)) { return (i); } /* entry doesn't match; * add file length to get start of next file; bump to next entry */ *pstart += entry.de_nblocks; } }/********************************************************************************* rt11FsFlush - flush RT-11 file output buffer** This routine guarantees that any output that has been requested* is actually written to the disk. In particular, writes that have* been buffered are written to the disk.** RETURNS:* OK, or ERROR if unable to write.*/LOCAL STATUS rt11FsFlush ( FAST RT_FILE_DESC *pFd /* pointer to file descriptor */ ) { int block; if (pFd->rfd_modified) { /* write out the current (dirty) block and reset 'modified' indicator */ block = pFd->rfd_start + (pFd->rfd_curptr / RT_BYTES_PER_BLOCK); if (rt11FsWrtBlock (pFd->rfd_vdptr, block, 1, pFd->rfd_buffer) != OK) return (ERROR); pFd->rfd_modified = FALSE; } return (OK); }/********************************************************************************* rt11FsFreeFd - free a file descriptor*/LOCAL void rt11FsFreeFd ( RT_FILE_DESC *pFd /* pointer to file descriptor to free */ ) { semTake (rt11FsFdSemId, WAIT_FOREVER); pFd->rfd_status = NOT_IN_USE; semGive (rt11FsFdSemId); }/********************************************************************************* rt11FsGetFd - get an available file descriptor** RETURNS: pointer to file descriptor, or NULL if none available.*/LOCAL RT_FILE_DESC *rt11FsGetFd (void) { FAST RT_FILE_DESC *pRtFd; FAST int i; semTake (rt11FsFdSemId, WAIT_FOREVER); for (i = 0, pRtFd = &rt11FsFd [0]; i < rt11FsMaxFiles; i++, pRtFd++) { if (pRtFd->rfd_status == NOT_IN_USE) { pRtFd->rfd_status = OK; semGive (rt11FsFdSemId); return (pRtFd); } } semGive (rt11FsFdSemId); errnoSet (S_rt11FsLib_NO_FREE_FILE_DESCRIPTORS); return (NULL); }/********************************************************************************* rt11FsGetEntry - get a directory entry from an RT-11 volume** This routines gets the specified directory entry from the specified* volume.** Possession of the volume descriptor semaphore must have been secured* before this routine is called.** RETURNS: a copy of the requested entry.*/LOCAL void rt11FsGetEntry ( RT_VOL_DESC *vdptr, /* pointer to volume descriptor */ int entryNum, /* number of entry to get (first entry = 0) */ RT_DIR_ENTRY *pEntry /* pointer where to return directory entry */ ) { bcopy ((char *) &(vdptr->vd_dir_seg->ds_entries[entryNum]), (char *) pEntry, sizeof (RT_DIR_ENTRY)); }/********************************************************************************* rt11FsInit - prepare to use the rt11Fs library** This routine initializes the rt11Fs library. It must be called exactly* once, before any other routine in the library. The <maxFiles> parameter* specifies the number of rt11Fs files that may be open at once. This* routine initializes the necessary memory structures and semaphores.** This routine is called automatically from the root task, usrRoot(),* in usrConfig.c when the configuration macro INCLUDE_RT11FS is defined.** RETURNS:* OK, or ERROR if memory is insufficient.*/STATUS rt11FsInit ( int maxFiles /* max no. of simultaneously */ /* open rt11Fs files */ ) { int i; /* Install rt11FsLib routines in I/O system driver table */ rt11FsDrvNum = iosDrvInstall ((FUNCPTR) rt11FsCreate, rt11FsDelete, (FUNCPTR) rt11FsOpen, rt11FsClose, rt11FsRead, rt11FsWrite, rt11FsIoctl); if (rt11FsDrvNum == ERROR) return (ERROR); /* can't install as driver */ /* initialize interlocking of file descriptor list access */ rt11FsFdSemId = semCreate (); semGive (rt11FsFdSemId); rt11FsMaxFiles = maxFiles; rt11FsFd = (RT_FILE_DESC *) malloc ((unsigned) (rt11FsMaxFiles * sizeof (RT_FILE_DESC))); if (rt11FsFd == (RT_FILE_DESC *) NULL) return (ERROR); for (i = 0; i < rt11FsMaxFiles; i++) rt11FsFreeFd (&rt11FsFd[i]); return (OK); }/********************************************************************************* rt11FsInsEntry - insert a new directory entry on an RT-11 volume** This routines inserts the specified directory entry into the specified* volume at the specified entry index.** Possession of the volume descriptor semaphore must have been secured* before this routine is called.** NOTE: Currently this routine does not handle the case of attempting* to add an entry to a full directory.*/LOCAL void rt11FsInsEntry ( RT_VOL_DESC *vdptr, /* pointer to volume descriptor */ int entryNum, /* number of entry to insert (first entry = 0) */ RT_DIR_ENTRY *pEntry /* pointer to entry to insert */ ) { RT_DIR_ENTRY previous_entry; RT_DIR_ENTRY entry; /* replace current entry at entryNum with new */ rt11FsGetEntry (vdptr, entryNum, &entry); rt11FsPutEntry (vdptr, entryNum, pEntry); /* replace each entry with the previous */ while (entry.de_status != DES_END) { previous_entry = entry; entryNum++; rt11FsGetEntry (vdptr, entryNum, &entry); rt11FsPutEntry (vdptr, entryNum, &previous_entry); } /* put end-marker entry in next slot */ rt11FsPutEntry (vdptr, entryNum + 1, &entry); }/********************************************************************************* rt11FsIoctl - do device specific control function** This routine performs the following ioctl() functions:** .CS* FIODISKINIT: Initialize the disk volume. This routine does not* format the disk, this must be done by the driver.* FIODIRENTRY: Returns pointer to the next dir entry, into* the REQ_DIR_ENTRY pointed to by arg.* FIORENAME: Rename the file to the string pointed to by arg.* FIOSEEK: Sets the file's current byte position to* the position specified by arg.* FIOWHERE: Returns the current byte position in the file.* FIOFLUSH: Flush file output buffer.* Guarantees that any output that has been requested* is actually written to the device.* FIONREAD: Return in arg the number of unread bytes.* FIODISKCHANGE: Indicate media change. See rt11FsReadyChange().* FIOSQUEEZE: Reclaim fragmented free space on RT-11 volume* FIOREADDIR: Read one entry from directory and return file name.* FIOFSTATGET: Get file status info from directory entry.* FIOGETFL: Return in arg the file's open mode.* .CE** Any ioctl() functions which cannot be handled by rt11FsLib are passed to* the device driver.** If an ioctl() fails, the task status (see errnoGet()) indicates* the nature of the error.** RETURNS:* OK, or* ERROR if function failed or unknown function, or* current byte pointer for FIOWHERE.**/LOCAL STATUS rt11FsIoctl ( RT_FILE_DESC *pFd, /* file descriptor of file to control */ int function, /* function code */ int arg /* some argument */ ) { int where;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -