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
status_t
Inode::ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
{
	ASSERT(de != NULL);

	uint32 attempt = 0;
	do {
		RPC::Server* serv = fFileSystem->Server();
		Request request(serv, fFileSystem);
		RequestBuilder& req = request.Builder();

		req.PutFH(fInfo.fHandle);
		req.LookUpUp();
		req.GetFH();

		if (fFileSystem->IsAttrSupported(FATTR4_FILEID)) {
			Attribute attr[] = { FATTR4_FILEID };
			req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
		}

		status_t result = request.Send();
		if (result != B_OK)
			return result;

		ReplyInterpreter& reply = request.Reply();

		if (HandleErrors(attempt, reply.NFS4Error(), serv))
			continue;

		reply.PutFH();
		result = reply.LookUpUp();
		if (result != B_OK)
			return result;

		FileHandle fh;
		reply.GetFH(&fh);

		uint64 fileId;
		if (fFileSystem->IsAttrSupported(FATTR4_FILEID)) {
			AttrValue* values;
			uint32 count;
			result = reply.GetAttr(&values, &count);
			if (result != B_OK)
				return result;

			fileId = values[0].fData.fValue64;
			delete[] values;
		} else
			fileId = fFileSystem->AllocFileId();

		return FillDirEntry(de, FileIdToInoT(fileId), "..", pos, size);
	} while (true);
}
Esempio n. 3
0
status_t
Inode::CreateState(const char* name, int mode, int perms, OpenState* state,
	OpenDelegationData* delegationData) {
	ASSERT(name != NULL);
	ASSERT(state != NULL);
	ASSERT(delegationData != NULL);

	uint64 fileID;
	FileHandle handle;
	ChangeInfo changeInfo;

	status_t result = CreateFile(name, mode, perms, state, &changeInfo,
		&fileID, &handle, delegationData);
	if (result != B_OK)
		return result;

	FileInfo fileInfo;
	fileInfo.fFileId = fileID;
	fileInfo.fHandle = handle;

	fFileSystem->InoIdMap()->AddName(fileInfo, fInfo.fNames, name,
		FileIdToInoT(fileID));

	fCache->Lock();
	if (fCache->Valid()) {
		if (changeInfo.fAtomic
			&& fCache->ChangeInfo() == changeInfo.fBefore) {
			fCache->AddEntry(name, fileID, true);
			fCache->SetChangeInfo(changeInfo.fAfter);
		} else
			fCache->Trash();
	}
	fCache->Unlock();

	state->fFileSystem = fFileSystem;
	state->fInfo = fileInfo;
	state->fMode = mode & O_RWMASK;

	return B_OK;
}
Esempio n. 4
0
status_t
Inode::ReadDir(void* _buffer, uint32 size, uint32* _count,
	OpenDirCookie* cookie)
{
	ASSERT(_buffer != NULL);
	ASSERT(_count != NULL);
	ASSERT(cookie != NULL);

	if (cookie->fEOF) {
		*_count = 0;
		return B_OK;
	}

	status_t result;
	DirectoryCache* cache = cookie->fAttrDir ? fAttrCache : fCache;
	if (cookie->fSnapshot == NULL) {
		cache->Lock();
		result = cache->Revalidate();
		if (result != B_OK) {
			cache->Unlock();
			return result;
		}

		DirectoryCacheSnapshot* snapshot;
		result = cache->GetSnapshot(&snapshot);
		if (result != B_OK) {
			cache->Unlock();
			return result;
		}

		cookie->fSnapshot = new DirectoryCacheSnapshot(*snapshot);
		cache->Unlock();

		if (cookie->fSnapshot == NULL)
			return B_NO_MEMORY;
	}

	char* buffer = reinterpret_cast<char*>(_buffer);
	uint32 pos = 0;
	uint32 i = 0;
	bool overflow = false;

	if (cookie->fSpecial == 0 && i < *_count && !cookie->fAttrDir) {
		struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);

		status_t result;
		result = FillDirEntry(de, fInfo.fFileId, ".", pos, size);

		if (result == B_BUFFER_OVERFLOW)
			overflow = true;
		else if (result == B_OK) {
			pos += de->d_reclen;
			i++;
			cookie->fSpecial++;
		} else
			return result;
	}

	if (cookie->fSpecial == 1 && i < *_count && !cookie->fAttrDir) {
		struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
		
		status_t result;
		result = ReadDirUp(de, pos, size);
		if (result == B_ENTRY_NOT_FOUND) {
			result = FillDirEntry(de, FileIdToInoT(fInfo.fFileId), "..", pos,
				size);
		}

		if (result == B_BUFFER_OVERFLOW)
			overflow = true;
		else if (result == B_OK) {
			pos += de->d_reclen;
			i++;
			cookie->fSpecial++;
		} else
			return result;
	}

	MutexLocker _(cookie->fSnapshot->fLock);
	for (; !overflow && i < *_count; i++) {
		struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
		NameCacheEntry* temp = cookie->fCurrent;

		if (cookie->fCurrent == NULL)
			cookie->fCurrent = cookie->fSnapshot->fEntries.Head();
		else {
			cookie->fCurrent
				= cookie->fSnapshot->fEntries.GetNext(cookie->fCurrent);
		}

		if (cookie->fCurrent == NULL) {
			cookie->fEOF = true;
			break;
		}

		if (FillDirEntry(de, cookie->fCurrent->fNode, cookie->fCurrent->fName,
			pos, size) == B_BUFFER_OVERFLOW) {
			cookie->fCurrent = temp;
			overflow = true;
			break;
		}

		pos += de->d_reclen;
	}

	if (i == 0 && overflow)
		return B_BUFFER_OVERFLOW;

	*_count = i;

	return B_OK;
}
Esempio n. 5
0
status_t
Inode::GetDirSnapshot(DirectoryCacheSnapshot** _snapshot,
	OpenDirCookie* cookie, uint64* _change, bool attribute)
{
	ASSERT(_snapshot != NULL);

	DirectoryCacheSnapshot* snapshot = new DirectoryCacheSnapshot;
	if (snapshot == NULL)
		return B_NO_MEMORY;

	uint64 change = 0;
	uint64 dirCookie = 0;
	uint64 dirCookieVerf = 0;
	bool eof = false;

	while (!eof) {
		uint32 count;
		DirEntry* dirents;

		status_t result = ReadDirOnce(&dirents, &count, cookie, &eof, &change,
			&dirCookie, &dirCookieVerf, attribute);
		if (result != B_OK) {
			delete snapshot;
			return result;
		}

		uint32 i;
		for (i = 0; i < count; i++) {

			// FATTR4_FSID is mandatory
			void* data = dirents[i].fAttrs[0].fData.fPointer;
			FileSystemId* fsid = reinterpret_cast<FileSystemId*>(data);
			if (*fsid != fFileSystem->FsId())
				continue;

			if (strstr(dirents[i].fName, "-haiku-attrs") != NULL)
				continue;

			ino_t id;
			if (!attribute) {
				if (dirents[i].fAttrCount == 2)
					id = FileIdToInoT(dirents[i].fAttrs[1].fData.fValue64);
				else
					id = FileIdToInoT(fFileSystem->AllocFileId());
			} else
				id = 0;
	
			const char* name = dirents[i].fName;
			if (attribute)
				name = FileToAttrName(name);
			if (name == NULL) {
				delete snapshot;
				delete[] dirents;
				return B_NO_MEMORY;
			}

			NameCacheEntry* entry = new NameCacheEntry(name, id);
			if (attribute)
				free(const_cast<char*>(name));

			if (entry == NULL || entry->fName == NULL) {
				if (entry != NULL)
					delete entry;
				delete snapshot;
				delete[] dirents;
				return B_NO_MEMORY;
			}
			snapshot->fEntries.Add(entry);
		}

		delete[] dirents;
	}

	*_snapshot = snapshot;
	*_change = change;

	return B_OK;
}