📄 cdromfslib.c
字号:
PTSizeLB = ROUND_UP (pVdLst->PTSize, pVdLst->LBSize) / pVdLst->LBSize; /* if PT already in buffer, following call do nothing */ pPT = cdromFsGetLB (pVdLst, pVdLst->PTStartLB, PTSizeLB, pSecBuf); return (pPT); }/***************************************************************************** cdromFsNextPTRec - pass to a next PT record.** As result, *ppPT points to the next PT record.** RETURNS: offset of record from PT start or 0 if last record encounted*/LOCAL u_long cdromFsNextPTRec ( u_char ** ppPT, /* address of ptr to current record */ /* within buffer, containing PT */ u_long offset, /* offset of current record from PT start */ u_long PTSize /* path table size (stored in volume */ /* descriptor */ ) { short size; /* current PT record size */ /* skip current PT record */ PT_REC_SIZE (size, *ppPT); offset += size; *ppPT += size; /* * set of zero bytes may follow PT record, if that is last record in LB. * First non zero byte starts next record */ for (; offset < PTSize; offset++, (*ppPT)++) if (**ppPT != 0) break; return (offset); }/***************************************************************************** cdromFsShiftCount - count shift for transfer <source> to <dest>.** This routine takes two values, that are power of two and counts* the difference of powers, which is, for instance, the number of* bits to shift <source> in order to get <dest>.* If <source> <= <dest>, the result is positive and <dest> == <source>* << the result.** If <source> > <dest>, the result is negative and <dest> == <source>* >> - the result.** Because <dest> may be less, than <source>, (-1) may not be used as error* indication return code, so an impossible value of 100 is taken for this* purpose.** RETURNS: number of bits to shift <source>, in order to get <dest>* or a value of (100) if it is impossible to calculate shift count.** ERRNO: S_cdromFsLib_ONE_OF_VALUES_NOT_POWER_OF_2.*/LOCAL u_char cdromFsShiftCount ( u_long source, u_long dest ) { u_char i; if (source <= dest) { for (i = 0; i < sizeof (u_long) * 8; i++) if ((source << i) == dest) return i; } else /* source > dest */ { for (i = 1; i < sizeof (u_long) * 8; i++) if ((dest << i) == source) return (-i); } errnoSet (S_cdromFsLib_ONE_OF_VALUES_NOT_POWER_OF_2); return (100); }/***************************************************************************** cdromFsVDAddToList - add VD to VD list.** Allocate VD list structure, fill in its fields (from <pVDData> buffer)* and add to VD list.** RETURNS: OK or ERROR if any failed.** ERRNO: S_cdromFsLib_SUCH_PATH_TABLE_SIZE_NOT_SUPPORTED,* S_cdromFsLib_MAX_DIR_HIERARCHY_LEVEL_OVERFLOW,* S_memLib_NOT_ENOUGH_MEMORY*/LOCAL STATUS cdromFsVDAddToList ( CDROM_VOL_DESC_ID pVolDesc, const u_char * pVDData, /* data, has been got from disk */#ifdef CDROMFS_MULTI_SESSION_SUPPORT u_long SesiPseudoLBNum, /* LB number at which session starts */ /* if let (LB size = VD size) */#endif /* CDROMFS_MULTI_SESSION_SUPPORT */ u_long VDPseudoLBNum, /* LB number, contains given VD, */ /* if let (LB size = VD size) */ u_short uniCodeLev, /* See T_CDROMFS_VD_LST.uniCodeLev */ u_char VDSizeToLSSizeShift /* relation between VD size */ /* and LS size */ ) { T_CDROMFS_VD_LST_ID pVDList; assert (pVolDesc != NULL); assert (pVDData != NULL); pVDList = KHEAP_ALLOC (sizeof (T_CDROMFS_VD_LST)); if (pVDList == NULL) return (ERROR); bzero ((u_char *) pVDList, sizeof (T_CDROMFS_VD_LST)); pVDList->uniCodeLev = uniCodeLev; pVDList->pVolDesc = pVolDesc; C_BUF_TO_LONG (pVDList->volSize, pVDData, ISO_VD_VOL_SPACE_SIZE); /* since PT is stored in memory, max PT size is restricted */ C_BUF_TO_LONG (pVDList->PTSize, pVDData, ISO_VD_PT_SIZE); C_BUF_TO_LONG (pVDList->PTSizeOnCD, pVDData, ISO_VD_PT_SIZE); if (pVDList->PTSizeOnCD > CDROM_LIB_MAX_PT_SIZE) { errnoSet (S_cdromFsLib_SUCH_PATH_TABLE_SIZE_NOT_SUPPORTED); KHEAP_FREE ((char *)pVDList); return (ERROR); } C_BUF_TO_LONG (pVDList->PTStartLB, pVDData, ISO_VD_PT_OCCUR); C_BUF_TO_LONG (pVDList->rootDirSize, pVDData, ISO_VD_ROOT_DIR_REC + ISO_DIR_REC_DATA_LEN); C_BUF_TO_LONG (pVDList->rootDirStartLB, pVDData, ISO_VD_ROOT_DIR_REC + ISO_DIR_REC_EXTENT_LOCATION); C_BUF_TO_SHORT (pVDList->volSetSize, pVDData, ISO_VD_VOL_SET_SIZE); C_BUF_TO_SHORT (pVDList->volSeqNum, pVDData, ISO_VD_VOL_SEQUENCE_N); /* * ISO-9660 6.2.2 Logical Block * sizeof(Logical Block) <= sizeof(Logical Sector). * sizeof(Logical Block) is always a power of 2. * * cdromFsLib implementation * sizeof(Logical Block) = pVDList->LBSize. * sizeof(Logical Sector) = sizeof(Logical Block) << pVDList->LSToLSShift. */ C_BUF_TO_SHORT (pVDList->LBSize, pVDData, ISO_VD_LB_SIZE); pVDList->LBToLSShift = cdromFsShiftCount (pVDList->LBSize, pVolDesc->sectSize); pVDList->type = ((T_ISO_VD_HEAD_ID)pVDData)->type; pVDList->fileStructVersion = *(pVDData + ISO_VD_FILE_STRUCT_VER); pVDList->VDPseudoLBNum = VDPseudoLBNum; /* * read PT to buffer and init dirLevBorders...[]. * In accordance with ISO9660 all directories records in * PT are sorted by hierarchy levels and are numbered from 1. * (only root has number 1 and lays on level 1). * Number of levels restricted to 8 for ISO 9660 or 120 for Joliet. * dirLevBordersOff[ n ] contains offset of first PT record on level * (n+2) (root excluded and array encounted from 0) from PT start. * dirLevLastRecNum[ n ] contains number of last PT record on level * (n+2). * Base of algorithm: * Storing number of last PT rec on hierarchy level <n> in * <prevLevLastRecNum>, will skip level <n+1>, on which all * directories have parent only within n; first directory * which parent dir number exceeds <prevLevLastRecNum> * starts level n+2. */ { u_char * pPT; u_int offset, /* absolute offset from PT start */ level, /* hierarchy level (minus 2) */ prevLevLastRecNum, /* number of last PT rec on */ /* previous hierarchy level */ prevRecNum ; /* previous PT record number */ pPT = cdromFsPTGet (pVDList, NULL); if (pPT == NULL) { KHEAP_FREE ((char *)pVDList); return (ERROR); } /* * pass over root dir entry, dir hierarchy level 1; * root dir record is first PT record and its number is 1 */ offset = cdromFsNextPTRec (&pPT, 0, pVDList->PTSize); level = 0; /* not put to array data for root directory */ prevRecNum = 1; /* root number in PT */ prevLevLastRecNum = 1; bzero ((u_char *)(pVDList->dirLevBordersOff), sizeof(pVDList->dirLevBordersOff)); bzero ((u_char *)(pVDList->dirLevLastRecNum), sizeof(pVDList->dirLevLastRecNum)); /* * over this loop all dir hierarchy levels' bounds in PT * will be found. */ pVDList->dirLevBordersOff[0] = offset; for (; offset < pVDList->PTSize && level < CDROM_MAX_DIR_LEV - 1;) { u_int prev; /* parent dir number for current record */ PT_PARENT_REC (prev, pPT);#ifdef DEBUG /* debugging */ DBG_COP_TO_BUF (pPT + ISO_PT_REC_DI, *pPT); DBG_MSG(200)("%d. %4d\t%20s\tparent # %3d, D_ID_LEN %2d level %d\n", __LINE__, prevRecNum + 1, dbgvBuf, (int)prev, (int)*pPT, level + 2);#endif /* DEBUG */ /* if directory level overed */ if (prev > prevLevLastRecNum) { /* close level */ pVDList->dirLevLastRecNum[level] = prevRecNum; level++; if (level > CDROM_MAX_DIR_LEV - 1) break; /* current level first record offset within PT */ pVDList->dirLevBordersOff[level] = offset; prevLevLastRecNum = prevRecNum; } prevRecNum ++; offset = cdromFsNextPTRec (&pPT, offset, pVDList->PTSize); } /* close last level */ pVDList->dirLevLastRecNum[level] = prevRecNum; /* * may be loop breaking only because CDROM_MAX_DIR_LEV overloading * before fully PT exhausting, that is an error */ if (offset < pVDList->PTSize) { KHEAP_FREE ((char *)pVDList); errnoSet (S_cdromFsLib_MAX_DIR_HIERARCHY_LEVEL_OVERFLOW); return (ERROR); } pVDList->numDirLevs = level + 1; /* <level> starts from 0 */ pVDList->numPTRecs = prevRecNum; } /* hierarchy bounds init */ /* VD have been built. Add it to VD list */ pVDList->magic = VD_LIST_MAG; lstAdd (&(pVolDesc->VDList), (NODE *)pVDList); return (OK); }/***************************************************************************** cdromFsVolUnmount - mark in all device depends data, that volume unmounted.** All volume descriptors are deallocated.* FDList not deallocated, but only marked as "file unaccessible.** RETURNS: N/A** ERRNO: S_cdromFsLib_SEMGIVE_ERROR*/LOCAL void cdromFsVolUnmount ( CDROM_VOL_DESC_ID pVolDesc /* cdrom volume decriptor id */ ) { T_CDROM_FILE_ID pFDList; T_CDROMFS_VD_LST_ID pVDList; assert (pVolDesc != NULL); assert (pVolDesc->mDevSem != NULL); if (semTake (pVolDesc->mDevSem, WAIT_FOREVER) == ERROR) return; /* * mark all opened files as unaccessible * * SPR#70072 This must be done before the below * lstFree (&(pVolDesc->VDList)); so that cdromFsFDFree() does not * corrupt memory by removing the FD from that list after the list * has already been freed. */ for (pFDList = (T_CDROM_FILE_ID)lstFirst (&(pVolDesc->FDList)); pFDList != NULL; pFDList = (T_CDROM_FILE_ID)lstNext ((NODE *)pFDList)) { pFDList->inList = 0; /* SPR#70072 */ } /* free VD list with PT buffers */ for (pVDList = (T_CDROMFS_VD_LST_ID)lstFirst (&(pVolDesc->VDList)); pVDList != NULL; pVDList = (T_CDROMFS_VD_LST_ID)lstNext ((NODE *)pVDList)) { cdromFsSectBufFree (&(pVDList->PTBuf)); } lstFree (&(pVolDesc->VDList)); /* mark in VD, that volume unmounted */ pVolDesc->unmounted = 1;#ifdef CDROMFS_MULTI_SESSION_SUPPORT /* for Multisession, set Session to default */ pVolDesc->SesiToRead = DEFAULT_SESSION;#endif /* CDROMFS_MULTI_SESSION_SUPPORT */ if (semGive (pVolDesc->mDevSem) == ERROR) errnoSet (S_cdromFsLib_SEMGIVE_ERROR); assert (lstCount (&(pVolDesc->VDList)) == 0); }/***************************************************************************** cdromFsVolMount - mount cdrom volume.** This routine reads the volume descriptors and creates VD lists.* This routine checks which CD-Rom mode is set and adds only this VD's* to the list which mode is set. (mode can be Joliet, ISO9660 or AUTO mode)** RETURNS: OK or ERROR** ERRNO: S_cdromFsLib_UNKNOWN_FILE_SYSTEM, S_cdromFsLib_SEMGIVE_ERROR, or* any errno may be set by supplementary functions, for example* S_memLib_NOT_ENOUGH_MEMORY from malloc().*/LOCAL STATUS cdromFsVolMount ( CDROM_VOL_DESC_ID pVolDesc /* cdrom volume decriptor id */ ) { T_CDROMFS_VD_LST VDList; /* volume descriptor list */ u_long LBRead; /* logical blk to read */#ifdef CDROMFS_MULTI_SESSION_SUPPORT u_long sesStartLB; /* Session start LB */#endif /* CDROMFS_MULTI_SESSION_SUPPORT */ u_char VDLast = 0; u_char primVDMounted; /* primary VD mounted flag */ u_char UCSLevel; /* which UCS-2 Level is used */ u_char * pVDData; assert (pVolDesc != NULL); assert (pVolDesc->mDevSem != NULL); /* private semaphore */ if (semTake (pVolDesc->mDevSem, WAIT_FOREVER) == ERROR) return ERROR; /* before mount new volume, it have to unmount previous */ if (! pVolDesc->unmounted) cdromFsVolUnmount (pVolDesc); pVolDesc->pBlkDev->bd_readyChanged = FALSE; /* * before VD was read let LB size equal to VD size, since * each VD defines its own LB size. Because VD size and LS size are * powers of 2, one may be get from second by means of shift. */ VDList.LBSize = ISO_VD_SIZE; VDList.LBToLSShift = cdromFsShiftCount (ISO_VD_SIZE, pVolDesc->sectSize); VDList.pVolDesc = pVolDesc; /* data in buffer remain from unmounted volume, so invalid */ LET_SECT_BUF_EMPTY (&(VDList.pVolDesc->sectBuf)); /* no one primary VD was found yet */ primVDMounted = 0;#ifdef CDROMFS_MULTI_SESSION_SUPPORT sesStartLB =#endif /* CDROMFS_MULTI_SESSION_SUPPORT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -