📄 fs_fat32.c
字号:
* ****************************************************************************/static int fat_unlink(struct inode *mountpt, const char *relpath){ struct fat_mountpt_s *fs; int ret; /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); /* Get the mountpoint private data from the inode structure */ fs = mountpt->i_private; /* Check if the mount is still healthy */ fat_semtake(fs); ret = fat_checkmount(fs); if (ret == OK) { /* If the file is open, the correct behavior is to remove the file * name, but to keep the file cluster chain in place until the last * open reference to the file is closed. */#warning "Need to defer deleting cluster chain if the file is open" /* Remove the file */ ret = fat_remove(fs, relpath, FALSE); } fat_semgive(fs); return ret;}/**************************************************************************** * Name: fat_mkdir * * Description: Create a directory * ****************************************************************************/static int fat_mkdir(struct inode *mountpt, const char *relpath, mode_t mode){ struct fat_mountpt_s *fs; struct fat_dirinfo_s dirinfo; ubyte *direntry; ubyte *direntry2; size_t parentsector; ssize_t dirsector; sint32 dircluster; uint32 parentcluster; uint32 crtime; unsigned int i; int ret; /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); /* Get the mountpoint private data from the inode structure */ fs = mountpt->i_private; /* Check if the mount is still healthy */ fat_semtake(fs); ret = fat_checkmount(fs); if (ret != OK) { goto errout_with_semaphore; } /* Find the directory where the new directory should be created. */ ret = fat_finddirentry(fs, &dirinfo, relpath); /* If anything exists at this location, then we fail with EEXIST */ if (ret == OK) { ret = -EEXIST; goto errout_with_semaphore; } /* What we want to see is for fat_finddirentry to fail with -ENOENT. * This error means that no failure occurred but that nothing exists * with this name. */ if (ret != -ENOENT) { goto errout_with_semaphore; } /* NOTE: There is no check that dirinfo.fd_name contains the final * directory name. We could be creating an intermediate directory * in the full relpath. */ /* Allocate a directory entry for the new directory in this directory */ ret = fat_allocatedirentry(fs, &dirinfo); if (ret != OK) { goto errout_with_semaphore; } parentsector = fs->fs_currentsector; /* Allocate a cluster for new directory */ dircluster = fat_createchain(fs); if (dircluster < 0) { ret = dircluster; goto errout_with_semaphore; } else if (dircluster < 2) { ret = -ENOSPC; goto errout_with_semaphore; } dirsector = fat_cluster2sector(fs, dircluster); if (dirsector < 0) { ret = dirsector; goto errout_with_semaphore; } /* Flush any existing, dirty data in fs_buffer (because we need * it to create the directory entries. */ ret = fat_fscacheflush(fs); if (ret < 0) { goto errout_with_semaphore; } /* Get a pointer to the first directory entry in the sector */ direntry = fs->fs_buffer; /* Now erase the contents of fs_buffer */ fs->fs_currentsector = dirsector; memset(direntry, 0, fs->fs_hwsectorsize); /* Now clear all sectors in the new directory cluster (except for the first) */ for (i = 1; i < fs->fs_fatsecperclus; i++) { ret = fat_hwwrite(fs, direntry, ++dirsector, 1); if (ret < 0) { goto errout_with_semaphore; } } /* Now create the "." directory entry in the first directory slot */ memset(&direntry[DIR_NAME], ' ', 8+3); direntry[DIR_NAME] = '.'; DIR_PUTATTRIBUTES(direntry, FATATTR_DIRECTORY); crtime = fat_systime2fattime(); DIR_PUTCRTIME(direntry, crtime & 0xffff); DIR_PUTWRTTIME(direntry, crtime & 0xffff); DIR_PUTCRDATE(direntry, crtime >> 16); DIR_PUTWRTDATE(direntry, crtime >> 16); /* Create ".." directory entry in the second directory slot */ direntry2 = direntry + 32; /* So far, the two entries are nearly the same */ memcpy(direntry2, direntry, 32); direntry2[DIR_NAME+1] = '.'; /* Now add the cluster information to both directory entries */ DIR_PUTFSTCLUSTHI(direntry, dircluster >> 16); DIR_PUTFSTCLUSTLO(direntry, dircluster); parentcluster = dirinfo.dir.fd_startcluster; if (fs->fs_type != FSTYPE_FAT32 && parentcluster == fs->fs_rootbase) { parentcluster = 0; } DIR_PUTFSTCLUSTHI(direntry2, parentcluster >> 16); DIR_PUTFSTCLUSTLO(direntry2, parentcluster); /* Save the first sector of the directory cluster and re-read * the parentsector */ fs->fs_dirty = TRUE; ret = fat_fscacheread(fs, parentsector); if (ret < 0) { goto errout_with_semaphore; } /* Initialize the new entry directory entry in the parent directory */ direntry = dirinfo.fd_entry; memset(direntry, 0, 32); memcpy(direntry, dirinfo.fd_name, 8+3);#ifdef CONFIG_FLAT_LCNAMES DIR_PUTNTRES(direntry, dirinfo.fd_ntflags);#endif DIR_PUTATTRIBUTES(dirinfo.fd_entry, FATATTR_DIRECTORY); /* Same creation time as for . and .. */ DIR_PUTCRTIME(dirinfo.fd_entry, crtime & 0xffff); DIR_PUTWRTTIME(dirinfo.fd_entry, crtime & 0xffff); DIR_PUTCRDATE(dirinfo.fd_entry, crtime >> 16); DIR_PUTWRTDATE(dirinfo.fd_entry, crtime >> 16); /* Set subdirectory start cluster */ DIR_PUTFSTCLUSTLO(dirinfo.fd_entry, dircluster); DIR_PUTFSTCLUSTHI(dirinfo.fd_entry, dircluster >> 16); /* Now update the FAT32 FSINFO sector */ fs->fs_dirty = TRUE; ret = fat_updatefsinfo(fs); if (ret < 0) { goto errout_with_semaphore; } fat_semgive(fs); return OK;errout_with_semaphore: fat_semgive(fs); return ret;}/**************************************************************************** * Name: fat_rmdir * * Description: Remove a directory * ****************************************************************************/int fat_rmdir(struct inode *mountpt, const char *relpath){ struct fat_mountpt_s *fs; int ret; /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); /* Get the mountpoint private data from the inode structure */ fs = mountpt->i_private; /* Check if the mount is still healthy */ fat_semtake(fs); ret = fat_checkmount(fs); if (ret == OK) { /* If the directory is open, the correct behavior is to remove the directory * name, but to keep the directory cluster chain in place until the last * open reference to the directory is closed. */#warning "Need to defer deleting cluster chain if the directory is open" /* Remove the directory */ ret = fat_remove(fs, relpath, TRUE); } fat_semgive(fs); return ret;}/**************************************************************************** * Name: fat_rename * * Description: Rename a file or directory * ****************************************************************************/int fat_rename(struct inode *mountpt, const char *oldrelpath, const char *newrelpath){ struct fat_mountpt_s *fs; struct fat_dirinfo_s dirinfo; size_t oldsector; ubyte *olddirentry; ubyte *newdirentry; ubyte dirstate[32-11]; int ret; /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); /* Get the mountpoint private data from the inode structure */ fs = mountpt->i_private; /* Check if the mount is still healthy */ fat_semtake(fs); ret = fat_checkmount(fs); if (ret != OK) { goto errout_with_semaphore; } /* Find the directory entry for the oldrelpath */ ret = fat_finddirentry(fs, &dirinfo, oldrelpath); if (ret != OK) { /* Some error occurred -- probably -ENOENT */ goto errout_with_semaphore; } /* Save the information that will need to recover the * directory sector and directory entry offset to the * old directory. */ olddirentry = dirinfo.fd_entry; /* One more check: Make sure that the oldrelpath does * not refer to the root directory. We can't rename the * root directory. */ if (!olddirentry) { ret = -EXDEV; goto errout_with_semaphore; } oldsector = fs->fs_currentsector; memcpy(dirstate, &olddirentry[DIR_ATTRIBUTES], 32-11); /* No find the directory where we should create the newpath object */ ret = fat_finddirentry(fs, &dirinfo, newrelpath); if (ret == OK) { /* It is an error if the object at newrelpath already exists */ ret = -EEXIST; goto errout_with_semaphore; } /* What we expect is -ENOENT mean that the full directory path was * followed but that the object does not exists in the terminal directory. */ if (ret != -ENOENT) { goto errout_with_semaphore; } /* Reserve a directory entry */ ret = fat_allocatedirentry(fs, &dirinfo); if (ret != OK) { goto errout_with_semaphore; } /* Create the new directory entry */ newdirentry = dirinfo.fd_entry; memcpy(&newdirentry[DIR_ATTRIBUTES], dirstate, 32-11); memcpy(&newdirentry[DIR_NAME], dirinfo.fd_name, 8+3);#ifdef CONFIG_FLAT_LCNAMES DIR_PUTNTRES(newdirentry, dirinfo.fd_ntflags);#else DIR_PUTNTRES(newdirentry, 0);#endif fs->fs_dirty = TRUE; /* Now flush the new directory entry to disk and read the sector * containing the old directory entry. */ ret = fat_fscacheread(fs, oldsector); if (ret < 0) { goto errout_with_semaphore; } /* Remove the old entry */ olddirentry[DIR_NAME] = DIR0_EMPTY; fs->fs_dirty = TRUE; /* Write the old entry to disk and update FSINFO if necessary */ ret = fat_updatefsinfo(fs); if (ret < 0) { goto errout_with_semaphore; } fat_semgive(fs); return OK;errout_with_semaphore: fat_semgive(fs); return ret;}/**************************************************************************** * Name: fat_stat * * Description: Return information about a file or directory * ****************************************************************************/static int fat_stat(struct inode *mountpt, const char *relpath, struct stat *buf){ struct fat_mountpt_s *fs; struct fat_dirinfo_s dirinfo; uint16 date; uint16 date2; uint16 time; ubyte attribute; int ret; /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); /* Get the mountpoint private data from the inode structure */ fs = mountpt->i_private; /* Check if the mount is still healthy */ fat_semtake(fs); ret = fat_checkmount(fs); if (ret != OK) { goto errout_with_semaphore; } /* Find the directory entry corresponding to relpath. */ ret = fat_finddirentry(fs, &dirinfo, relpath); /* If nothing was found, then we fail with EEXIST */ if (ret < 0) { goto errout_with_semaphore; } memset(buf, 0, sizeof(struct stat)); if (!dirinfo.fd_entry) { /* It's directory name of mount point */ buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR|S_IWOTH|S_IWGRP|S_IWUSR; ret = OK; goto errout_with_semaphore; } /* Get the FAT attribute and map it so some meaningful mode_t values */ attribute = DIR_GETATTRIBUTES(dirinfo.fd_entry); if ((attribute & FATATTR_VOLUMEID) != 0) { ret = -ENOENT; goto errout_with_semaphore; } /* Set the access permissions. The file/directory is always readable * by everyone but may be writeable by no-one. */ buf->st_mode = S_IROTH|S_IRGRP|S_IRUSR; if ((attribute & FATATTR_READONLY) == 0) { buf->st_mode |= S_IWOTH|S_IWGRP|S_IWUSR; } /* We will report only types file or directory */ if ((attribute & FATATTR_DIRECTORY) != 0) { buf->st_mode |= S_IFDIR; } else { buf->st_mode |= S_IFREG; } /* File/directory size, access block size */ buf->st_size = DIR_GETFILESIZE(dirinfo.fd_entry); buf->st_blksize = fs->fs_fatsecperclus * fs->fs_hwsectorsize; buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize; /* Times */ date = DIR_GETWRTDATE(dirinfo.fd_entry); time = DIR_GETWRTTIME(dirinfo.fd_entry); buf->st_mtime = fat_fattime2systime(time, date); date2 = DIR_GETLASTACCDATE(dirinfo.fd_entry); if (date == date2) { buf->st_atime = buf->st_mtime; } else { buf->st_atime = fat_fattime2systime(0, date2); } date = DIR_GETCRDATE(dirinfo.fd_entry); time = DIR_GETCRTIME(dirinfo.fd_entry); buf->st_ctime = fat_fattime2systime(time, date); ret = OK;errout_with_semaphore: fat_semgive(fs); return ret;}/**************************************************************************** * Public Functions ****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -