示例#1
0
// verify that an inode is still valid.
// that is, there's a process with the given PID running, and it's an instance of the same program that created it.
// to speed this up, only check the hash of the process binary if the modtime has changed
// return 1 if valid 
// return 0 if not valid 
// return negative on error
int runfs_inode_is_valid( struct runfs_inode* inode, pid_t pid ) {
   
   int rc = 0;
   struct pstat ps;
   int flags = 0;
   
   memset( &ps, 0, sizeof(struct pstat) );
   
   if( inode->verify_discipline & RUNFS_VERIFY_HASH ) {
      flags |= PSTAT_HASH;
   }
   
   rc = pstat( pid, &ps, flags );
   if( rc < 0 ) {
      fskit_error("pstat(%d) rc = %d\n", pid, rc );
      return rc;
   }
   
   rc = runfs_inode_is_created_by_proc( inode, &ps, inode->verify_discipline );
   if( rc < 0 ) {
      fskit_error("runfs_inode_is_created_by_proc(%d) rc = %d\n", pid, rc );
      return rc;
   }
   
   return rc;
}
示例#2
0
// set up fskit for FUSE
// this is the "easy" method that handles the filesystem initialization for you.
// return 0 on success
// return -ENOMEM on OOM
// return -errno on error
int fskit_fuse_init( struct fskit_fuse_state* state, void* core_state ) {

   int rc = 0;

   // set up library
   rc = fskit_library_init();
   if( rc != 0 ) {
      fskit_error( "fskit_library_init rc = %d\n", rc );
      return rc;
   }

   // set up fskit
   struct fskit_core* core = fskit_core_new();
   if( core == NULL ) {
      return -ENOMEM;
   }

   rc = fskit_core_init( core, core_state );
   if( rc != 0 ) {

      fskit_error( "fskit_core_init rc = %d\n", rc );
      return rc;
   }

   return fskit_fuse_init_fs( state, core );
}
示例#3
0
int main( int argc, char** argv ) {

   struct fskit_core* core = NULL;
   int rc;
   char name_buf[10];
   struct fskit_file_handle* fh = NULL;
   void* output;

   rc = fskit_test_begin( &core, NULL );
   if( rc != 0 ) {
      exit(1);
   }

   for( int i = 0; i < 256; i++ ) {

      sprintf(name_buf, "/%d", i );

      fh = fskit_create( core, name_buf, 0, i, 0644, &rc );

      if( fh == NULL ) {
         fskit_error("fskit_create('%s') rc = %d\n", name_buf, rc );
         exit(1);
      }

      fskit_close( core, fh );
   }

   for( int i = 0; i < 256; i++ ) {

      sprintf(name_buf, "/%d", i );

      struct stat sb;
      memset( &sb, 0xFF, sizeof(struct stat) );

      rc = fskit_stat( core, name_buf, 0, i, &sb );

      if( rc != 0 ) {
         fskit_error("fskit_stat('%s') rc = %d\n", name_buf, rc );
         exit(1);
      }

      fskit_debug("%s: stat(st_dev=%lX st_ino=%lX st_mode=%o st_nlink=%lu st_uid=%d st_gid=%d st_rdev=%lX st_size=%jd st_blksize=%ld st_blocks=%ld)\n",
               name_buf, sb.st_dev, sb.st_ino, sb.st_mode, sb.st_nlink, sb.st_uid, sb.st_gid, sb.st_rdev, sb.st_size, sb.st_blksize, sb.st_blocks );
   }

   fskit_print_tree( stdout, fskit_core_get_root( core ) );

   fskit_test_end( core, &output );

   return 0;
}
示例#4
0
int main( int argc, char** argv ) {

   struct fskit_core core;
   int rc;
   char name_buf[10];
   struct fskit_file_handle* fh = NULL;
   void* output;

   const struct timeval times[2] = {
      {12345, 67890},
      {23456, 78901}
   };

   rc = fskit_test_begin( &core, NULL );
   if( rc != 0 ) {
      exit(1);
   }

   for( int i = 0; i < 256; i++ ) {

      sprintf(name_buf, "/%d", i );

      fh = fskit_create( &core, name_buf, 0, i, 0644, &rc );

      if( fh == NULL ) {
         fskit_error("fskit_create('%s') rc = %d\n", name_buf, rc );
         exit(1);
      }

      fskit_close( &core, fh );
   }

   for( int i = 0; i < 256; i++ ) {

      sprintf(name_buf, "/%d", i );

      rc = fskit_utimes( &core, name_buf, 0, i, times );

      if( rc != 0 ) {
         fskit_error("fskit_utimes('%s') rc = %d\n", name_buf, rc );
         exit(1);
      }
   }

   fskit_print_tree( stdout, &core.root );

   fskit_test_end( &core, &output );

   return 0;
}
示例#5
0
文件: stat.c 项目: cmotc/fskit
// NOTE: fent cannot be locked
int fskit_do_user_stat( struct fskit_core* core, char const* fs_path, struct fskit_entry* fent, struct stat* sb ) {

   int rc = 0;
   int cbrc = 0;
   char name[FSKIT_FILESYSTEM_NAMEMAX+1];
   
   struct fskit_route_dispatch_args dargs;

   memset( name, 0, FSKIT_FILESYSTEM_NAMEMAX+1 );
   fskit_basename( fs_path, name );
   
   fskit_route_stat_args( &dargs, name, sb );

   rc = fskit_route_call_stat( core, fs_path, fent, &dargs, &cbrc );

   if( rc == -EPERM || rc == -ENOSYS ) {
      // no stat defined
      return 0;
   }
   else if( rc != 0 || cbrc != 0 ) {
       
      fskit_error("fskit_route_call_stat rc = %d, cbrc = %d\n", rc, cbrc );
   }

   return cbrc;
}
示例#6
0
文件: readlink.c 项目: PeteGozz/fskit
// read the target in a symlink (including the null character at the end)
// return the number of bytes read on success (up to MIN(buflen, linkpath size))
// return -EINVAL if the entry isn't a symlink
// return -EIO if the entry is corrupt (indicates a bug in fskit)
// return -errno if path resolution fails
ssize_t fskit_readlink( struct fskit_core* core, char const* path, uint64_t user, uint64_t group, char* buf, size_t buflen ) {

   int err = 0;
   ssize_t num_read = 0;
   struct fskit_entry* fent = NULL;

   // find this
   fent = fskit_entry_resolve_path( core, path, user, group, false, &err );
   if( err != 0 || fent == NULL ) {
      return err;
   }

   // symlink?
   if( fent->type != FSKIT_ENTRY_TYPE_LNK ) {
      fskit_entry_unlock( fent );
      return -EINVAL;
   }

   // sanity check
   if( fent->symlink_target == NULL ) {

      fskit_error("BUG: fskit entry %" PRIX64 " (at %p) is a symlink, but has no target path set\n", fent->file_id, fent );
      fskit_entry_unlock( fent );
      return -EIO;
   }

   // read it (including null character)
   num_read = (ssize_t)MIN( buflen, (unsigned)fent->size + 1 );

   memcpy( buf, fent->symlink_target, num_read );

   fskit_entry_unlock( fent );
   return num_read;
}
示例#7
0
文件: open.c 项目: PeteGozz/fskit
// 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;
}
示例#8
0
文件: common.cpp 项目: jaromil/fskit
// begin a functional test
int fskit_test_begin( struct fskit_core* core, void* test_data ) {

   int rc = 0;

   rc = fskit_library_init();
   if( rc != 0 ) {
      fskit_error("fskit_library_init rc = %d\n", rc );
      return rc;
   }

   rc = fskit_core_init( core, test_data );
   if( rc != 0 ) {
      fskit_error("fskit_core_init rc = %d\n", rc );
   }

   return rc;
}
示例#9
0
文件: common.cpp 项目: jaromil/fskit
int fskit_test_mkdir_LR_recursive( struct fskit_core* core, char const* path, int depth ) {

   if( depth <= 0 ) {
      return 0;
   }

   fskit_debug("mkdir('%s')\n", path );
   
   int rc = fskit_mkdir( core, path, 0755, 0, 0 );
   if( rc != 0 ) {
      fskit_error("fskit_mkdir('%s') rc = %d\n", path, rc );
      return rc;
   }

   char* new_path_1 = fskit_fullpath( path, "L", NULL );
   char* new_path_2 = fskit_fullpath( path, "R", NULL );

   rc = fskit_test_mkdir_LR_recursive( core, new_path_1, depth - 1 );
   if( rc != 0 ) {
      fskit_error("fskit_test_mkdir_LR_recursive('%s') rc = %d\n", new_path_1, rc );

      free( new_path_1 );
      free( new_path_2 );
      return rc;
   }

   rc = fskit_test_mkdir_LR_recursive( core, new_path_2, depth - 1 );
   if( rc != 0 ) {
      fskit_error("fskit_test_mkdir_LR_recursive('%s') rc = %d\n", new_path_2, rc );

      free( new_path_1 );
      free( new_path_2 );
      return rc;
   }

   free( new_path_1 );
   free( new_path_2 );

   return 0;
}
示例#10
0
文件: common.cpp 项目: jaromil/fskit
// end a functional test
int fskit_test_end( struct fskit_core* core, void** test_data ) {

   int rc = 0;

   rc = fskit_detach_all( core, "/", core->root.children );
   if( rc != 0 ) {
      fskit_error("fskit_detach_all(\"/\") rc = %d\n", rc );
      return rc;
   }

   rc = fskit_core_destroy( core, test_data );
   if( rc != 0 ) {
      fskit_error("fskit_core_destroy rc = %d\n", rc );
      return rc;
   }

   rc = fskit_library_shutdown();
   if( rc != 0 ) {
      return rc;
   }

   return rc;
}
示例#11
0
// shut down fskit fuse
int fskit_fuse_shutdown( struct fskit_fuse_state* state, void** core_state ) {

   struct fskit_core* core = state->core;
   int rc = 0;

   if( core != NULL ) {
       // clean up
       // blow away all inodes
       rc = fskit_detach_all( core, "/" );
       if( rc != 0 ) {
          fskit_error( "fskit_detach_all(\"/\") rc = %d\n", rc );
       }

       // destroy the core
       rc = fskit_core_destroy( core, core_state );
       if( rc != 0 ) {
          fskit_error( "fskit_core_destroy rc = %d\n", rc );
       }

       // shut down the library
       rc = fskit_library_shutdown();
       if( rc != 0 ) {
          fskit_error( "fskit_library_shutdown rc = %d\n", rc );
       }

       free( core );
       state->core = NULL;
   }

   // free mountpoint
   if( state->mountpoint != NULL ) {
      free( state->mountpoint );
      state->mountpoint = NULL;
   }

   return rc;
}
示例#12
0
文件: trunc.c 项目: jaromil/fskit
// truncate a file to a given size
// return 0 on success
// return negative on failure
int fskit_trunc( struct fskit_core* core, char const* path, uint64_t user, uint64_t group, off_t new_size ) {

   int err = 0;
   int rc = 0;

   // get the fent
   struct fskit_entry* fent = fskit_entry_resolve_path( core, path, user, group, true, &err );
   if( fent == NULL || err != 0 ) {
      return err;
   }

   // reference the fent, so it won't go anywhere
   fent->open_count++;

   fskit_entry_unlock( fent );

   rc = fskit_run_user_trunc( core, path, fent, new_size, NULL );

   // unreference
   fskit_entry_wlock( fent );

   fent->open_count--;

   // need to free?  note that this may unlock and re-lock fent, but only if it cannot be resolved by any path
   // NOTE: this may unlock and destroy the fent
   rc = fskit_entry_try_destroy_and_free( core, path, fent );
   if( rc > 0 ) {

      // fent was unlocked and destroyed
      rc = 0;
   }
   else if( rc < 0 ) {

      // some error occurred
      fskit_error("fskit_entry_try_destroy(%p) rc = %d\n", fent, rc );
      fskit_entry_unlock( fent );

      return rc;
   }
   else {

      // done with this entry
      fskit_entry_unlock( fent );
   }

   return rc;
}
示例#13
0
文件: stat.c 项目: jaromil/fskit
int fskit_do_user_stat( struct fskit_core* core, char const* fs_path, struct fskit_entry* fent, struct stat* sb ) {

   int rc = 0;
   int cbrc = 0;

   struct fskit_route_dispatch_args dargs;

   fskit_route_stat_args( &dargs, sb );

   rc = fskit_route_call_stat( core, fs_path, fent, &dargs, &cbrc );

   if( rc == -EPERM || rc == -ENOSYS ) {
      // no stat defined
      return 0;
   }
   else if( rc != 0 || cbrc != 0 ) {
       
      fskit_error("fskit_route_call_stat rc = %d, cbrc = %d\n", rc, cbrc );
   }

   return cbrc;
}
示例#14
0
int main( int argc, char** argv ) {

   struct fskit_core core;
   int rc;
   void* output;
   struct fskit_path_iterator* itr = NULL;
   struct fskit_file_handle* fh = NULL;

   rc = fskit_test_begin( &core, NULL );
   if( rc != 0 ) {
      exit(1);
   }

   rc = fskit_test_mkdir_LR_recursive( &core, "/root", 7 );
   if( rc != 0 ) {
      fskit_error("fskit_test_mkdir_LR_recursive('/root') rc = %d\n", rc );
      exit(1);
   }
   
   fh = fskit_create( &core, "/root/L/R/L/R/L/R/.foo", 0, 0, 0777, &rc );
   if( fh == NULL ) {
      fskit_error("fskit_create('/root/L/R/L/R/L/R/.foo') rc = %d\n", rc );
      exit(1);
   }
   
   fskit_close( &core, fh );
   
   fh = fskit_create( &core, "/bar.f", 0, 0, 0777, &rc );
   if( fh == NULL ) {
      fskit_error("fskit_create('/bar.f') rc = %d\n", rc );
      exit(1);
   }
   
   fskit_close( &core, fh );
   
   rc = fskit_mkdir( &core, "/bar.d", 0755, 0, 0 );
   if( rc < 0 ) {
      fskit_error("fskit_mkdir('/bar.d') rc = %d\n", rc );
      exit(1);  
   }
   
   /////////////////////////////////////////////////////////////////////////////////////
   printf("\n\nIterate succeeds...\n\n");
   
   for( itr = fskit_path_begin( &core, "/root/L/R/L/R/L/R/.foo", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) {
      
      struct fskit_entry* cur = fskit_path_iterator_entry( itr );
      char* cur_path = fskit_path_iterator_path( itr );
      
      printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path );
      
      free( cur_path );
   }
   
   printf("Iterator error: %d\n", fskit_path_iterator_error( itr ) );
   
   fskit_path_iterator_release( itr );
   
   
   printf("\n\n");
   
   
   for( itr = fskit_path_begin( &core, "/bar.f", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) {
      
      struct fskit_entry* cur = fskit_path_iterator_entry( itr );
      char* cur_path = fskit_path_iterator_path( itr );
      
      printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path );
      
      free( cur_path );
   }
   
   printf("Iterator error: %d\n", fskit_path_iterator_error( itr ) );
   
   fskit_path_iterator_release( itr );
   
   
   printf("\n\n");
   
   
   for( itr = fskit_path_begin( &core, "/bar.d", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) {
      
      struct fskit_entry* cur = fskit_path_iterator_entry( itr );
      char* cur_path = fskit_path_iterator_path( itr );
      
      printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path );
      
      free( cur_path );
   }
   
   printf("Iterator error: %d\n", fskit_path_iterator_error( itr ) );
   
   fskit_path_iterator_release( itr );
   
   
   /////////////////////////////////////////////////////////////////////////////////////
   printf("\n\nIterate succeeds on path with duplicate . and /...\n\n");
   
   for( itr = fskit_path_begin( &core, "././root/L/R//L//././/R/L//.///R", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) {
      
      struct fskit_entry* cur = fskit_path_iterator_entry( itr );
      char* cur_path = fskit_path_iterator_path( itr );
      
      printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path );
      
      free( cur_path );
   }

   printf("Iterator error: %d\n", fskit_path_iterator_error( itr ) );

   fskit_path_iterator_release( itr );
      
   printf("\n\n");
   
   for( itr = fskit_path_begin( &core, "/././root///././/.//.", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) {
      
      struct fskit_entry* cur = fskit_path_iterator_entry( itr );
      char* cur_path = fskit_path_iterator_path( itr );
      
      printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path );
      
      free( cur_path );
   }

   printf("Iterator error: %d\n", fskit_path_iterator_error( itr ) );

   fskit_path_iterator_release( itr );
      
   /////////////////////////////////////////////////////////////////////////////////////
   printf("\n\nIterate fails (path too long)...\n\n");
   
   for( itr = fskit_path_begin( &core, "/root/L/R/L/R/L/R/L/R/L/R/L/R/L/R/L/R", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) {
      
      struct fskit_entry* cur = fskit_path_iterator_entry( itr );
      char* cur_path = fskit_path_iterator_path( itr );
      
      printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path );
      
      free( cur_path );
   }
   
   printf("Iterator error: %d\n", fskit_path_iterator_error( itr ) );
   
   fskit_path_iterator_release( itr );
   
   /////////////////////////////////////////////////////////////////////////////////////
   printf("\n\nIterate fails (path does not exist)...\n\n");
   
   for( itr = fskit_path_begin( &core, "/root/L/R/L/foo/L/R", true ); !fskit_path_end( itr ); fskit_path_next( itr ) ) {
      
      struct fskit_entry* cur = fskit_path_iterator_entry( itr );
      char* cur_path = fskit_path_iterator_path( itr );
      
      printf("Entry %016" PRIX64 " (%p): %c %s\n", fskit_entry_get_file_id( cur ), cur, fskit_entry_get_type( cur ) == FSKIT_ENTRY_TYPE_FILE ? 'F' : 'D', cur_path );
      
      free( cur_path );
   }
   
   printf("Iterator error: %d\n\n\n", fskit_path_iterator_error( itr ) );
   
   fskit_path_iterator_release( itr );
   
   fskit_test_end( &core, &output );

   return 0;
}
示例#15
0
文件: common.cpp 项目: jaromil/fskit
// print out a tree to the given file stream
int fskit_print_tree( FILE* out, struct fskit_entry* root ) {

   struct fskit_entry* node = NULL;
   char* next_path = NULL;
   char type_str[10];
   int rc = 0;
   fskit_entry_set_itr itr;
   fskit_entry_set* child = NULL;

   vector< struct fskit_entry* > frontier;
   vector< char* > frontier_paths;

   frontier.push_back( root );
   frontier_paths.push_back( strdup(root->name) );

   while( frontier.size() > 0 ) {

      node = frontier[0];
      next_path = frontier_paths[0];

      frontier.erase( frontier.begin() );
      frontier_paths.erase( frontier_paths.begin() );

      fskit_type_to_string( node->type, type_str );

      fprintf( out, "%s: inode=%" PRIX64 " size=%jd mode=%o user=%" PRIu64 " group=%" PRIu64 " ctime=(%" PRId64 ".%" PRId32 ") mtime=(%" PRId64 ".%" PRId32 ") atime=(%" PRId64 ".%" PRId32 ") mem=%p \"%s\"\n",
                    type_str, node->file_id, node->size, node->mode, node->owner, node->group, node->ctime_sec, node->ctime_nsec, node->mtime_sec, node->mtime_nsec, node->atime_sec, node->atime_nsec, node, next_path );

      if( node->type == FSKIT_ENTRY_TYPE_DIR ) {

         if( node->children == NULL ) {
            fskit_error("ERR: children of %p == NULL\n", node );

            rc = -EINVAL;
            break;
         }

         // explore children
         for( child = fskit_entry_set_begin( node->children, &itr ); child != NULL; child = fskit_entry_set_next( &itr ) ) {

            char const* name = fskit_entry_set_name_at( &itr );
            struct fskit_entry* child = fskit_entry_set_child_at( &itr );

            if( child == NULL ) {
               continue;
            }
            if( strcmp(".", name) == 0 || strcmp("..", name) == 0 ) {
               continue;
            }

            frontier.push_back( child );
            frontier_paths.push_back( fskit_fullpath( next_path, child->name, NULL ) );
         }
      }

      free( next_path );
   }

   if( rc != 0 ) {

      for( unsigned int i = 0; i < frontier_paths.size(); i++ ) {

         if( frontier_paths.at(i) ) {
            free( frontier_paths.at(i) );
         }
      }

      frontier_paths.clear();
   }

   return rc;
}
示例#16
0
文件: closedir.c 项目: jaromil/fskit
// close a directory handle, freeing it.
// a directory may be unlinked on close, if this was the last handle to it, and its link count was zero.
// if this happens, then app_dir_data will contain the directory's app data, and the directory will be freed.
// return 0 on success
// return the following errors:
// * EBADF if the directory handle is invalid
// * EDEADLK if there is a bug in the lock handling
int fskit_closedir( struct fskit_core* core, struct fskit_dir_handle* dirh ) {

   int rc = 0;

   rc = fskit_dir_handle_wlock( dirh );
   if( rc != 0 ) {
      // indicates deadlock; shouldn't happen
      fskit_error("BUG: fskit_dir_handle_wlock(%p) rc = %d\n", dirh, rc );
      return rc;
   }

   if( dirh->dent == NULL ) {

      fskit_dir_handle_unlock( dirh );
      return -EBADF;
   }

   // run user-given close route.  Note that this may unlock dirh->dent and re-lock it, but only if it is fully unlinked.
   rc = fskit_run_user_close( core, dirh->path, dirh->dent, dirh->app_data );
   if( rc != 0 ) {

      fskit_error("fskit_run_user_close(%s) rc = %d\n", dirh->path, rc );
      
      fskit_dir_handle_unlock( dirh );
      return rc;
   }

   rc = fskit_entry_wlock( dirh->dent );
   if( rc != 0 ) {

      // shouldn't happen; indicates deadlock
      fskit_error("BUG: fskit_entry_wlock(%p) rc = %d\n", dirh->dent, rc );

      fskit_dir_handle_unlock( dirh );
      return rc;
   }
   
   // no longer open
   dirh->dent->open_count--;

   // see if we can destroy this....
   // NOTE: this may unlock and free dirh->dent
   rc = fskit_entry_try_destroy_and_free( core, dirh->path, dirh->dent );
   if( rc > 0 ) {

      // dent was unlocked and destroyed
      dirh->dent = NULL;
      rc = 0;
   }
   if( rc < 0 ) {

      // some error occurred
      fskit_error("fskit_entry_try_destroy(%p) rc = %d\n", dirh->dent, rc );
      fskit_entry_unlock( dirh->dent );

      return rc;
   }
   else {
      
      // not destroyed.
      // done with this directory
      fskit_entry_unlock( dirh->dent );
   }

   // get rid of this handle
   fskit_dir_handle_unlock( dirh );
   fskit_dir_handle_destroy( dirh );

   return 0;
}
示例#17
0
// run fskit with fuse
int fskit_fuse_main( struct fskit_fuse_state* state, int argc, char** argv ) {

   int rc = 0;

   // set up FUSE
   struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
   struct fuse_chan* ch = NULL;
   struct fuse* fs = NULL;
   int multithreaded = 1;
   int foreground = 0;
   char* mountpoint = NULL;

   // parse command-line...
   rc = fuse_parse_cmdline( &args, &mountpoint, &multithreaded, &foreground );
   if( rc < 0 ) {

      fskit_error("fuse_parse_cmdline rc = %d\n", rc );
      fuse_opt_free_args(&args);

      return rc;
   }

   if( mountpoint == NULL ) {

      fskit_error("%s", "No mountpoint given\n");
      fuse_opt_free_args(&args);

      return rc;
   }

   state->mountpoint = strdup( mountpoint );

   // mount
   ch = fuse_mount( mountpoint, &args );
   if( ch == NULL ) {

      rc = -errno;
      fskit_error("fuse_mount failed, errno = %d\n", rc );

      fuse_opt_free_args(&args);

      if( rc == 0 ) {
          rc = -EPERM;
      }

      return rc;
   }

   // create the filesystem
   fs = fuse_new( ch, &args, &state->ops, sizeof(state->ops), state );
   fuse_opt_free_args(&args);

   if( fs == NULL ) {

      // failed
      rc = -errno;
      fskit_error("fuse_new failed, errno = %d\n", rc );

      fuse_unmount( mountpoint, ch );

      if( rc == 0 ) {
          rc = -EPERM;
      }

      return rc;
   }

   // daemonize if running in the background
   fskit_debug("FUSE daemonize: foreground=%d\n", foreground);
   rc = fuse_daemonize( foreground );
   if( rc != 0 ) {

      // failed
      fskit_error("fuse_daemonize(%d) rc = %d\n", foreground, rc );

      fuse_unmount( mountpoint, ch );
      fuse_destroy( fs );

      return rc;
   }

   // set up FUSE signal handlers
   rc = fuse_set_signal_handlers( fuse_get_session(fs) );
   if( rc < 0 ) {

      // failed
      fskit_error("fuse_set_signal_handlers rc = %d\n", rc );

      fuse_unmount( mountpoint, ch );
      fuse_destroy( fs );
      return rc;
   }

   // if we have a post-mount callback, call it now, since FUSE is ready to receive requests
   if( state->postmount != NULL ) {

      rc = (*state->postmount)( state, state->postmount_cls );
      if( rc != 0 ) {

         fskit_error("fskit postmount callback rc = %d\n", rc );

         fuse_unmount( mountpoint, ch );
         fuse_destroy( fs );

         return rc;
      }
   }

   // run the filesystem--start processing requests
   fskit_debug("%s", "FUSE main loop entered\n");
   if( multithreaded ) {
      rc = fuse_loop_mt( fs );
   }
   else {
      rc = fuse_loop( fs );
   }

   fskit_debug("%s", "FUSE main loop finished\n");
   fuse_teardown( fs, mountpoint );

   return rc;
}
示例#18
0
文件: opendir.c 项目: PeteGozz/fskit
// 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;
}
示例#19
0
文件: mkdir.c 项目: PeteGozz/fskit
// low-level mkdir: create a child and insert it into the parent.
// parent must be a directory
// parent must be write-locked
// return -EEXIST if an entry with the given name (path_basename) already exists in parent.
// return -EIO if we couldn't allocate an inode
// return -ENOMEM if we couldn't allocate memory
static int fskit_mkdir_lowlevel( struct fskit_core* core, char const* path, struct fskit_entry* parent, char const* path_basename, mode_t mode, uint64_t user, uint64_t group, void* cls ) {

   // resolve the child within the parent
   struct fskit_entry* child = fskit_entry_set_find_name( parent->children, path_basename );
   int err = 0;
   void* app_dir_data = NULL;

   if( child != NULL ) {

      fskit_entry_wlock( child );

      err = fskit_entry_try_garbage_collect( core, path, parent, child );

      if( err >= 0 ) {

         if( err == 0 ) {
            
            // detached but not destroyed
            fskit_entry_unlock( child );
         }

         // name is free
         child = NULL;
      }
      else {
         
         fskit_entry_unlock( child );
         if( err == -EEXIST ) {

            // still exists; can't be garbage-collected
            return -EEXIST;
         }
         else {

            // shouldn't happen
            fskit_error("BUG: fskit_entry_try_garbage_collect(%s) rc = %d\n", path, err );
            return -EIO;
         }
      }
   }

   if( child == NULL ) {

      // create an fskit_entry and attach it
      child = CALLOC_LIST( struct fskit_entry, 1 );
      if( child == NULL ) {
         return -ENOMEM;
      }

      // get an inode for this child
      uint64_t child_inode = fskit_core_inode_alloc( core, parent, child );
      if( child_inode == 0 ) {

         // error in allocation
         fskit_error("fskit_core_inode_alloc(%s) failed\n", path );

         fskit_safe_free( child );

         return -EIO;
      }
      
      // set up the directory
      err = fskit_entry_init_dir( child, parent, child_inode, user, group, mode );
      if( err != 0 ) {
         fskit_error("fskit_entry_init_dir(%s) rc = %d\n", path, err );

         fskit_safe_free( child );
         return err;
      }

      // reference this directory, so it won't disappear during the user's route
      child->open_count++;
      
      // almost done.  run the route callback for this path if needed
      err = fskit_run_user_mkdir( core, path, parent, child, mode, cls, &app_dir_data );
      
      child->open_count--;
      
      if( err != 0 ) {

         // user route failed
         fskit_error("fskit_run_user_mkdir(%s) rc = %d\n", path, err );

         fskit_entry_destroy( core, child, false );
         fskit_safe_free( child );
      }
      else {

         fskit_entry_set_user_data( child, app_dir_data );

         // attach to parent
         fskit_entry_attach_lowlevel( parent, child, path_basename );
      }
   }
示例#20
0
文件: open.c 项目: PeteGozz/fskit
// create/open a file, with the given flags and (if creating) mode
// on success, return a file handle to the created/opened file.
// on failure, return NULL and set *err to the appropriate errno
struct fskit_file_handle* fskit_open_ex( struct fskit_core* core, char const* _path, uint64_t user, uint64_t group, int flags, mode_t mode, void* cls, int* err ) {

   if( fskit_check_flags( flags ) != 0 ) {
      *err = -EINVAL;
      return NULL;
   }

   int rc = 0;

   char* path = strdup(_path);

   if( path == NULL ) {
      *err = -ENOMEM;
      return NULL;
   }

   fskit_sanitize_path( path );

   size_t basename_len = fskit_basename_len( path );
   if( basename_len > FSKIT_FILESYSTEM_NAMEMAX ) {

      free( path );
      *err = -ENAMETOOLONG;

      return NULL;
   }

   void* handle_data = NULL;

   // resolve the parent of this child (and write-lock it)
   char* path_dirname = fskit_dirname( path, NULL );
   char path_basename[FSKIT_FILESYSTEM_NAMEMAX + 1];

   memset( path_basename, 0, FSKIT_FILESYSTEM_NAMEMAX + 1 );

   fskit_basename( path, path_basename );

   struct fskit_file_handle* ret = NULL;

   // write-lock parent--we need to ensure that the child does not disappear on us between attaching it and routing the user-given callback
   struct fskit_entry* parent = fskit_entry_resolve_path( core, path_dirname, user, group, true, err );

   if( parent == NULL ) {

      fskit_safe_free( path_dirname );
      fskit_safe_free( path );

      // err is set appropriately
      return NULL;
   }

   fskit_safe_free( path_dirname );

   rc = fskit_do_parent_check( parent, flags, user, group );
   if( rc != 0 ) {

      // can't perform this operation
      fskit_entry_unlock( parent );
      fskit_safe_free( path );
      *err = rc;
      return NULL;
   }

   // resolve the child (which may be in the process of being deleted)
   struct fskit_entry* child = fskit_entry_set_find_name( parent->children, path_basename );
   bool created = false;

   if( flags & O_CREAT ) {

      if( child != NULL ) {

         fskit_entry_wlock( child );

         // it might have been marked for garbage-collection
         rc = fskit_entry_try_garbage_collect( core, path, parent, child );

         if( rc >= 0 ) {

            if( rc == 0 ) {
               
               // not destroyed, but no longer attached
               fskit_entry_unlock( child );
            }

            // safe to create
            child = NULL;
         }
         else {

            // can't garbage-collect--child still exists
            fskit_entry_unlock( parent );
            fskit_entry_unlock( child );
            fskit_safe_free( path );

            if( rc == -EEXIST ) {

               *err = -EEXIST;
               return NULL;
            }
            else {

               // shouldn't happen
               fskit_error("BUG: fskit_entry_try_garbage_collect(%s) rc = %d\n", path, rc );

               *err = -EIO;
            }

            return NULL;
         }
      }

      if( child == NULL ) {

         // can create!
         // NOTE: do *not* lock child--it has to be unlocked for running user-given routes
         rc = fskit_do_create( core, parent, path, mode, user, group, cls, &child, &handle_data );
         if( rc != 0 ) {

            fskit_entry_unlock( parent );
            fskit_safe_free( path );
            *err = rc;
            return NULL;
         }

         // created!
         created = true;
      }
   }

   else if( child == NULL ) {

      // not found
      fskit_entry_unlock( parent );
      fskit_safe_free( path );
      *err = -ENOENT;
      return NULL;
   }

   // now child exists.
   // don't lock it, though, since we have to pass it to truncate or open 
   
   // do we have to truncate?
   if( (flags & O_TRUNC) && (flags & (O_RDWR | O_WRONLY)) ) {

      // run user truncate
      // NOTE: do *not* lock it--it has to be unlocked for running user-given routes
      rc = fskit_run_user_trunc( core, path, child, 0, NULL );
      if( rc != 0 ) {

         // truncate failed
         fskit_entry_unlock( parent );
         fskit_safe_free( path );
         *err = rc;
         return NULL;
      }
   }

   if( !created ) {
      
      // do the open
      // NOTE: do *not* lock it--it has to be unlocked for running user-given routes
      rc = fskit_do_open( core, path, parent, child, flags, user, group, &handle_data );
      if( rc != 0 ) {

         // open failed
         fskit_entry_unlock( parent );
         fskit_safe_free( path );
         *err = rc;
         return NULL;
      }
   }
   
   // done with parent 
   fskit_entry_unlock( parent );

   // still here--we can open the file now!
   fskit_entry_set_atime( child, NULL );
   ret = fskit_file_handle_create( core, child, path, flags, handle_data );

   fskit_safe_free( path );

   if( ret == NULL ) {
      // only possible if we're out of memory!
      *err = -ENOMEM;
   }

   return ret;
}
示例#21
0
int main( int argc, char** argv ) {

   struct fskit_core core;
   int rc;
   char name_buf[10];
   char name_buf2[10];

   struct fskit_file_handle* fh = NULL;
   void* output;

   rc = fskit_test_begin( &core, NULL );
   if( rc != 0 ) {
      exit(1);
   }

   // setup
   for( int i = 0; i < 10; i++ ) {

      // create /a$i

      memset(name_buf, 0, 10 );
      sprintf(name_buf, "/a%d", i );

      fh = fskit_create( &core, name_buf, 0, i, 0644, &rc );

      if( fh == NULL ) {
         fskit_error("fskit_create('%s') rc = %d\n", name_buf, rc );
         exit(1);
      }

      fskit_close( &core, fh );

      // mkdir /d$i

      memset(name_buf, 0, 10 );
      sprintf(name_buf, "/d%d", i );

      rc = fskit_mkdir( &core, name_buf, 0755, 0, 0 );
      if( rc != 0 ) {
         fskit_error("fskit_mkdir('%s') rc = %d\n", name_buf, rc );
         exit(1);
      }
   }

   printf("Initial tree:\n");
   fskit_print_tree( stdout, &core.root );

   // rename in the same directory
   // rename /a$i to /b$i
   for( int i = 0; i < 10; i++ ) {

      memset(name_buf, 0, 10 );
      memset(name_buf2, 0, 10 );

      sprintf(name_buf, "/a%d", i );
      sprintf(name_buf2, "/b%d", i );

      rc = fskit_rename( &core, name_buf, name_buf2, 0, 0 );
      if( rc != 0 ) {
         fskit_error("fskit_rename('%s', '%s') rc = %d\n", name_buf, name_buf2, rc );
         exit(1);
      }
   }

   printf("Rename /a$i to /b$i");
   fskit_print_tree( stdout, &core.root );

   // rename into a deeper directory
   // rename /b$i to /d$i/a$i
   for( int i = 0; i < 10; i++ ) {

      memset(name_buf, 0, 10 );
      memset(name_buf2, 0, 10 );

      sprintf(name_buf, "/b%d", i );
      sprintf(name_buf2, "/d%d/a%d", i, i );

      rc = fskit_rename( &core, name_buf, name_buf2, 0, 0 );
      if( rc != 0 ) {
         fskit_error("fskit_rename('%s', '%s') rc = %d\n", name_buf, name_buf2, rc );
         exit(1);
      }
   }


   printf("Rename /b$i to /d$i/a$i");
   fskit_print_tree( stdout, &core.root );

   // rename into a shallower directory
   // rename /d$i/a$i to /a$i
   for( int i = 0; i < 10; i++ ) {

      memset(name_buf, 0, 10 );
      memset(name_buf2, 0, 10 );

      sprintf(name_buf, "/d%d/a%d", i, i );
      sprintf(name_buf2, "/a%d", i );

      rc = fskit_rename( &core, name_buf, name_buf2, 0, 0 );
      if( rc != 0 ) {
         fskit_error("fskit_rename('%s', '%s') rc = %d\n", name_buf, name_buf2, rc );
         exit(1);
      }
   }

   printf("Rename /d/a$i to /a$i");
   fskit_print_tree( stdout, &core.root );

   fskit_test_end( &core, &output );

   return 0;
}