// utime int fs_entry_utime( struct fs_core* core, char const* path, struct utimbuf* tb, uint64_t user, uint64_t volume ) { int err = 0; uint64_t parent_id = 0; char* parent_name = NULL; struct fs_entry* fent = fs_entry_resolve_path_and_parent_info( core, path, user, volume, true, &err, &parent_id, &parent_name ); if( !fent || err ) { if( !err ) err = -ENOMEM; return err; } // check permissions if( tb == NULL && !IS_WRITEABLE( fent->mode, fent->owner, fent->volume, user, volume ) ) { fs_entry_unlock( fent ); return -EACCES; } if( tb != NULL && fent->owner != user ) { fs_entry_unlock( fent ); return -EACCES; } if( tb != NULL ) { fent->mtime_sec = tb->modtime; fent->atime = tb->actime; } else { struct timespec ts; clock_gettime( CLOCK_REALTIME, &ts ); fent->mtime_sec = ts.tv_sec; fent->mtime_nsec = ts.tv_nsec; fent->atime = fent->mtime_sec; } fent->atime = currentTimeSeconds(); // post update struct md_entry up; fs_entry_to_md_entry( core, &up, fent, parent_id, parent_name ); int rc = ms_client_update( core->ms, &fent->write_nonce, &up ); if( rc != 0 ) { errorf("ms_client_update(%s) rc = %d\n", path, rc ); } md_entry_free( &up ); fs_entry_unlock( fent ); return rc; }
// open a directory, but fail-fast if we can't get path metadata struct fs_dir_handle* fs_entry_opendir( struct fs_core* core, char const* fs_path, uint64_t user, uint64_t vol, int* err ) { // ensure path ends in / char path[PATH_MAX]; strcpy( path, fs_path ); md_sanitize_path( path ); int rc = fs_entry_revalidate_path( core, path ); if( rc != 0 ) { SG_error("fs_entry_revalidate_path(%s) rc = %d\n", path, rc ); return NULL; } uint64_t parent_id = 0; char* parent_name = NULL; struct fs_entry* dir = fs_entry_resolve_path_and_parent_info( core, path, user, vol, true, err, &parent_id, &parent_name ); if( dir == NULL ) { return NULL; } // make sure it's a directory if( dir->ftype != FTYPE_DIR ) { *err = -ENOTDIR; fs_entry_unlock( dir ); return NULL; } // open this directory dir->open_count++; struct fs_dir_handle* dirh = fs_dir_handle_create( dir, path, parent_id, parent_name ); rc = fs_dir_handle_open( dirh ); if( rc != 0 ) { fs_dir_handle_destroy( dirh ); free( dirh ); dirh = NULL; *err = rc; } // release the directory fs_entry_unlock( dir ); free( parent_name ); return dirh; }
// chmod int fs_entry_chmod( struct fs_core* core, char const* path, uint64_t user, uint64_t volume, mode_t mode ) { int err = 0; uint64_t parent_id = 0; char* parent_name = NULL; struct fs_entry* fent = fs_entry_resolve_path_and_parent_info( core, path, user, volume, true, &err, &parent_id, &parent_name ); if( !fent || err ) { if( !err ) err = -ENOMEM; return err; } // can't chmod unless we own the file if( fent->owner != user ) { fs_entry_unlock( fent ); free( parent_name ); return -EPERM; } fent->mode = mode; // post update struct md_entry up; fs_entry_to_md_entry( core, &up, fent, parent_id, parent_name ); int rc = ms_client_update( core->ms, &fent->write_nonce, &up ); if( rc != 0 ) { errorf("ms_client_update(%s) rc = %d\n", path, rc ); } md_entry_free( &up ); fs_entry_unlock( fent ); free( parent_name ); return rc; }