Example #1
0
STATIC off_t
fat_seek(fs_handle handle, off_t off, int whence)
{
   off_t curr_pos = (off_t) ((fat_file_handle *)handle)->pos;

   switch (whence) {

   case SEEK_SET:

      if (off < 0)
         return -EINVAL; /* invalid negative offset */

      fat_rewind(handle);
      break;

   case SEEK_END:

      if (off >= 0)
         break;

      fat_file_handle *h = (fat_file_handle *) handle;
      off = (off_t) h->e->DIR_FileSize + off;

      if (off < 0)
         return -EINVAL;

      fat_rewind(handle);
      break;

   case SEEK_CUR:

      if (off < 0) {

         off = curr_pos + off;

         if (off < 0)
            return -EINVAL;

         fat_rewind(handle);
      }

      break;

   default:
      return -EINVAL;
   }

   return fat_seek_forward(handle, off);
}
Example #2
0
/* open a directory */
DIR * opendir(const char *dirname)
{
    DEBUGF("opendir(dirname=\"%s\"\n", dirname);

    DIR *dirp = NULL;

    file_internal_lock_WRITER();

    int rc;

    struct dirstr_desc * const dir = alloc_dirstr();
    if (!dir)
        FILE_ERROR(EMFILE, RC);

    rc = open_stream_internal(dirname, FF_DIR, &dir->stream, NULL);
    if (rc < 0)
    {
        DEBUGF("Open failed: %d\n", rc);
        FILE_ERROR(ERRNO, RC);
    }

#ifdef HAVE_MULTIVOLUME
    /* volume counter is relevant only to the system root */
    dir->volumecounter = rc > 1 ? 0 : INT_MAX;
#endif /* HAVE_MULTIVOLUME */

    fat_rewind(&dir->stream.fatstr);
    rewinddir_dirent(&dir->scan);

    dirp = (DIR *)dir;
file_error:
    file_internal_unlock_WRITER();
    return dirp;
}
Example #3
0
/* actually do the open gruntwork */
static int open_internal_inner2(const char *path,
                                struct filestr_desc *file,
                                unsigned int callflags)
{
    int rc;

    struct path_component_info compinfo;
    rc = open_stream_internal(path, callflags, &file->stream, &compinfo);
    if (rc < 0)
    {
        DEBUGF("Open failed: %d\n", rc);
        FILE_ERROR_RETURN(ERRNO, rc * 10 - 1);
    }

    bool created = false;

    if (rc > 0)
    {
        if (callflags & FF_EXCL)
        {
            DEBUGF("File exists\n");
            FILE_ERROR(EEXIST, -2);
        }

        if (compinfo.attr & ATTR_DIRECTORY)
        {
            if ((callflags & FD_WRITE) || !(callflags & FF_ANYTYPE))
            {
                DEBUGF("File is a directory\n");
                FILE_ERROR(EISDIR, -3);
            }

            compinfo.filesize = MAX_DIRECTORY_SIZE; /* allow file ops */
        }
    }
    else if (callflags & FF_CREAT)
    {
        if (compinfo.attr & ATTR_DIRECTORY)
        {
            DEBUGF("File is a directory\n");
            FILE_ERROR(EISDIR, -5);
        }

        /* not found; try to create it */

        callflags &= ~FO_TRUNC;
        rc = create_stream_internal(&compinfo.parentinfo, compinfo.name, 
                                    compinfo.length, ATTR_NEW_FILE, callflags,
                                    &file->stream);
        if (rc < 0)
            FILE_ERROR(ERRNO, rc * 10 - 6);

        created = true;
    }
    else
    {
        DEBUGF("File not found\n");
        FILE_ERROR(ENOENT, -7);
    }

    fat_rewind(&file->stream.fatstr);
    file->sizep = fileobj_get_sizep(&file->stream);
    file->offset = 0;

    if (!created)
    {
        /* size from storage applies to first stream only otherwise it's
           already up to date */
        const bool first = fileobj_get_flags(&file->stream) & FO_SINGLE;
        if (first)
            *file->sizep = compinfo.filesize;

        if (callflags & FO_TRUNC)
        {
            /* if the file is kind of "big" then free some space now */
            rc = ftruncate_internal(file, 0, *file->sizep >= O_TRUNC_THRESH);
            if (rc < 0)
            {
                DEBUGF("O_TRUNC failed: %d\n", rc);
                FILE_ERROR(ERRNO, rc * 10 - 4);
            }
        }
    }

    rc = 0;
file_error:
    if (rc < 0)
        close_stream_internal(&file->stream);

    return rc;
}