// write up to buflen bytes into buf, starting at the given offset in the file. // return the number of bytes written on success. // return negative on failure. ssize_t fskit_write( struct fskit_core* core, struct fskit_file_handle* fh, char const* buf, size_t buflen, off_t offset ) { fskit_file_handle_rlock( fh ); // sanity check if( (fh->flags & (O_RDWR | O_WRONLY)) == 0 ) { fskit_file_handle_unlock( fh ); return -EBADF; } ssize_t num_written = fskit_run_user_write( core, fh->path, fh->fent, buf, buflen, offset, fh->app_data ); if( num_written >= 0 ) { // update metadata fskit_entry_wlock( fh->fent ); fskit_entry_set_mtime( fh->fent, NULL ); fskit_entry_set_atime( fh->fent, NULL ); fh->fent->size = ((unsigned)(offset + buflen) > fh->fent->size ? offset + buflen : fh->fent->size); fskit_entry_unlock( fh->fent ); } fskit_file_handle_unlock( fh ); return num_written; }
// i/o continuation, called with the same locks held as the trunc() static int fskit_trunc_cont( struct fskit_core* core, struct fskit_entry* fent, off_t new_size, ssize_t trunc_rc ) { if( trunc_rc == 0 ) { // update metadata fskit_entry_set_mtime( fent, NULL ); fskit_entry_set_atime( fent, NULL ); fent->size = new_size; } return 0; }
// continuation for successful write // fent must be write-locked int fskit_write_cont( struct fskit_core* core, struct fskit_entry* fent, off_t offset, ssize_t num_written ) { if( num_written >= 0 ) { fskit_entry_set_mtime( fent, NULL ); fskit_entry_set_atime( fent, NULL ); off_t size_delta = 0; if( offset + num_written > fent->size ) { size_delta = (offset + num_written) - fent->size; } fent->size += size_delta; } return 0; }
// update timestamps on an inode on write/truncate // always succeeds // NOTE: inode->entry must be write-locked! int UG_write_timestamp_update( struct UG_inode* inode, struct timespec* ts ) { fskit_entry_set_mtime( UG_inode_fskit_entry( inode ), ts ); return 0; }