📄 cdromfslib.c
字号:
{ semGive (pVolDesc->mDevSem); logMsg ("Warning: unknown CD-ROM format detected, ignored.\n", 0,0,0,0,0,0); errnoSet (S_cdromFsLib_UNNOWN_FILE_SYSTEM); return ERROR; } /* device successfully mounted */ pVolDesc->unmounted = 0; /* return semaphore */ if (semGive (pVolDesc->mDevSem) == ERROR) { cdromFsVolUnmount (pVolDesc); errnoSet (S_cdromFsLib_SEMGIVE_ERROR); return ERROR; } return OK; }/********************************************************************************* cdromFsSplitPath - split path to sequential directories/file names.** Names in <path> must be separate by '\' or '/'. Content of path* is changed by the routine.* The routine overwrites '/' and '\' by '\0', to break the path to* distinct directorys/file names, counting path levels by the way.* xx//yy and xx/./yy cases are just truncated from the path;* in xx/../yy case level xx/.. is "caved" from path.* As result path looks like just d1\0d2\0---dn\0f.** RETURNS: number of names within path or (-1).*/LOCAL int cdromFsSplitPath ( u_char * path /* file / directory path */ ) { u_char * prevPathLev; u_char * curName; u_char * ptr; int lev, pathLen, len; if (*path == EOS) return 0; pathLen = strlen(path) + 1; /* include EOS */ /* * truncate from path some special cases such as * xx//yy, xx/./yy, xx/../yy and replace '/', '\' to '\0' */ curName = path; for (ptr = path, lev = 0 ; ptr != NULL;) { /* find '/' */ ptr = (u_char *) strchr (curName, SLASH); if (ptr == NULL) ptr = (u_char *) strchr (curName, BACK_SLASH); if (ptr != NULL) *ptr = EOS; len = strlen (curName) + 1; /* include EOS */ pathLen = max (pathLen - len, 0); /* length of the rest */ /* xx//yy, xx/./yy */ if ((*curName == POINT && *(curName + 1) == EOS) || (*curName == EOS)) { memmove(curName, curName + len, pathLen); } /* xx/../yy, in this case 'xx' will be deleted from path */ else if (*curName == POINT && *(curName + 1) == POINT && *(curName + 2) == EOS) { /* return to the previous level name (if it may be done) */ if (lev > 0) { for (prevPathLev = curName - 2; *(prevPathLev - 1) != EOS && prevPathLev != path; prevPathLev --); } else { *path = EOS; return (0); } /* go one level down */ memmove (prevPathLev, curName + len, pathLen); curName = prevPathLev; lev --; } /* normal case */ else { lev ++; curName += len; } } /* for */ return lev; }/******************************************************************************** * cdromFsFillFDForDir - fill T_CDROM_FILE for directory (only from PT record).** This routine fill in fields of T_CDROM_FILE structure (ptr on with* comes in <pFD>) for directory, that is described by <pPTRec> PT record** RETURNS: OK or ERROR if malloc() or disk access error occur.*/LOCAL STATUS cdromFsFillFDForDir ( T_CDROMFS_VD_LST_ID pVDList, /* ptr to VD list */ T_CDROM_FILE_ID pFD, /* FD to fill */ u_char * pPTRec, /* directory PT record */ u_int dirRecNumInPT, /* dir number in PT */ u_int dirRecOffInPT /* dir rec offset from PT start */ ) { u_short EARSize; assert (pVDList != NULL); assert (pVDList->magic == VD_LIST_MAG); assert (pVDList->pVolDesc != NULL); assert (pVDList->pVolDesc->magic == VD_SET_MAG); assert (pFD != NULL); assert (pPTRec != NULL); assert (*pPTRec != 0); /* DIR ID Length */ /* * These fields are not needed to be filled for a directory: * pFD->parentDirPTOffset; * pFD->parentDirStartLB; * pFD->FFirstRecLBNum; * pFD->FFirstDirRecOffInDir; * pFD->FFirstDirRecOffInLB; * pFD->FRecords; * pFD->FCSStartLB; * pFD->FCSFUSizeLB; * pFD->FCSGapSizeLB; * pFD->FCDOffInMDU; * pFD->FCMDUStartLB; */ bzero (pFD->name, sizeof (pFD->name)); bcopy (pPTRec + ISO_PT_REC_DI, pFD->name, *pPTRec); PT_PARENT_REC (pFD->parentDirNum, pPTRec); C_BUF_TO_LONG (pFD->FStartLB, pPTRec, ISO_PT_REC_EXTENT_LOCATION); EARSize = *(pPTRec + ISO_PT_REC_EAR_LEN); pFD->FStartLB += EARSize; pFD->FDataStartOffInLB = 0; /* * Directory is stored as one extension, without records and * interleaving */ pFD->FMDUType = EAR_REC_FORM_IGNORE; pFD->FMDUSize = 0; pFD->FCSInterleaved = CDROM_NOT_INTERLEAVED; pFD->FType = S_IFDIR; /* init buffer for device access */ if (cdromFsSectBufAlloc (pVDList->pVolDesc, &(pFD->sectBuf), 0) == ERROR) return ERROR; /* current condition for readDir call */ pFD->FCDirRecNum = 0; pFD->FCDirRecAbsOff = 0; pFD->FCDirRecOffInLB= 0; pFD->FCDirRecLB = pFD->FStartLB; pFD->FCSAbsOff = 0; /* start position */ pFD->FCSSequenceSetNum = pVDList->volSeqNum; pFD->FDType = (u_short)(-1); /* not one request was served */ pFD->FCDAbsLB = pFD->FStartLB; pFD->FCDAbsPos = 0; pFD->FCDOffInLB = 0; pFD->FNumRecs = 0; pFD->FCEOF = 0; /* some directory specific fields */ pFD->DNumInPT = dirRecNumInPT; pFD->DRecOffInPT = dirRecOffInPT; pFD->DRecLBPT = 0; /* * TBD: not need currently. May be counted in * principal by parent function */ pFD->DRecOffLBPT = 0; /* read first directory record and get special dir descriptions */ pPTRec = cdromFsGetLB (pVDList, pFD->FStartLB, &(pFD->sectBuf)); if (pPTRec == NULL) { cdromFsSectBufFree (&(pFD->sectBuf)); return ERROR; } pFD->FCDirRecPtr = pPTRec; /* first directory record must contain 0x00 as name */ if (*(pPTRec + ISO_DIR_REC_FI) != 0) { errnoSet (S_cdromFsLib_INVALID_DIRECTORY_STRUCTURE); cdromFsSectBufFree (&(pFD->sectBuf)); return ERROR; } C_BUF_TO_LONG (pFD->FSize, pPTRec, ISO_DIR_REC_DATA_LEN); pFD->FCSSize = pFD->FSize; pFD->FCSSizeLB = A_PER_B (pVDList->LBSize, pFD->FCSSize); pFD->FCSFlags = *(pPTRec + ISO_DIR_REC_FLAGS); /* fill FAbsTime field (u_long time format) */ pFD->FDateTime = *(T_FILE_DATE_TIME_ID)(pPTRec + ISO_DIR_REC_DATA_TIME); pFD->pVDList = pVDList; pFD->volUnmount = 0; pFD->magic = FD_MAG; /* connect to volume's FD list */ if (!pFD->inList) lstAdd (&(pVDList->pVolDesc->FDList), (NODE *)pFD); pFD->inList = 1; return OK; }/********************************************************************************* cdromFsFillFDForFile - fill T_CDROM_FILE for file (from file's dir record).** At the beginning, pFD points to FD, which contains description of file* parent directory, and exact file's entry as encounted over* internal cdromFsIoctl readDir calls.* This routine fill in the fields of T_CDROM_FILE structure, pointed by <pFD>,* for file, exchanging its previous content.** RETURNS: OK or ERROR.*/LOCAL STATUS cdromFsFillFDForFile ( T_CDROMFS_VD_LST_ID pVDList, /* ptr to vol desc list */ T_CDROM_FILE_ID pFD /* FD to fill, containing parent */ /* directory description currently */ ) { T_CDROM_FILE workFD; u_short EARSize; u_char * pDirRec; u_long dirRecsTotSize; /* all file's dir records total size */ struct tm recTime; assert (pVDList != NULL); assert (pVDList->magic == VD_LIST_MAG); assert (pFD != NULL); /* count total size file's dir records */ /* for return to current state, let store pFD */ workFD = *pFD; /* skip all records */ do { dirRecsTotSize = *(pFD->FCDirRecPtr); } while (cdromFsSkipDirRec (pFD, DRF_LAST_REC) == OK); /* restore initial state */ RESTORE_FD (workFD, *pFD, ERROR); /* ptr to first file's dir record */ pDirRec = pFD->FCDirRecPtr; /* init workFD */ bzero (&workFD, sizeof(workFD)); workFD.sectBuf = pFD->sectBuf; workFD.FRecords = malloc (dirRecsTotSize); if (workFD.FRecords == NULL) return ERROR; /* fill static file data */ bcopy (pDirRec + ISO_DIR_REC_FI, workFD.name, *(pDirRec + ISO_DIR_REC_LEN_FI)); C_BUF_TO_LONG (workFD.FStartLB, pDirRec, ISO_DIR_REC_EXTENT_LOCATION); EARSize = *(pDirRec + ISO_DIR_REC_EAR_LEN); workFD.FStartLB += EARSize; workFD.FDataStartOffInLB = 0; workFD.FFirstRecLBNum = pFD->FCDirRecLB; workFD.FFirstDirRecOffInLB = pFD->FCDirRecOffInLB; workFD.FType = S_IFREG; /* fill FAbsTime field (u_long time format) */ workFD.FDateTime = *(T_FILE_DATE_TIME_ID)(pDirRec + ISO_DIR_REC_DATA_TIME); recTime.tm_sec = pFD->FDateTime.seconds; recTime.tm_min = pFD->FDateTime.minuts; recTime.tm_hour = pFD->FDateTime.hour; recTime.tm_mday = pFD->FDateTime.day; recTime.tm_mon = pFD->FDateTime.month - 1; recTime.tm_year = pFD->FDateTime.year; workFD.FDateTimeLong = mktime(&recTime); /* parent directory description */ workFD.parentDirNum = pFD->DNumInPT; workFD.parentDirPTOffset = pFD->DRecOffInPT; workFD.parentDirStartLB = pFD->FStartLB; /* current file section description */ C_BUF_TO_LONG (workFD.FCSSize, pDirRec, ISO_DIR_REC_DATA_LEN); workFD.FCSSizeLB = A_PER_B(pVDList->LBSize, workFD.FCSSize); workFD.FCSFlags = *(pDirRec + ISO_DIR_REC_FLAGS); /* interleaving */ workFD.FCSFUSizeLB = *(pDirRec + ISO_DIR_REC_FU_SIZE); workFD.FCSGapSizeLB = *(pDirRec + ISO_DIR_REC_IGAP_SIZE); workFD.FCSInterleaved = (workFD.FCSFUSizeLB)? CDROM_INTERLEAVED : CDROM_NOT_INTERLEAVED; /* TBD: read EAR and time and permissions init */ workFD.FCDirRecNum = 0; workFD.FCSAbsOff = 0; /* start position */ C_BUF_TO_SHORT (workFD.FCSSequenceSetNum, pDirRec, ISO_DIR_REC_VOL_SEQU_N); workFD.FCSStartLB = workFD.FStartLB; /* current data position */ workFD.FCDAbsLB = workFD.FStartLB; workFD.FCDAbsPos = 0; workFD.FCDOffInLB = 0; /* only EAR prefaces data itself */ workFD.FCEOF = 0; /* fill in file's dir records buffer and count file length */ assert (workFD.FRecords != NULL); pDirRec = workFD.FRecords; workFD.FSize = 0; do { bcopy (pFD->FCDirRecPtr, pDirRec, *(pFD->FCDirRecPtr)); C_BUF_TO_LONG (dirRecsTotSize, pDirRec, ISO_DIR_REC_DATA_LEN); workFD.FSize += dirRecsTotSize; pDirRec += *(pFD->FCDirRecPtr); } while (cdromFsSkipDirRec(pFD, DRF_LAST_REC) == OK); workFD.FCDirRecPtr = workFD.FRecords; workFD.pVDList = pVDList; workFD.volUnmount = 0; workFD.magic = FD_MAG; /* pFD already in FD-list (so comes) */ workFD.list = pFD->list; workFD.inList = 1; *pFD = workFD; return OK; }/********************************************************************************* cdromFsStrUp - to convert string to upper case.** RETURNS: N/A.*/LOCAL void cdromFsStrUp ( u_char * str, /* string */ int len /* length */ ) { for (len --; len >= 0; len --) str[len] = toupper(str[len]); }/********************************************************************************* cdromFsFindFileInDir - to find file in given directory.** This routine searches directory, described by <pFD> for name <name>.* If <name> includes version number (xxx{;ver num}), it's considered* as absolute file name, If no version supplied (xx[;]),* routine searches directory for last file version.* If file found, cdromFsFillFDForFile() is called, to refill* <pFD> fields for file.** RETURNS: OK if file found and <pFD> refilled, or ERROR.*/LOCAL STATUS cdromFsFindFileInDir ( T_CDROMFS_VD_LST_ID pVDList, /* ptr to volume descriptor list */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -