/** * Remove the target file or link */ void ext2_rm(struct ext2_disk *disk, const char *target_file_name) { // Read info about the containing directory char *last_segment; uint32_t container_inode; struct ext2_inode *containing_directory = ext2_traverse_path(disk, NULL, target_file_name, &last_segment, &container_inode); struct ext2_directory_entry *entry; if ((entry = ext2_read_entry_from_directory(disk, containing_directory, last_segment)) == NULL) { // File does not exist errx(1, "File with name %s does not exist", last_segment); } else if (IS_DIRECTORY(ext2_get_inode(disk, 0, entry->inode_addr))) { // Target is a directory errx(1, "Cannot remove directory %s", last_segment); } else { // Save the inode number uint32_t inode_addr = entry->inode_addr; // Remove the directory entry by clearing its fields entry->inode_addr = 0; entry->size = 0; entry->name_length = 0; entry->type_indicator = 0; entry->name = 0; // Decrement the hard link count if (--ext2_get_inode(disk, 0, inode_addr)->num_links == 0) // No more hard links point to the inode; free the inode and data blocks ext2_free_inode(disk, inode_addr); } }
static int romfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, FAR struct fs_dirent_s *dir) { FAR struct romfs_mountpt_s *rm; FAR struct romfs_dirinfo_s dirinfo; int ret; fvdbg("relpath: '%s'\n", relpath); /* Sanity checks */ DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); /* Recover our private data from the inode instance */ rm = mountpt->i_private; /* Make sure that the mount is still healthy */ romfs_semtake(rm); ret = romfs_checkmount(rm); if (ret != OK) { fdbg("romfs_checkmount failed: %d\n", ret); goto errout_with_semaphore; } /* Find the requested directory */ ret = romfs_finddirentry(rm, &dirinfo, relpath); if (ret < 0) { fdbg("Failed to find directory '%s': %d\n", relpath, ret); goto errout_with_semaphore; } /* Verify that it is some kind of directory */ if (!IS_DIRECTORY(dirinfo.rd_next)) { /* The entry is not a directory */ fdbg("'%s' is not a directory: %d\n", relpath); ret = -ENOTDIR; goto errout_with_semaphore; } /* The entry is a directory */ memcpy(&dir->u.romfs, &dirinfo.rd_dir, sizeof(struct fs_romfsdir_s)); romfs_semgive(rm); return OK; errout_with_semaphore: romfs_semgive(rm); return ret; }
/** * Read the directory containing the item with the given path (i.e. traverse each path segment until the last), * starting at the given current working directory. * Exit with an error if a directory along the path could not be found. */ struct ext2_inode *ext2_traverse_path(struct ext2_disk *disk, struct ext2_inode *cwd, const char *file_path, char **last_segment, uint32_t *container_inode) { if (file_path[0] == '/') { // Start from the root path struct ext2_inode *root_directory = ext2_get_inode(disk, 0, 2); *container_inode = 2; if (file_path[1] == '\0') { // Path is just "/"; return the root directory *last_segment = ""; return root_directory; } // Otherwise, recurse using root_directory as cwd return ext2_traverse_path(disk, root_directory, file_path + 1, last_segment, container_inode); } else { // file_path is relative to cwd; search for first path segment in cwd // Copy file_path into str char *str = malloc(strlen(file_path) + 1); strcpy(str, file_path); // Get the first path segment from str char *segment = strsep(&str, "/"); if (str == NULL) { // `segment` is the last path segment; return this cwd *last_segment = segment; return cwd; } // Find the directory inode in this directory struct ext2_directory_entry *entry_found = ext2_read_entry_from_directory(disk, cwd, segment); *container_inode = entry_found->inode_addr; struct ext2_inode *inode_found = ext2_get_inode(disk, 0, entry_found->inode_addr); if (inode_found == NULL) { // Could not find inode in directory errx(1, "Could not find file or directory %s", segment); } else if (IS_DIRECTORY(inode_found)) { // Found a directory, and is not last path segment // Recurse with file_found as cwd return ext2_traverse_path(disk, inode_found, str, last_segment, container_inode); } else { errx(1, "File %s is not a directory", segment); } } }
int translate_stat(iso9660_stat_t * src,struct stat * dest) { struct fuse_context * ctx = fuse_get_context(); if_status * status = (if_status *) ctx->private_data; // dest->st_dev ignored // dest->st_ino ignored. Can be useful dest->st_mode = IS_DIRECTORY(src) ? status->default_dir_mode : status->default_file_mode; dest->st_nlink = 1; // ??? dest->st_uid = status->owner_uid; dest->st_gid = status->owner_gid; dest->st_size = src->size; // TODO Check endianity time_t ct = mktime(&src->tm); // we don't keep track of last access... dest->st_atim.tv_sec = dest->st_mtim.tv_sec = dest->st_ctim.tv_sec = ct; return 0; }
static int romfs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir) { FAR struct romfs_mountpt_s *rm; uint32_t linkoffset; uint32_t next; uint32_t info; uint32_t size; int ret; fvdbg("Entry\n"); /* Sanity checks */ DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); /* Recover our private data from the inode instance */ rm = mountpt->i_private; /* Make sure that the mount is still healthy */ romfs_semtake(rm); ret = romfs_checkmount(rm); if (ret != OK) { fdbg("romfs_checkmount failed: %d\n", ret); goto errout_with_semaphore; } /* Loop, skipping over unsupported items in the file system */ for (;;) { /* Have we reached the end of the directory */ if (!dir->u.romfs.fr_curroffset) { /* We signal the end of the directory by returning the * special error -ENOENT */ fdbg("End of directory\n"); ret = -ENOENT; goto errout_with_semaphore; } /* Parse the directory entry */ ret = romfs_parsedirentry(rm, dir->u.romfs.fr_curroffset, &linkoffset, &next, &info, &size); if (ret < 0) { fdbg("romfs_parsedirentry failed: %d\n", ret); goto errout_with_semaphore; } /* Save the filename */ ret = romfs_parsefilename(rm, dir->u.romfs.fr_curroffset, dir->fd_dir.d_name); if (ret < 0) { fdbg("romfs_parsefilename failed: %d\n", ret); goto errout_with_semaphore; } /* Set up the next directory entry offset */ dir->u.romfs.fr_curroffset = next & RFNEXT_OFFSETMASK; /* Check the file type */ if (IS_DIRECTORY(next)) { dir->fd_dir.d_type = DTYPE_DIRECTORY; break; } else if (IS_FILE(next)) { dir->fd_dir.d_type = DTYPE_FILE; break; } } errout_with_semaphore: romfs_semgive(rm); return ret; }
static int romfs_open(FAR struct file *filep, FAR const char *relpath, int oflags, mode_t mode) { struct romfs_dirinfo_s dirinfo; FAR struct romfs_mountpt_s *rm; FAR struct romfs_file_s *rf; int ret; fvdbg("Open '%s'\n", relpath); /* Sanity checks */ DEBUGASSERT(filep->f_priv == NULL && filep->f_inode != NULL); /* Get mountpoint private data from the inode reference from the file * structure */ rm = (FAR struct romfs_mountpt_s*)filep->f_inode->i_private; DEBUGASSERT(rm != NULL); /* Check if the mount is still healthy */ romfs_semtake(rm); ret = romfs_checkmount(rm); if (ret != OK) { fdbg("romfs_checkmount failed: %d\n", ret); goto errout_with_semaphore; } /* ROMFS is read-only. Any attempt to open with any kind of write * access is not permitted. */ if ((oflags & O_WRONLY) != 0 || (oflags & O_RDONLY) == 0) { fdbg("Only O_RDONLY supported\n"); ret = -EACCES; goto errout_with_semaphore; } /* Initialize the directory info structure */ memset(&dirinfo, 0, sizeof(struct romfs_dirinfo_s)); /* Locate the directory entry for this path */ ret = romfs_finddirentry(rm, &dirinfo, relpath); if (ret < 0) { fdbg("Failed to find directory directory entry for '%s': %d\n", relpath, ret); goto errout_with_semaphore; } /* The full path exists -- but is the final component a file * or a directory? */ if (IS_DIRECTORY(dirinfo.rd_next)) { /* It is a directory */ ret = -EISDIR; fdbg("'%s' is a directory\n", relpath); goto errout_with_semaphore; } #ifdef CONFIG_FILE_MODE # warning "Missing check for privileges based on inode->i_mode" #endif /* Create an instance of the file private data to describe the opened * file. */ rf = (FAR struct romfs_file_s *)kmm_zalloc(sizeof(struct romfs_file_s)); if (!rf) { fdbg("Failed to allocate private data\n", ret); ret = -ENOMEM; goto errout_with_semaphore; } /* Initialize the file private data (only need to initialize * non-zero elements) */ rf->rf_size = dirinfo.rd_size; /* Get the start of the file data */ ret = romfs_datastart(rm, dirinfo.rd_dir.fr_curroffset, &rf->rf_startoffset); if (ret < 0) { fdbg("Failed to locate start of file data: %d\n", ret); goto errout_with_semaphore; } /* Configure buffering to support access to this file */ ret = romfs_fileconfigure(rm, rf); if (ret < 0) { fdbg("Failed configure buffering: %d\n", ret); goto errout_with_semaphore; } /* Attach the private date to the struct file instance */ filep->f_priv = rf; /* Then insert the new instance into the mountpoint structure. * It needs to be there (1) to handle error conditions that effect * all files, and (2) to inform the umount logic that we are busy * (but a simple reference count could have done that). */ rf->rf_next = rm->rm_head; rm->rm_head = rf->rf_next; romfs_semgive(rm); return OK; /* Error exits */ errout_with_semaphore: romfs_semgive(rm); return ret; }
static int romfs_stat(FAR struct inode *mountpt, FAR const char *relpath, FAR struct stat *buf) { FAR struct romfs_mountpt_s *rm; FAR struct romfs_dirinfo_s dirinfo; int ret; fvdbg("Entry\n"); /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); /* Get the mountpoint private data from the inode structure */ rm = mountpt->i_private; /* Check if the mount is still healthy */ romfs_semtake(rm); ret = romfs_checkmount(rm); if (ret != OK) { fdbg("romfs_checkmount failed: %d\n", ret); goto errout_with_semaphore; } /* Find the directory entry corresponding to relpath. */ ret = romfs_finddirentry(rm, &dirinfo, relpath); /* If nothing was found, then we fail with EEXIST */ if (ret < 0) { fvdbg("Failed to find directory: %d\n", ret); goto errout_with_semaphore; } memset(buf, 0, sizeof(struct stat)); if (IS_DIRECTORY(dirinfo.rd_next)) { /* It's a read-only directory name */ buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR; if (IS_EXECUTABLE(dirinfo.rd_next)) { buf->st_mode |= S_IXOTH|S_IXGRP|S_IXUSR; } } else if (IS_FILE(dirinfo.rd_next)) { /* It's a read-only file name */ buf->st_mode = S_IFREG|S_IROTH|S_IRGRP|S_IRUSR; if (IS_EXECUTABLE(dirinfo.rd_next)) { buf->st_mode |= S_IXOTH|S_IXGRP|S_IXUSR; } } else { /* Otherwise, pretend like the unsupported node does not exist */ fvdbg("Unsupported inode: %d\n", dirinfo.rd_next); ret = -ENOENT; goto errout_with_semaphore; } /* File/directory size, access block size */ buf->st_size = dirinfo.rd_size; buf->st_blksize = rm->rm_hwsectorsize; buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize; ret = OK; errout_with_semaphore: romfs_semgive(rm); return ret; }