📄 cdromfslib.c
字号:
T_CDROM_FILE_ID pFD, /* cdrom file descriptor ID */ u_char * name, /* file name */ u_char * pPTRec, /* ptr to path table record */ u_int dirRecNumInPT, /* dir record no. in path table */ u_int dirRecOffInPT /* dir record offset in path table */ ) { DIR dir; BOOL absName = FALSE; T_CDROM_FILE bufFD; char * pChar; char found; assert (pVDList != NULL); assert (pFD != NULL); assert (name != NULL); DBG_MSG(300)("name = %s\n", name); /* what is the name, - absolute or to find last version? */ pChar = strchr (name, SEMICOL); if (pChar != NULL) { if (isdigit (*(pChar + 1))) absName = TRUE; else *(pChar) = EOS; } found = 0;retry: while (cdromFsIoctl (pFD, FIOREADDIR, (int)&dir) == OK) { int compRes; /* truncate current name in case last version search */ if (!absName) { pChar = strchr(dir.dd_dirent.d_name, SEMICOL); if (pChar != NULL) *pChar = EOS; } compRes = strcmp (name, dir.dd_dirent.d_name); /* names in dir are sorted lexicographically */ if (!absName && compRes < 0) break; /* any version of file found */ if (compRes == 0) { found = 1; /* if requested version */ if (absName) return (cdromFsFillFDForFile (pVDList, pFD)); bufFD = *pFD; /* safe found */ } } /* while */ if (found == 0) { /* case sensitive not found */ if (cdromFsFillFDForDir (pVDList, pFD, pPTRec, dirRecNumInPT, dirRecOffInPT) == ERROR) return ERROR; cdromFsStrUp (name, strlen(name)); found = (char)(-1); /* case insensitive */ goto retry; } if(found == (char)(-1)) return ERROR; /* not case sensitive nor insensitive found */ RESTORE_FD (bufFD, *pFD, ERROR); /* return to a last found version */ return (cdromFsFillFDForFile(pVDList, pFD)); } /********************************************************************************* cdromFsFindDirOnLevel - find directory within given PT dir hierarchy level.** This routine trys to find <name> within <dirLev>* PT dir hierarchy level, that have parent dir number <parDirNum>.* <pPT> points to PT buffer.* In <pPTRec> will be returned ptr to found PT record (if will).** RETURNS: record number or 0 if not found.*/LOCAL int cdromFsFindDirOnLevel ( T_CDROMFS_VD_LST_ID pVDList, /* ptr to volume descriptor list */ u_char * name, /* dir name to search for (EOS terminated) */ u_char * pPT, /* PT buffer */ u_int parDirNum, /* evidently */ u_int pathLev, /* level of <name> within path */ /* first path name lays on */ /* zero path level, but on second dir */ /* hierarchy level, so */ u_char ** ppRecord /* address of current PT record ptr */ ) { int offset; /* abs offset from PT start */ u_char * pUpCaseName = NULL; /* ptr to upper case name found */ u_short recNum; /* current record number */ u_short upCaseRecNum = 0; /* record number of upper case name found */ u_short curRecParent; /* current record's parent record number */ u_short nameLen; /* <name> length */ u_char upCaseName[100] = {EOS}; /* * let us path = "/d0/d1/---[/fname]" * first path name <d0> lays on zero path level, but on second directory * hierarchy level, so if Level is dir hierarchy level, on which * lays <name>, Level = <pathLev>+2, and therefore <pathLev> may * be used for encounting dir hierarchy levels' bounds arrays. */ offset = pVDList->dirLevBordersOff[ pathLev ]; pPT += offset; recNum = (pathLev == 0)? 2: pVDList->dirLevLastRecNum[ pathLev -1 ] + 1; nameLen = strlen(name); strncpy (upCaseName, name, nameLen + 1); cdromFsStrUp (upCaseName, nameLen); for (; recNum <= pVDList->dirLevLastRecNum[ pathLev ]; recNum ++, offset = cdromFsNextPTRec(&pPT, offset, pVDList->PTSize)) { int compRes; /* strncmp result */ PT_PARENT_REC (curRecParent, pPT); if (curRecParent != parDirNum || nameLen != (u_short)*pPT) continue; compRes = strncmp(name, pPT + ISO_PT_REC_DI, nameLen); if (compRes == 0) { *ppRecord = pPT; return recNum; } else if (strncmp(upCaseName, pPT + ISO_PT_REC_DI, nameLen) == 0) { pUpCaseName = pPT; upCaseRecNum = recNum; } else if (compRes < 0) /* PT records are sorted by name increasing */ break; } if (pUpCaseName == NULL) /* not found */ return 0; /* name found in upper case only */ *ppRecord = pUpCaseName; return (upCaseRecNum); } /********************************************************************************* cdromFsFindPathInDirHierar - find file/directory within given dir hierarchy.** This routine tries to find <path> within given VD dir hierarchy.* and fill in T_CDROM_FILE structure.* Path levels (dir/file names) have to be splitted by EOS.** RETURNS: OK or ERROR if path not found.*/LOCAL STATUS cdromFsFindPathInDirHierar ( T_CDROMFS_VD_LST_ID pVDList, /* ptr to volume desc list */ u_char * path, /* path */ u_int numPathLevs, /* number of names in path */ T_CDROM_FILE_ID pFD, /* FD to fill if full path found */ int options /* not used currently */ ) { int curPathLev, parDirNum; u_char * pPT; u_char * pPTRec; STATUS retStat = ERROR; assert (pVDList != NULL); assert (path != NULL); assert (pFD != NULL); /* * numPathLevs may not exceed number of directory hierarchy levels * plus one for file name */ if(numPathLevs > pVDList->numDirLevs + 1) return ERROR; pPT = cdromFsPTGet (pVDList, NULL); if (pPT == NULL) goto ret; for (curPathLev = 0, parDirNum = 1, pPTRec = pPT; curPathLev < numPathLevs && curPathLev < pVDList->numDirLevs; path += strlen(path) + 1) { parDirNum = cdromFsFindDirOnLevel (pVDList, path, pPT, parDirNum, curPathLev, &pPTRec); curPathLev++; if (parDirNum == 0) /* last name not found */ break; } if (curPathLev == numPathLevs || (curPathLev == numPathLevs - 1 && parDirNum != 0 && curPathLev == pVDList->numDirLevs) ) { retStat = cdromFsFillFDForDir (pVDList, pFD, pPTRec, parDirNum, 0 /* not use now, since PT is read * wholly */ ); if (retStat == ERROR || (parDirNum != 0 && curPathLev == numPathLevs)) /* path found */ goto ret; } else goto ret; retStat = cdromFsFindFileInDir (pVDList, pFD, path, pPTRec, parDirNum, 0); ret: return retStat; } /********************************************************************************* cdromFsFindPath - find file/directory on given volume.** This routine trys to find <path> within all volume* primary/supplementary directory hierarcies and creates and fills in* T_CDROM_FILE structure for following accsess.* levels in path have to be splitted by '\' or '/'.** ERRNO: S_cdromFsLib_MAX_DIR_LEV_OVERFLOW* S_cdromFsLib_NO_SUCH_FILE_OR_DIRECTORY** RETURNS: T_CDROM_FILE_ID or NULL if any error encounted.*/LOCAL T_CDROM_FILE_ID cdromFsFindPath ( CDROM_VOL_DESC_ID pVolDesc, /* ptr to volume descriptor */ u_char * path, /* path */ int options /* search options */ ) { T_CDROMFS_VD_LST_ID pVDList; T_CDROM_FILE_ID pFD; u_char pPath[ CDROM_MAX_PATH_LEN + 1 ] = {EOS}; u_int numPathLevs; assert (pVolDesc != NULL); assert (path != NULL); #ifndef ERR_SET_SELF errnoSet(OK);#else errno = OK;#endif /* prepare path for processing (split to distinct directorys/file names) */ strncpy (pPath, path, CDROM_MAX_PATH_LEN); path = pPath; numPathLevs = cdromFsSplitPath (path); if (numPathLevs == (-1)) return (T_CDROM_FILE_ID)ERROR; if (numPathLevs > CDROM_MAX_DIR_LEV + 1) /* one for file */ { errnoSet (S_cdromFsLib_MAX_DIR_HIERARCHY_LEVEL_OVERFLOW); return (T_CDROM_FILE_ID) ERROR; } /* allocate T_CDROM_FILE structure */ pFD = cdromFsFDAlloc (pVolDesc); if (pFD == NULL) return (T_CDROM_FILE_ID)ERROR; for (pVDList = (T_CDROMFS_VD_LST_ID) lstFirst (&(pVolDesc->VDList)); pVDList != NULL; pVDList = (T_CDROMFS_VD_LST_ID) lstNext ((NODE *)pVDList)) { if (cdromFsFindPathInDirHierar (pVDList, path, numPathLevs, pFD, options) == OK) return pFD; } /* file/directory not found */ cdromFsFDFree (pFD); if (errnoGet() == OK) errnoSet (S_cdromFsLib_NO_SUCH_FILE_OR_DIRECTORY); return (T_CDROM_FILE_ID)ERROR; }/********************************************************************************* cdromFsFillStat - filling of stat structure ** This routine transfers data from T_CDROM_FILE structure to stat structure* defined in <sys/stat.h>** RETURNS: OK or ERROR if it cannot fill stat structure*/LOCAL STATUS cdromFsFillStat ( T_CDROM_FILE_ID fd, /* File descriptor */ struct stat * arg /* Pointer to stat structure */ ) { u_char *ptr; /* pointer to LogBlock */ struct tm recTime; /* temp. structure */ short tmp = 0; /* to form permission flags */ short tmp2 = 0; /* to convert flags from EAR */ arg->st_blksize = fd->pVDList->LBSize; /* We read by LogBlocks */ if (fd->FType == S_IFDIR) /* In the case of directory */ { ptr = cdromFsGetLB (fd->pVDList, fd->FStartLB, &(fd->sectBuf)); if (ptr == NULL) return ERROR; /* pointer to a sequence of Dir. Records, not data */ ptr += fd->FDataStartOffInLB; } else { ptr = fd->FRecords; /* In the case of File Section */ } arg->st_size = fd->FSize; arg->st_blocks = A_PER_B (fd->pVDList->LBSize, fd->FSize); /* time fields */ recTime.tm_sec = fd->FDateTime.seconds; recTime.tm_min = fd->FDateTime.minuts; recTime.tm_hour = fd->FDateTime.hour; recTime.tm_mday = fd->FDateTime.day; recTime.tm_mon = fd->FDateTime.month - 1; recTime.tm_year = fd->FDateTime.year; fd->FDateTimeLong = mktime (&recTime); /* * The DOS-FS time fields are not supported from VxWorks 5.2 * and above, but REQUIRED for 5.1.1 and lower to see valid * file dates. */#ifdef VXWORKS_511 arg->st_fYear = fd->FDateTime.year + 1900; arg->st_fMonth = fd->FDateTime.month; arg->st_fDay = fd->FDateTime.day; arg->st_fHour = fd->FDateTime.hour; arg->st_fMinute = fd->FDateTime.minuts; arg->st_fSecond = fd->FDateTime.seconds; fd->FDateTimeLong = 0;#endif /* VXWORKS_511 */ arg->st_atime = arg->st_mtime = arg->st_ctime = fd->FDateTimeLong; /* bits of permissions processing */ if (*(ptr + ISO_DIR_REC_FLAGS) & DRF_PROTECT) { if (*(ptr + ISO_DIR_REC_EAR_LEN) == 0) /* EAR must appear */ { errnoSet (S_cdromFsLib_INVALID_DIR_REC_STRUCT); return ERROR; } /* Read ExtAttrRecord */ ptr = cdromFsGetLB (fd->pVDList, fd->FStartLB - *(ptr + ISO_DIR_REC_EAR_LEN), &(fd->sectBuf)); if (ptr == NULL) return ERROR; /* * Now we should transfer permission bits from ExtAttrRec * Sequential reading of two bytes (processor independent) */ tmp2 = (*(ptr + ISO_EAR_PERMIT) << 8) | *(ptr + ISO_EAR_PERMIT + 1); tmp |= (tmp2 & 0x01) ? 0 : S_IROTH; tmp |= (tmp2 & 0x04) ? 0 : S_IXOTH; tmp |= (tmp2 & 0x10) ? 0 : S_IRUSR; tmp |= (tmp2 & 0x40) ? 0 : S_IXUSR; tmp |= (tmp2 & 0x100) ? 0 : S_IRGRP; tmp |= (tmp2 & 0x400) ? 0 : S_IXGRP; tmp |= (tmp2 & 0x1000) ? 0 : S_IROTH; tmp |= (tmp2 & 0x4000) ? 0 : S_IXOTH; } else { /* Every user has rights to read and execute */ tmp = S_ISUID | S_ISGID | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; } arg->st_mode = fd->FType | tmp; /* not fd->FDType */ return OK; }/********************************************************************************* cdromFsCountMdu - counts current position offset in MDU ** This function counts only one value contained in a file descriptor of* cdromFs system - FCDOffInMDU. For this purpose reading of the file itself* is necessary (sequential, record after record). It is assumed that* absolute position of file pointer is written in the fd, and the previous* file pointer posit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -