CoreResult coreQueryDirEntries(CryptedVolume * pVolume, CryptedFileID id, CryptedDirEntry * * ppEntries) { CoreResult cr, crread; CryptedFileInfo info; CryptedFilePos cbRead; octet * pabBuffer; *ppEntries = 0; /* Get file info. */ cr = coreQueryFileInfo(pVolume, id, &info); if (cr) return cr; if (!CFF_ISDIR(info.flFlags)) return CORERC_NOT_DIRECTORY; if (!info.cbFileSize) return CORERC_OK; /* Allocate memory for the encoded directory data. */ pabBuffer = sysAllocSecureMem(info.cbFileSize); if (!pabBuffer) return CORERC_NOT_ENOUGH_MEMORY; /* Read the directory. Continue even if an error occurs, because part of the directory might still be readable. */ crread = coreReadFromFile(pVolume, id, 0, info.cbFileSize, pabBuffer, &cbRead); /* Decode the directory data. */ cr = decodeDir(cbRead, pabBuffer, ppEntries); sysFreeSecureMem(pabBuffer); return crread ? crread : cr; }
/* Set the archived bit and the last write time. */ APIRET easChanged(CryptedVolume * pVolume, CryptedFileID idFile, bool fHidden, struct sffsi * psffsi) { CoreResult cr; CryptedFileInfo info; cr = coreQueryFileInfo(pVolume, idFile, &info); if (cr) return coreResultToOS2(cr); info.flFlags |= CFF_OS2A; info.timeWrite = curTime(); if (psffsi) { psffsi->sfi_tstamp = (psffsi->sfi_tstamp | ST_PWRITE) & ~ST_SWRITE; coreToSffsi(fHidden, &info, psffsi); } return coreResultToOS2(coreSetFileInfo(pVolume, idFile, &info)); }
APIRET setLevel1Info(CryptedVolume * pVolume, struct sffsi * psffsi, CryptedFileID idFile, CryptedFileID idDir, bool fHidden, PFILESTATUS pStat) { CoreResult cr; APIRET rc; CryptedFileInfo info; cr = coreQueryFileInfo(pVolume, idFile, &info); if (cr) return coreResultToOS2(cr); if (!beq(CFF_ISDIR(info.flFlags), pStat->attrFile & FILE_DIRECTORY)) return ERROR_INVALID_PARAMETER; if (rc = doTimeChange(* (ULONG *) &pStat->fdateCreation, &info.timeCreation, psffsi, ST_SCREAT)) return rc; if (rc = doTimeChange(* (ULONG *) &pStat->fdateLastAccess, &info.timeAccess, psffsi, ST_SREAD)) return rc; if (rc = doTimeChange(* (ULONG *) &pStat->fdateLastWrite, &info.timeWrite, psffsi, ST_SWRITE)) return rc; extractDOSAttr(pStat->attrFile, &info); cr = coreSetFileInfo(pVolume, idFile, &info); if (cr) return coreResultToOS2(cr); if (!beq(fHidden, pStat->attrFile & FILE_HIDDEN)) { fHidden = pStat->attrFile & FILE_HIDDEN; cr = setHiddenFlag(pVolume, idDir, idFile, fHidden); if (cr) return coreResultToOS2(cr); } if (psffsi) coreToSffsi(fHidden, &info, psffsi); return NO_ERROR; }
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; } }
APIRET doFileInfo(struct sffsi * psffsi, ULONG flFlag, ULONG ulLevel, VolData * pVolData, CryptedFileID idFile, CryptedFileID idDir, bool fHidden, ULONG cbData, char * pData) { CoreResult cr; APIRET rc; CryptedVolume * pVolume = pVolData->pVolume; CryptedFileInfo info; PGEALIST pgeas; /* Access the file and get file info. */ cr = coreQueryFileInfo(pVolume, idFile, &info); if (cr) return coreResultToOS2(cr); if (flFlag & FI_SET) { /* Set file info. */ switch (ulLevel) { case FIL_STANDARD: /* Set file info. */ if (cbData < sizeof(FILESTATUS)) return ERROR_INVALID_PARAMETER; return setLevel1Info(pVolume, psffsi, idFile, idDir, fHidden, (PFILESTATUS) pData); case FIL_QUERYEASIZE: /* Set EAs. */ rc = addEAs(pVolume, idFile, (PFEALIST) pData); if (rc) return rc; return easChanged(pVolume, idFile, fHidden, psffsi); default: logMsg(L_EVIL, "unknown set-FS_[FILE|PATH]INFO info level: %d", ulLevel); return ERROR_NOT_SUPPORTED; } } else { /* Query file info. */ switch (ulLevel) { case FIL_STANDARD: case FIL_QUERYEASIZE: /* Query level 1 or 2 file info. */ memset(pData, 0, cbData); return storeFileInfo(0, 0, 0, 0, fHidden, &info, &pData, &cbData, ulLevel, 0, 0); case FIL_QUERYEASFROMLIST: /* Query level 3 (EA) file info. */ /* The GEAs are stored in the exchange buffer which is about to be overwritten; so make a copy. */ pgeas = alloca(((PGEALIST) pData)->cbList); memcpy(pgeas, pData, ((PGEALIST) pData)->cbList); return storeEAsInFEAList(pVolume, idFile, &info, pgeas, 65536, pData); case 4: /* Store the entire EA set. */ return storeEAsInFEAList(pVolume, idFile, &info, 0, 65536, pData); default: logMsg(L_EVIL, "unknown query-FS_[FILE|PATH]INFO info level: %d", ulLevel); return ERROR_NOT_SUPPORTED; } } }
/* Update file time stamps if required. Flush none, some or all of the file to disk. */ APIRET stampFileAndFlush(VolData * pVolData, CryptedFileID idFile, struct sffsi * psffsi, int flush) { CoreResult cr; CryptedVolume * pVolume = pVolData->pVolume; CryptedFileInfo info; /* If any of the ST_Sxxx stamp bits is set, copy the sffsi times into the info sector. */ if (!pVolData->fReadOnly && ((psffsi->sfi_tstamp & (ST_SCREAT | ST_SWRITE)) || ((psffsi->sfi_tstamp & ST_SREAD) && !pVolData->pServerData->fLazyLastAccess))) { cr = coreQueryFileInfo(pVolume, idFile, &info); if (cr) return coreResultToOS2(cr); /* Copy the time stamps from the sffsi. */ os2TimeToCore( * (FDATE *) &psffsi->sfi_cdate, * (FTIME *) &psffsi->sfi_ctime, &info.timeCreation); os2TimeToCore( * (FDATE *) &psffsi->sfi_adate, * (FTIME *) &psffsi->sfi_atime, &info.timeAccess); os2TimeToCore( * (FDATE *) &psffsi->sfi_mdate, * (FTIME *) &psffsi->sfi_mtime, &info.timeWrite); if (psffsi->sfi_tstamp & ST_SWRITE) info.flFlags |= CFF_OS2A; /* Write the info sector. */ cr = coreSetFileInfo(pVolume, idFile, &info); if (cr) return coreResultToOS2(cr); } psffsi->sfi_tstamp = 0; switch (flush) { case SFAF_NOFLUSH: break; case SFAF_FLUSHINFO: /* Flush the info sector if it's in the cache and dirty. */ cr = coreFlushSector(pVolume, INFOSECTORFILE_ID, coreQueryInfoSectorNumber(pVolume, idFile)); if (cr) return coreResultToOS2(cr); break; case SFAF_FLUSHALL: if (cr = coreFlushFile(pVolume, idFile)) return coreResultToOS2(cr); break; default: abort(); } return NO_ERROR; }