static int PFAT_FStat_Dir(struct File *dir, struct VFS_File_Stat *stat) { /* FIXME: for now, there is only one directory */ struct PFAT_Instance *instance = (struct PFAT_Instance*) dir->mountPoint->fsData; Copy_Stat(stat, &instance->rootDirEntry); return 0; }
/* * Get metadata for given file. Need to find the file from the given path. */ int GOSFS_Stat(struct Mount_Point *mountPoint, const char *path, struct VFS_File_Stat *stat) { int rc = 0; int blockNum = 0; // The GOSFS block the fileNode(file or dir) exists in bool found = 0; char name[MAX_NAME_SIZE] = {}; GOSFSsuperblock *super = (GOSFSsuperblock *)mountPoint->fsData; GOSFSptr *gosfsEntry = Safe_Calloc(sizeof(GOSFSptr)); GOSFSdirectory *currDir = Safe_Calloc(PAGE_SIZE); /* Grab the root directory from disk */ blockNum = super->rootDir; GOSFS_Block_Read(mountPoint->dev, super->rootDir, currDir); while(*path != 0) { memset(name, '\0', MAX_NAME_SIZE); memset(gosfsEntry, '\0', sizeof(GOSFSptr)); Get_Next_Name_In_Path(&path, name); found = GOSFS_Lookup(currDir, name, blockNum, gosfsEntry); /* Entry exists but not a file and not end of path */ if (found == true && gosfsEntry->node.isDirectory == 0 && *path != 0) { rc = ENOTDIR; goto fail; } /* Entry exists but directory ,search in that dir */ if (found == true && gosfsEntry->node.isDirectory == 1 && *path != 0) { blockNum = gosfsEntry->node.blocks[0]; GOSFS_Block_Read(mountPoint->dev, blockNum, currDir); continue; } /* If entry does not exist then fail */ if (found == false ) { rc = ENOTFOUND; goto fail; } } /* Copy metadata */ Copy_Stat(stat, &gosfsEntry->node); fail: done: Free(gosfsEntry); Free(currDir); return rc; }
/* * Stat function for PFAT filesystems. */ static int PFAT_Stat(struct Mount_Point *mountPoint, const char *path, struct VFS_File_Stat *stat) { struct PFAT_Instance *instance = (struct PFAT_Instance*) mountPoint->fsData; directoryEntry *entry; KASSERT(path != 0); KASSERT(stat != 0); Debug("PFAT_Stat(%s)\n", path); entry = PFAT_Lookup(instance, path); if (entry == 0) return ENOTFOUND; Copy_Stat(stat, entry); return 0; }
/* * Read next directory entry from an open directory. * Return 1 on success, < 0 on failure. */ int GOSFS_Read_Entry(struct File *dir, struct VFS_Dir_Entry *entry) { int rc = 1; GOSFSfileNode *currNode = 0; GOSFSdirectory *currDir = Safe_Calloc(PAGE_SIZE); GOSFSptr *currEntry = (GOSFSptr *)dir->fsData; /* struct File is not a directory */ if (currEntry->node.isDirectory == 0) { rc = ENOTDIR; goto fail; } /* file position at end of dir */ if (dir->filePos >= MAX_FILES_PER_DIR) { rc = EINVALID; goto fail; } /* Grab the open directory's actual directory structure from disk */ GOSFS_Block_Read(dir->mountPoint->dev, currEntry->node.blocks[0], currDir); /* Get the next non-empty entry */ for (; dir->filePos < MAX_FILES_PER_DIR; dir->filePos++) { currNode = &currDir->files[dir->filePos]; if (currNode->isUsed == 1) { memcpy(entry->name, currNode->name, MAX_NAME_SIZE); Copy_Stat(&entry->stats, currNode); dir->filePos++; goto done; } } rc = ENOTFOUND; fail: done: Free(currDir); return rc; }
/* * Read a directory entry. */ static int PFAT_Read_Entry(struct File *dir, struct VFS_Dir_Entry *entry) { directoryEntry *pfatDirEntry; struct PFAT_Instance *instance = (struct PFAT_Instance*) dir->mountPoint->fsData; if (dir->filePos >= dir->endPos) return VFS_NO_MORE_DIR_ENTRIES; /* Reached the end of the directory. */ pfatDirEntry = &instance->rootDir[dir->filePos++]; /* * Note: we don't need to bounds check here, because * generic struct VFS_Dir_Entry objects have much more space for filenames * than PFAT directoryEntry objects. */ strncpy(entry->name, pfatDirEntry->fileName, sizeof(pfatDirEntry->fileName)); entry->name[sizeof(pfatDirEntry->fileName)] = '\0'; Copy_Stat(&entry->stats, pfatDirEntry); return 0; }
/* * FStat function for PFAT files. */ static int PFAT_FStat(struct File *file, struct VFS_File_Stat *stat) { struct PFAT_File *pfatFile = (struct PFAT_File*) file->fsData; Copy_Stat(stat, pfatFile->entry); return 0; }
/* * Read data from current position in file. * Return > 0 on success, < 0 on failure. */ int GOSFS_Read(struct File *file, void *buf, ulong_t numBytes) { int bytesRead = 0; int bytesToRead = 0; int blockNum = 0; int offset = file->filePos % PAGE_SIZE; int endPos = file->filePos + numBytes; int numDirEntries = 0; int dirEntriesRead = 0; int index = 0; void *tempBuffer = 0; struct Block_Device *dev = file->mountPoint->dev; GOSFSptr *entry = (GOSFSptr *)file->fsData; GOSFSfileNode *node = &entry->node; GOSFSfileNode *currNode = 0; GOSFSdirectory *currDir = 0; struct VFS_Dir_Entry *dirEntry = 0; /* If the read is called on a directory, read dir entries into buffer */ if (node->isDirectory == 1) { currDir = Safe_Calloc(PAGE_SIZE); dirEntry = Safe_Calloc(sizeof(struct VFS_Dir_Entry)); numDirEntries = numBytes; // Num dir entries I need to read if ((file->filePos + numDirEntries) > file->endPos) { numDirEntries = file->endPos - file->filePos; } GOSFS_Block_Read(dev, node->blocks[0], currDir); /* Write the number of dir entries we need to the buffer */ while (numDirEntries > 0) { memset(dirEntry, '\0', sizeof(struct VFS_Dir_Entry)); currNode = &currDir->files[file->filePos]; memcpy(dirEntry->name, currNode->name, MAX_NAME_SIZE); Copy_Stat(&dirEntry->stats, currNode); memcpy(buf, dirEntry, sizeof(struct VFS_Dir_Entry)); buf += sizeof(struct VFS_Dir_Entry); numDirEntries--; dirEntriesRead++; file->filePos++; } Free(dirEntry); Free(currDir); return dirEntriesRead; } /* If read is called on a file */ else { /* No read access */ if ((file->mode & O_READ) == 0) { return EACCESS; } /* If trying to read more bytes than exists, only read what's left */ if (endPos > file->endPos) { numBytes = file->endPos - file->filePos; } tempBuffer = Safe_Calloc(PAGE_SIZE); while (numBytes > 0) { memset(tempBuffer, '\0', PAGE_SIZE); blockNum = Get_Blocknum_To_Read(file); if (blockNum == 0) return -1; if (numBytes < (PAGE_SIZE - offset)) { bytesToRead = numBytes; } else if (numBytes >= (PAGE_SIZE - offset)) { bytesToRead = PAGE_SIZE - offset; } GOSFS_Block_Read(dev, blockNum, tempBuffer); memcpy(buf, tempBuffer + offset, bytesToRead); offset = 0; file->filePos += bytesToRead; bytesRead += bytesToRead; numBytes -= bytesToRead; } Free(tempBuffer); return bytesRead; } }
/* * Get metadata for given File. Called with a file descriptor. */ int GOSFS_FStat(struct File *file, struct VFS_File_Stat *stat) { GOSFSptr *entry = (GOSFSptr *)file->fsData; Copy_Stat(stat, &entry->node); return 0; }