📄 pfat.c
字号:
KASSERT(instance != 0); Mutex_Lock(&instance->lock); /* * See if this file has already been opened. * If so, use the existing PFAT_File object. */ for (pfatFile = Get_Front_Of_PFAT_File_List(&instance->fileList); pfatFile != 0; pfatFile = Get_Next_In_PFAT_File_List(pfatFile)) { if (pfatFile->entry == entry) break; } if (pfatFile == 0) { /* Determine size of data block cache for file. */ numBlocks = Round_Up_To_Block(entry->fileSize) / SECTOR_SIZE; /* * Allocate File object, PFAT_File object, file block data cache, * and valid cache block bitset */ if ((pfatFile = (struct PFAT_File *) Malloc(sizeof(*pfatFile))) == 0 || (fileDataCache = Malloc(numBlocks * SECTOR_SIZE)) == 0 || (validBlockSet = Create_Bit_Set(numBlocks)) == 0) { goto memfail; } /* Populate PFAT_File */ pfatFile->entry = entry; pfatFile->numBlocks = numBlocks; pfatFile->fileDataCache = fileDataCache; pfatFile->validBlockSet = validBlockSet; Mutex_Init(&pfatFile->lock); /* Add to instance's list of PFAT_File objects. */ Add_To_Back_Of_PFAT_File_List(&instance->fileList, pfatFile); KASSERT(pfatFile->nextPFAT_File_List == 0); } /* Success! */ goto done;memfail: if (pfatFile != 0) Free(pfatFile); if (fileDataCache != 0) Free(fileDataCache); if (validBlockSet != 0) Free(validBlockSet);done: Mutex_Unlock(&instance->lock); return pfatFile;}/* * Open function for PFAT filesystems. */static int PFAT_Open(struct Mount_Point *mountPoint, const char *path, int mode, struct File **pFile){ int rc = 0; struct PFAT_Instance *instance = (struct PFAT_Instance*) mountPoint->fsData; directoryEntry *entry; struct PFAT_File *pfatFile = 0; struct File *file = 0; /* Reject attempts to create or write */ if ((mode & (O_WRITE | O_CREATE)) != 0) return EACCESS; /* Look up the directory entry */ entry = PFAT_Lookup(instance, path); if (entry == 0) return ENOTFOUND; /* Make sure the entry is not a directory. */ if (entry->directory) return EACCESS; /* Get PFAT_File object */ pfatFile = Get_PFAT_File(instance, entry); if (pfatFile == 0) goto done; /* Create the file object. */ file = Allocate_File(&s_pfatFileOps, 0, entry->fileSize, pfatFile, 0, 0); if (file == 0) { rc = ENOMEM; goto done; } /* Success! */ *pFile = file;done: return rc;}/* * Open_Directory function for PFAT filesystems. */static int PFAT_Open_Directory(struct Mount_Point *mountPoint, const char *path, struct File **pDir){ /* * FIXME: for now, we only support a single directory. * This makes this function pretty simple. * We just store the current cursor index in the File object. */ struct PFAT_Instance *instance = (struct PFAT_Instance*) mountPoint->fsData; struct File *dir; if (strcmp(path, "/") != 0) return ENOTFOUND; dir = (struct File*) Malloc(sizeof(*dir)); if (dir == 0) return ENOMEM; dir->ops = &s_pfatDirOps; dir->filePos = 0; /* next dir entry to be read */ dir->endPos = instance->fsinfo.rootDirectoryCount; /* number of directory entries */ dir->fsData = 0; *pDir = dir; return 0;}/* * 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;}/* * Sync function for PFAT filesystems. */static int PFAT_Sync(struct Mount_Point *mountPoint){ /* Read only filesystem: this is a no-op. */ return 0;}/* * Mount_Point_Ops for PFAT filesystem. */struct Mount_Point_Ops s_pfatMountPointOps = { PFAT_Open, 0, /* Create_Directory() */ PFAT_Open_Directory, PFAT_Stat, PFAT_Sync, 0 /* Delete */};/* * If the given PFAT instance has a paging file, * register it as the paging device, unless a paging device * has already been registered. */static void PFAT_Register_Paging_File(struct Mount_Point *mountPoint, struct PFAT_Instance *instance){ directoryEntry *pagefileEntry; struct Paging_Device *pagedev = 0; size_t nameLen; char *fileName = 0; if (Get_Paging_Device() != 0) return; /* A paging device is already registered */ pagefileEntry = PFAT_Lookup(instance, PAGEFILE_FILENAME); if (pagefileEntry == 0) return; /* No paging file in this filesystem */ /* TODO: verify that paging file is contiguous */ /* Create Paging_Device object. */ pagedev = (struct Paging_Device*) Malloc(sizeof(*pagedev)); if (pagedev == 0) goto memfail; nameLen = strlen(mountPoint->pathPrefix) + strlen(PAGEFILE_FILENAME) + 3; fileName = (char*) Malloc(nameLen); if (fileName == 0) goto memfail; /* Format page filename */ snprintf(fileName, nameLen, "/%s%s", mountPoint->pathPrefix, PAGEFILE_FILENAME); /* Initialize Paging_Device */ pagedev->fileName = fileName; pagedev->dev = mountPoint->dev; pagedev->startSector = pagefileEntry->firstBlock; pagedev->numSectors = pagefileEntry->fileSize / SECTOR_SIZE; /* Register it */ Register_Paging_Device(pagedev); return;memfail: Print(" Error: could not create paging device for pfat on %s (%s)\n", mountPoint->pathPrefix, mountPoint->dev->name); if (pagedev != 0) Free(pagedev); if (fileName != 0) Free(fileName);}/* * Mount function for PFAT filesystem. */static int PFAT_Mount(struct Mount_Point *mountPoint){ struct PFAT_Instance *instance = 0; bootSector *fsinfo; void *bootSect = 0; int rootDirSize; int rc; int i; /* Allocate instance. */ instance = (struct PFAT_Instance*) Malloc(sizeof(*instance)); if (instance == 0) goto memfail; memset(instance, '\0', sizeof(*instance)); fsinfo = &instance->fsinfo; Debug("Created instance object\n"); /* * Allocate buffer to read bootsector, * which contains metainformation about the PFAT filesystem. */ bootSect = Malloc(SECTOR_SIZE); if (bootSect == 0) goto memfail; /* Read boot sector */ if ((rc = Block_Read(mountPoint->dev, 0, bootSect)) < 0) goto fail; Debug("Read boot sector\n"); /* Copy filesystem parameters from boot sector */ memcpy(&instance->fsinfo, ((char*)bootSect) + PFAT_BOOT_RECORD_OFFSET, sizeof(bootSector)); Debug("Copied boot record\n"); /* Does magic number match? */ if (fsinfo->magic != PFAT_MAGIC) { Print("Bad magic number (%x) for PFAT filesystem\n", fsinfo->magic); goto invalidfs; } Debug("Magic number is good!\n"); /* Do filesystem params look reasonable? */ if (fsinfo->fileAllocationOffset <= 0 || fsinfo->fileAllocationLength <= 0 || fsinfo->rootDirectoryCount < 0 || fsinfo->rootDirectoryOffset <= 0) { Print("Invalid parameters for PFAT filesystem\n"); goto invalidfs; } Debug("PFAT filesystem parameters appear to be good!\n"); /* Allocate in-memory FAT */ instance->fat = (int*) Malloc(fsinfo->fileAllocationLength * SECTOR_SIZE); if (instance->fat == 0) goto memfail; /* Read the FAT */ for (i = 0; i < fsinfo->fileAllocationLength; ++i) { int blockNum = fsinfo->fileAllocationOffset + i; char *p = ((char*)instance->fat) + (i * SECTOR_SIZE); if ((rc = Block_Read(mountPoint->dev, blockNum, p)) < 0) goto fail; } Debug("Read FAT successfully!\n"); /* Allocate root directory */ rootDirSize = Round_Up_To_Block(sizeof(directoryEntry) * fsinfo->rootDirectoryCount); instance->rootDir = (directoryEntry*) Malloc(rootDirSize); /* Read the root directory */ Debug("Root directory size = %d\n", rootDirSize); for (i = 0; i < rootDirSize; i += SECTOR_SIZE) { int blockNum = fsinfo->rootDirectoryOffset + i; if ((rc = Block_Read(mountPoint->dev, blockNum, instance->rootDir + (i*SECTOR_SIZE))) < 0) goto fail; } Debug("Read root directory successfully!\n"); /* Create the fake root directory entry. */ memset(&instance->rootDirEntry, '\0', sizeof(directoryEntry)); instance->rootDirEntry.readOnly = 1; instance->rootDirEntry.directory = 1; instance->rootDirEntry.fileSize = instance->fsinfo.rootDirectoryCount * sizeof(directoryEntry); /* Initialize instance lock and PFAT_File list. */ Mutex_Init(&instance->lock); Clear_PFAT_File_List(&instance->fileList); /* Attempt to register a paging file */ PFAT_Register_Paging_File(mountPoint, instance); /* * Success! * This mount point is now ready * to handle file accesses. */ mountPoint->ops = &s_pfatMountPointOps; mountPoint->fsData = instance; return 0;memfail: rc = ENOMEM; goto fail;invalidfs: rc = EINVALIDFS; goto fail;fail: if (instance != 0) { if (instance->fat != 0) Free(instance->fat); if (instance->rootDir != 0) Free(instance->rootDir); Free(instance); } if (bootSect != 0) Free(bootSect); return rc;}static struct Filesystem_Ops s_pfatFilesystemOps = { 0, // Format &PFAT_Mount,};/* ---------------------------------------------------------------------- * Public functions * ---------------------------------------------------------------------- */void Init_PFAT(void){ Register_Filesystem("pfat", &s_pfatFilesystemOps);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -