Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
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;
}
Esempio n. 7
0
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;
}