Exemple #1
0
static int cfs_create(const char *path, mode_t mode, struct fuse_file_info *info)
{
    FILE *temp_file;

    if (*temp_dir)
    {
        char tmp_path[PATH_MAX];
        strncpy(tmp_path, path, PATH_MAX);

        char *pch;
        while((pch = strchr(tmp_path, '/'))) {
            *pch = '.';
        }

        char file_path[PATH_MAX];
        snprintf(file_path, PATH_MAX, "%s/.cloudfuse%ld-%s", temp_dir,
                 (long)getpid(), tmp_path);
        temp_file = fopen(file_path, "w+b");
    }
    else
        temp_file = tmpfile();

    openfile *of = (openfile *)malloc(sizeof(openfile));
    of->fd = dup(fileno(temp_file));
    fclose(temp_file);
    of->flags = info->flags;
    info->fh = (uintptr_t)of;
    update_dir_cache(path, 0, 0, 0);
    info->direct_io = 1;
    return 0;
}
static int cfs_truncate(const char* path, off_t size)
{
  debugf(DBG_LEVEL_NORM, "cfs_truncate(%s) size=%lu", path, size);
  cloudfs_object_truncate(path, size);
  update_dir_cache(path, size, 0, 0);
  debugf(DBG_LEVEL_NORM, "exit: cfs_truncate(%s)", path);
  return 0;
}
Exemple #3
0
static int cfs_mkdir(const char *path, mode_t mode)
{
    if (cloudfs_create_directory(path))
    {
        update_dir_cache(path, 0, 1, 0);
        return 0;
    }
    return -ENOENT;
}
Exemple #4
0
static int cfs_ftruncate(const char *path, off_t size, struct fuse_file_info *info)
{
    openfile *of = (openfile *)(uintptr_t)info->fh;
    if (ftruncate(of->fd, size))
        return -errno;
    lseek(of->fd, 0, SEEK_SET);
    update_dir_cache(path, size, 0, 0);
    return 0;
}
Exemple #5
0
static int cfs_symlink(const char *src, const char *dst)
{
    if(cloudfs_create_symlink(src, dst))
    {
        update_dir_cache(dst, 1, 0, 1);
        return 0;
    }
    return -EIO;
}
Exemple #6
0
static int cfs_create(const char *path, mode_t mode, struct fuse_file_info *info)
{
  FILE *temp_file = tmpfile();
  openfile *of = (openfile *)malloc(sizeof(openfile));
  of->fd = dup(fileno(temp_file));
  fclose(temp_file);
  of->flags = info->flags;
  info->fh = (uintptr_t)of;
  update_dir_cache(path, 0, 0);
  info->direct_io = 1;
  return 0;
}
static int cfs_symlink(const char* src, const char* dst)
{
  debugf(DBG_LEVEL_NORM, KBLU"cfs_symlink(%s, %s)", src, dst);
  if (cloudfs_create_symlink(src, dst))
  {
    update_dir_cache(dst, 1, 0, 1);
    debugf(DBG_LEVEL_NORM, KBLU"exit0: cfs_symlink(%s, %s)", src, dst);
    return 0;
  }
  debugf(DBG_LEVEL_NORM, KRED"exit1: cfs_symlink(%s, %s) io error", src, dst);
  return -EIO;
}
static int cfs_ftruncate(const char* path, off_t size,
                         struct fuse_file_info* info)
{
  debugf(DBG_LEVEL_NORM, KBLU "cfs_ftruncate(%s) size=%lu", path, size);
  file_buffer_size = size;
  openfile* of = (openfile*)(uintptr_t)info->fh;
  if (ftruncate(of->fd, size))
    return -errno;
  lseek(of->fd, 0, SEEK_SET);
  update_dir_cache(path, size, 0, 0);
  debugf(DBG_LEVEL_NORM, KBLU "exit: cfs_ftruncate(%s)", path);
  return 0;
}
static int cfs_mkdir(const char* path, mode_t mode)
{
  debugf(DBG_LEVEL_NORM, KBLU "cfs_mkdir(%s)", path);
  int response = cloudfs_create_directory(path);
  if (response)
  {
    update_dir_cache(path, 0, 1, 0);
    debug_list_cache_content();
    debugf(DBG_LEVEL_NORM, KBLU "exit 0: cfs_mkdir(%s)", path);
    return 0;
  }
  debugf(DBG_LEVEL_NORM, KRED "exit 1: cfs_mkdir(%s) response=%d", path,
         response);
  return -ENOENT;
}
Exemple #10
0
static int cfs_rename(const char *src, const char *dst)
{
    dir_entry *src_de = path_info(src);
    if (!src_de)
        return -ENOENT;
    if (src_de->isdir)
        return -EISDIR;
    if (cloudfs_copy_object(src, dst))
    {
        /* FIXME this isn't quite right as doesn't preserve last modified */
        update_dir_cache(dst, src_de->size, 0, 0);
        return cfs_unlink(src);
    }
    return -EIO;
}
Exemple #11
0
static int cfs_write(const char* path, const char* buf, size_t length,
                     off_t offset, struct fuse_file_info* info)
{
  debugf(DBG_LEVEL_EXTALL, KBLU "cfs_write(%s) bufflength=%lu offset=%lu", path,
         length, offset);
  // FIXME: Potential inconsistent cache update if pwrite fails?
  update_dir_cache(path, offset + length, 0, 0);
  //int result = pwrite(info->fh, buf, length, offset);
  int result = pwrite(((openfile*)(uintptr_t)info->fh)->fd, buf, length, offset);
  int errsv = errno;
  if (errsv == 0)
    debugf(DBG_LEVEL_EXTALL, KBLU "exit 0: cfs_write(%s) result=%d:%s", path,
           errsv, strerror(errsv));
  else
    debugf(DBG_LEVEL_EXTALL, KBLU "exit 1: cfs_write(%s) "KRED"result=%d:%s", path,
           errsv, strerror(errsv));
  return result;
}
Exemple #12
0
static int cfs_flush(const char *path, struct fuse_file_info *info)
{
    openfile *of = (openfile *)(uintptr_t)info->fh;
    if (of)
    {
        update_dir_cache(path, cloudfs_file_size(of->fd), 0, 0);
        if (of->flags & O_RDWR || of->flags & O_WRONLY)
        {
            FILE *fp = fdopen(dup(of->fd), "r");
            rewind(fp);
            if (!cloudfs_object_read_fp(path, fp))
            {
                fclose(fp);
                return -ENOENT;
            }
            fclose(fp);
        }
    }
    return 0;
}
Exemple #13
0
static int cfs_open(const char *path, struct fuse_file_info *info)
{
  FILE *temp_file = tmpfile();
  if (!(info->flags & O_WRONLY))
  {
    if (!object_write_fp(path, temp_file))
    {
      fclose(temp_file);
      return -ENOENT;
    }
    update_dir_cache(path, 0, 0);
  }
  openfile *of = (openfile *)malloc(sizeof(openfile));
  of->fd = dup(fileno(temp_file));
  fclose(temp_file);
  of->flags = info->flags;
  info->fh = (uintptr_t)of;
  info->direct_io = 1;
  return 0;
}
Exemple #14
0
static int cfs_rename(const char* src, const char* dst)
{
  debugf(DBG_LEVEL_NORM, KBLU"cfs_rename(%s, %s)", src, dst);
  dir_entry* src_de = path_info(src);
  if (!src_de)
  {
    debugf(DBG_LEVEL_NORM, KRED"exit 0: cfs_rename(%s,%s) not-found", src, dst);
    return -ENOENT;
  }
  if (src_de->isdir)
  {
    debugf(DBG_LEVEL_NORM, KRED"exit 1: cfs_rename(%s,%s) cannot rename dirs!",
           src, dst);
    return -EISDIR;
  }
  if (cloudfs_copy_object(src, dst))
  {
    /* FIXME this isn't quite right as doesn't preserve last modified */
    //fix done in cloudfs_copy_object()
    update_dir_cache(dst, src_de->size, 0, 0);
    int result = cfs_unlink(src);

    dir_entry* dst_de = path_info(dst);
    if (!dst_de)
      debugf(DBG_LEVEL_NORM, KRED"cfs_rename(%s,%s) dest-not-found-in-cache", src,
             dst);
    else
    {
      debugf(DBG_LEVEL_NORM, KBLU"cfs_rename(%s,%s) upload ok", src, dst);
      //copy attributes, shortcut, rather than forcing a download from cloud
      copy_dir_entry(src_de, dst_de);
    }

    debugf(DBG_LEVEL_NORM, KBLU"exit 3: cfs_rename(%s,%s)", src, dst);
    return result;
  }
  debugf(DBG_LEVEL_NORM, KRED"exit 4: cfs_rename(%s,%s) io error", src, dst);
  return -EIO;
}
Exemple #15
0
static int cfs_write(const char *path, const char *buf, size_t length, off_t offset, struct fuse_file_info *info)
{
    update_dir_cache(path, offset + length, 0, 0);
    return pwrite(((openfile *)(uintptr_t)info->fh)->fd, buf, length, offset);
}
Exemple #16
0
// open (download) file from cloud
// todo: implement etag optimisation, download only if content changed, http://www.17od.com/2012/12/19/ten-useful-openstack-swift-features/
static int cfs_open(const char* path, struct fuse_file_info* info)
{
  debugf(DBG_LEVEL_NORM, KBLU "cfs_open(%s)", path);
  FILE* temp_file = NULL;
  int errsv;
  dir_entry* de = path_info(path);

  if (*temp_dir)
  {
    char file_path_safe[NAME_MAX];
    get_safe_cache_file_path(path, file_path_safe, temp_dir);

    debugf(DBG_LEVEL_EXT, "cfs_open: try open (%s)", file_path_safe);
    if (access(file_path_safe, F_OK) != -1)
    {
      // file exists
      temp_file = fopen(file_path_safe, "r");
      errsv = errno;
      if (temp_file == NULL)
      {
        debugf(DBG_LEVEL_NORM,
               KRED"exit 0: cfs_open can't open temp_file=[%s] err=%d:%s", file_path_safe,
               errsv, strerror(errsv));
        return -ENOENT;
      }
      else
        debugf(DBG_LEVEL_EXT, "cfs_open: file exists");
    }
    else
    {
      errsv = errno;
      debugf(DBG_LEVEL_EXT, "cfs_open: file not in cache, err=%s", strerror(errsv));
      //FIXME: commented out as this condition will not be meet in some odd cases and program will crash
      //if (!(info->flags & O_WRONLY)) {
      debugf(DBG_LEVEL_EXT, "cfs_open: opening for write");

      // we need to lock on the filename another process could open the file
      // while we are writing to it and then only read part of the file

      // duplicate the directory caching datastructure to make the code easier
      // to understand.

      // each file in the cache needs:
      //  filename, is_writing, last_closed, is_removing
      // the first time a file is opened a new entry is created in the cache
      // setting the filename and is_writing to true.  This check needs to be
      // wrapped with a lock.
      //
      // each time a file is closed we set the last_closed for the file to now
      // and we check the cache for files whose last
      // closed is greater than cache_timeout, then start a new thread rming
      // that file.

      // TODO: just to prevent this craziness for now
      temp_file = fopen(file_path_safe, "w+b");
      errsv = errno;
      if (temp_file == NULL)
      {
        debugf(DBG_LEVEL_NORM,
               KRED"exit 1: cfs_open cannot open temp_file=[%s] err=%d:%s", file_path_safe,
               errsv, strerror(errsv));
        return -ENOENT;
      }

      if (!cloudfs_object_write_fp(path, temp_file))
      {
        fclose(temp_file);
        debugf(DBG_LEVEL_NORM, KRED "exit 2: cfs_open(%s) cannot download/write",
               path);
        return -ENOENT;
      }
    }
  }
  else
  {
    temp_file = tmpfile();
    if (temp_file == NULL)
    {
      debugf(DBG_LEVEL_NORM, KRED"exit 3: cfs_open cannot create temp_file err=%s",
             strerror(errno));
      return -ENOENT;
    }

    if (!(info->flags & O_TRUNC))
    {
      if (!cloudfs_object_write_fp(path, temp_file) && !(info->flags & O_CREAT))
      {
        fclose(temp_file);
        debugf(DBG_LEVEL_NORM, KRED"exit 4: cfs_open(%s) cannot download/write", path);
        return -ENOENT;
      }
    }
  }

  update_dir_cache(path, (de ? de->size : 0), 0, 0);
  openfile* of = (openfile*)malloc(sizeof(openfile));
  of->fd = dup(fileno(temp_file));
  if (of->fd == -1)
  {
    //FIXME: potential leak if free not used?
    free(of);
    debugf(DBG_LEVEL_NORM, KRED "exit 5: cfs_open(%s) of->fd", path);
    return -ENOENT;
  }
  fclose(temp_file);
  //TODO: why this allocation to of?
  of->flags = info->flags;
  info->fh = (uintptr_t)of;
  info->direct_io = 1;
  info->nonseekable = 0;
  //FIXME: potential leak if free(of) not used? although if free(of) is used will generate bad descriptor errors
  debugf(DBG_LEVEL_NORM, KBLU "exit 6: cfs_open(%s)", path);
  return 0;
}
Exemple #17
0
static int cfs_open(const char *path, struct fuse_file_info *info)
{
    FILE *temp_file;
    dir_entry *de = path_info(path);

    if (*temp_dir)
    {
        char tmp_path[PATH_MAX];
        strncpy(tmp_path, path, PATH_MAX);

        char *pch;
        while((pch = strchr(tmp_path, '/'))) {
            *pch = '.';
        }

        char file_path[PATH_MAX];
        snprintf(file_path, PATH_MAX, "%s/.cloudfuse%ld-%s", temp_dir,
                 (long)getpid(), tmp_path);

        if(access(file_path, F_OK) != -1)
        {
            // file exists
            temp_file = fopen(file_path, "r");
        }
        else if (!(info->flags & O_WRONLY))
        {
            // we need to lock on the filename another process could open the file
            // while we are writing to it and then only read part of the file

            // duplicate the directory caching datastructure to make the code easier
            // to understand.

            // each file in the cache needs:
            //  filename, is_writing, last_closed, is_removing
            // the first time a file is opened a new entry is created in the cache
            // setting the filename and is_writing to true.  This check needs to be
            // wrapped with a lock.
            //
            // each time a file is closed we set the last_closed for the file to now
            // and we check the cache for files whose last
            // closed is greater than cache_timeout, then start a new thread rming
            // that file.

            // TODO: just to prevent this craziness for now
            temp_file = fopen(file_path, "w+b");

            if (!cloudfs_object_write_fp(path, temp_file))
            {
                fclose(temp_file);
                return -ENOENT;
            }
        }
    }
    else
    {
        temp_file = tmpfile();
        if (!(info->flags & O_WRONLY))
        {
            if (!cloudfs_object_write_fp(path, temp_file))
            {
                fclose(temp_file);
                return -ENOENT;
            }
        }
    }

    update_dir_cache(path, (de ? de->size : 0), 0, 0);

    openfile *of = (openfile *)malloc(sizeof(openfile));
    of->fd = dup(fileno(temp_file));
    if (of->fd == -1)
        return -ENOENT;
    fclose(temp_file);
    of->flags = info->flags;
    info->fh = (uintptr_t)of;
    info->direct_io = 1;
    return 0;
}
Exemple #18
0
//todo: flush will upload a file again even if just file attributes are changed.
//optimisation needed to detect if content is changed and to only save meta when just attribs are modified.
static int cfs_flush(const char* path, struct fuse_file_info* info)
{
  debugf(DBG_LEVEL_NORM, KBLU "cfs_flush(%s)", path);
  debug_print_descriptor(info);
  openfile* of = (openfile*)(uintptr_t)info->fh;
  int errsv = 0;

  if (of)
  {
    // get the actual file size and truncate it. This ensures that if the new file is smaller
    // than the previous one, the proper size is uploaded.
    struct stat stbuf;
    cfs_getattr(path, &stbuf);
    update_dir_cache(path, stbuf.st_size, 0, 0);
    ftruncate(of->fd, stbuf.st_size);

    if (of->flags & O_RDWR || of->flags & O_WRONLY)
    {
      FILE* fp = fdopen(dup(of->fd), "r");
      errsv = errno;
      if (fp != NULL)
      {
        rewind(fp);
        //calculate md5 hash, compare with cloud hash to determine if file content is changed
        char md5_file_hash_str[MD5_DIGEST_HEXA_STRING_LEN] = "\0";
        file_md5(fp, md5_file_hash_str);
        dir_entry* de = check_path_info(path);
        if (de && de->md5sum != NULL && (!strcasecmp(md5_file_hash_str, de->md5sum)))
        {
          //file content is identical, no need to upload entire file, just update metadata
          debugf(DBG_LEVEL_NORM, KBLU
                 "cfs_flush(%s): skip full upload as content did not change", path);
          cloudfs_update_meta(de);
        }
        else
        {
          rewind(fp);
          debugf(DBG_LEVEL_NORM, KBLU
                 "cfs_flush(%s): perform full upload as content changed (or no file found in cache)",
                 path);
          if (!cloudfs_object_read_fp(path, fp))
          {
            fclose(fp);
            errsv = errno;
            debugf(DBG_LEVEL_NORM, KRED"exit 0: cfs_flush(%s) result=%d:%s", path, errsv,
                   strerror(errno));
            return -ENOENT;
          }
        }
        fclose(fp);
        errsv = errno;
      }
      else
        debugf(DBG_LEVEL_EXT, KRED "status: cfs_flush, err=%d:%s", errsv,
               strerror(errno));
    }
  }
  debugf(DBG_LEVEL_NORM, KBLU "exit 1: cfs_flush(%s) result=%d:%s", path, errsv,
         strerror(errno));
  return 0;
}
Exemple #19
0
static int cfs_create(const char* path, mode_t mode,
                      struct fuse_file_info* info)
{
  debugf(DBG_LEVEL_NORM, KBLU "cfs_create(%s)", path);
  FILE* temp_file;
  int errsv;
  char file_path_safe[NAME_MAX] = "";

  if (*temp_dir)
  {
    get_safe_cache_file_path(path, file_path_safe, temp_dir);
    temp_file = fopen(file_path_safe, "w+b");
    errsv = errno;
    if (temp_file == NULL)
    {
      debugf(DBG_LEVEL_NORM, KRED
             "exit 0: cfs_create cannot open temp file %s.error %s\n", file_path_safe,
             strerror(errsv));
      return -EIO;
    }
  }
  else
  {
    temp_file = tmpfile();
    errsv = errno;
    if (temp_file == NULL)
    {
      debugf(DBG_LEVEL_NORM, KRED
             "exit 1: cfs_create cannot open tmp file for path %s.error %s\n", path,
             strerror(errsv));
      return -EIO;
    }
  }
  openfile* of = (openfile*)malloc(sizeof(openfile));
  of->fd = dup(fileno(temp_file));
  fclose(temp_file);
  of->flags = info->flags;
  info->fh = (uintptr_t)of;
  update_dir_cache(path, 0, 0, 0);
  info->direct_io = 1;
  dir_entry* de = check_path_info(path);
  if (de)
  {
    debugf(DBG_LEVEL_EXT, KCYN"cfs_create(%s): found in cache", path);
    struct timespec now;
    clock_gettime(CLOCK_REALTIME, &now);
    debugf(DBG_LEVEL_EXT, KCYN"cfs_create(%s) set utimes as now", path);
    de->atime.tv_sec = now.tv_sec;
    de->atime.tv_nsec = now.tv_nsec;
    de->mtime.tv_sec = now.tv_sec;
    de->mtime.tv_nsec = now.tv_nsec;
    de->ctime.tv_sec = now.tv_sec;
    de->ctime.tv_nsec = now.tv_nsec;

    char time_str[TIME_CHARS] = "";
    get_timespec_as_str(&(de->atime), time_str, sizeof(time_str));
    debugf(DBG_LEVEL_EXT, KCYN"cfs_create: atime=[%s]", time_str);
    get_timespec_as_str(&(de->mtime), time_str, sizeof(time_str));
    debugf(DBG_LEVEL_EXT, KCYN"cfs_create: mtime=[%s]", time_str);
    get_timespec_as_str(&(de->ctime), time_str, sizeof(time_str));
    debugf(DBG_LEVEL_EXT, KCYN"cfs_create: ctime=[%s]", time_str);

    //set chmod & chown
    de->chmod = mode;
    de->uid = geteuid();
    de->gid = getegid();
  }
  else
    debugf(DBG_LEVEL_EXT, KBLU "cfs_create(%s) "KYEL"dir-entry not found", path);
  debugf(DBG_LEVEL_NORM, KBLU "exit 2: cfs_create(%s)=(%s) result=%d:%s", path,
         file_path_safe, errsv, strerror(errsv));
  return 0;
}