Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
         
   }
}
Esempio n. 3
0
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;
   }
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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);
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
   }
}
Esempio n. 11
0
/* 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;
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
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;
}