Example #1
0
// do a file open
// child must *not* be locked.
// parent must be write-locked, but it will be unlocked and re-locked.  The child will be referenced during that time, so the parent is guaranteed not to disappear
// on success, fill in the handle data
int fskit_do_open( struct fskit_core* core, char const* path, struct fskit_entry* parent, struct fskit_entry* child, int flags, uint64_t user, uint64_t group, void** handle_data ) {

   int rc = 0;

   // block other processes so we can do access checks
   fskit_entry_wlock( child );
   
   // sanity check
   if( child->link_count == 0 || child->deletion_in_progress || child->type == FSKIT_ENTRY_TYPE_DEAD ) {
      rc = -ENOENT;
   }

   // sanity check
   else if( child->type == FSKIT_ENTRY_TYPE_DIR ) {
      rc = -EISDIR;
   }

   // access control for normal open
   // check read/write status of flags, and bail on error
   else if( (!(flags & O_RDWR) && !(flags & O_WRONLY))  && !FSKIT_ENTRY_IS_READABLE(child->mode, child->owner, child->group, user, group) ) {
      rc = -EACCES;  // not readable
   }
   else if( (flags & O_WRONLY) && !FSKIT_ENTRY_IS_WRITEABLE(child->mode, child->owner, child->group, user, group) ) {
      rc = -EACCES;  // not writable
   }
   else if( (flags & O_RDWR) && (!FSKIT_ENTRY_IS_READABLE(child->mode, child->owner, child->group, user, group) || !FSKIT_ENTRY_IS_WRITEABLE(child->mode, child->owner, child->group, user, group)) ) {
      rc = -EACCES;  // not readable or not writable
   }
   
   if( rc == 0 ) {
      
      // reference the child
      fskit_entry_ref_entry( child );
   }
   
   fskit_entry_unlock( child );

   if( rc != 0 ) {
      // can't open
      return rc;
   }
   
   // safe to allow access to the child while the user route is running, since the child (and thus the parent) can't get unlinked
   fskit_entry_unlock( parent );
   
   // open will succeed according to fskit.  invoke the user callback to generate handle data
   rc = fskit_run_user_open( core, path, child, flags, handle_data );
   
   // reaquire...
   fskit_entry_wlock( parent );
   
   if( rc != 0 ) {
      fskit_error("fskit_run_user_open(%s) rc = %d\n", path, rc );

      fskit_entry_unref( core, path, child );
   }
   
   return rc;
}
Example #2
0
// update a file's manifest, in response to a remote call 
// return 0 on success
// return -ENOENT if not found
// return -ESTALE if not local
// return -errno on error 
// NOTE: the permissions will already have been checked by the server
static int UG_impl_manifest_patch( struct SG_gateway* gateway, struct SG_request_data* reqdat, struct SG_manifest* write_delta, void* cls ) {
   
   int rc = 0;
   int ref_rc = 0;
   struct fskit_entry* fent = NULL;
   struct UG_state* ug = (struct UG_state*)SG_gateway_cls( gateway );
   
   struct fskit_core* fs = UG_state_fs( ug );
   struct UG_inode* inode = NULL;
   
   struct ms_client* ms = SG_gateway_ms( gateway );
   uint64_t volume_id = ms_client_get_volume_id( ms );

   rc = UG_consistency_path_ensure_fresh( gateway, reqdat->fs_path );
   if( rc != 0 ) {
      SG_error("UG_consistency_path_ensure_fresh('%s') rc = %d\n", reqdat->fs_path, rc );
      return rc;
   }

   rc = UG_consistency_manifest_ensure_fresh( gateway, reqdat->fs_path );
   if( rc != 0 ) {
      SG_error("UG_consistency_manifest_ensure_fresh('%s') rc = %d\n", reqdat->fs_path, rc );
      return rc;
   }
   
   // look up 
   fent = fskit_entry_resolve_path( fs, reqdat->fs_path, reqdat->user_id, volume_id, true, &rc );
   if( fent == NULL ) {
      
      return rc;
   }
   
   inode = (struct UG_inode*)fskit_entry_get_user_data( fent );
   
   // must be coordinated by us 
   if( UG_inode_coordinator_id( inode ) != SG_gateway_id( gateway ) ) {
      
      fskit_entry_unlock( fent );
      return -ESTALE;
   }
   
   // update the manifest 
   fskit_entry_ref_entry( fent );
   rc = UG_write_patch_manifest( gateway, reqdat, inode, write_delta );
   
   fskit_entry_unlock( fent );

   ref_rc = fskit_entry_unref( fs, reqdat->fs_path, fent );
   if( ref_rc != 0 ) {
      SG_warn("fskit_entry_unref('%s') rc = %d\n", reqdat->fs_path, rc );
   }
   
   return rc;
}
Example #3
0
File: stat.c Project: jaromil/fskit
// stat a path.
// fill in the stat buffer on success.
// return the usual path resolution errors.
int fskit_stat( struct fskit_core* core, char const* fs_path, uint64_t user, uint64_t group, struct stat* sb ) {

   int rc = 0;

   // ref this entry, so it won't disappear on stat
   struct fskit_entry* fent = fskit_entry_ref( core, fs_path, &rc );
   if( fent == NULL ) {
      
      return rc;
   }
   
   // stat it
   rc = fskit_fstat( core, fs_path, fent, sb );

   fskit_entry_unref( core, fs_path, fent );
   
   return rc;
}
Example #4
0
// open a directory.
// On success, return an fskit_dir_handle
// Return any error code via the *err argument (which will be non-zero if there was an error).
// on error, return NULL, and set *err appropriately:
// * -ENAMETOOLONG if _path is too long
// * -EACCES if some part of _path is in accessible to the given user and group
// * -ENOTDIR if the entry referred to by _path isn't a directory
// * -ENOENT if the entry doesn't exist
// * -ENOMEM on OOM
struct fskit_dir_handle* fskit_opendir( struct fskit_core* core, char const* _path, uint64_t user, uint64_t group, int* err ) {

   void* app_handle_data = NULL;
   int rc = 0;
   struct fskit_entry* dir = NULL;
   struct fskit_dir_handle* dirh = NULL;
   char path[PATH_MAX];
   
   if( strlen(_path) >= PATH_MAX ) {
      // too long
      *err = -ENAMETOOLONG;
      return NULL;
   }

   // ensure path ends in /
   memset( path, 0, PATH_MAX );
   strncpy( path, _path, PATH_MAX - 1 );

   fskit_sanitize_path( path );

   dir = fskit_entry_resolve_path( core, path, user, group, true, err );
   if( dir == NULL ) {
      // resolution error; err is set appropriately
      return NULL;
   }

   // make sure it's a directory
   if( dir->type != FSKIT_ENTRY_TYPE_DIR ) {
      *err = -ENOTDIR;
      fskit_entry_unlock( dir );
      return NULL;
   }

   // reference it--it cannot be unlinked 
   fskit_entry_ref_entry( dir );
   fskit_entry_unlock( dir );
   
   // generate handle data
   rc = fskit_run_user_open( core, path, dir, 0, &app_handle_data );
   
   fskit_entry_wlock( dir );
   
   if( rc != 0 ) {

      // user-run open code failed
      fskit_error("fskit_run_user_open(%s) rc = %d\n", path, rc );
      fskit_entry_unlock( dir );
      *err = rc;
      
      fskit_entry_unref( core, path, dir );
      return NULL;
   }
   
   // make a handle to it
   dirh = fskit_dir_handle_create( dir, path, app_handle_data );
   if( dirh == NULL ) {
      
      // OOM
      fskit_entry_unlock( dir );
      fskit_entry_unref( core, path, dir );
      *err = -ENOMEM;
   }

   else {
      // release the directory
      fskit_entry_unlock( dir );
   }

   return dirh;
}