Exemple #1
0
/**
 * 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);
    }
}
Exemple #2
0
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;
}
Exemple #3
0
/**
 * 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);
        }
    }
}
Exemple #4
0
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;
}
Exemple #5
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;
}
Exemple #6
0
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;
}
Exemple #7
0
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;
}