Пример #1
0
// low-level mkdir
int fs_entry_mkdir_lowlevel( struct fs_core* core, char const* path, struct fs_entry* parent, char const* path_basename, mode_t mode, uint64_t user, uint64_t vol, int64_t mtime_sec, int32_t mtime_nsec ) {
   
   // resolve the child
   struct fs_entry* child = fs_entry_set_find_name( parent->children, path_basename );
   int err = 0;
   if( child == NULL ) {

      // create an fs_entry and attach it
      child = CALLOC_LIST( struct fs_entry, 1 );

      fs_entry_init_dir( core, child, path_basename, 0, fs_entry_next_file_version(), user, 0, vol, mode, mtime_sec, mtime_nsec, 0, 0 );
      
      // add . and ..
      fs_entry_set_insert( child->children, ".", child );
      fs_entry_set_insert( child->children, "..", parent );

      fs_entry_attach_lowlevel( core, parent, child );
   }
Пример #2
0
// make a node (regular files only at this time)
int fs_entry_mknod( struct fs_core* core, char const* path, mode_t mode, dev_t dev, uint64_t user, uint64_t vol ) {
    // only regular files at this time...
    if( ! ( S_ISREG( mode ) || S_ISFIFO( mode ) ) ) {
        return -ENOTSUP;
    }

    // revalidate this path
    int rc = fs_entry_revalidate_path( core, path );
    if( rc != 0 && rc != -ENOENT ) {
        // consistency cannot be guaranteed
        SG_error("fs_entry_revalidate_path(%s) rc = %d\n", path, rc );
        return rc;
    }

    int err = 0;

    // get the parent directory and lock it
    char* path_dirname = md_dirname( path, NULL );
    struct fs_entry* parent = fs_entry_resolve_path( core, path_dirname, user, vol, true, &err );
    free( path_dirname );

    if( !IS_DIR_READABLE( parent->mode, parent->owner, parent->volume, user, vol ) ) {
        // not searchable
        fs_entry_unlock( parent );
        return -EACCES;
    }

    if( !IS_WRITEABLE( parent->mode, parent->owner, parent->volume, user, vol ) ) {
        // not writeable
        fs_entry_unlock( parent );
        return -EACCES;
    }

    uint64_t parent_id = parent->file_id;
    char* parent_name = strdup( parent->name );

    char* path_basename = md_basename( path, NULL );

    // make sure it doesn't exist already (or isn't in the process of being deleted, since we might have to re-create it if deleting it fails)
    if( fs_entry_set_find_name( parent->children, path_basename ) != NULL ) {
        free( path_basename );
        fs_entry_unlock( parent );
        free( parent_name );
        return -EEXIST;
    }

    struct fs_entry* child = (struct fs_entry*)calloc( sizeof(struct fs_entry), 1 );

    struct timespec ts;
    clock_gettime( CLOCK_REALTIME, &ts );
    int mmode = 0;
    if (S_ISFIFO(mode)) {
        mmode = ( mode & 0777 ) | S_IFIFO;
        err = fs_entry_init_fifo( core, child, path_basename, 0, fs_entry_next_file_version(), user, core->gateway, vol, mmode, 0, ts.tv_sec, ts.tv_nsec, 0, 0 );
    }
    if (S_ISREG(mode)) {
        mmode = ( mode & 0777 );
        err = fs_entry_init_file( core, child, path_basename, 0, fs_entry_next_file_version(), user, core->gateway, vol, mmode, 0, ts.tv_sec, ts.tv_nsec, 0, 0 );
    }

    if( err == 0 ) {

        // mark it as created in this session
        child->created_in_session = true;

        // we're creating, so this manifest is initialized (to zero blocks)
        child->manifest->initialize_empty( child->version );

        fs_entry_wlock( child );

        // call the driver
        err = driver_create_file( core, core->closure, path, child );

        if( err != 0 ) {
            // undo
            SG_error("driver_create_file(%s) rc = %d\n", path, err );

            child->open_count = 0;

            fs_entry_unlock( child );
            fs_entry_destroy( child, false );
            free( child );
        }

        else {

            // attach the file
            fs_entry_attach_lowlevel( core, parent, child );

            struct md_entry data;
            fs_entry_to_md_entry( core, &data, child, parent_id, parent_name );

            // create the child on the MS, obtaining its file ID and write nonce
            err = ms_client_create( core->ms, &child->file_id, &child->write_nonce, &data );

            md_entry_free( &data );

            if( err != 0 ) {
                SG_error( "ms_client_create(%s) rc = %d\n", path, err );
                err = -EREMOTEIO;

                child->open_count = 0;
                fs_entry_unlock( child );
                fs_entry_detach_lowlevel( core, parent, child );
                free( child );
            }
            else {
                fs_entry_unlock( child );
            }
        }
    }

    fs_entry_unlock( parent );

    free( parent_name );
    free( path_basename );

    return err;
}
Пример #3
0
// carry out the create locally.
// check permissions, initialize the child, and add it as a child of parent.
// return the initialized child (which will NOT be locked) via *ret_child
// return 0 on success
// return -EACCES on permission failure
// parent MUST be write locked
int fs_entry_do_create( struct fs_core* core, char const* path, struct fs_entry* parent, struct fs_entry** ret_child, uint64_t user, uint64_t vol, mode_t mode ) {

    int rc = 0;
    struct fs_entry* child = NULL;


    if( !IS_WRITEABLE(parent->mode, parent->owner, parent->volume, user, vol) ) {
        // can't create
        return -EACCES;
    }
    else {
        struct timespec ts;
        clock_gettime( CLOCK_REALTIME, &ts );

        // can create--initialize the child
        child = SG_CALLOC( struct fs_entry, 1 );

        char* path_basename = md_basename( path, NULL );

        rc = fs_entry_init_file( core, child, path_basename, 0, fs_entry_next_file_version(), user, core->gateway, vol, mode, 0, ts.tv_sec, ts.tv_nsec, 0, 0 );

        free( path_basename );

        if( rc != 0 ) {
            SG_error("fs_entry_init_file(%s) rc = %d\n", path, rc );

            fs_entry_destroy( child, false );
            free( child );

            return rc;
        }
        else {
            // mark it as created in this session
            child->created_in_session = true;

            // we're creating, so this manifest is initialized (to zero blocks)
            child->manifest->initialize_empty( child->version );

            // run the driver
            int driver_rc = driver_create_file( core, core->closure, path, child );
            if( driver_rc != 0 ) {
                SG_error("driver_create_file(%s) rc = %d\n", path, driver_rc );

                fs_entry_destroy( child, false );
                free( child );

                return driver_rc;
            }

            // insert it into the filesystem
            fs_entry_wlock( child );

            // open it
            child->open_count++;
            fs_entry_setup_working_data( core, child );

            fs_entry_attach_lowlevel( core, parent, child );

            fs_entry_unlock( child );

            *ret_child = child;
        }
    }

    return 0;
}