1/*
2 * Copyright 2021, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Augustin Cavalier <waddlesplash>
7 */
8
9#include <dirent.h>
10#include <unistd.h>
11#include <util/kernel_cpp.h>
12#include <string.h>
13
14#include <AutoDeleter.h>
15#include <fs_cache.h>
16#include <fs_info.h>
17#include <vfs.h>
18#include <NodeMonitor.h>
19#include <file_systems/DeviceOpener.h>
20#include <file_systems/fs_ops_support.h>
21#include <util/AutoLock.h>
22
23#include "ntfs.h"
24
25extern "C" {
26#include "libntfs/bootsect.h"
27#include "libntfs/dir.h"
28#include "utils/utils.h"
29}
30
31//#define TRACE_NTFS
32#ifdef TRACE_NTFS
33#	define TRACE(X...)	dprintf("ntfs: " X)
34#else
35#	define TRACE(X...) ;
36#endif
37#define CALLED()		TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
38#define ERROR(X...)		dprintf("ntfs: error: " X)
39
40
41struct identify_cookie {
42	NTFS_BOOT_SECTOR boot;
43};
44
45extern "C" int mkntfs_main(const char* devpath, const char* label);
46
47typedef CObjectDeleter<ntfs_inode, int, ntfs_inode_close> NtfsInodeCloser;
48typedef CObjectDeleter<ntfs_attr, void, ntfs_attr_close> NtfsAttrCloser;
49static status_t fs_access(fs_volume* _volume, fs_vnode* _node, int accessMode);
50
51
52//	#pragma mark - Scanning
53
54
55static float
56fs_identify_partition(int fd, partition_data* partition, void** _cookie)
57{
58	CALLED();
59
60	NTFS_BOOT_SECTOR boot;
61	if (read_pos(fd, 0, (void*)&boot, 512) != 512) {
62		ERROR("identify_partition: failed to read boot sector\n");
63		return -1;
64	}
65
66	if (!ntfs_boot_sector_is_ntfs(&boot)) {
67		ERROR("identify_partition: boot signature doesn't match\n");
68		return -1;
69	}
70
71	identify_cookie* cookie = new identify_cookie;
72	if (cookie == NULL) {
73		ERROR("identify_partition: cookie allocation failed\n");
74		return -1;
75	}
76
77	memcpy(&cookie->boot, &boot, sizeof(boot));
78	*_cookie = cookie;
79
80	// This value overrides the Intel partition identifier.
81	return 0.82f;
82}
83
84
85static status_t
86fs_scan_partition(int fd, partition_data* partition, void* _cookie)
87{
88	CALLED();
89
90	identify_cookie *cookie = (identify_cookie*)_cookie;
91	partition->status = B_PARTITION_VALID;
92	partition->flags |= B_PARTITION_FILE_SYSTEM;
93	partition->content_size = sle64_to_cpu(cookie->boot.number_of_sectors)
94		* le16_to_cpu(cookie->boot.bpb.bytes_per_sector);
95	partition->block_size = le16_to_cpu(cookie->boot.bpb.bytes_per_sector);
96
97	// get volume name
98	ntfs_volume* ntVolume;
99	char path[B_PATH_NAME_LENGTH];
100	if (ioctl(fd, B_GET_PATH_FOR_DEVICE, path) != 0) {
101		ntVolume = utils_mount_volume(path, NTFS_MNT_RDONLY | NTFS_MNT_RECOVER);
102		if (ntVolume == NULL)
103			return errno ? errno : B_ERROR;
104
105		if (ntVolume->vol_name != NULL && ntVolume->vol_name[0] != '\0')
106			partition->content_name = strdup(ntVolume->vol_name);
107		else
108			partition->content_name = strdup("");
109		ntfs_umount(ntVolume, true);
110	}
111
112	return partition->content_name != NULL ? B_OK : B_NO_MEMORY;
113}
114
115
116static void
117fs_free_identify_partition_cookie(partition_data* partition, void* _cookie)
118{
119	CALLED();
120
121	delete (identify_cookie*)_cookie;
122}
123
124
125//	#pragma mark -
126
127
128static status_t
129fs_initialize(int fd, partition_id partitionID, const char* name,
130	const char* parameterString, off_t partitionSize, disk_job_id job)
131{
132	TRACE("fs_initialize: '%s', %s\n", name, parameterString);
133
134	update_disk_device_job_progress(job, 0);
135
136	char path[B_PATH_NAME_LENGTH];
137	if (ioctl(fd, B_GET_PATH_FOR_DEVICE, path) == 0)
138		return B_BAD_VALUE;
139
140	status_t result = mkntfs_main(path, name);
141	if (result != 0)
142		return result;
143
144	result = scan_partition(partitionID);
145	if (result != B_OK)
146		return result;
147
148	update_disk_device_job_progress(job, 1);
149	return B_OK;
150}
151
152
153static status_t
154fs_mount(fs_volume* _volume, const char* device, uint32 flags,
155	const char* args, ino_t* _rootID)
156{
157	CALLED();
158
159	volume* volume = new struct volume;
160	vnode* root = new vnode;
161	if (volume == NULL || root == NULL)
162		return B_NO_MEMORY;
163	ObjectDeleter<struct volume> volumeDeleter(volume);
164
165	mutex_init(&volume->lock, "NTFS volume lock");
166	volume->fs_info_flags = B_FS_IS_PERSISTENT;
167
168	unsigned long ntfsFlags = NTFS_MNT_RECOVER | NTFS_MNT_MAY_RDONLY;
169	if ((flags & B_MOUNT_READ_ONLY) != 0 || DeviceOpener(device, O_RDWR).IsReadOnly())
170		ntfsFlags |= NTFS_MNT_RDONLY;
171
172	// mount
173	volume->ntfs = utils_mount_volume(device, ntfsFlags);
174	if (volume->ntfs == NULL)
175		return errno;
176
177	if (NVolReadOnly(volume->ntfs)) {
178		if ((ntfsFlags & NTFS_MNT_RDONLY) == 0)
179			ERROR("volume is hibernated, mounted as read-only\n");
180		volume->fs_info_flags |= B_FS_IS_READONLY;
181	}
182
183	if (ntfs_volume_get_free_space(volume->ntfs) != 0) {
184		ntfs_umount(volume->ntfs, true);
185		return B_ERROR;
186	}
187
188	const bool showSystem = false, showHidden = true, hideDot = false;
189	if (ntfs_set_shown_files(volume->ntfs, showSystem, showHidden, hideDot) != 0) {
190		ntfs_umount(volume->ntfs, true);
191		return B_ERROR;
192	}
193
194	// Fetch mount path, used when reading NTFS symlinks.
195	dev_t deviceID;
196	ino_t nodeID;
197	status_t status = vfs_get_mount_point(_volume->id, &deviceID, &nodeID);
198	char* mountpoint;
199	if (status == B_OK) {
200		mountpoint = (char*)malloc(PATH_MAX);
201		status = vfs_entry_ref_to_path(deviceID, nodeID, NULL, true,
202			mountpoint, PATH_MAX);
203		if (status == B_OK) {
204			char* reallocated = (char*)realloc(mountpoint, strlen(mountpoint) + 1);
205			if (reallocated != NULL)
206				mountpoint = reallocated;
207		} else {
208			free(mountpoint);
209			mountpoint = NULL;
210		}
211	}
212	if (status != B_OK)
213		mountpoint = strdup("");
214
215	// TODO: uid/gid mapping and real permissions
216
217	// construct lowntfs_context
218	volume->lowntfs.haiku_fs_volume = _volume;
219	volume->lowntfs.current_close_state_vnode = NULL;
220
221	volume->lowntfs.vol = volume->ntfs;
222	volume->ntfs->abs_mnt_point = volume->lowntfs.abs_mnt_point = mountpoint;
223	volume->lowntfs.dmask = 0;
224	volume->lowntfs.fmask = S_IXUSR | S_IXGRP | S_IXOTH;
225	volume->lowntfs.dmtime = 0;
226	volume->lowntfs.special_files = NTFS_FILES_INTERIX;
227	volume->lowntfs.posix_nlink = 0;
228	volume->lowntfs.inherit = 0;
229	volume->lowntfs.windows_names = 1;
230	volume->lowntfs.latest_ghost = 0;
231
232	*_rootID = root->inode = FILE_root;
233	root->parent_inode = (u64)-1;
234	root->mode = S_IFDIR | ACCESSPERMS;
235	root->uid = root->gid = 0;
236	root->size = 0;
237
238	status = publish_vnode(_volume, root->inode, root, &gNtfsVnodeOps, S_IFDIR, 0);
239	if (status != B_OK) {
240		ntfs_umount(volume->ntfs, true);
241		return status;
242	}
243
244	volumeDeleter.Detach();
245
246	_volume->private_volume = volume;
247	_volume->ops = &gNtfsVolumeOps;
248	return B_OK;
249}
250
251
252static status_t
253fs_unmount(fs_volume* _volume)
254{
255	CALLED();
256	volume* volume = (struct volume*)_volume->private_volume;
257
258	if (ntfs_umount(volume->ntfs, false) < 0)
259		return errno;
260
261	delete volume;
262	_volume->private_volume = NULL;
263
264	return B_OK;
265}
266
267
268static status_t
269fs_read_fs_info(fs_volume* _volume, struct fs_info* info)
270{
271	CALLED();
272	volume* volume = (struct volume*)_volume->private_volume;
273	MutexLocker lock(volume->lock);
274
275	info->flags = volume->fs_info_flags;
276	info->block_size = volume->ntfs->cluster_size;
277	info->total_blocks = volume->ntfs->nr_clusters;
278	info->free_blocks = volume->ntfs->free_clusters;
279
280	info->io_size = 65536;
281
282	strlcpy(info->volume_name, volume->ntfs->vol_name, sizeof(info->volume_name));
283	strlcpy(info->fsh_name, "NTFS", sizeof(info->fsh_name));
284
285	return B_OK;
286}
287
288
289static status_t
290fs_write_fs_info(fs_volume* _volume, const struct fs_info* info, uint32 mask)
291{
292	CALLED();
293	volume* volume = (struct volume*)_volume->private_volume;
294	MutexLocker lock(volume->lock);
295
296	if ((volume->fs_info_flags & B_FS_IS_READONLY) != 0)
297		return B_READ_ONLY_DEVICE;
298
299	status_t status = B_OK;
300
301	if ((mask & FS_WRITE_FSINFO_NAME) != 0) {
302		ntfschar* label = NULL;
303		int label_len = ntfs_mbstoucs(info->volume_name, &label);
304		if (label_len <= 0 || label == NULL)
305			return -1;
306		MemoryDeleter nameDeleter(label);
307
308		if (ntfs_volume_rename(volume->ntfs, label, label_len) != 0)
309			status = errno;
310	}
311
312	return status;
313}
314
315
316//	#pragma mark -
317
318
319static status_t
320fs_init_vnode(fs_volume* _volume, ino_t parent, ino_t nid, vnode** _vnode, bool publish = false)
321{
322	volume* volume = (struct volume*)_volume->private_volume;
323	ASSERT_LOCKED_MUTEX(&volume->lock);
324
325	ntfs_inode* ni = ntfs_inode_open(volume->ntfs, nid);
326	if (ni == NULL)
327		return ENOENT;
328	NtfsInodeCloser niCloser(ni);
329
330	vnode* node = new vnode;
331	if (node == NULL)
332		return B_NO_MEMORY;
333	ObjectDeleter<vnode> vnodeDeleter(node);
334
335	struct stat statbuf;
336	if (ntfs_fuse_getstat(&volume->lowntfs, NULL, ni, &statbuf) != 0)
337		return errno;
338
339	node->inode = nid;
340	node->parent_inode = parent;
341	node->uid = statbuf.st_uid;
342	node->gid = statbuf.st_gid;
343	node->mode = statbuf.st_mode;
344	node->size = statbuf.st_size;
345
346	// cache the node's name
347	char path[B_FILE_NAME_LENGTH];
348	if (utils_inode_get_name(ni, path, sizeof(path)) == 0)
349		return B_NO_MEMORY;
350	node->name = strdup(strrchr(path, '/') + 1);
351
352	if (publish) {
353		status_t status = publish_vnode(_volume, node->inode, node, &gNtfsVnodeOps, node->mode, 0);
354		if (status != B_OK)
355			return status;
356	}
357
358	if ((node->mode & S_IFDIR) == 0) {
359		node->file_cache = file_cache_create(_volume->id, nid, node->size);
360		if (node->file_cache == NULL)
361			return B_NO_INIT;
362	}
363
364	vnodeDeleter.Detach();
365	*_vnode = node;
366	return B_OK;
367}
368
369
370static status_t
371fs_get_vnode(fs_volume* _volume, ino_t nid, fs_vnode* _node, int* _type,
372	uint32* _flags, bool reenter)
373{
374	TRACE("get_vnode %" B_PRIdINO "\n", nid);
375	volume* volume = (struct volume*)_volume->private_volume;
376	MutexLocker lock(reenter ? NULL : &volume->lock);
377
378	vnode* vnode;
379	status_t status = fs_init_vnode(_volume, -1 /* set by fs_lookup */, nid, &vnode);
380	if (status != B_OK)
381		return status;
382
383	_node->private_node = vnode;
384	_node->ops = &gNtfsVnodeOps;
385	*_type = vnode->mode;
386	*_flags = 0;
387
388	return B_OK;
389}
390
391
392static status_t
393fs_put_vnode(fs_volume* _volume, fs_vnode* _node, bool reenter)
394{
395	CALLED();
396	volume* volume = (struct volume*)_volume->private_volume;
397	MutexLocker lock(reenter ? NULL : &volume->lock);
398	vnode* node = (vnode*)_node->private_node;
399
400	file_cache_delete(node->file_cache);
401	delete node;
402	return B_OK;
403}
404
405
406static status_t
407fs_remove_vnode(fs_volume* _volume, fs_vnode* _node, bool reenter)
408{
409	CALLED();
410	volume* volume = (struct volume*)_volume->private_volume;
411	MutexLocker lock(reenter ? NULL : &volume->lock);
412	vnode* node = (vnode*)_node->private_node;
413
414	if (ntfs_fuse_release(&volume->lowntfs, node->parent_inode, node->inode,
415			node->lowntfs_close_state, node->lowntfs_ghost) != 0)
416		return errno;
417
418	file_cache_delete(node->file_cache);
419	delete node;
420	return B_OK;
421}
422
423
424int*
425ntfs_haiku_get_close_state(struct lowntfs_context *ctx, u64 ino)
426{
427	if (ctx->current_close_state_vnode != NULL)
428		panic("NTFS current_close_state_vnode should be NULL!");
429
430	vnode* node = NULL;
431	if (get_vnode((fs_volume*)ctx->haiku_fs_volume, ino, (void**)&node) != B_OK)
432		return NULL;
433	ctx->current_close_state_vnode = node;
434	return &node->lowntfs_close_state;
435}
436
437
438void
439ntfs_haiku_put_close_state(struct lowntfs_context *ctx, u64 ino, u64 ghost)
440{
441	vnode* node = (vnode*)ctx->current_close_state_vnode;
442	if (node == NULL)
443		return;
444
445	node->lowntfs_ghost = ghost;
446	if ((node->lowntfs_close_state & CLOSE_GHOST) != 0) {
447		fs_volume* _volume = (fs_volume*)ctx->haiku_fs_volume;
448		entry_cache_remove(_volume->id, node->parent_inode, node->name);
449		notify_entry_removed(_volume->id, node->parent_inode, node->name, node->inode);
450		remove_vnode(_volume, node->inode);
451	}
452
453	ctx->current_close_state_vnode = NULL;
454	put_vnode((fs_volume*)ctx->haiku_fs_volume, node->inode);
455}
456
457
458static bool
459fs_can_page(fs_volume* _volume, fs_vnode* _node, void* _cookie)
460{
461	return true;
462}
463
464
465static status_t
466fs_read_pages(fs_volume* _volume, fs_vnode* _node, void* _cookie,
467	off_t pos, const iovec* vecs, size_t count, size_t* _numBytes)
468{
469	volume* volume = (struct volume*)_volume->private_volume;
470	MutexLocker lock(volume->lock);
471	vnode* node = (vnode*)_node->private_node;
472
473	TRACE("read_pages inode: %" B_PRIdINO", pos: %" B_PRIdOFF "; vecs: %p; "
474		"count: %" B_PRIuSIZE "; numBytes: %" B_PRIuSIZE "\n", node->inode, pos,
475		vecs, count, *_numBytes);
476
477	ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode);
478	if (ni == NULL)
479		return B_FILE_ERROR;
480	NtfsInodeCloser niCloser(ni);
481
482	if (pos < 0 || pos >= ni->data_size)
483		return B_BAD_VALUE;
484
485	size_t bytesLeft = min_c(*_numBytes, size_t(ni->data_size - pos));
486	*_numBytes = 0;
487	for (size_t i = 0; i < count && bytesLeft > 0; i++) {
488		const size_t ioSize = min_c(bytesLeft, vecs[i].iov_len);
489		const int read = ntfs_fuse_read(ni, pos, (char*)vecs[i].iov_base, ioSize);
490		if (read < 0)
491			return errno;
492
493		pos += read;
494		*_numBytes += read;
495		bytesLeft -= read;
496
497		if (size_t(read) != ioSize)
498			return errno;
499	}
500
501	return B_OK;
502}
503
504
505static status_t
506fs_write_pages(fs_volume* _volume, fs_vnode* _node, void* _cookie,
507	off_t pos, const iovec* vecs, size_t count, size_t* _numBytes)
508{
509	volume* volume = (struct volume*)_volume->private_volume;
510	MutexLocker lock(volume->lock);
511	vnode* node = (vnode*)_node->private_node;
512
513	TRACE("write_pages inode: %" B_PRIdINO", pos: %" B_PRIdOFF "; vecs: %p; "
514		"count: %" B_PRIuSIZE "; numBytes: %" B_PRIuSIZE "\n", node->inode, pos,
515		vecs, count, *_numBytes);
516
517	ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode);
518	if (ni == NULL)
519		return B_FILE_ERROR;
520	NtfsInodeCloser niCloser(ni);
521
522	if (pos < 0 || pos >= ni->data_size)
523		return B_BAD_VALUE;
524
525	size_t bytesLeft = min_c(*_numBytes, size_t(ni->data_size - pos));
526	*_numBytes = 0;
527	for (size_t i = 0; i < count && bytesLeft > 0; i++) {
528		const size_t ioSize = min_c(bytesLeft, vecs[i].iov_len);
529		const int written = ntfs_fuse_write(&volume->lowntfs, ni, (char*)vecs[i].iov_base, ioSize, pos);
530		if (written < 0)
531			return errno;
532
533		pos += written;
534		*_numBytes += written;
535		bytesLeft -= written;
536
537		if (size_t(written) != ioSize)
538			return errno;
539	}
540
541	return B_OK;
542}
543
544
545//	#pragma mark -
546
547
548static status_t
549fs_lookup(fs_volume* _volume, fs_vnode* _directory, const char* name,
550	ino_t* _vnodeID)
551{
552	TRACE("fs_lookup: name address: %p (%s)\n", name, name);
553	volume* volume = (struct volume*)_volume->private_volume;
554	MutexLocker lock(volume->lock);
555	vnode* directory = (vnode*)_directory->private_node;
556
557	status_t result;
558	if (strcmp(name, ".") == 0) {
559		*_vnodeID = directory->inode;
560	} else if (strcmp(name, "..") == 0) {
561		if (directory->inode == FILE_root)
562			return ENOENT;
563		*_vnodeID = directory->parent_inode;
564	} else {
565		u64 inode = ntfs_fuse_inode_lookup(&volume->lowntfs, directory->inode, name);
566		if (inode == (u64)-1)
567			return errno;
568		*_vnodeID = inode;
569	}
570
571	result = entry_cache_add(_volume->id, directory->inode, name, *_vnodeID);
572	if (result != B_OK)
573		return result;
574
575	vnode* node = NULL;
576	result = get_vnode(_volume, *_vnodeID, (void**)&node);
577	if (result != B_OK)
578		return result;
579
580	if (node->parent_inode == (u64)-1)
581		node->parent_inode = directory->inode;
582
583	TRACE("fs_lookup: ID %" B_PRIdINO "\n", *_vnodeID);
584	return B_OK;
585}
586
587
588static status_t
589fs_get_vnode_name(fs_volume* _volume, fs_vnode* _node, char* buffer, size_t bufferSize)
590{
591	// CALLED();
592	vnode* node = (vnode*)_node->private_node;
593
594	if (strlcpy(buffer, node->name, bufferSize) >= bufferSize)
595		return B_BUFFER_OVERFLOW;
596	return B_OK;
597}
598
599
600static status_t
601fs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd,
602	void* buffer, size_t bufferLength)
603{
604	// TODO?
605	return B_DEV_INVALID_IOCTL;
606}
607
608
609static status_t
610fs_read_stat(fs_volume* _volume, fs_vnode* _node, struct stat* stat)
611{
612	CALLED();
613	volume* volume = (struct volume*)_volume->private_volume;
614	MutexLocker lock(volume->lock);
615	vnode* node = (vnode*)_node->private_node;
616
617	ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode);
618	if (ni == NULL)
619		return errno;
620	NtfsInodeCloser niCloser(ni);
621
622	if (ntfs_fuse_getstat(&volume->lowntfs, NULL, ni, stat) != 0)
623		return errno;
624	return B_OK;
625}
626
627
628static status_t
629fs_write_stat(fs_volume* _volume, fs_vnode* _node, const struct stat* stat, uint32 mask)
630{
631	CALLED();
632	volume* volume = (struct volume*)_volume->private_volume;
633	MutexLocker lock(volume->lock);
634	vnode* node = (vnode*)_node->private_node;
635
636	if ((volume->fs_info_flags & B_FS_IS_READONLY) != 0)
637		return B_READ_ONLY_DEVICE;
638
639	ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode);
640	if (ni == NULL)
641		return B_FILE_ERROR;
642	NtfsInodeCloser niCloser(ni);
643
644	bool updateTime = false;
645	const uid_t euid = geteuid();
646
647	const bool isOwnerOrRoot = (euid == 0 || euid == (uid_t)node->uid);
648	const bool hasWriteAccess = fs_access(_volume, _node, W_OK);
649
650	if ((mask & B_STAT_SIZE) != 0 && node->size != stat->st_size) {
651		if ((node->mode & S_IFDIR) != 0)
652			return B_IS_A_DIRECTORY;
653		if (!hasWriteAccess)
654			return B_NOT_ALLOWED;
655
656		ntfs_attr* na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
657		if (na == NULL)
658			return errno;
659		NtfsAttrCloser naCloser(na);
660
661		if (ntfs_attr_truncate(na, stat->st_size) != 0)
662			return errno;
663		node->size = na->data_size;
664		file_cache_set_size(node->file_cache, node->size);
665
666		updateTime = true;
667	}
668
669	if ((mask & B_STAT_UID) != 0) {
670		// only root should be allowed
671		if (euid != 0)
672			return B_NOT_ALLOWED;
673
674		// We don't support this (yet.)
675		if (node->uid != stat->st_uid)
676			return B_UNSUPPORTED;
677	}
678
679	if ((mask & B_STAT_GID) != 0) {
680		// only the user or root can do that
681		if (!isOwnerOrRoot)
682			return B_NOT_ALLOWED;
683
684		// We don't support this (yet.)
685		if (node->gid != stat->st_gid)
686			return B_UNSUPPORTED;
687	}
688
689	if ((mask & B_STAT_MODE) != 0) {
690		// only the user or root can do that
691		if (!isOwnerOrRoot)
692			return B_NOT_ALLOWED;
693
694		// We don't support this (yet.)
695		if (node->mode != stat->st_mode)
696			return B_UNSUPPORTED;
697	}
698
699	if ((mask & B_STAT_CREATION_TIME) != 0) {
700		// the user or root can do that or any user with write access
701		if (!isOwnerOrRoot && !hasWriteAccess)
702			return B_NOT_ALLOWED;
703
704		ni->creation_time = timespec2ntfs(stat->st_crtim);
705	}
706
707	if ((mask & B_STAT_MODIFICATION_TIME) != 0) {
708		// the user or root can do that or any user with write access
709		if (!isOwnerOrRoot && !hasWriteAccess)
710			return B_NOT_ALLOWED;
711
712		ni->last_data_change_time = timespec2ntfs(stat->st_mtim);
713	}
714
715	if ((mask & B_STAT_CHANGE_TIME) != 0 || updateTime) {
716		// the user or root can do that or any user with write access
717		if (!isOwnerOrRoot && !hasWriteAccess)
718			return B_NOT_ALLOWED;
719
720		ni->last_mft_change_time = timespec2ntfs(stat->st_ctim);
721	}
722
723	if ((mask & B_STAT_ACCESS_TIME) != 0) {
724		// the user or root can do that or any user with write access
725		if (!isOwnerOrRoot && !hasWriteAccess)
726			return B_NOT_ALLOWED;
727
728		ni->last_access_time = timespec2ntfs(stat->st_atim);
729	}
730
731	ntfs_inode_mark_dirty(ni);
732
733	notify_stat_changed(_volume->id, node->parent_inode, node->inode, mask);
734	return B_OK;
735}
736
737
738static status_t
739fs_generic_create(fs_volume* _volume, vnode* directory, const char* name, int mode,
740	ino_t* _inode)
741{
742	volume* volume = (struct volume*)_volume->private_volume;
743	ASSERT_LOCKED_MUTEX(&volume->lock);
744
745	if ((directory->mode & S_IFDIR) == 0)
746		return B_BAD_TYPE;
747
748	ino_t inode = -1;
749	if (ntfs_fuse_create(&volume->lowntfs, directory->inode, name, mode & (S_IFMT | 07777),
750			0, (char*)NULL, &inode) != 0)
751		return errno;
752
753	vnode* node;
754	status_t status = fs_init_vnode(_volume, directory->inode, inode, &node, true);
755	if (status != B_OK)
756		return status;
757
758	entry_cache_add(_volume->id, directory->inode, name, inode);
759	notify_entry_created(_volume->id, directory->inode, name, inode);
760	*_inode = inode;
761	return B_OK;
762}
763
764
765static status_t
766fs_create(fs_volume* _volume, fs_vnode* _directory, const char* name,
767	int openMode, int mode, void** _cookie, ino_t* _vnodeID)
768{
769	CALLED();
770	volume* volume = (struct volume*)_volume->private_volume;
771	MutexLocker lock(volume->lock);
772	vnode* directory = (vnode*)_directory->private_node;
773
774	if ((directory->mode & S_IFDIR) == 0)
775		return B_NOT_A_DIRECTORY;
776
777	status_t status = fs_access(_volume, _directory, W_OK);
778	if (status != B_OK)
779		return status;
780
781#if 1
782	if ((openMode & O_NOCACHE) != 0)
783		return B_UNSUPPORTED;
784#endif
785
786	status = fs_generic_create(_volume, directory, name, S_IFREG | (mode & 07777), _vnodeID);
787	if (status != B_OK)
788		return status;
789
790	file_cookie* cookie = new file_cookie;
791	if (cookie == NULL)
792		return B_NO_MEMORY;
793	ObjectDeleter<file_cookie> cookieDeleter(cookie);
794
795	cookie->open_mode = openMode;
796
797	cookieDeleter.Detach();
798	*_cookie = cookie;
799	return B_OK;
800}
801
802
803static status_t
804fs_open(fs_volume* _volume, fs_vnode* _node, int openMode, void** _cookie)
805{
806	CALLED();
807	volume* volume = (struct volume*)_volume->private_volume;
808	MutexLocker lock(volume->lock);
809	vnode* node = (vnode*)_node->private_node;
810
811	// opening a directory read-only is allowed (but no data can be read)
812	if ((node->mode & S_IFDIR) != 0 && (openMode & O_RWMASK) != 0)
813		return B_IS_A_DIRECTORY;
814	if ((openMode & O_DIRECTORY) != 0 && (node->mode & S_IFDIR) == 0)
815		return B_NOT_A_DIRECTORY;
816
817	status_t status = fs_access(_volume, _node, open_mode_to_access(openMode));
818	if (status != B_OK)
819		return status;
820
821	ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode);
822	if (ni == NULL)
823		return errno;
824	NtfsInodeCloser niCloser(ni);
825
826	file_cookie* cookie = new file_cookie;
827	if (cookie == NULL)
828		return B_NO_MEMORY;
829	ObjectDeleter<file_cookie> cookieDeleter(cookie);
830
831	cookie->open_mode = openMode;
832
833	// We don't actually support uncached mode; it would require us to handle
834	// passing user buffers to libntfs, among other things.
835#if 0
836	if ((openMode & O_NOCACHE) != 0 && node->file_cache != NULL) {
837		status_t status = file_cache_disable(node->file_cache);
838		if (status != B_OK)
839			return status;
840	}
841#else
842	if ((openMode & O_NOCACHE) != 0)
843		return B_UNSUPPORTED;
844#endif
845
846	if ((openMode & O_TRUNC) != 0) {
847		if ((openMode & O_RWMASK) == O_RDONLY)
848			return B_NOT_ALLOWED;
849
850		ntfs_attr* na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
851		if (na == NULL)
852			return errno;
853		NtfsAttrCloser naCloser(na);
854
855		if (ntfs_attr_truncate(na, 0) != 0)
856			return errno;
857		node->size = na->data_size;
858		file_cache_set_size(node->file_cache, node->size);
859	}
860
861	cookieDeleter.Detach();
862	*_cookie = cookie;
863	return B_OK;
864}
865
866
867static status_t
868fs_read(fs_volume* _volume, fs_vnode* _node, void* _cookie, off_t pos,
869	void* buffer, size_t* length)
870{
871	vnode* node = (vnode*)_node->private_node;
872	file_cookie* cookie = (file_cookie*)_cookie;
873
874	if ((node->mode & S_IFDIR) != 0)
875		return B_IS_A_DIRECTORY;
876
877	ASSERT((cookie->open_mode & O_RWMASK) == O_RDONLY || (cookie->open_mode & O_RDWR) != 0);
878
879	return file_cache_read(node->file_cache, cookie, pos, buffer, length);
880}
881
882
883static status_t
884fs_write(fs_volume* _volume, fs_vnode* _node, void* _cookie, off_t pos,
885	const void* buffer, size_t* _length)
886{
887	CALLED();
888	volume* volume = (struct volume*)_volume->private_volume;
889	MutexLocker lock(volume->lock);
890	vnode* node = (vnode*)_node->private_node;
891	file_cookie* cookie = (file_cookie*)_cookie;
892
893	if ((node->mode & S_IFDIR) != 0)
894		return B_IS_A_DIRECTORY;
895
896	ASSERT((cookie->open_mode & O_WRONLY) != 0 || (cookie->open_mode & O_RDWR) != 0);
897
898	if (cookie->open_mode & O_APPEND)
899		pos = node->size;
900	if (pos < 0)
901		return B_BAD_VALUE;
902
903	if (pos + s64(*_length) > node->size) {
904		ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode);
905		if (ni == NULL)
906			return errno;
907		NtfsInodeCloser niCloser(ni);
908
909		ntfs_attr* na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
910		if (na == NULL)
911			return errno;
912		NtfsAttrCloser naCloser(na);
913
914		if (ntfs_attr_truncate(na, pos + *_length) != 0)
915			return errno;
916		node->size = na->data_size;
917		file_cache_set_size(node->file_cache, node->size);
918	}
919
920	lock.Unlock();
921
922	status_t status = file_cache_write(node->file_cache, cookie, pos, buffer, _length);
923	if (status != B_OK)
924		return status;
925
926	lock.Lock();
927
928	// periodically notify if the file size has changed
929	if ((node->lowntfs_close_state & CLOSE_GHOST) == 0
930			&& cookie->last_size != node->size
931			&& system_time() > cookie->last_notification + INODE_NOTIFICATION_INTERVAL) {
932		notify_stat_changed(_volume->id, node->parent_inode, node->inode,
933			B_STAT_MODIFICATION_TIME | B_STAT_SIZE | B_STAT_INTERIM_UPDATE);
934		cookie->last_size = node->size;
935		cookie->last_notification = system_time();
936	}
937	return status;
938}
939
940
941static status_t
942fs_fsync(fs_volume* _volume, fs_vnode* _node)
943{
944	CALLED();
945	vnode* node = (vnode*)_node->private_node;
946
947	return file_cache_sync(node->file_cache);
948}
949
950
951static status_t
952fs_close(fs_volume *_volume, fs_vnode *_node, void *_cookie)
953{
954	CALLED();
955
956	// Nothing to do.
957	return B_OK;
958}
959
960
961static status_t
962fs_free_cookie(fs_volume* _volume, fs_vnode* _node, void* _cookie)
963{
964	file_cookie* cookie = (file_cookie*)_cookie;
965	delete cookie;
966	return B_OK;
967}
968
969
970static status_t
971fs_generic_unlink(fs_volume* _volume, fs_vnode* _directory, const char* name, RM_TYPES type)
972{
973	volume* volume = (struct volume*)_volume->private_volume;
974	MutexLocker lock(volume->lock);
975	vnode* directory = (vnode*)_directory->private_node;
976
977	status_t status = fs_access(_volume, _directory, W_OK);
978	if (status != B_OK)
979		return status;
980
981	if (ntfs_fuse_rm(&volume->lowntfs, directory->inode, name, type) != 0)
982		return errno;
983
984	// remove_vnode() et al. will be called by put_close_state.
985	return B_OK;
986}
987
988
989static status_t
990fs_unlink(fs_volume* _volume, fs_vnode* _directory, const char* name)
991{
992	CALLED();
993	return fs_generic_unlink(_volume, _directory, name, RM_LINK);
994}
995
996
997static status_t
998fs_rename(fs_volume* _volume, fs_vnode* _oldDir, const char* oldName,
999	fs_vnode* _newDir, const char* newName)
1000{
1001	CALLED();
1002	volume* volume = (struct volume*)_volume->private_volume;
1003	MutexLocker lock(volume->lock);
1004
1005	vnode* old_directory = (vnode*)_oldDir->private_node;
1006	vnode* new_directory = (vnode*)_newDir->private_node;
1007
1008	if (old_directory == new_directory && strcmp(oldName, newName) == 0)
1009		return B_OK;
1010
1011	status_t status = fs_access(_volume, _oldDir, W_OK);
1012	if (status == B_OK)
1013		status = fs_access(_volume, _newDir, W_OK);
1014	if (status != B_OK)
1015		return status;
1016
1017	// Prevent moving a directory into one of its own children.
1018	if (old_directory != new_directory) {
1019		u64 oldIno = ntfs_fuse_inode_lookup(&volume->lowntfs, old_directory->inode, oldName);
1020		if (oldIno == (u64)-1)
1021			return B_ENTRY_NOT_FOUND;
1022
1023		ino_t parent = new_directory->inode;
1024		const ino_t root = FILE_root;
1025
1026		while (true) {
1027			if (parent == oldIno)
1028				return B_BAD_VALUE;
1029			else if (parent == root || parent == old_directory->inode)
1030				break;
1031
1032			vnode* parentNode;
1033			if (get_vnode(_volume, parent, (void**)&parentNode) != B_OK)
1034				return B_ERROR;
1035
1036			parent = parentNode->parent_inode;
1037			put_vnode(_volume, parentNode->inode);
1038		}
1039	}
1040
1041	if (ntfs_fuse_rename(&volume->lowntfs, old_directory->inode, oldName,
1042			new_directory->inode, newName) != 0)
1043		return errno;
1044
1045	u64 ino = ntfs_fuse_inode_lookup(&volume->lowntfs, new_directory->inode, newName);
1046	if (ino == (u64)-1)
1047		return B_ENTRY_NOT_FOUND;
1048
1049	vnode* node;
1050	status = get_vnode(_volume, ino, (void**)&node);
1051	if (status != B_OK)
1052		return status;
1053
1054	free(node->name);
1055	node->name = strdup(newName);
1056	node->parent_inode = new_directory->inode;
1057
1058	if ((node->mode & S_IFDIR) != 0)
1059		entry_cache_add(_volume->id, ino, "..", new_directory->inode);
1060
1061	put_vnode(_volume, ino);
1062
1063	entry_cache_remove(_volume->id, old_directory->inode, oldName);
1064	entry_cache_add(_volume->id, new_directory->inode, newName, ino);
1065	notify_entry_moved(_volume->id, old_directory->inode, oldName,
1066		new_directory->inode, newName, ino);
1067
1068	return B_OK;
1069}
1070
1071
1072static status_t
1073fs_access(fs_volume* _volume, fs_vnode* _node, int accessMode)
1074{
1075	// CALLED();
1076	volume* volume = (struct volume*)_volume->private_volume;
1077	vnode* node = (vnode*)_node->private_node;
1078
1079	if ((accessMode & W_OK) != 0 && (volume->fs_info_flags & B_FS_IS_READONLY) != 0)
1080		return B_READ_ONLY_DEVICE;
1081
1082	return check_access_permissions(accessMode, node->mode, node->gid, node->uid);
1083}
1084
1085
1086static status_t
1087fs_read_link(fs_volume* _volume, fs_vnode* _node, char* buffer, size_t* bufferSize)
1088{
1089	CALLED();
1090	volume* volume = (struct volume*)_volume->private_volume;
1091	MutexLocker lock(volume->lock);
1092	vnode* node = (vnode*)_node->private_node;
1093
1094	if (ntfs_fuse_readlink(&volume->lowntfs, node->inode, buffer, bufferSize) != 0)
1095		return errno;
1096	return B_OK;
1097}
1098
1099
1100//	#pragma mark - Directory functions
1101
1102
1103static status_t
1104fs_create_dir(fs_volume* _volume, fs_vnode* _directory, const char* name, int mode)
1105{
1106	CALLED();
1107	volume* volume = (struct volume*)_volume->private_volume;
1108	MutexLocker lock(volume->lock);
1109	vnode* directory = (vnode*)_directory->private_node;
1110
1111	status_t status = fs_access(_volume, _directory, W_OK);
1112	if (status != B_OK)
1113		return status;
1114
1115	ino_t inode = -1;
1116	status = fs_generic_create(_volume, directory, name, S_IFDIR | (mode & 07777), &inode);
1117	if (status != B_OK)
1118		return status;
1119
1120	return B_OK;
1121}
1122
1123
1124static status_t
1125fs_remove_dir(fs_volume* _volume, fs_vnode* _directory, const char* name)
1126{
1127	CALLED();
1128	ino_t directory_inode = ((vnode*)_directory->private_node)->inode;
1129	status_t status = fs_generic_unlink(_volume, _directory, name, RM_DIR);
1130	if (status != B_OK)
1131		return status;
1132
1133	entry_cache_remove(_volume->id, directory_inode, "..");
1134	return B_OK;
1135}
1136
1137
1138static status_t
1139fs_open_dir(fs_volume* _volume, fs_vnode* _node, void** _cookie)
1140{
1141	CALLED();
1142	vnode* node = (vnode*)_node->private_node;
1143
1144	status_t status = fs_access(_volume, _node, R_OK);
1145	if (status != B_OK)
1146		return status;
1147
1148	if ((node->mode & S_IFDIR) == 0)
1149		return B_NOT_A_DIRECTORY;
1150
1151	directory_cookie* cookie = new directory_cookie;
1152	if (cookie == NULL)
1153		return B_NO_MEMORY;
1154
1155	cookie->first = cookie->current = NULL;
1156	*_cookie = (void*)cookie;
1157	return B_OK;
1158}
1159
1160
1161static int
1162_ntfs_readdir_callback(void* _cookie, const ntfschar* ntfs_name, const int ntfs_name_len,
1163	const int name_type, const s64 pos, const MFT_REF mref, const unsigned dt_type)
1164{
1165	if (name_type == FILE_NAME_DOS)
1166		return 0;
1167
1168	directory_cookie* cookie = (directory_cookie*)_cookie;
1169
1170	char* name = NULL;
1171	int name_len = ntfs_ucstombs(ntfs_name, ntfs_name_len, &name, 0);
1172	if (name_len <= 0 || name == NULL)
1173		return -1;
1174	MemoryDeleter nameDeleter(name);
1175
1176	directory_cookie::entry* entry =
1177		(directory_cookie::entry*)malloc(sizeof(directory_cookie::entry) + name_len);
1178	if (entry == NULL)
1179		return -1;
1180	entry->next = NULL;
1181
1182	entry->inode = MREF(mref);
1183	entry->name_length = name_len;
1184	memcpy(entry->name, name, name_len + 1);
1185
1186	if (cookie->first == NULL) {
1187		cookie->first = cookie->current = entry;
1188	} else {
1189		cookie->current->next = entry;
1190		cookie->current = entry;
1191	}
1192
1193	return 0;
1194}
1195
1196
1197static status_t
1198fs_read_dir(fs_volume* _volume, fs_vnode* _node, void* _cookie,
1199	struct dirent* dirent, size_t bufferSize, uint32* _num)
1200{
1201	CALLED();
1202	directory_cookie* cookie = (directory_cookie*)_cookie;
1203
1204	// TODO: While lowntfs-3g seems to also read the entire directory at once into memory,
1205	// we could optimize things here by storing the data in the vnode, not the inode, and
1206	// only freeing it after some period of inactivity.
1207
1208	// See if we need to read the directory ourselves first.
1209	if (cookie->first == NULL) {
1210		volume* volume = (struct volume*)_volume->private_volume;
1211		MutexLocker lock(volume->lock);
1212		vnode* node = (vnode*)_node->private_node;
1213
1214		ntfs_inode* ni = ntfs_inode_open(volume->ntfs, node->inode);
1215		if (ni == NULL)
1216			return errno;
1217		NtfsInodeCloser niCloser(ni);
1218
1219		s64 pos = 0;
1220		if (ntfs_readdir(ni, &pos, cookie, _ntfs_readdir_callback) != 0)
1221			return errno;
1222		cookie->current = cookie->first;
1223	}
1224	if (cookie->first == NULL)
1225		return ENOENT;
1226	if (cookie->current == NULL) {
1227		*_num = 0;
1228		return B_OK;
1229	}
1230
1231	uint32 maxCount = *_num;
1232	uint32 count = 0;
1233	while (count < maxCount && bufferSize > sizeof(struct dirent)) {
1234		size_t length = bufferSize - offsetof(struct dirent, d_name);
1235		if (length < (cookie->current->name_length + 1)) {
1236			// the remaining name buffer length is too small
1237			if (count == 0)
1238				return B_BUFFER_OVERFLOW;
1239			break;
1240		}
1241		length = cookie->current->name_length;
1242
1243		dirent->d_dev = _volume->id;
1244		dirent->d_ino = cookie->current->inode;
1245		strlcpy(dirent->d_name, cookie->current->name, length + 1);
1246
1247		dirent = next_dirent(dirent, length, bufferSize);
1248		count++;
1249
1250		cookie->current = cookie->current->next;
1251		if (cookie->current == NULL)
1252			break;
1253	}
1254
1255	*_num = count;
1256	return B_OK;
1257}
1258
1259
1260static status_t
1261fs_rewind_dir(fs_volume* /*_volume*/, fs_vnode* /*node*/, void *_cookie)
1262{
1263	CALLED();
1264	directory_cookie* cookie = (directory_cookie*)_cookie;
1265	cookie->current = cookie->first;
1266	return B_OK;
1267}
1268
1269
1270static status_t
1271fs_close_dir(fs_volume* /*_volume*/, fs_vnode* /*node*/, void* /*_cookie*/)
1272{
1273	return B_OK;
1274}
1275
1276
1277static status_t
1278fs_free_dir_cookie(fs_volume* _volume, fs_vnode* _node, void* _cookie)
1279{
1280	CALLED();
1281	directory_cookie* cookie = (directory_cookie*)_cookie;
1282	if (cookie == NULL)
1283		return B_OK;
1284
1285	// Free entries.
1286	cookie->current = cookie->first;
1287	while (cookie->current != NULL) {
1288		directory_cookie::entry* next = cookie->current->next;
1289		free(cookie->current);
1290		cookie->current = next;
1291	}
1292
1293	delete cookie;
1294	return B_OK;
1295}
1296
1297
1298fs_volume_ops gNtfsVolumeOps = {
1299	&fs_unmount,
1300	&fs_read_fs_info,
1301	&fs_write_fs_info,
1302	NULL,	// fs_sync,
1303	&fs_get_vnode,
1304};
1305
1306
1307fs_vnode_ops gNtfsVnodeOps = {
1308	/* vnode operations */
1309	&fs_lookup,
1310	&fs_get_vnode_name,
1311	&fs_put_vnode,
1312	&fs_remove_vnode,
1313
1314	/* VM file access */
1315	&fs_can_page,
1316	&fs_read_pages,
1317	&fs_write_pages,
1318
1319	NULL,	// io
1320	NULL,	// cancel_io
1321
1322	NULL,	// get_file_map
1323
1324	&fs_ioctl,
1325	NULL,
1326	NULL,	// fs_select
1327	NULL,	// fs_deselect
1328	&fs_fsync,
1329
1330	&fs_read_link,
1331	NULL,	// fs_create_symlink
1332
1333	NULL,	// fs_link,
1334	&fs_unlink,
1335	&fs_rename,
1336
1337	&fs_access,
1338	&fs_read_stat,
1339	&fs_write_stat,
1340	NULL,	// fs_preallocate
1341
1342	/* file operations */
1343	&fs_create,
1344	&fs_open,
1345	&fs_close,
1346	&fs_free_cookie,
1347	&fs_read,
1348	&fs_write,
1349
1350	/* directory operations */
1351	&fs_create_dir,
1352	&fs_remove_dir,
1353	&fs_open_dir,
1354	&fs_close_dir,
1355	&fs_free_dir_cookie,
1356	&fs_read_dir,
1357	&fs_rewind_dir,
1358
1359	/* attribute directory operations */
1360	NULL, 	// fs_open_attr_dir,
1361	NULL,	// fs_close_attr_dir,
1362	NULL,	// fs_free_attr_dir_cookie,
1363	NULL,	// fs_read_attr_dir,
1364	NULL,	// fs_rewind_attr_dir,
1365
1366	/* attribute operations */
1367	NULL,	// fs_create_attr,
1368	NULL,	// fs_open_attr,
1369	NULL,	// fs_close_attr,
1370	NULL,	// fs_free_attr_cookie,
1371	NULL,	// fs_read_attr,
1372	NULL,	// fs_write_attr,
1373	NULL,	// fs_read_attr_stat,
1374	NULL,	// fs_write_attr_stat,
1375	NULL,	// fs_rename_attr,
1376	NULL,	// fs_remove_attr,
1377};
1378
1379
1380static file_system_module_info sNtfsFileSystem = {
1381	{
1382		"file_systems/ntfs" B_CURRENT_FS_API_VERSION,
1383		0,
1384		NULL,
1385	},
1386
1387	"ntfs",							// short_name
1388	"NT File System",				// pretty_name
1389
1390	// DDM flags
1391	0
1392	| B_DISK_SYSTEM_IS_FILE_SYSTEM
1393	| B_DISK_SYSTEM_SUPPORTS_INITIALIZING
1394	| B_DISK_SYSTEM_SUPPORTS_WRITING
1395	,
1396
1397	// scanning
1398	fs_identify_partition,
1399	fs_scan_partition,
1400	fs_free_identify_partition_cookie,
1401	NULL,	// free_partition_content_cookie()
1402
1403	&fs_mount,
1404
1405	// capability querying operations
1406	NULL,	// get_supported_operations
1407
1408	NULL,	// validate_resize
1409	NULL,	// validate_move
1410	NULL,	// validate_set_content_name
1411	NULL,	// validate_set_content_parameters
1412	NULL,	// validate_initialize,
1413
1414	/* shadow partition modification */
1415	NULL,	// shadow_changed
1416
1417	/* writing */
1418	NULL,	// defragment
1419	NULL,	// repair
1420	NULL,	// resize
1421	NULL,	// move
1422	NULL,	// set_content_name
1423	NULL,	// set_content_parameters
1424	fs_initialize,
1425	NULL	// uninitialize
1426};
1427
1428
1429module_info *modules[] = {
1430	(module_info *)&sNtfsFileSystem,
1431	NULL,
1432};
1433