⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pfat.c

📁 geekos 0.3.0简单的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 + -