Esempio n. 1
0
// PublishVNode
status_t
Volume::PublishVNode(Node *node)
{
	status_t error = NodeAdded(node);
	if (error == B_OK) {
		error = publish_vnode(GetID(), node->GetID(), node);
		if (error != B_OK)
			NodeRemoved(node);
	}
	return error;
}
static status_t
fs_mount(fs_volume* _volume, const char* device, uint32 flags,
	const char* args, ino_t* _rootID)
{
	bool allowJoliet = true;
	iso9660_volume* volume;

	// Check for a 'nojoliet' parm
	// all we check for is the existance of 'nojoliet' in the parms.
	if (args != NULL) {
		uint32 i;
		char* spot;
		char* buf = strdup(args);

		uint32 len = strlen(buf);
		// lower case the parms data
		for (i = 0; i < len + 1; i++)
			buf[i] = tolower(buf[i]);

		// look for nojoliet
		spot = strstr(buf, "nojoliet");
		if (spot != NULL)
			allowJoliet = false;

		free(buf);
	}

	// Try and mount volume as an ISO volume.
	status_t result = ISOMount(device, O_RDONLY, &volume, allowJoliet);
	if (result == B_OK) {
		*_rootID = ISO_ROOTNODE_ID;

		_volume->private_volume = volume;
		_volume->ops = &gISO9660VolumeOps;
		volume->volume = _volume;
		volume->id = _volume->id;

		result = publish_vnode(_volume, *_rootID, &volume->rootDirRec,
			&gISO9660VnodeOps,
			volume->rootDirRec.attr.stat[FS_DATA_FORMAT].st_mode, 0);
		if (result != B_OK) {
			block_cache_delete(volume->fBlockCache, false);
			free(volume);
			result = B_ERROR;
		}
	}
	return result;
}
Esempio n. 3
0
// Mount
status_t
Volume::Mount(fs_volume *fsVolume, const char *path)
{
	Unmount();
	status_t error = (path ? B_OK : B_BAD_VALUE);
	fFSVolume = fsVolume;
	// load the settings
	if (error == B_OK) {
		fSettings = new(nothrow) Settings;
		if (fSettings)
			error = fSettings->SetTo(path);
		else
			error = B_NO_MEMORY;
	}
	// copy the device name
	if (error == B_OK) {
		fDeviceName = new(nothrow) char[strlen(path) + 1];
		if (fDeviceName)
			strcpy(fDeviceName, path);
		else
			error = B_NO_MEMORY;
	}
	// open disk
	if (error == B_OK) {
		fDevice = open(path, O_RDONLY);
		if (fDevice < 0)
			SET_ERROR(error, errno);
	}
	// read and analyze super block
	if (error == B_OK)
		error = _ReadSuperBlock();

	if (error == B_OK)
		UpdateName(fsVolume->partition);

	// create and init block cache
	if (error == B_OK) {
		fBlockCache = new(nothrow) BlockCache;
		if (fBlockCache)
			error = fBlockCache->Init(fDevice, CountBlocks(), GetBlockSize());
		else
			error = B_NO_MEMORY;
	}
	// create the tree
	if (error == B_OK) {
		fTree = new(nothrow) Tree;
		if (!fTree)
			error = B_NO_MEMORY;
	}
	// get the root node and init the tree
	if (error == B_OK) {
		Block *rootBlock = NULL;
		error = fBlockCache->GetBlock(fSuperBlock->GetRootBlock(), &rootBlock);
REPORT_ERROR(error);
		if (error == B_OK) {
			rootBlock->SetKind(Block::KIND_FORMATTED);
			error = fTree->Init(this, rootBlock->ToNode(),
								fSuperBlock->GetTreeHeight());
REPORT_ERROR(error);
			rootBlock->Put();
		}
	}
	// get the root VNode (i.e. the root dir)
	if (error == B_OK) {
		fRootVNode = new(nothrow) VNode;
		if (fRootVNode) {
			error = FindVNode(REISERFS_ROOT_PARENT_OBJECTID,
							  REISERFS_ROOT_OBJECTID, fRootVNode);
REPORT_ERROR(error);
			if (error == B_OK) {
				error = publish_vnode(fFSVolume, fRootVNode->GetID(),
					fRootVNode, &gReiserFSVnodeOps, S_IFDIR, 0);
			}
REPORT_ERROR(error);
		} else
			error = B_NO_MEMORY;
	}
	// init the hash function
	if (error == B_OK)
		_InitHashFunction();
	// init the negative entry list
	if (error == B_OK)
		_InitNegativeEntries();
	// cleanup on error
	if (error != B_OK)
		Unmount();
	RETURN_ERROR(error);
}
Esempio n. 4
0
static status_t
nfs4_mount(fs_volume* volume, const char* device, uint32 flags,
			const char* args, ino_t* _rootVnodeID)
{
	TRACE("volume = %p, device = %s, flags = %" B_PRIu32 ", args = %s", volume,
		device, flags, args);

	status_t result;

	/* prepare idmapper server */
	MutexLocker locker(gIdMapperLock);
	gIdMapper = new(std::nothrow) IdMap;
	if (gIdMapper == NULL)
		return B_NO_MEMORY;

	result = gIdMapper->InitStatus();
	if (result != B_OK) {
		delete gIdMapper;
		gIdMapper = NULL;
		return result;
	}
	locker.Unlock();

	AddressResolver* resolver;
	MountConfiguration config;
	char* path;
	result = ParseArguments(args, &resolver, &path, &config);
	if (result != B_OK)
		return result;
	MemoryDeleter pathDeleter(path);

	RPC::Server* server;
	result = gRPCServerManager->Acquire(&server, resolver, CreateNFS4Server);
	delete resolver;
	if (result != B_OK)
		return result;
	
	FileSystem* fs;
	result = FileSystem::Mount(&fs, server, path, volume->id, config);
	if (result != B_OK) {
		gRPCServerManager->Release(server);
		return result;
	}

	Inode* inode = fs->Root();
	if (inode == NULL) {
		delete fs;
		gRPCServerManager->Release(server);

		return B_IO_ERROR;
	}

	volume->private_volume = fs;
	volume->ops = &gNFSv4VolumeOps;

	VnodeToInode* vti = new VnodeToInode(inode->ID(), fs);
	if (vti == NULL) {
		delete fs;
		gRPCServerManager->Release(server);
		return B_NO_MEMORY;
	}

	vti->Replace(inode);
	result = publish_vnode(volume, inode->ID(), vti, &gNFSv4VnodeOps,
							inode->Type(), 0);
	if (result != B_OK)
		return result;

	*_rootVnodeID = inode->ID();

	TRACE("*_rootVnodeID = %" B_PRIi64, inode->ID());

	return B_OK;
}
Esempio n. 5
0
status_t
Volume::PublishNode(Node* node, uint32 flags)
{
	return publish_vnode(fFSVolume, node->BlockIndex(), node,
		&gCheckSumFSVnodeOps, node->Mode(), flags);
}
Esempio n. 6
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;
}
Esempio n. 7
0
status_t
Volume::Mount(const char* deviceName, uint32 flags)
{
	// TODO: validate the FS in write mode as well!
#if (B_HOST_IS_LENDIAN && defined(BFS_BIG_ENDIAN_ONLY)) \
	|| (B_HOST_IS_BENDIAN && defined(BFS_LITTLE_ENDIAN_ONLY))
	// in big endian mode, we only mount read-only for now
	flags |= B_MOUNT_READ_ONLY;
#endif

	DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0
		? O_RDONLY : O_RDWR);
	fDevice = opener.Device();
	if (fDevice < B_OK)
		RETURN_ERROR(fDevice);

	if (opener.IsReadOnly())
		fFlags |= VOLUME_READ_ONLY;

	// read the superblock
	if (Identify(fDevice, &fSuperBlock) != B_OK) {
		FATAL(("invalid superblock!\n"));
		return B_BAD_VALUE;
	}

	// initialize short hands to the superblock (to save byte swapping)
	fBlockSize = fSuperBlock.BlockSize();
	fBlockShift = fSuperBlock.BlockShift();
	fAllocationGroupShift = fSuperBlock.AllocationGroupShift();

	// check if the device size is large enough to hold the file system
	off_t diskSize;
	if (opener.GetSize(&diskSize, &fDeviceBlockSize) != B_OK)
		RETURN_ERROR(B_ERROR);
	if (diskSize < (NumBlocks() << BlockShift()))
		RETURN_ERROR(B_BAD_VALUE);

	// set the current log pointers, so that journaling will work correctly
	fLogStart = fSuperBlock.LogStart();
	fLogEnd = fSuperBlock.LogEnd();

	if ((fBlockCache = opener.InitCache(NumBlocks(), fBlockSize)) == NULL)
		return B_ERROR;

	fJournal = new(std::nothrow) Journal(this);
	if (fJournal == NULL)
		return B_NO_MEMORY;

	status_t status = fJournal->InitCheck();
	if (status < B_OK) {
		FATAL(("could not initialize journal: %s!\n", strerror(status)));
		return status;
	}

	// replaying the log is the first thing we will do on this disk
	status = fJournal->ReplayLog();
	if (status != B_OK) {
		FATAL(("Replaying log failed, data may be corrupted, volume "
			"read-only.\n"));
		fFlags |= VOLUME_READ_ONLY;
			// TODO: if this is the boot volume, Bootscript will assume this
			// is a CD...
			// TODO: it would be nice to have a user visible alert instead
			// of letting him just find this in the syslog.
	}

	status = fBlockAllocator.Initialize();
	if (status != B_OK) {
		FATAL(("could not initialize block bitmap allocator!\n"));
		return status;
	}

	fRootNode = new(std::nothrow) Inode(this, ToVnode(Root()));
	if (fRootNode != NULL && fRootNode->InitCheck() == B_OK) {
		status = publish_vnode(fVolume, ToVnode(Root()), (void*)fRootNode,
			&gBFSVnodeOps, fRootNode->Mode(), 0);
		if (status == B_OK) {
			// try to get indices root dir

			if (!Indices().IsZero()) {
				fIndicesNode = new(std::nothrow) Inode(this,
					ToVnode(Indices()));
			}

			if (fIndicesNode == NULL
				|| fIndicesNode->InitCheck() < B_OK
				|| !fIndicesNode->IsContainer()) {
				INFORM(("bfs: volume doesn't have indices!\n"));

				if (fIndicesNode) {
					// if this is the case, the index root node is gone bad,
					// and BFS switch to read-only mode
					fFlags |= VOLUME_READ_ONLY;
					delete fIndicesNode;
					fIndicesNode = NULL;
				}
			} else {
				// we don't use the vnode layer to access the indices node
			}
		} else {
			FATAL(("could not create root node: publish_vnode() failed!\n"));
			delete fRootNode;
			return status;
		}
	} else {
		status = B_BAD_VALUE;
		FATAL(("could not create root node!\n"));
		return status;
	}

	// all went fine
	opener.Keep();
	return B_OK;
}
Esempio n. 8
0
static status_t
ext2_create_symlink(fs_volume* _volume, fs_vnode* _directory, const char* name,
	const char* path, int mode)
{
	TRACE("ext2_create_symlink()\n");

	Volume* volume = (Volume*)_volume->private_volume;
	Inode* directory = (Inode*)_directory->private_node;

	if (volume->IsReadOnly())
		return B_READ_ONLY_DEVICE;

	if (!directory->IsDirectory())
		return B_BAD_TYPE;

	status_t status = directory->CheckPermissions(W_OK);
	if (status != B_OK)
		return status;

	TRACE("ext2_create_symlink(): Starting transaction\n");
	Transaction transaction(volume->GetJournal());

	Inode* link;
	ino_t id;
	status = Inode::Create(transaction, directory, name, S_SYMLINK | 0777,
		0, (uint8)EXT2_TYPE_SYMLINK, NULL, &id, &link);
	if (status != B_OK)
		return status;

	// TODO: We have to prepare the link before publishing?

	size_t length = strlen(path);
	TRACE("ext2_create_symlink(): Path (%s) length: %d\n", path, (int)length);
	if (length < EXT2_SHORT_SYMLINK_LENGTH) {
		strcpy(link->Node().symlink, path);
		link->Node().SetSize((uint32)length);

		TRACE("ext2_create_symlink(): Publishing vnode\n");
		publish_vnode(volume->FSVolume(), id, link, &gExt2VnodeOps,
			link->Mode(), 0);
		put_vnode(volume->FSVolume(), id);
	} else {
		TRACE("ext2_create_symlink(): Publishing vnode\n");
		publish_vnode(volume->FSVolume(), id, link, &gExt2VnodeOps,
			link->Mode(), 0);
		put_vnode(volume->FSVolume(), id);

		if (!link->HasFileCache()) {
			status = link->CreateFileCache();
			if (status != B_OK)
				return status;
		}

		size_t written = length;
		status = link->WriteAt(transaction, 0, (const uint8*)path, &written);
		if (status == B_OK && written != length)
			status = B_IO_ERROR;
	}

	if (status == B_OK)
		status = link->WriteBack(transaction);

	entry_cache_add(volume->ID(), directory->ID(), name, id);

	status = transaction.Done();
	if (status != B_OK) {
		entry_cache_remove(volume->ID(), directory->ID(), name);
		return status;
	}

	notify_entry_created(volume->ID(), directory->ID(), name, id);

	TRACE("ext2_create_symlink(): Done\n");

	return status;
}