📄 cdromfslib.c
字号:
LBRead = 0; /* set LB to session 0 */ /* Determine session to use */ { /* calculated ISO_PVD_BASE_LS */ CDROM_TRACK_RECORD cdStatus; cdStatus.bufferLength = (CDROM_MAX_TRACKS * sizeof (readTocHeaderType)) + sizeof (readTocSessionDescriptorType); cdStatus.statBuffer = KHEAP_ALLOC (cdStatus.bufferLength);#ifdef CDROMFS_MULTI_SESSION_SUPPORT if (cdromFsTocRead(pVolDesc, &cdStatus) == OK) { u_short SesiNum; readTocHeaderType * pTocHeader = (readTocHeaderType *) cdStatus.statBuffer; readTocSessionDescriptorType * pTocSessionDescriptor; /* determine latest session on CD */ pVolDesc->SesiOnCD = pTocHeader->lastSessionNumber - 1; /* and use this as the default session */ SesiNum = pVolDesc->SesiOnCD; /* is there another session requested ? */ if (pVolDesc->SesiToRead != DEFAULT_SESSION) { /* * Yes. Requested session must be smaller than number of * sessions on disc */ if (pVolDesc->SesiToRead < pVolDesc->SesiOnCD) /* use this one instead of the default */ SesiNum = pVolDesc->SesiToRead; else /* * Requested session is too large. * Switch to default session. */ pVolDesc->SesiToRead = DEFAULT_SESSION; } pTocSessionDescriptor = (readTocSessionDescriptorType *) (pTocHeader + 1); pTocSessionDescriptor += SesiNum; sesStartLB = ntohl (*(UINT32 *) (pTocSessionDescriptor->sessionStartAddress)); LBRead = sesStartLB; }#else /* CDROMFS_MULTI_SESSION_SUPPORT */#endif /* CDROMFS_MULTI_SESSION_SUPPORT */ KHEAP_FREE (cdStatus.statBuffer); } /* Multisession */ /* by ISO/Joliet, first volume descriptor always lays in ISO_PVD_BASE_LS */ LBRead += ISO_PVD_BASE_LS; for (VDLast = 0; ! VDLast && LBRead < pVolDesc->pBlkDev->bd_nBlocks; LBRead ++) { /* read VD from disk */ pVDData = cdromFsGetLB (&VDList, LBRead, 1, NULL); if (pVDData == NULL) { cdromFsVolUnmount (pVolDesc); semGive (pVolDesc->mDevSem); return ERROR; } /* check standard ISO volume ID */ if (strncmp (((T_ISO_VD_HEAD_ID)pVDData)->stdID, ISO_STD_ID , ISO_STD_ID_SIZE)) { /* not ISO volume ID */ /* * may be any unknown VD in set, but not first, that must be * ISO primary VD only (at least in current version) */ if (primVDMounted) /* primary have been found already */ continue; else { cdromFsVolUnmount (pVolDesc); semGive (pVolDesc->mDevSem); DBG_MSG(0)("%d. Warning: unknown CR-ROM format detected," " ignored.\n", __LINE__); errnoSet (S_cdromFsLib_UNKNOWN_FILE_SYSTEM); return ERROR; } } /* check VD ID */ /* * Only VD set termination, primary and supplementary VD are * interesting; and not process secondary copies of primary VD. * * Check ISO 2022 UCS-2 Escape Sequences as recorded in the ISO * 9660 SVD. */ if (memcmp(pVDData + ISO_VD_ESCAPE_SEC, UCS_2_LEVEL1_ID, 3) == 0) UCSLevel = 1; /* UCS-2 Level 1 is used */ /* * check ISO 2022 UCS-2 Escape Sequences as recorded in the ISO * 9660 SVD */ else if(memcmp(pVDData + ISO_VD_ESCAPE_SEC, UCS_2_LEVEL2_ID, 3) == 0) UCSLevel = 2; /* UCS-2 Level 2 is used */ /* * check ISO 2022 UCS-2 Escape Sequences as recorded in the ISO * 9660 SVD */ else if(memcmp(pVDData + ISO_VD_ESCAPE_SEC, UCS_2_LEVEL3_ID, 3) == 0) UCSLevel = 3; /* UCS-2 Level 3 is used */ else UCSLevel = 0; if (((T_ISO_VD_HEAD_ID)pVDData)->type == ISO_VD_SETTERM) VDLast = 1; else if ((((T_ISO_VD_HEAD_ID)pVDData)->type == ISO_VD_PRIMARY && ! primVDMounted) || ((T_ISO_VD_HEAD_ID)pVDData)->type == ISO_VD_SUPPLEM) { /* first VD on volume must be primary (look ISO 9660) */ if (((T_ISO_VD_HEAD_ID)pVDData)->type == ISO_VD_SUPPLEM && ! primVDMounted) { cdromFsVolUnmount (pVolDesc); /* * The following DIRMode change is required for the * following reason: If we try to switch from ISO to * Joliet on a disc that does not contain a SVD, then the * mounting will fail. If we do not switch back to * default, then it is not possible to do this using IOCTL * commands. It is also not possible in this circumstance * to open the device as it can not read anything from the * disc anymore. */ pVolDesc->DIRMode = MODE_DEFAULT; semGive (pVolDesc->mDevSem); DBG_MSG(0)("%d. Warning: unknown CR-ROM format detected," " ignored.\n", __LINE__); errnoSet (S_cdromFsLib_UNKNOWN_FILE_SYSTEM); return ERROR; } if (pVolDesc->DIRMode == MODE_AUTO) { if (cdromFsVDAddToList (pVolDesc, pVDData,#ifdef CDROMFS_MULTI_SESSION_SUPPORT sesStartLB,#endif /* CDROMFS_MULTI_SESSION_SUPPORT */ LBRead, UCSLevel, VDList.LBToLSShift) == ERROR) { cdromFsVolUnmount (pVolDesc); semGive (pVolDesc->mDevSem); return ERROR; } } else if ((UCSLevel > 0) && (pVolDesc->DIRMode == MODE_JOLIET)) { if (cdromFsVDAddToList (pVolDesc, pVDData,#ifdef CDROMFS_MULTI_SESSION_SUPPORT sesStartLB,#endif /* CDROMFS_MULTI_SESSION_SUPPORT */ LBRead, UCSLevel, VDList.LBToLSShift) == ERROR) { cdromFsVolUnmount (pVolDesc); semGive (pVolDesc->mDevSem); return ERROR; } } else if ((UCSLevel == 0) && (pVolDesc->DIRMode == MODE_ISO9660)) { if (cdromFsVDAddToList (pVolDesc, pVDData,#ifdef CDROMFS_MULTI_SESSION_SUPPORT sesStartLB,#endif /* CDROMFS_MULTI_SESSION_SUPPORT */ LBRead, UCSLevel, VDList.LBToLSShift) == ERROR) { cdromFsVolUnmount (pVolDesc); semGive (pVolDesc->mDevSem); return ERROR; } } /* if primary VD found in VD set */ if (((T_ISO_VD_HEAD_ID)pVDData)->type == ISO_VD_PRIMARY) primVDMounted = 1; } /* else if */ } /* for */ /* each volume contains at least one, primary volume descriptor. */ if (lstCount (&(pVolDesc->VDList)) == 0) { cdromFsVolUnmount (pVolDesc); /* * The following DIRMode change is required for the the same * reason as above. */ pVolDesc->DIRMode = MODE_DEFAULT; semGive (pVolDesc->mDevSem); DBG_MSG(0)("%d. Warning: unknown CR-ROM format detected, ignored.\n", __LINE__); errnoSet (S_cdromFsLib_UNKNOWN_FILE_SYSTEM); return ERROR; } assert (lstFirst(&(pVolDesc->VDList)) != NULL); /* device successfully mounted */ pVolDesc->unmounted = 0; /* return semaphore */ if (semGive (pVolDesc->mDevSem) == ERROR) { cdromFsVolUnmount (pVolDesc); errnoSet (S_cdromFsLib_SEMGIVE_ERROR); return ERROR; } return OK; }/***************************************************************************** cdromFsDirDateTime2Long - convert ISO directory Date/Time to UNIX time_t** This routine converts date/time in ISO directory format* (T_FILE_DATE_TIME) to the UNIX long time format.* See ISO-9660 Section 9.1.5, Table 9, page 20.** RETURNS: Converted time** NOMANUAL*/LOCAL time_t cdromFsDirDateTime2Long ( const T_FILE_DATE_TIME * pDateTime /* Pointer to ISO date/time */ ) { struct tm recTime; /* For mktime() */ recTime.tm_sec = pDateTime->seconds; recTime.tm_min = pDateTime->minuts; recTime.tm_hour = pDateTime->hour; recTime.tm_mday = pDateTime->day; recTime.tm_mon = pDateTime->month - 1; recTime.tm_year = pDateTime->year; return (mktime (&recTime)); }/***************************************************************************** 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** INTERNAL* Changes pPTRec.** RETURNS: OK or ERROR if malloc() or disk access error occur.** ERRNO: S_cdromFsLib_INVALID_DIRECTORY_STRUCTURE,* S_memLib_NOT_ENOUGH_MEMORY.*/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_short EARSize; /* EAR size in bytes */ 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->FRecords; * pFD->FCSStartLB; * pFD->FCSFUSizeLB; * pFD->FCSGapSizeLB; */ 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; /* * Directory is stored as one extension, without records and * interleaving */ 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->FCDirRecAbsOff = 0; /* Current entry is first */ pFD->FCDirFirstRecLB = pFD->FStartLB; /* First file section */ pFD->FCSAbsOff = 0; pFD->FDType = (u_short)(-1); /* not one request was served */ pFD->FCDAbsPos = 0; pFD->FCEOF = 0; /* some directory specific fields */ pFD->DNumInPT = dirRecNumInPT;#if 0 /* NOT USED until record format files supported */ pFD->DRecLBPT = 0; /* * TBD: not need currently. May be counted in * principal by parent function */ pFD->DRecOffLBPT = 0;#endif /* NOT USED until record format files supported */ /* * read first directory record and get special dir descriptions * * Size of directory not known, therefore do not read ahead. */ pPTRec = cdromFsGetLB (pVDList, pFD->FStartLB, 1, &(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; /* fill FAbsTime field (u_long time format) */ pFD->FDateTimeLong = cdromFsDirDateTime2Long ((T_FILE_DATE_TIME_ID) (pPTRec + ISO_DIR_REC_DATA_TIME)); pFD->pVDList = pVDList; pFD->magic = FD_MAG; /* connect to volume's FD list */ if (!pFD->inList) lstAdd (&(pVDList->pVolDesc->FDList), (NODE *)pFD); pF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -