Esempio n. 1
0
status_t
Inode::Create(const char* name, int mode, int perms, OpenFileCookie* cookie,
	OpenDelegationData* data, ino_t* id)
{
	ASSERT(name != NULL);
	ASSERT(cookie != NULL);
	ASSERT(data != NULL);

	cookie->fMode = mode;
	cookie->fLocks = NULL;

	OpenState* state = new(std::nothrow) OpenState;
	if (state == NULL)
		return B_NO_MEMORY;

	status_t result = CreateState(name, mode, perms, state, data);
	if (result != B_OK) {
		delete state;
		return result;
	}

	cookie->fOpenState = state;
	cookie->fFileSystem = fFileSystem;

	*id = FileIdToInoT(state->fInfo.fFileId);

	fFileSystem->AddOpenFile(state);
	fFileSystem->Root()->MakeInfoInvalid();

	notify_entry_created(fFileSystem->DevId(), ID(), name, *id);

	return B_OK;
}
Esempio n. 2
0
static status_t
ext2_create_dir(fs_volume* _volume, fs_vnode* _directory, const char* name,
	int mode)
{
	TRACE("ext2_create_dir()\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_dir(): Starting transaction\n");
	Transaction transaction(volume->GetJournal());

	ino_t id;
	status = Inode::Create(transaction, directory, name,
		S_DIRECTORY | (mode & S_IUMSK), 0, EXT2_TYPE_DIRECTORY, NULL, &id);
	if (status != B_OK)
		return status;

	put_vnode(volume->FSVolume(), id);

	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_dir(): Done\n");

	return B_OK;
}
Esempio n. 3
0
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(NotifyListenerRequest* request)
{
	// check and execute the request
	status_t result = B_OK;
	if (fVolume && request->device != fVolume->GetID())
		result = B_BAD_VALUE;

	// get the names
	// name
	char* name = (char*)request->name.GetData();
	int32 nameLen = request->name.GetSize();
	if (name && (nameLen <= 0))
		name = NULL;
	else if (name)
		name[nameLen - 1] = '\0';	// NULL-terminate to be safe

	// old name
	char* oldName = (char*)request->oldName.GetData();
	int32 oldNameLen = request->oldName.GetSize();
	if (oldName && (oldNameLen <= 0))
		oldName = NULL;
	else if (oldName)
		oldName[oldNameLen - 1] = '\0';	// NULL-terminate to be safe

	// check the names
	if (result == B_OK) {
		switch (request->operation) {
			case B_ENTRY_MOVED:
				if (!oldName) {
					ERROR(("NotifyListenerRequest: NULL oldName for "
						"B_ENTRY_MOVED\n"));
					result = B_BAD_VALUE;
					break;
				}
				// fall through...
			case B_ENTRY_CREATED:
			case B_ENTRY_REMOVED:
			case B_ATTR_CHANGED:
				if (!name) {
					ERROR(("NotifyListenerRequest: NULL name for opcode: %"
						B_PRId32 "\n", request->operation));
					result = B_BAD_VALUE;
				}
				break;
			case B_STAT_CHANGED:
				break;
		}
	}

	// execute the request
	if (result == B_OK) {
		switch (request->operation) {
			case B_ENTRY_CREATED:
				PRINT(("notify_entry_created(%" B_PRId32 ", %" B_PRId64 ", "
					"\"%s\", %" B_PRId64 ")\n", request->device,
					request->directory, name, request->node));
				result = notify_entry_created(request->device,
					request->directory, name, request->node);
				break;

			case B_ENTRY_REMOVED:
				PRINT(("notify_entry_removed(%" B_PRId32 ", %" B_PRId64 ", "
					"\"%s\", %" B_PRId64 ")\n", request->device,
					request->directory, name, request->node));
				result = notify_entry_removed(request->device,
					request->directory, name, request->node);
				break;

			case B_ENTRY_MOVED:
				PRINT(("notify_entry_moved(%" B_PRId32 ", %" B_PRId64 ", "
					"\"%s\", %" B_PRId64 ", \"%s\", %" B_PRId64 ")\n",
					request->device, request->oldDirectory, oldName,
					request->directory, name, request->node));
				result = notify_entry_moved(request->device,
					request->oldDirectory, oldName, request->directory, name,
					request->node);
				break;

			case B_STAT_CHANGED:
				PRINT(("notify_stat_changed(%" B_PRId32 ", %" B_PRId64 ", "
					"0x%" B_PRIx32 ")\n", request->device, request->node,
					request->details));
				result = notify_stat_changed(request->device, request->node,
					request->details);
				break;

			case B_ATTR_CHANGED:
				PRINT(("notify_attribute_changed(%" B_PRId32 ", %" B_PRId64 ", "
					"\"%s\", 0x%" B_PRIx32 ")\n", request->device,
					request->node, name, (int32)request->details));
				result = notify_attribute_changed(request->device,
					request->node, name, (int32)request->details);
				break;

			default:
				ERROR(("NotifyQueryRequest: unsupported operation: %" B_PRId32
					"\n", request->operation));
				result = B_BAD_VALUE;
				break;
		}
	}

	// prepare the reply
	RequestAllocator allocator(fPort->GetPort());
	NotifyListenerReply* reply;
	status_t error = AllocateRequest(allocator, &reply);
	if (error != B_OK)
		return error;

	reply->error = result;

	// send the reply
	return fPort->SendRequest(&allocator);
}
Esempio n. 4
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;
}
Esempio n. 5
0
static status_t
ext2_create(fs_volume* _volume, fs_vnode* _directory, const char* name,
	int openMode, int mode, void** _cookie, ino_t* _vnodeID)
{
	Volume* volume = (Volume*)_volume->private_volume;
	Inode* directory = (Inode*)_directory->private_node;

	TRACE("ext2_create()\n");

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

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

	TRACE("ext2_create(): Creating cookie\n");

	// Allocate cookie
	file_cookie* cookie = new(std::nothrow) file_cookie;
	if (cookie == NULL)
		return B_NO_MEMORY;
	ObjectDeleter<file_cookie> cookieDeleter(cookie);

	cookie->open_mode = openMode;
	cookie->last_size = 0;
	cookie->last_notification = system_time();

	TRACE("ext2_create(): Starting transaction\n");

	Transaction transaction(volume->GetJournal());

	TRACE("ext2_create(): Creating inode\n");

	Inode* inode;
	bool created;
	status_t status = Inode::Create(transaction, directory, name,
		S_FILE | (mode & S_IUMSK), openMode, EXT2_TYPE_FILE, &created, _vnodeID,
		&inode, &gExt2VnodeOps);
	if (status != B_OK)
		return status;

	TRACE("ext2_create(): Created inode\n");

	if ((openMode & O_NOCACHE) != 0) {
		status = inode->DisableFileCache();
		if (status != B_OK)
			return status;
	}

	entry_cache_add(volume->ID(), directory->ID(), name, *_vnodeID);

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

	*_cookie = cookie;
	cookieDeleter.Detach();

	if (created)
		notify_entry_created(volume->ID(), directory->ID(), name, *_vnodeID);

	return B_OK;
}