📄 cdromfslib.c
字号:
/* allocate sector reading buffer (by default size) */ if (cdromFsSectBufAlloc (pVolDesc, & (pFD->sectBuf), 0) == ERROR) { KHEAP_FREE ((char *)pFD); return (NULL); } pFD->inList = 0; /* FD not included to volume FD list yet */ pFD->magic = FD_MAG; return (pFD); }/***************************************************************************** cdromFsFDFree - deallocate a file descriptor structure** This routine deallocates all allocated memory associated with the specified* file descriptor structure.** RETURNS: N/A.*/LOCAL void cdromFsFDFree ( T_CDROM_FILE_ID pFD ) { pFD->magic = 0; cdromFsSectBufFree (&(pFD->sectBuf));#ifdef CDROMFS_MODE_AUTO_COMBINE_VOLUME_DESCRIPTORS if (pFD->pMultDir != 0) /* Moved here from cdromFsClose() */ KHEAP_FREE (pFD->pMultDir);#endif /* CDROMFS_MODE_AUTO_COMBINE_VOLUME_DESCRIPTORS */ if (pFD->FRecords != NULL) KHEAP_FREE (pFD->FRecords); if (pFD->inList) lstDelete (&(pFD->pVDList->pVolDesc->FDList), (NODE *)pFD); pFD->inList = 0; KHEAP_FREE ((char *)pFD); }/***************************************************************************** cdromFsSectBufAlloc - allocate a buffer for reading volume sectors** This routine is designed to allocate a buffer for reading volume data* by Logical Sectors. If the <numSectInBuf> parameter is a value greater* than zero, the buffer size is assumed to be equal to <numSectInBuf>* times the sector size. If you specify a <numSectInBuf> of 0, the buffer* size is CDROM_COM_BUF_SIZE.** The buffer may already have been connected with given control structure.* If one is large enough, but not two, it is just left intact, if not, -* free it.** After use, buffer must be deallocated by means of cdromFsSectBufFree ().** RETURNS: OK or ERROR;** ERRNO: S_memLib_NOT_ENOUGH_MEMORY*/LOCAL STATUS cdromFsSectBufAlloc ( CDROM_VOL_DESC_ID pVolDesc, SEC_BUF_ID pSecBuf, /* buffer control structure */ /* to which buffer is connected */ int numSectInBuf /* LS in buffer */ ) { assert (pVolDesc != NULL); assert (pSecBuf != NULL); numSectInBuf = (numSectInBuf == 0)? CDROM_COM_BUF_SIZE: numSectInBuf; /* * may be, any buffer has already been connected with given * control structure. Check its size. */ if (pSecBuf->magic == SEC_BUF_MAG && pSecBuf->sectData != NULL) { if (pSecBuf->maxSects >= numSectInBuf && pSecBuf->maxSects <= numSectInBuf + 1) return OK; pSecBuf->magic = 0; KHEAP_FREE (pSecBuf->sectData); } /* newly init control structure */ LET_SECT_BUF_EMPTY (pSecBuf); pSecBuf->maxSects = numSectInBuf; /* allocation */ pSecBuf->sectData = KHEAP_ALLOC (numSectInBuf * pVolDesc->sectSize); if (pSecBuf->sectData == NULL) return ERROR; pSecBuf->magic = SEC_BUF_MAG; return (OK); }/***************************************************************************** cdromFsSectBufAllocBySize - allocate buffer for reading volume.** After use, buffer must be deallocated by means of cdromFsSectBufFree ().* This routine calls cdromFsSectBufAlloc() with sufficient* number of sectors covers <size>.* If <size> == 0, allocated buffer is 1 sector size.** RETURNS: OK or ERROR;*/LOCAL STATUS cdromFsSectBufAllocBySize ( CDROM_VOL_DESC_ID pVolDesc, SEC_BUF_ID pSecBuf, /* buffer control structure */ /* to which buffer is connected */ int size /* minimum buffer size in bytes */ ) { assert (pVolDesc != NULL); /* SPR#34659 failed */ assert (pSecBuf != NULL); return (cdromFsSectBufAlloc (pVolDesc , pSecBuf, A_PER_B (pVolDesc->sectSize, size) + 1)); }/***************************************************************************** cdromFsSectBufFree - deallocate volume sector buffer.** RETURNS: N/A*/LOCAL void cdromFsSectBufFree ( SEC_BUF_ID pSecBuf /* buffer control structure */ ) { assert (pSecBuf != NULL); if (pSecBuf->magic == SEC_BUF_MAG && pSecBuf->sectData != NULL) KHEAP_FREE (pSecBuf->sectData); /* buffer structure is unusable now */ pSecBuf->sectData = NULL; pSecBuf->magic = 0; }/***************************************************************************** cdromFsGetLS - read logical sector from volume.** This routine tries to find requested LS in <pSecBuf> and, if failed,* reads sector from device. Number of read sectors equal to buffer size.** RETURNS: ptr on LS within buffer or NULL if error accessing device.** ERRNO: S_cdromFsLib_DEVICE_REMOVED, if CD disk has not been ejected;* or any, may be set by block device driver read function.*/LOCAL u_char * cdromFsGetLS ( CDROM_VOL_DESC_ID pVolDesc, u_long LSNum, /* logical sector to get */ u_long maxLSs, /* maximum LS to read */ SEC_BUF_ID pSecBuf /* sector data control structure, */ /* to put data to */ ) { assert (pVolDesc != NULL); assert (pSecBuf->sectData != NULL); assert (pSecBuf->magic == SEC_BUF_MAG); /* SPR#75766 Next assert() failed. */ assert (LSNum < pVolDesc->pBlkDev->bd_nBlocks / pVolDesc->LSToPhSSizeMult); if (maxLSs == 0) maxLSs = 1; DBG_MSG(400)("%d. access for sector %lu\n", __LINE__, LSNum); /* check for disk has not been ejected */ if (pVolDesc->pBlkDev->bd_readyChanged) { cdromFsVolUnmount (pVolDesc); errnoSet (S_cdromFsLib_DEVICE_REMOVED); return (NULL); } /* may be sector already in buffer ('if' for negative condition) */ if (pSecBuf->numSects == 0 || LSNum < pSecBuf->startSecNum || LSNum >= pSecBuf->startSecNum + pSecBuf->numSects) { /* sector not in the buffer, read it from disk */ BLK_DEV * pBlkDev = pVolDesc->pBlkDev; u_long numLSRead; assert (pBlkDev != NULL); /* * num read sects must not exceed last CD volume sector * This is needed to avoid reading off the end of a volume. */ numLSRead = min (pBlkDev->bd_nBlocks / pVolDesc->LSToPhSSizeMult - LSNum, pSecBuf->maxSects); /* * num read sects must not exceed last allowed read ahead sector * This is needed to avoid reading off the end of a file section. * On a CD-R those blocks might not be recorded at all. */ numLSRead = min (numLSRead, maxLSs); /* Do the read */ if (pBlkDev->bd_blkRd (pBlkDev, LSNum * pVolDesc->LSToPhSSizeMult, numLSRead * pVolDesc->LSToPhSSizeMult, pSecBuf->sectData) == ERROR) { LET_SECT_BUF_EMPTY (pSecBuf); DBG_MSG(0)("%d. CDROM ERROR: error reading volume sect" " %lu - %lu\a\n", __LINE__, LSNum, pSecBuf->numSects); return (NULL); } /* successfully read */ pSecBuf->startSecNum = LSNum; pSecBuf->numSects = numLSRead; } return (pSecBuf->sectData + (LSNum - pSecBuf->startSecNum) * pVolDesc->sectSize); }/***************************************************************************** cdromFsGetLB - get logical block** This routine tries to find requested LB in <pSecBuf> and, if it fails,* reads sector, containing the LB from device.* <pSecBuf> is used as sector buffer. If <pSecBuf> is NULL, global* volume buffer is used.** RETURNS: ptr on LB within buffer or NULL if error with set errno* to appropriate value.*/LOCAL u_char * cdromFsGetLB ( T_CDROMFS_VD_LST_ID pVDList, u_long LBNum, /* logical block to get */ u_long maxLBs, /* maximum LB to read */ SEC_BUF_ID pSecBuf /* sector data control structure, */ /* to put data to */ ) { u_int secNum; /* LS, contane LB */ u_int maxLSs; /* maximum LS to read */ u_char * pData; /* ptr to LB within read data buffer */ CDROM_VOL_DESC_ID pVolDesc; assert (pVDList != NULL); assert (LBNum > 15); /* SPR#80424 failed */ pVolDesc = pVDList->pVolDesc; assert (pVolDesc != NULL); if (pSecBuf == NULL) /* to use common buffer */ pSecBuf = &(pVDList->pVolDesc->sectBuf); assert (pSecBuf->sectData != NULL); DBG_MSG(300)("%d. access for LB %lu\n", __LINE__, LBNum); secNum = LBNum >> pVDList->LBToLSShift; /* LS, contain LB */ maxLSs = maxLBs >> pVDList->LBToLSShift; pData = cdromFsGetLS (pVolDesc, secNum, maxLSs, pSecBuf); if (pData == NULL) return NULL; DBG_MSG(400)("%d. offset in buf: %lu(last bits = %lu)\n", __LINE__, pVDList->LBSize * LAST_BITS (LBNum, pVDList->LBToLSShift), LAST_BITS (LBNum, pVDList->LBToLSShift)); return (pData + pVDList->LBSize * LAST_BITS (LBNum, pVDList->LBToLSShift)); }/***************************************************************************** cdromFsDIRGet - get directory from the current root folder** This routine tries to find requested directory for an specifically FD.* The routine call the function cdromFsGetLB with Directory RecLB** RETURNS: ptr on LB from directory buffer or NULL if any error occurred.*/LOCAL u_char * cdromFsDIRGet ( T_CDROM_FILE_ID pFD /* FD to fill, containing parent */ ) { u_long headSizeLB; /* Size of directory in LBs */ u_long headLBIndex; /* (Destination) LB in dir preceding head */ u_long headLBNum; /* (Destination) LB containing dir record */ u_long headRemLB; /* (Destination) Remaining LB in the directory */ u_char * pHeadLb; /* (Destination) Point to LB of dir record */#ifdef CDROMFS_MODE_AUTO_COMBINE_VOLUME_DESCRIPTORS u_char * pNextLb; /* (Source) Point to LB of same directory */ /* in another volume descriptor */ u_int headDirEnt; /* (Destination) # of dir records in pHead dir */ u_int nextDirEnt; /* (Source) # of dir records in pNext dir */ u_int nrMulVD; /* Loop index */#endif /* CDROMFS_MODE_AUTO_COMBINE_VOLUME_DESCRIPTORS */ assert (pFD != NULL); /* Get the logical block that contains the directory record */ headLBIndex = pFD->FCDirRecAbsOff / pFD->pVDList->LBSize; headLBNum = pFD->FCDirFirstRecLB + headLBIndex; headSizeLB = ROUND_UP (pFD->FSize, pFD->pVDList->LBSize) / pFD->pVDList->LBSize; headRemLB = headSizeLB - headLBIndex; pHeadLb = cdromFsGetLB (pFD->pVDList, headLBNum, headRemLB, &(pFD->sectBuf));#ifdef CDROMFS_MODE_AUTO_COMBINE_VOLUME_DESCRIPTORS if (pFD->nrMultDir !=0 && pFD->pMultDir[0] !=0) { for (nrMulVD = 0; nrMulVD < pFD->nrMultDir; nrMulVD++) { headDirEnt = cdromFsFindDirEntered (pHeadLb, pFD->pVDList->LBSize); /* Get the logical block that contains the alternate record */ pNextLb = cdromFsGetLB (pFD->pVDList, pFD->pMultDir[nrMulVD], 1, 0); nextDirEnt = cdromFsFindDirEntered (pNextLb, pFD->pVDList->LBSize); if (nextDirEnt > 2) { cdromFsAddRecsToFD (pNextLb, 2, pHeadLb, headDirEnt, nextDirEnt-2, (pFD->sectBuf.numSects - (headLBNum - pFD->sectBuf.startSecNum)) * pFD->pVDList->pVolDesc->sectSize); } } }#endif /* CDROMFS_MODE_AUTO_COMBINE_VOLUME_DESCRIPTORS */ return (pHeadLb); }/***************************************************************************** cdromFsPTGet - retrieve Path Table for given VD from volume.** By default, if pSecBuf == NULL, volume dir hierarchy PT buffer* is used for storing path table. It is allocated only once and* is deallocated over volume unmounting.** Only if pSecBuf != NULL required space for PT automaticly allocated in it.** RETURNS: ptr to PT or NULL if any error occurred.*/LOCAL u_char * cdromFsPTGet ( T_CDROMFS_VD_LST_ID pVdLst, SEC_BUF_ID pSecBuf /* may be NULL. Ptr to buffer control */ /* structure to read PT to */ ) { u_char * pPT; /* Return value */ u_long PTSizeLB; /* Number of LB in path table */ assert (pVdLst != NULL); if (pSecBuf == NULL) /* use volume dir hierarchy PT buffer */ pSecBuf = &(pVdLst->PTBuf); /* * if the buffer already has been allocated, the following call does * nothing */ /* * SPR#34659 Problem pVdList->pVolDesc can be set to NULL by * cdromFsVolUnmount() concurrent with cdromFsOpen(). This is fixed * by cdromFsVolLock() added to cdromFsOpen(). */ if (cdromFsSectBufAllocBySize (pVdLst->pVolDesc, pSecBuf, pVdLst->PTSize) == ERROR) return NULL; /* Compute size of PT in blocks */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -