static APIRET changeDir(ServerData * pServerData, struct chdir * pchdir) { int iExtent; if (VERIFYFIXED(pchdir->szDir) || verifyPathName(pchdir->szDir)) return ERROR_INVALID_PARAMETER; logMsg(L_DBG, "CD_EXPLICIT, curdir=%s, newdir=%s", pchdir->cdfsi.cdi_curdir, pchdir->szDir); /* Walk the directory tree to find the name in szDir. */ iExtent=isoQueryDirExtentFromPath( pchdir->pVolData, pchdir->pVolData->iRootExtent, pchdir->szDir + 2, NULL); if(!iExtent) { return ERROR_PATH_NOT_FOUND; } return NO_ERROR; }
APIRET fsChDir(ServerData * pServerData, struct chdir * pchdir) { if (VERIFYFIXED(pchdir->cdfsi.cdi_curdir)) return ERROR_INVALID_PARAMETER; logMsg(L_DBG, "FS_CHDIR, flag=%d, cdfsi.dir=%s, cdfsi.flags=%d", pchdir->fsFlag, pchdir->cdfsi.cdi_curdir, pchdir->cdfsi.cdi_flags); switch (pchdir->fsFlag) { case CD_EXPLICIT: return changeDir(pServerData, pchdir); case CD_VERIFY: return verifyDir(pServerData, pchdir); case CD_FREE: return freeDir(pServerData, pchdir); default: logMsg(L_EVIL, "unknown FS_CHDIR flag: %d", pchdir->fsFlag); return ERROR_NOT_SUPPORTED; } }
APIRET fsAttach(ServerData * pServerData, struct attach * pattach) { APIRET rc; logMsg(L_DBG, "FS_ATTACH, flag=%hd, szDev=%s, cbParm=%d", pattach->fsFlag, pattach->szDev, pattach->cbParm); if (VERIFYFIXED(pattach->szDev) || (strlen(pattach->szDev) != 2) || (pattach->szDev[1] != ':')) return ERROR_INVALID_PARAMETER; switch (pattach->fsFlag) { case FSA_ATTACH: rc = attachVolume(pServerData, pattach); memset(pServerData->pData, 0, sizeof(IFS_ATTACH)); /* burn */ return rc; case FSA_DETACH: return detachVolume(pServerData, pattach); case FSA_ATTACH_INFO: return queryAttachmentInfo(pServerData, pattach); default: logMsg(L_EVIL, "unknown FS_ATTACH flag: %d", pattach->fsFlag); return ERROR_NOT_SUPPORTED; } }
APIRET fsMkDir(ServerData * pServerData, struct mkdir * pmkdir) { CoreResult cr; APIRET rc; VolData * pVolData; CryptedVolume * pVolume; CHAR szName[CCHMAXPATH]; CryptedFileID idDir, idFile, idNewDir; CryptedFileInfo info; pmkdir->oError = 0; if (VERIFYFIXED(pmkdir->szName) || verifyPathName(pmkdir->szName)) return ERROR_INVALID_PARAMETER; GET_VOLUME(pmkdir); pVolume = pVolData->pVolume; logMsg(L_DBG, "FS_MKDIR, szName=%s, fsFlags=%d", pmkdir->szName, pmkdir->fsFlags); cr = findFromCurDir(pVolData, pmkdir->szName, &pmkdir->cdfsi, &pmkdir->cdfsd, pmkdir->iCurDirEnd, &idDir, &idFile, 0, szName); if (!idDir) return coreResultToOS2(cr); if (cr == CORERC_OK) return ERROR_ACCESS_DENIED; if (cr != CORERC_FILE_NOT_FOUND) return coreResultToOS2(cr); /* No. Create a new directory. */ memset(&info, 0, sizeof(info)); info.flFlags = CFF_IFDIR | 0700; /* rwx for user */ info.cRefs = 1; info.cbFileSize = 0; info.timeWrite = info.timeAccess = info.timeCreation = curTime(); info.idParent = idDir; /* uid and gid are set to 0 */ cr = coreCreateBaseFile(pVolume, &info, &idNewDir); if (cr) return coreResultToOS2(cr); /* Set the extended attributes. */ if (pmkdir->fHasEAs) { rc = addEAs(pVolume, idNewDir, (PFEALIST) pServerData->pData); if (rc) { coreDeleteFile(pVolume, idNewDir); return rc; } } /* Add the directory to the parent directory. */ cr = coreAddEntryToDir(pVolume, idDir, szName, idNewDir, 0); if (cr) { coreDeleteFile(pVolume, idNewDir); return coreResultToOS2(cr); } return NO_ERROR; }
APIRET fsRmDir(ServerData * pServerData, struct rmdir * prmdir) { if (VERIFYFIXED(prmdir->szName) || verifyPathName(prmdir->szName)) return ERROR_INVALID_PARAMETER; logMsg(L_DBG, "FS_RMDIR, szName=%s", prmdir->szName); return ERROR_WRITE_PROTECT; }
APIRET fsMkDir(ServerData * pServerData, struct mkdir * pmkdir) { pmkdir->oError = 0; if (VERIFYFIXED(pmkdir->szName) || verifyPathName(pmkdir->szName)) return ERROR_INVALID_PARAMETER; logMsg(L_DBG, "FS_CHDIR, szName=%s, fsFlags=%d", pmkdir->szName, pmkdir->fsFlags); return ERROR_WRITE_PROTECT; }
APIRET fsRmDir(ServerData * pServerData, struct rmdir * prmdir) { CoreResult cr; VolData * pVolData; CryptedVolume * pVolume; CHAR szName[CCHMAXPATH]; CryptedFileID idDir; CryptedFileID idFile; CryptedDirEntry * pFirstEntry; if (VERIFYFIXED(prmdir->szName) || verifyPathName(prmdir->szName)) return ERROR_INVALID_PARAMETER; GET_VOLUME(prmdir); pVolume = pVolData->pVolume; logMsg(L_DBG, "FS_RMDIR, szName=%s", prmdir->szName); cr = findFromCurDir(pVolData, prmdir->szName, &prmdir->cdfsi, &prmdir->cdfsd, prmdir->iCurDirEnd, &idDir, &idFile, 0, szName); if (cr) return coreResultToOS2(cr); /* Yes. Read the directory contents. (This implicitly makes sure that pFile is a directory. */ cr = coreQueryDirEntries(pVolume, idFile, &pFirstEntry); if (cr || pFirstEntry) { coreFreeDirEntries(pFirstEntry); return cr ? coreResultToOS2(cr) : ERROR_CURRENT_DIRECTORY; } /* The directory is empty, so we can proceed with the deletion. */ /* Remove the directory from its parent directory. */ cr = coreMoveDirEntry(pVolume, szName, idDir, 0, 0); if (cr) return coreResultToOS2(cr); /* Delete the directory. */ cr = coreDeleteFile(pVolume, idFile); if (cr) return coreResultToOS2(cr); return NO_ERROR; }
APIRET fsPathInfo(ServerData * pServerData, struct pathinfo * ppathinfo) { CoreResult cr; VolData * pVolData; CryptedVolume * pVolume; CHAR szName[CCHMAXPATH]; CryptedFileID idDir; CryptedFileID idFile; CryptedDirEntry * pDirEntry; bool fHidden; if (VERIFYFIXED(ppathinfo->szName) || verifyPathName(ppathinfo->szName)) return ERROR_INVALID_PARAMETER; GET_VOLUME(ppathinfo); pVolume = pVolData->pVolume; logMsg(L_DBG, "FS_PATHINFO, szName=%s, usLevel=%hd, " "cbData=%hd, fsFlag=%04hx", ppathinfo->szName, ppathinfo->usLevel, ppathinfo->cbData, ppathinfo->fsFlag); cr = findFromCurDir(pVolData, ppathinfo->szName, &ppathinfo->cdfsi, &ppathinfo->cdfsd, ppathinfo->iCurDirEnd, &idDir, &idFile, &pDirEntry, szName); if (cr) return coreResultToOS2(cr); fHidden = pDirEntry->flFlags & CDF_HIDDEN; coreFreeDirEntries(pDirEntry); return doFileInfo( 0, ppathinfo->fsFlag, ppathinfo->usLevel, pVolData, idFile, idDir, fHidden, ppathinfo->cbData, (char *) pServerData->pData); }
static APIRET changeDir(ServerData * pServerData, struct chdir * pchdir) { CoreResult cr; VolData * pVolData; CryptedVolume * pVolume; CryptedFileID idDir; CryptedFileInfo info; if (VERIFYFIXED(pchdir->szDir) || verifyPathName(pchdir->szDir)) return ERROR_INVALID_PARAMETER; GET_VOLUME(pchdir); pVolume = pVolData->pVolume; logMsg(L_DBG, "CD_EXPLICIT, newdir=%s", pchdir->szDir); cr = findFromCurDir2(pVolData, pchdir->szDir, &pchdir->cdfsi, &pchdir->cdfsd, pchdir->iCurDirEnd, &idDir, 0); if (cr) return coreResultToOS2(cr); /* Get info */ cr = coreQueryFileInfo(pVolume, idDir, &info); if (cr) return coreResultToOS2(cr); /* Is this really a directory? */ if (!CFF_ISDIR(info.flFlags)) /* This error code is not entirely concise, but it's what OS/2 wants to see. */ return ERROR_PATH_NOT_FOUND; pchdir->cdfsd.data[0] = idDir; return NO_ERROR; }
APIRET fsFileAttribute(ServerData * pServerData, struct fileattribute * pfileattribute) { CoreResult cr; VolData * pVolData; CryptedVolume * pVolume; CHAR szName[CCHMAXPATH]; CryptedFileID idDir; CryptedFileID idFile; CryptedFileInfo info, info2; CryptedDirEntry * pDirEntry; bool fHidden; if (VERIFYFIXED(pfileattribute->szName) || verifyPathName(pfileattribute->szName)) return ERROR_INVALID_PARAMETER; GET_VOLUME(pfileattribute); pVolume = pVolData->pVolume; logMsg(L_DBG, "FS_FILEATTRIBUTE, szName=%s, fsFlag=%hd, fsAttr=%hd", pfileattribute->szName, pfileattribute->fsFlag, pfileattribute->fsAttr); cr = findFromCurDir(pVolData, pfileattribute->szName, &pfileattribute->cdfsi, &pfileattribute->cdfsd, pfileattribute->iCurDirEnd, &idDir, &idFile, &pDirEntry, szName); if (cr) return coreResultToOS2(cr); fHidden = pDirEntry->flFlags & CDF_HIDDEN; coreFreeDirEntries(pDirEntry); /* Access the file and get file info. */ cr = coreQueryFileInfo(pVolume, idFile, &info); if (cr) return coreResultToOS2(cr); if (pfileattribute->fsFlag & FA_SET) { /* Set the file attributes. */ /* Update the hidden flag in the directory, if necessary. */ if (!beq(fHidden, pfileattribute->fsAttr & FILE_HIDDEN)) { cr = setHiddenFlag(pVolume, idDir, idFile, pfileattribute->fsAttr & FILE_HIDDEN); if (cr) return coreResultToOS2(cr); } /* Update the flags in the info sector, if necessary. */ info2 = info; extractDOSAttr(pfileattribute->fsAttr, &info2); if (info2.flFlags != info.flFlags) { cr = coreSetFileInfo(pVolume, idFile, &info2); if (cr) return coreResultToOS2(cr); } return NO_ERROR; } else { /* Query the file attributes. */ pfileattribute->fsAttr = makeDOSAttr(fHidden, &info); return NO_ERROR; } }
/* FS_FINDFROMNAME is used by the 32-bit DosFindNext API. */ APIRET fsFindFromName(ServerData * pServerData, struct findfromname * pfindfromname) { APIRET rc; CryptedVolume * pVolume = pfindfromname->pVolData->pVolume; SearchData * pSearchData = pfindfromname->pSearchData; PGEALIST pgeas = 0; if (VERIFYFIXED(pfindfromname->szName)) return ERROR_INVALID_PARAMETER; logMsg(L_DBG, "FS_FINDFROMNAME, cMatch=%d, " "usLevel=%d, fsFlags=%d, cbData=%d, " "ulPosition=%d, szName=%s", pfindfromname->cMatch, pfindfromname->usLevel, pfindfromname->fsFlags, pfindfromname->cbData, pfindfromname->ulPosition, pfindfromname->szName); #if 0 if (pSearchData->iNext != pfindfromname->ulPosition + 1) { /* Does the kernel actually give us ulPositions not equal to the previous pSearchData->iNext? Apparently only when the previous item(s) did not match, but then they still won't match so we can skip them. So this code is commented out. */ logMsg(L_EVIL, "interesting ulPosition (%ld vs. %ld)", pfindfromname->ulPosition, pSearchData->iNext); #if 0 pSearchData->pNext = &pSearchData->dot; #endif pSearchData->iNext = 0; while (pSearchData->pIsoNext && (pSearchData->iNext != pfindfromname->ulPosition)) advanceSearch(pSearchData); if (!pSearchData->pIsoNext) return ERROR_INVALID_PARAMETER; advanceSearch(pSearchData); } #endif /* The GEAs are stored in the exchange buffer which is about to be overwritten; so make a copy. */ if (pfindfromname->usLevel == FIL_QUERYEASFROMLIST) { pgeas = alloca(((PGEALIST) pServerData->pData)->cbList); memcpy(pgeas, pServerData->pData, ((PGEALIST) pServerData->pData)->cbList); } /* Store up to the requested number of items. */ rc = storeDirContents( pVolume, pSearchData, pgeas, (char *) pServerData->pData, pfindfromname->cbData, pfindfromname->usLevel, &pfindfromname->cMatch, pfindfromname->fsFlags); if (rc) return rc; logMsg(L_DBG, "%d entries returned", pfindfromname->cMatch); return NO_ERROR; }
APIRET fsFindFirst(ServerData * pServerData, struct findfirst * pfindfirst) { APIRET rc; CryptedVolume * pVolume = pfindfirst->pVolData->pVolume; CHAR szDir[CCHMAXPATH]; SearchData * pSearchData; PGEALIST pgeas = 0; struct iso_directory_record * idr; IsoDirEntry* pIsoDirEntry=NULL; int iSize; int iExtent; pfindfirst->pSearchData = 0; if (VERIFYFIXED(pfindfirst->szName) || verifyPathName(pfindfirst->szName)) return ERROR_INVALID_PARAMETER; logMsg(L_DBG, "FS_FINDFIRST, curdir=%s, name=%s, " "iCurDirEnd=%d, fsAttr=%04hx, cMatch=%d, " "usLevel=%d, fsFlags=%04hx, cbData=%d", pfindfirst->cdfsi.cdi_curdir, pfindfirst->szName, pfindfirst->iCurDirEnd, pfindfirst->fsAttr, pfindfirst->cMatch, pfindfirst->usLevel, pfindfirst->fsFlags, pfindfirst->cbData); /* FIL_STANDARD : 1 FIL_QUERYEASIZE : 2 FIL_QUERYEASFROMLIST : 3 */ if (pfindfirst->usLevel != FIL_STANDARD && pfindfirst->usLevel != FIL_QUERYEASIZE && pfindfirst->usLevel != FIL_QUERYEASFROMLIST ) { logMsg(L_EVIL, "unknown FS_FINDFIRST info level: %d", pfindfirst->usLevel); return ERROR_NOT_SUPPORTED; } /* Allocate the SearchData structure. */ pSearchData = malloc(sizeof(SearchData)); if (!pSearchData) return ERROR_NOT_ENOUGH_MEMORY; pSearchData->pFirstInIsoDir = 0; pSearchData->flAttr = pfindfirst->fsAttr; /* Split the search specification. */ splitPath(pfindfirst->szName + 2, szDir, pSearchData->szName); logMsg(L_DBG, "dir=%s, spec=%s", szDir, pSearchData->szName); if (!*pSearchData->szName) { freeSearchData(pSearchData); return ERROR_INVALID_PARAMETER; } if(strlen(szDir)) { /* Walk the directory tree to find the name in szDir. */ pIsoDirEntry=isoQueryIsoEntryFromPath( pfindfirst->pVolData, szDir); if(!pIsoDirEntry) { logMsg(L_DBG, "Entry for %s not found", szDir); freeSearchData(pSearchData); return ERROR_PATH_NOT_FOUND; } logMsg(L_DBG, "Entry for %s found.", szDir); iExtent=pIsoDirEntry->iExtent; iSize=pIsoDirEntry->iSize; if(!S_ISDIR(pIsoDirEntry->fstat_buf.st_mode)) { free(pIsoDirEntry); logMsg(L_DBG, "Entry is not an directory", szDir); freeSearchData(pSearchData); return ERROR_PATH_NOT_FOUND; } free(pIsoDirEntry); } else { iExtent=pfindfirst->pVolData->iRootExtent; /* Get the contents of the directory from ISO file. */ idr=(struct iso_directory_record *)pfindfirst->pVolData->ipd.root_directory_record; iSize=isonum_733((unsigned char *)idr->size); } pIsoDirEntry=getDirEntries(szDir, iExtent, iSize, pfindfirst->pVolData, 0); pSearchData->pFirstInIsoDir=pIsoDirEntry; pSearchData->pIsoNext=pIsoDirEntry; if(pIsoDirEntry) { #if 0 logMsg(L_DBG, "Found following entries:"); do { logMsg(L_DBG, "Name is: %s, extent: %d, parent extent: %d", pIsoDirEntry->chrName,pIsoDirEntry->iExtent,pIsoDirEntry->iParentExtent); pIsoDirEntry=pIsoDirEntry->pNext; }while(pIsoDirEntry); #endif } else { freeSearchData(pSearchData); return ERROR_FILE_NOT_FOUND; } /* The GEAs are stored in the exchange buffer which is about to be overwritten; so make a copy. */ if (pfindfirst->usLevel == FIL_QUERYEASFROMLIST) { pgeas = alloca(((PGEALIST) pServerData->pData)->cbList); memcpy(pgeas, pServerData->pData, ((PGEALIST) pServerData->pData)->cbList); } /* Store up to the requested number of items. */ rc = storeDirContents( pVolume, pSearchData, pgeas, (char *) pServerData->pData, pfindfirst->cbData, pfindfirst->usLevel, &pfindfirst->cMatch, pfindfirst->fsFlags); if (rc && (rc != ERROR_EAS_DIDNT_FIT)) { freeSearchData(pSearchData); return rc; } logMsg(L_DBG, "%d entries returned", pfindfirst->cMatch); #if 0 /*!! ???????????*/ if(!pfindfirst->cMatch) { freeSearchData(pSearchData); /*return ERROR_NO_MORE_FILES;*/ return ERROR_FILE_NOT_FOUND; } #endif pfindfirst->pSearchData = pSearchData; pfindfirst->pVolData->cSearches++; return rc; }
static APIRET attachVolume(ServerData * pServerData, struct attach * pattach) { VolData * pVolData; IFS_ATTACH * parms = (IFS_ATTACH *) pServerData->pData; int rc; struct iso_primary_descriptor jpd; struct hs_primary_descriptor *hpd; struct iso_directory_record *idr = 0; /* For codepage */ ULONG ulCp[4]; ULONG ulInfoLen=0; char *ptr; pattach->pVolData = 0; if ((pattach->cbParm != sizeof(IFS_ATTACH)) || VERIFYFIXED(parms->szBasePath) ) return ERROR_INVALID_PARAMETER; for (ptr = parms->szBasePath; *ptr; ptr++) if (*ptr == '/') *ptr = '\\'; logMsg(L_DBG, "attaching drive, isopath=%s, offset: %d, charset: %s", parms->szBasePath, parms->iOffset, parms->szCharSet); if ((strncmp(parms->szBasePath, "\\\\", 2) != 0) && /* UNC */ (strncmp(parms->szBasePath, "////", 2) != 0) && /* UNC */ ((strlen(parms->szBasePath) < 3) || (!isalpha((unsigned char) parms->szBasePath[0])) || (parms->szBasePath[1] != ':') || ((parms->szBasePath[2] != '\\') && (parms->szBasePath[2] != '/')))) return ERROR_INVALID_PARAMETER; /* Max sector not tested, yet */ if(parms->iOffset<0) return ERROR_ISOFS_INVALIDOFFSET; /* Allocate a VolData structure. */ pVolData = malloc(sizeof(VolData)); if (!pVolData) { logMsg(L_EVIL, "out of memory"); return ERROR_NOT_ENOUGH_MEMORY; } memset(pVolData,0,sizeof(VolData)); pVolData->pServerData = pServerData; pVolData->chDrive = toupper(pattach->szDev[0]); pVolData->cOpenFiles = 0; pVolData->cSearches = 0; strncpy(pVolData->fileName,parms->szBasePath,sizeof(pVolData->fileName)); pVolData->iSectorOffset=parms->iOffset; strncpy(pVolData->szCharSet,parms->szCharSet,sizeof(pVolData->szCharSet)); /* Load translation table */ if(strlen(pVolData->szCharSet)) { pVolData->nls = load_nls(pVolData->szCharSet); if(!pVolData->nls) logMsg(L_EVIL, "Can't load table for charset %s",pVolData->szCharSet); } else { /* Use default system codepage */ if(DosQueryCp(sizeof(ulCp),ulCp,&ulInfoLen)==NO_ERROR) { /* Check if mkisofs supports our CP */ if(checkCpSupport((int)ulCp[0])) { sprintf(pVolData->szCharSet,"cp%d",(int)ulCp[0]); pVolData->nls = load_nls(pVolData->szCharSet); if(!pVolData->nls) logMsg(L_EVIL, "Can't load table for system codepage %s",pVolData->szCharSet); } } } /* ISO file */ pVolData->isoFile=sysOpenFile(pVolData->fileName, SOF_FAIL_IF_NEW | SOF_OPEN_IF_EXISTS | SOF_DENYWRITE | SOF_READONLY, 0); if(!pVolData->isoFile) { logMsg(L_EVIL, "Can't open ISO file"); /* Unload translation table */ if(pVolData->nls) unload_nls(pVolData->nls); free(pVolData); return ERROR_ISOFS_FILEOPEN; } /* Get info from ISO file */ lseek(pVolData->isoFile->h, ((off_t)(16 + pVolData->iSectorOffset)) <<11, 0); rc=read(pVolData->isoFile->h, &pVolData->ipd, sizeof(pVolData->ipd)); logMsg(L_DBG, "ISO primary descriptor read from ISO file (%d Bytes)",rc); /****************************************/ hpd = (struct hs_primary_descriptor *) &pVolData->ipd; if ((hpd->type[0] == ISO_VD_PRIMARY) && (strncmp(hpd->id, HIGH_SIERRA_ID, sizeof(hpd->id)) == 0) && (hpd->version[0] == 1)) { pVolData->high_sierra = 1; idr = (struct iso_directory_record *) hpd->root_directory_record; memcpy(&pVolData->chrCDName,&hpd->volume_id,32); } else if ((pVolData->ipd.type[0] != ISO_VD_PRIMARY) || (strncmp(pVolData->ipd.id, ISO_STANDARD_ID, sizeof(pVolData->ipd.id)) != 0) || (pVolData->ipd.version[0] != 1)) { logMsg(L_EVIL, "Unable to find PVD"); /* Unload translation table */ if(pVolData->nls) unload_nls(pVolData->nls); sysCloseFile(pVolData->isoFile); free(pVolData); return ERROR_ISOFS_NOTISO; } if (!pVolData->high_sierra) { int block = 16; memcpy(&pVolData->chrCDName,&pVolData->ipd.volume_id,32); memcpy(&jpd, &pVolData->ipd, sizeof(pVolData->ipd)); while (((unsigned char) jpd.type[0] != ISO_VD_END) && (strncmp(jpd.id, ISO_STANDARD_ID, sizeof(jpd.id)) == 0) && (jpd.version[0] == 1)) { if( (unsigned char) jpd.type[0] == ISO_VD_SUPPLEMENTARY ) /* * Find the UCS escape sequence. */ if( jpd.escape_sequences[0] == '%' && jpd.escape_sequences[1] == '/' && (jpd.escape_sequences[3] == '\0' || jpd.escape_sequences[3] == ' ') && (jpd.escape_sequences[2] == '@' || jpd.escape_sequences[2] == 'C' || jpd.escape_sequences[2] == 'E') ) { pVolData->got_joliet = 1; break; } block++; lseek(pVolData->isoFile->h, ((off_t)(block + pVolData->iSectorOffset)) <<11, 0); read(pVolData->isoFile->h, &jpd, sizeof(jpd)); } if(pVolData->got_joliet) switch(jpd.escape_sequences[2]) { case '@': pVolData->ucs_level = 1; break; case 'C': pVolData->ucs_level = 2; break; case 'E': pVolData->ucs_level = 3; break; } if (pVolData->got_joliet) memcpy(&pVolData->ipd, &jpd, sizeof(pVolData->ipd)); idr = (struct iso_directory_record *) pVolData->ipd.root_directory_record; } /****************************************/ /* Fill in extent of root */ pVolData->root_directory_record = idr; pVolData->idRoot = isonum_733((unsigned char *)idr->extent);/* 733 */ pVolData->iRootExtent = pVolData->idRoot; pVolData->iRootSize=isonum_733((unsigned char *)idr->size); logMsg(L_DBG, "Extent of root is: %d ",pVolData->idRoot); pattach->pVolData = pVolData; pVolData->pNext = pServerData->pFirstVolume; pVolData->pPrev = 0; if (pVolData->pNext) pVolData->pNext->pPrev = pVolData; pServerData->pFirstVolume = pVolData; return NO_ERROR; }