int ntfs_fsync_r(struct _reent *r, int fd) { ntfs_log_trace("fd %p\n", (void *) fd); ntfs_file_state* file = STATE(((intptr_t)(s64)fd)); //ntfs_file_state* file = STATE(((s64) fd)); int ret = 0; // Sanity check if (!file || !file->vd || !file->ni || !file->data_na) { r->_errno = EINVAL; return -1; } // Lock ntfsLock(file->vd); // Sync the file (and its attributes) to disc ret = ntfsSync(file->vd, file->ni); if (ret) r->_errno = errno; // Unlock ntfsUnlock(file->vd); return ret; }
void ntfsCloseFile(ntfs_file_state *file) { // Sanity check if (!file || !file->vd) return; // Special case fix ups for compressed and/or encrypted files if (file->compressed) ntfs_attr_pclose(file->data_na); #ifdef HAVE_SETXATTR if (file->encrypted) ntfs_efs_fixup_attribute(NULL, file->data_na); #endif // Close the file data attribute (if open) if (file->data_na) ntfs_attr_close(file->data_na); // Sync the file (and its attributes) to disc if (file->write) { ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_ATIME | NTFS_UPDATE_CTIME); ntfsSync(file->vd, file->ni); } if (file->read) ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_ATIME); // Close the file (if open) if (file->ni) ntfsCloseEntry(file->vd, file->ni); // Reset the file state file->ni = NULL; file->data_na = NULL; file->flags = 0; file->read = false; file->write = false; file->append = false; file->pos = 0; file->len = 0; return; }
void ntfsCloseEntry (ntfs_vd *vd, ntfs_inode *ni) { // Sanity check if (!vd) { errno = ENODEV; return; } // Lock ntfsLock(vd); // Sync the entry (if it is dirty) if (NInoDirty(ni)) ntfsSync(vd, ni); // Close the entry ntfs_inode_close(ni); // Unlock ntfsUnlock(vd); return; }
void ntfsCloseFile (ntfs_file_state *file) { // Sanity check if (!file || !file->vd) return; // Special case fix ups for compressed and/or encrypted files if (file->compressed) ntfs_attr_pclose(file->data_na); if (file->encrypted) ntfs_efs_fixup_attribute(NULL, file->data_na); // Close the file data attribute (if open) if (file->data_na) ntfs_attr_close(file->data_na); // Sync the file (and its attributes) to disc if(file->write) ntfsSync(file->vd, file->ni); // Close the file (if open) if (file->ni) ntfsCloseEntry(file->vd, file->ni); // Reset the file state file->ni = NULL; file->data_na = NULL; file->flags = 0; file->read = false; file->write = false; file->append = false; file->pos = 0; file->len = 0; return; }
int ntfs_ftruncate_r(struct _reent *r, int fd, off_t len) { ntfs_log_trace("fd %p, len %llu\n", (void *) fd, (u64) len); ntfs_file_state* file = STATE(((intptr_t)(s64)fd)); //ntfs_file_state* file = STATE(((s64) fd)); // Sanity check if (!file || !file->vd || !file->ni || !file->data_na) { r->_errno = EINVAL; return -1; } // Lock ntfsLock(file->vd); // Check that we are allowed to write to this file if (!file->write) { ntfsUnlock(file->vd); r->_errno = EACCES; return -1; } // For compressed files, only deleting and expanding contents are implemented if (file->compressed && len > 0 && len < file->data_na->initialized_size) { ntfsUnlock(file->vd); r->_errno = ENOTSUP; return -1; } // Resize the files data attribute, either by expanding or truncating if (file->compressed && len > file->data_na->initialized_size) { char zero = 0; if (ntfs_attr_pwrite(file->data_na, len - 1, 1, &zero) <= 0) { ntfsUnlock(file->vd); r->_errno = errno; return -1; } } else { if (ntfs_attr_truncate(file->data_na, len)) { ntfsUnlock(file->vd); r->_errno = errno; return -1; } } // Mark the file for archiving (if we actually changed something) if (file->len != file->data_na->data_size) file->ni->flags |= FILE_ATTR_ARCHIVE; // Update file times (if we actually changed something) if (file->len != file->data_na->data_size) ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_AMCTIME); // Update the files data length file->len = file->data_na->data_size; // Sync the file (and its attributes) to disc ntfsSync(file->vd, file->ni); // Unlock ntfsUnlock(file->vd); return 0; }
int ntfsLink (ntfs_vd *vd, const char *old_path, const char *new_path) { ntfs_inode *dir_ni = NULL, *ni = NULL; char *dir = NULL; char *name = NULL; ntfschar *uname = NULL; int uname_len; int res = 0; // Sanity check if (!vd) { errno = ENODEV; return -1; } // You cannot link between devices if(vd != ntfsGetVolume(new_path)) { errno = EXDEV; return -1; } // Get the actual paths of the entry old_path = ntfsRealPath(old_path); new_path = ntfsRealPath(new_path); if (!old_path || !new_path) { errno = EINVAL; return -1; } // Lock ntfsLock(vd); // Get the unicode name for the entry and find its parent directory // TODO: This looks horrible, clean it up dir = strdup(new_path); if (!dir) { errno = EINVAL; goto cleanup; } name = strrchr(dir, '/'); if (name) name++; else name = dir; uname_len = ntfsLocalToUnicode(name, &uname); if (uname_len < 0) { errno = EINVAL; goto cleanup; } *name = 0; // Find the entry ni = ntfsOpenEntry(vd, old_path); if (!ni) { errno = ENOENT; res = -1; goto cleanup; } // Open the entries new parent directory dir_ni = ntfsOpenEntry(vd, dir); if (!dir_ni) { errno = ENOENT; res = -1; goto cleanup; } // Link the entry to its new parent if (ntfs_link(ni, dir_ni, uname, uname_len)) { res = -1; goto cleanup; } // Update entry times ntfsUpdateTimes(vd, dir_ni, NTFS_UPDATE_MCTIME); // Sync the entry to disc ntfsSync(vd, ni); cleanup: if(dir_ni) ntfsCloseEntry(vd, dir_ni); if(ni) ntfsCloseEntry(vd, ni); // use free because the value was not allocated with ntfs_alloc if(uname) free(uname); if(dir) ntfs_free(dir); // Unlock ntfsUnlock(vd); return res; }
ntfs_inode *ntfsCreate (ntfs_vd *vd, const char *path, mode_t type, const char *target) { ntfs_inode *dir_ni = NULL, *ni = NULL; char *dir = NULL; char *name = NULL; ntfschar *uname = NULL, *utarget = NULL; int uname_len, utarget_len; // Sanity check if (!vd) { errno = ENODEV; return NULL; } // You cannot link between devices if(target) { if(vd != ntfsGetVolume(target)) { errno = EXDEV; return NULL; } } // Get the actual paths of the entry path = ntfsRealPath(path); target = ntfsRealPath(target); if (!path) { errno = EINVAL; return NULL; } // Lock ntfsLock(vd); // Get the unicode name for the entry and find its parent directory // TODO: This looks horrible, clean it up dir = strdup(path); if (!dir) { errno = EINVAL; goto cleanup; } name = strrchr(dir, '/'); if (name) name++; else name = dir; uname_len = ntfsLocalToUnicode(name, &uname); if (uname_len < 0) { errno = EINVAL; goto cleanup; } name = strrchr(dir, '/'); if(name) { name++; name[0] = 0; } // Open the entries parent directory dir_ni = ntfsOpenEntry(vd, dir); if (!dir_ni) { goto cleanup; } // Create the entry switch (type) { // Symbolic link case S_IFLNK: if (!target) { errno = EINVAL; goto cleanup; } utarget_len = ntfsLocalToUnicode(target, &utarget); if (utarget_len < 0) { errno = EINVAL; goto cleanup; } ni = ntfs_create_symlink(dir_ni, 0, uname, uname_len, utarget, utarget_len); break; // Directory or file case S_IFDIR: case S_IFREG: ni = ntfs_create(dir_ni, 0, uname, uname_len, type); break; } // If the entry was created if (ni) { // Mark the entry for archiving ni->flags |= FILE_ATTR_ARCHIVE; // Mark the entry as dirty NInoSetDirty(ni); // Sync the entry to disc ntfsSync(vd, ni); // Update parent directories times ntfsUpdateTimes(vd, dir_ni, NTFS_UPDATE_MCTIME); } cleanup: if(dir_ni) ntfsCloseEntry(vd, dir_ni); // use free because the value was not allocated with ntfs_alloc if(utarget) free(utarget); if(uname) free(uname); if(dir) ntfs_free(dir); // Unlock ntfsUnlock(vd); return ni; }