Exemple #1
0
status_t
fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos,
	const void *buffer, size_t *_length)
{
	nspace *ns = (nspace *)_vol->private_volume;
	vnode *node = (vnode *)_node->private_node;
	attrcookie *cookie = (attrcookie *)_cookie;
	ntfs_inode *ni = NULL;
	ntfs_attr *na = NULL;
	size_t  size = *_length;
	char *attr_name = NULL;
	char *real_name = NULL;
	int total = 0;
	status_t result = B_NO_ERROR;

	TRACE("%s - ENTER  vnode: %d\n", __FUNCTION__, node->vnid);
	
	if (ns->flags & B_FS_IS_READONLY) {		
		return B_READ_ONLY_DEVICE;
	}

	if (pos < 0) {
		*_length = 0;
		return EINVAL;
	}

	LOCK_VOL(ns);

	ni = ntfs_inode_open(ns->ntvol, node->vnid);
	if (ni == NULL) {
		result = errno;
		goto exit;
	}
	na = ntfs_attr_open(ni, AT_DATA, cookie->uname, cookie->uname_len);
	if (na == NULL) {
		result = errno;
		goto exit;		
	}		

	pos += sizeof(uint32);

	// it is a named stream
	if (na != NULL) {
		if (cookie->omode & O_APPEND)
			pos = na->data_size;

		if (pos + size > na->data_size) {
			ntfs_mark_free_space_outdated(ns);
			if (ntfs_attr_truncate(na, pos + size))
				size = na->data_size - pos;
			else
				notify_stat_changed(ns->id, MREF(ni->mft_no), B_STAT_SIZE);
		}

		while (size) {
			off_t bytesWritten = ntfs_attr_pwrite(na, pos, size, buffer);
			if (bytesWritten < (s64)size)
				ERROR("%s - ntfs_attr_pwrite returned less bytes than "
					"requested.\n", __FUNCTION__);
			if (bytesWritten <= 0) {
				ERROR("%s - ntfs_attr_pwrite()<=0\n", __FUNCTION__);
				*_length = 0;
				result = EINVAL;
				goto exit;
			}
			size -= bytesWritten;
			pos += bytesWritten;
			total += bytesWritten;
		}

		*_length = total;
	} else {
		*_length = 0;
		result =  EINVAL;
		goto exit;
	}
	
	if (ntfs_ucstombs(na->name, na->name_len, &attr_name, 0) >= 0) {
		if (attr_name != NULL) {
			if(strncmp(attr_name, kHaikuAttrPrefix, strlen(kHaikuAttrPrefix)) !=0 )
				goto exit;
			real_name = attr_name + strlen(kHaikuAttrPrefix);						
			notify_attribute_changed(ns->id, MREF(ni->mft_no),
				real_name, B_ATTR_CHANGED);
			free(attr_name);
		}
	}
		
exit:	
	if (na != NULL)
		ntfs_attr_close(na);
	if (ni != NULL)
		ntfs_inode_close(ni);
		
	TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));

	UNLOCK_VOL(ns);
	
	return result;
}
status_t
fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie,off_t pos,
	const void *buffer, size_t *_length)
{
	nspace *ns = (nspace *)_vol->private_volume;
	//vnode *node = (vnode *)_node->private_node;
	attrcookie *cookie = (attrcookie *)_cookie;
	ntfs_inode *ni = cookie->inode;
	ntfs_attr *na = cookie->stream;
	size_t  size = *_length;
	int total = 0;
	status_t result = B_NO_ERROR;

	TRACE("%s - ENTER!!\n", __FUNCTION__);
	if (ns->flags & B_FS_IS_READONLY) {
		ERROR("ntfs is read-only\n");
		return EROFS;
	}

	if (pos < 0) {
		*_length = 0;
		return EINVAL;
	}


	LOCK_VOL(ns);

	TRACE("%s - ENTER\n", __FUNCTION__);

	// it is a named stream
	if (na) {
		if (cookie->omode & O_APPEND)
			pos = na->data_size;

		if (pos + size > na->data_size) {
			ntfs_mark_free_space_outdated(ns);
			if (ntfs_attr_truncate(na, pos + size))
				size = na->data_size - pos;
			else
				notify_stat_changed(ns->id, MREF(ni->mft_no), B_STAT_SIZE);
		}

		while (size) {
			off_t bytesWritten = ntfs_attr_pwrite(na, pos, size, buffer);
			if (bytesWritten < (s64)size)
				ERROR("%s - ntfs_attr_pwrite returned less bytes than "
					"requested.\n", __FUNCTION__);
			if (bytesWritten <= 0) {
				ERROR(("%s - ntfs_attr_pwrite()<=0\n", __FUNCTION__));
				*_length = 0;
				result = EINVAL;
				goto exit;
			}
			size -= bytesWritten;
			pos += bytesWritten;
			total += bytesWritten;
		}

		*_length = total;
	} else {
		*_length = 0;
		return EINVAL;
	}

	
	if (total > 0)
		fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_ATIME); // XXX needed ?

exit:
	
	TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));

	UNLOCK_VOL(ns);
	
	return result;
}
Exemple #3
0
status_t
fs_mount(fs_volume *_vol, const char *device, ulong flags, const char *args,
	ino_t *_rootID)
{
	nspace *ns;
	vnode *newNode = NULL;
	char lockname[32];
	void *handle;
	unsigned long mountFlags = 0;
	status_t result = B_NO_ERROR;

	ERRPRINT("fs_mount - ENTER\n");

	ns = ntfs_malloc(sizeof(nspace));
	if (!ns) {
		result = ENOMEM;
		goto exit;
	}

	*ns = (nspace) {
		.state = NF_FreeClustersOutdate | NF_FreeMFTOutdate,
		.show_sys_files = false,
		.ro = false,
		.flags = 0
	};

	strcpy(ns->devicePath,device);

	sprintf(lockname, "ntfs_lock %lx", ns->id);
	recursive_lock_init_etc(&(ns->vlock), lockname, MUTEX_FLAG_CLONE_NAME);

	handle = load_driver_settings("ntfs");
	ns->show_sys_files = ! (strcasecmp(get_driver_parameter(handle,
		"hide_sys_files", "true", "true"), "true") == 0);
	ns->ro = strcasecmp(get_driver_parameter(handle, "read_only", "false",
		"false"), "false") != 0;
	ns->noatime = strcasecmp(get_driver_parameter(handle, "no_atime", "true",
		"true"), "true") == 0;
	unload_driver_settings(handle);

	if (ns->ro || (flags & B_MOUNT_READ_ONLY) != 0) {
		mountFlags |= MS_RDONLY;
		ns->flags |= B_FS_IS_READONLY;
	}

	// TODO: this does not take read-only volumes into account!
	ns->ntvol = utils_mount_volume(device, mountFlags, true);
	if (ns->ntvol != NULL)
		result = B_NO_ERROR;
	else
		result = errno;

	if (result == B_NO_ERROR) {
		*_rootID = FILE_root;
		ns->id = _vol->id;
		_vol->private_volume = (void *)ns;
		_vol->ops = &gNTFSVolumeOps;

		newNode = (vnode*)ntfs_calloc(sizeof(vnode));
		if (newNode == NULL)
			result = ENOMEM;
		else {
			newNode->vnid = *_rootID;
			newNode->parent_vnid = -1;

			result = publish_vnode(_vol, *_rootID, (void*)newNode,
				&gNTFSVnodeOps, S_IFDIR, 0);
			if (result != B_NO_ERROR) {
				free(ns);
				result = EINVAL;
				goto exit;
			} else {
				result = B_NO_ERROR;
				ntfs_mark_free_space_outdated(ns);
				ntfs_calc_free_space(ns);
			}
		}
	}

exit:
	ERRPRINT("fs_mount - EXIT, result code is %s\n", strerror(result));

	return result;
}


status_t
fs_unmount(fs_volume *_vol)
{
	nspace *ns = (nspace*)_vol->private_volume;
	status_t result = B_NO_ERROR;

	ERRPRINT("fs_unmount - ENTER\n");

	ntfs_umount(ns->ntvol, true);

	recursive_lock_destroy(&(ns->vlock));

	free(ns);

	ERRPRINT("fs_unmount - EXIT, result is %s\n", strerror(result));

	return result;
}