1f659db05SAxel Dörfler/*
24b723e3fSAxel Dörfler * Copyright 2003-2013, Axel D��rfler, axeld@pinc-software.de.
32f019bd6SIngo Weinhold * Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de.
435b38c39SJessica Hamilton * Copyright 2017, Jessica Hamilton, jessica.l.hamilton@gmail.com.
504b9d56aSAxel Dörfler * Distributed under the terms of the MIT License.
604b9d56aSAxel Dörfler */
7f659db05SAxel Dörfler
8f659db05SAxel Dörfler
9085cf27bSIngo Weinhold#include <boot/vfs.h>
10085cf27bSIngo Weinhold
11085cf27bSIngo Weinhold#include <errno.h>
12085cf27bSIngo Weinhold#include <fcntl.h>
13085cf27bSIngo Weinhold#include <string.h>
14085cf27bSIngo Weinhold#include <sys/uio.h>
15085cf27bSIngo Weinhold#include <unistd.h>
1616885aacSAxel Dörfler
171cd06a22SAxel Dörfler#include <StorageDefs.h>
18085cf27bSIngo Weinhold
19066d5086SIngo Weinhold#include <AutoDeleter.h>
20066d5086SIngo Weinhold
21f659db05SAxel Dörfler#include <boot/platform.h>
221cd06a22SAxel Dörfler#include <boot/partitions.h>
23f659db05SAxel Dörfler#include <boot/stdio.h>
2404b9d56aSAxel Dörfler#include <boot/stage2.h>
25085cf27bSIngo Weinhold#include <syscall_utils.h>
26085cf27bSIngo Weinhold
275c0f8450SIngo Weinhold#include "package_support.h"
28085cf27bSIngo Weinhold#include "RootFileSystem.h"
29cbc85916SIngo Weinhold#include "file_systems/packagefs/packagefs.h"
30f659db05SAxel Dörfler
31f659db05SAxel Dörfler
32f150614aSAxel Dörflerusing namespace boot;
33f150614aSAxel Dörfler
34127b80ecSAxel Dörfler//#define TRACE_VFS
35127b80ecSAxel Dörfler#ifdef TRACE_VFS
36127b80ecSAxel Dörfler#	define TRACE(x) dprintf x
37f150614aSAxel Dörfler#else
38f150614aSAxel Dörfler#	define TRACE(x) ;
39f150614aSAxel Dörfler#endif
40f150614aSAxel Dörfler
41f659db05SAxel Dörfler
422f019bd6SIngo Weinholdstruct __DIR {
432f019bd6SIngo Weinhold	Directory*	directory;
442f019bd6SIngo Weinhold	void*		cookie;
452f019bd6SIngo Weinhold	dirent		entry;
462f019bd6SIngo Weinhold	char		nameBuffer[B_FILE_NAME_LENGTH - 1];
472f019bd6SIngo Weinhold};
482f019bd6SIngo Weinhold
492f019bd6SIngo Weinhold
50eced90eaSAxel Dörflerclass Descriptor {
51eced90eaSAxel Dörfler	public:
52eced90eaSAxel Dörfler		Descriptor(Node *node, void *cookie);
53eced90eaSAxel Dörfler		~Descriptor();
54eced90eaSAxel Dörfler
558de63d24SAxel Dörfler		ssize_t ReadAt(off_t pos, void *buffer, size_t bufferSize);
56eced90eaSAxel Dörfler		ssize_t Read(void *buffer, size_t bufferSize);
578de63d24SAxel Dörfler		ssize_t WriteAt(off_t pos, const void *buffer, size_t bufferSize);
58eced90eaSAxel Dörfler		ssize_t Write(const void *buffer, size_t bufferSize);
59eced90eaSAxel Dörfler
6059ae1c81SIngo Weinhold		void Stat(struct stat &stat);
6101e6d687SIngo Weinhold		status_t Seek(off_t position, int mode);
6216885aacSAxel Dörfler
63eced90eaSAxel Dörfler		off_t Offset() const { return fOffset; }
64eced90eaSAxel Dörfler		int32 RefCount() const { return fRefCount; }
65eced90eaSAxel Dörfler
66eced90eaSAxel Dörfler		status_t Acquire();
67eced90eaSAxel Dörfler		status_t Release();
68eced90eaSAxel Dörfler
698fbf1c61SAxel Dörfler		Node *GetNode() const { return fNode; }
708fbf1c61SAxel Dörfler
71eced90eaSAxel Dörfler	private:
72eced90eaSAxel Dörfler		Node	*fNode;
73eced90eaSAxel Dörfler		void	*fCookie;
74eced90eaSAxel Dörfler		off_t	fOffset;
75eced90eaSAxel Dörfler		int32	fRefCount;
76eced90eaSAxel Dörfler};
77eced90eaSAxel Dörfler
7886f26409SAxel Dörfler#define MAX_VFS_DESCRIPTORS 64
79f659db05SAxel Dörfler
8053bc5ce9SAxel DörflerNodeList gBootDevices;
8153bc5ce9SAxel DörflerNodeList gPartitions;
826822f148SAxel DörflerRootFileSystem *gRoot;
837c198b5dSAxel Dörflerstatic Descriptor *sDescriptors[MAX_VFS_DESCRIPTORS];
847c198b5dSAxel Dörflerstatic Node *sBootDevice;
85f659db05SAxel Dörfler
86f659db05SAxel Dörfler
87f659db05SAxel DörflerNode::Node()
88f659db05SAxel Dörfler	:
89f150614aSAxel Dörfler	fRefCount(1)
90f659db05SAxel Dörfler{
91f659db05SAxel Dörfler}
92f659db05SAxel Dörfler
93f659db05SAxel Dörfler
94f659db05SAxel DörflerNode::~Node()
95f659db05SAxel Dörfler{
96f659db05SAxel Dörfler}
97f659db05SAxel Dörfler
98f659db05SAxel Dörfler
99f659db05SAxel Dörflerstatus_t
100f659db05SAxel DörflerNode::Open(void **_cookie, int mode)
101f659db05SAxel Dörfler{
10241fc2405SAxel Dörfler	TRACE(("%p::Open()\n", this));
10316885aacSAxel Dörfler	return Acquire();
104f659db05SAxel Dörfler}
105f659db05SAxel Dörfler
106f659db05SAxel Dörfler
107f659db05SAxel Dörflerstatus_t
108f659db05SAxel DörflerNode::Close(void *cookie)
109f659db05SAxel Dörfler{
11041fc2405SAxel Dörfler	TRACE(("%p::Close()\n", this));
11116885aacSAxel Dörfler	return Release();
11216885aacSAxel Dörfler}
11316885aacSAxel Dörfler
11416885aacSAxel Dörfler
115cbc85916SIngo Weinholdstatus_t
116cbc85916SIngo WeinholdNode::ReadLink(char* buffer, size_t bufferSize)
117cbc85916SIngo Weinhold{
118cbc85916SIngo Weinhold	return B_BAD_VALUE;
119cbc85916SIngo Weinhold}
120cbc85916SIngo Weinhold
121cbc85916SIngo Weinhold
122085cf27bSIngo Weinholdstatus_t
12316885aacSAxel DörflerNode::GetName(char *nameBuffer, size_t bufferSize) const
12416885aacSAxel Dörfler{
12516885aacSAxel Dörfler	return B_ERROR;
12616885aacSAxel Dörfler}
12716885aacSAxel Dörfler
12816885aacSAxel Dörfler
1299da23568SFrançois Revolstatus_t
1309da23568SFrançois RevolNode::GetFileMap(struct file_map_run *runs, int32 *count)
1319da23568SFrançois Revol{
1329da23568SFrançois Revol	return B_ERROR;
1339da23568SFrançois Revol}
1349da23568SFrançois Revol
1359da23568SFrançois Revol
136085cf27bSIngo Weinholdint32
13716885aacSAxel DörflerNode::Type() const
13816885aacSAxel Dörfler{
13916885aacSAxel Dörfler	return 0;
14016885aacSAxel Dörfler}
14116885aacSAxel Dörfler
14216885aacSAxel Dörfler
143085cf27bSIngo Weinholdoff_t
14416885aacSAxel DörflerNode::Size() const
14516885aacSAxel Dörfler{
14616885aacSAxel Dörfler	return 0LL;
14716885aacSAxel Dörfler}
14816885aacSAxel Dörfler
14916885aacSAxel Dörfler
150082a2195SAxel Dörflerino_t
151082a2195SAxel DörflerNode::Inode() const
152082a2195SAxel Dörfler{
153082a2195SAxel Dörfler	return 0;
154082a2195SAxel Dörfler}
155082a2195SAxel Dörfler
156082a2195SAxel Dörfler
15759ae1c81SIngo Weinholdvoid
15859ae1c81SIngo WeinholdNode::Stat(struct stat& stat)
15959ae1c81SIngo Weinhold{
16059ae1c81SIngo Weinhold	stat.st_mode = Type();
16159ae1c81SIngo Weinhold	stat.st_size = Size();
16259ae1c81SIngo Weinhold	stat.st_ino = Inode();
16359ae1c81SIngo Weinhold}
16459ae1c81SIngo Weinhold
16559ae1c81SIngo Weinhold
166085cf27bSIngo Weinholdstatus_t
16716885aacSAxel DörflerNode::Acquire()
16816885aacSAxel Dörfler{
16916885aacSAxel Dörfler	fRefCount++;
17041fc2405SAxel Dörfler	TRACE(("%p::Acquire(), fRefCount = %ld\n", this, fRefCount));
17116885aacSAxel Dörfler	return B_OK;
17216885aacSAxel Dörfler}
17316885aacSAxel Dörfler
1749da23568SFrançois Revol
175085cf27bSIngo Weinholdstatus_t
17616885aacSAxel DörflerNode::Release()
17716885aacSAxel Dörfler{
17841fc2405SAxel Dörfler	TRACE(("%p::Release(), fRefCount = %ld\n", this, fRefCount));
179f150614aSAxel Dörfler	if (--fRefCount == 0) {
180f150614aSAxel Dörfler		TRACE(("delete node: %p\n", this));
18116885aacSAxel Dörfler		delete this;
182f150614aSAxel Dörfler		return 1;
183f150614aSAxel Dörfler	}
18416885aacSAxel Dörfler
185f659db05SAxel Dörfler	return B_OK;
186f659db05SAxel Dörfler}
187f659db05SAxel Dörfler
188f659db05SAxel Dörfler
189cd671115SAxel Dörfler//	#pragma mark -
190f659db05SAxel Dörfler
191f659db05SAxel Dörfler
192f659db05SAxel DörflerConsoleNode::ConsoleNode()
193f659db05SAxel Dörfler	: Node()
194f659db05SAxel Dörfler{
195f659db05SAxel Dörfler}
196f659db05SAxel Dörfler
197f659db05SAxel Dörfler
198f659db05SAxel Dörflerssize_t
199f659db05SAxel DörflerConsoleNode::Read(void *buffer, size_t bufferSize)
200f659db05SAxel Dörfler{
201f659db05SAxel Dörfler	return ReadAt(NULL, -1, buffer, bufferSize);
202f659db05SAxel Dörfler}
203f659db05SAxel Dörfler
204f659db05SAxel Dörfler
205f659db05SAxel Dörflerssize_t
206f659db05SAxel DörflerConsoleNode::Write(const void *buffer, size_t bufferSize)
207f659db05SAxel Dörfler{
208f659db05SAxel Dörfler	return WriteAt(NULL, -1, buffer, bufferSize);
209f659db05SAxel Dörfler}
210f659db05SAxel Dörfler
211f659db05SAxel Dörfler
212cd671115SAxel Dörfler//	#pragma mark -
213f659db05SAxel Dörfler
214f659db05SAxel Dörfler
2150dc4d1e5SIngo WeinholdDirectory::Directory()
2160dc4d1e5SIngo Weinhold	: Node()
21716885aacSAxel Dörfler{
21816885aacSAxel Dörfler}
21916885aacSAxel Dörfler
22016885aacSAxel Dörfler
221085cf27bSIngo Weinholdssize_t
22216885aacSAxel DörflerDirectory::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
22316885aacSAxel Dörfler{
22416885aacSAxel Dörfler	return B_ERROR;
22516885aacSAxel Dörfler}
22616885aacSAxel Dörfler
22716885aacSAxel Dörfler
228085cf27bSIngo Weinholdssize_t
22916885aacSAxel DörflerDirectory::WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize)
23016885aacSAxel Dörfler{
23116885aacSAxel Dörfler	return B_ERROR;
23216885aacSAxel Dörfler}
23316885aacSAxel Dörfler
23416885aacSAxel Dörfler
235085cf27bSIngo Weinholdint32
23616885aacSAxel DörflerDirectory::Type() const
23716885aacSAxel Dörfler{
23816885aacSAxel Dörfler	return S_IFDIR;
23916885aacSAxel Dörfler}
24016885aacSAxel Dörfler
24116885aacSAxel Dörfler
242cbc85916SIngo WeinholdNode*
243cbc85916SIngo WeinholdDirectory::Lookup(const char* name, bool traverseLinks)
244cbc85916SIngo Weinhold{
245cbc85916SIngo Weinhold	Node* node = LookupDontTraverse(name);
246cbc85916SIngo Weinhold	if (node == NULL)
247cbc85916SIngo Weinhold		return NULL;
248cbc85916SIngo Weinhold
249cbc85916SIngo Weinhold	if (!traverseLinks || !S_ISLNK(node->Type()))
250cbc85916SIngo Weinhold		return node;
251cbc85916SIngo Weinhold
252cbc85916SIngo Weinhold	// the node is a symbolic link, so we have to resolve the path
253cbc85916SIngo Weinhold	char linkPath[B_PATH_NAME_LENGTH];
254cbc85916SIngo Weinhold	status_t error = node->ReadLink(linkPath, sizeof(linkPath));
255cbc85916SIngo Weinhold
256cbc85916SIngo Weinhold	node->Release();
257cbc85916SIngo Weinhold		// we don't need this one anymore
258cbc85916SIngo Weinhold
259cbc85916SIngo Weinhold	if (error != B_OK)
260cbc85916SIngo Weinhold		return NULL;
261cbc85916SIngo Weinhold
262cbc85916SIngo Weinhold	// let open_from() do the real work
263cbc85916SIngo Weinhold	int fd = open_from(this, linkPath, O_RDONLY);
264cbc85916SIngo Weinhold	if (fd < 0)
265cbc85916SIngo Weinhold		return NULL;
266cbc85916SIngo Weinhold
267cbc85916SIngo Weinhold	node = get_node_from(fd);
268cbc85916SIngo Weinhold	if (node != NULL)
269cbc85916SIngo Weinhold		node->Acquire();
270cbc85916SIngo Weinhold
271cbc85916SIngo Weinhold	close(fd);
272cbc85916SIngo Weinhold	return node;
273cbc85916SIngo Weinhold}
274cbc85916SIngo Weinhold
275cbc85916SIngo Weinhold
276085cf27bSIngo Weinholdstatus_t
277085cf27bSIngo WeinholdDirectory::CreateFile(const char *name, mode_t permissions, Node **_node)
278085cf27bSIngo Weinhold{
279085cf27bSIngo Weinhold	return EROFS;
280085cf27bSIngo Weinhold}
281085cf27bSIngo Weinhold
282085cf27bSIngo Weinhold
28316885aacSAxel Dörfler//	#pragma mark -
28416885aacSAxel Dörfler
28516885aacSAxel Dörfler
2869e8dc2a9SIngo WeinholdMemoryDisk::MemoryDisk(const uint8* data, size_t size, const char* name)
2879e8dc2a9SIngo Weinhold	: Node(),
2889e8dc2a9SIngo Weinhold	  fData(data),
2899e8dc2a9SIngo Weinhold	  fSize(size)
2909e8dc2a9SIngo Weinhold{
2919e8dc2a9SIngo Weinhold	strlcpy(fName, name, sizeof(fName));
2929e8dc2a9SIngo Weinhold}
2939e8dc2a9SIngo Weinhold
2949e8dc2a9SIngo Weinhold
2959e8dc2a9SIngo Weinholdssize_t
2969e8dc2a9SIngo WeinholdMemoryDisk::ReadAt(void* cookie, off_t pos, void* buffer, size_t bufferSize)
2979e8dc2a9SIngo Weinhold{
298211483cbSFredrik Holmqvist	if (pos < 0)
299211483cbSFredrik Holmqvist		return B_BAD_VALUE;
300211483cbSFredrik Holmqvist	if ((size_t)pos >= fSize)
3019e8dc2a9SIngo Weinhold		return 0;
3029e8dc2a9SIngo Weinhold
3039e8dc2a9SIngo Weinhold	if (pos + bufferSize > fSize)
3049e8dc2a9SIngo Weinhold		bufferSize = fSize - pos;
3059e8dc2a9SIngo Weinhold
3069e8dc2a9SIngo Weinhold	memcpy(buffer, fData + pos, bufferSize);
3079e8dc2a9SIngo Weinhold	return bufferSize;
3089e8dc2a9SIngo Weinhold}
3099e8dc2a9SIngo Weinhold
3109e8dc2a9SIngo Weinhold
3119e8dc2a9SIngo Weinholdssize_t
3129e8dc2a9SIngo WeinholdMemoryDisk::WriteAt(void* cookie, off_t pos, const void* buffer,
3139e8dc2a9SIngo Weinhold	size_t bufferSize)
3149e8dc2a9SIngo Weinhold{
3159e8dc2a9SIngo Weinhold	return B_NOT_ALLOWED;
3169e8dc2a9SIngo Weinhold}
3179e8dc2a9SIngo Weinhold
3189e8dc2a9SIngo Weinhold
3199e8dc2a9SIngo Weinholdoff_t
3209e8dc2a9SIngo WeinholdMemoryDisk::Size() const
3219e8dc2a9SIngo Weinhold{
3229e8dc2a9SIngo Weinhold	return fSize;
3239e8dc2a9SIngo Weinhold}
3249e8dc2a9SIngo Weinhold
3259e8dc2a9SIngo Weinhold
3269e8dc2a9SIngo Weinholdstatus_t
3279e8dc2a9SIngo WeinholdMemoryDisk::GetName(char *nameBuffer, size_t bufferSize) const
3289e8dc2a9SIngo Weinhold{
3299e8dc2a9SIngo Weinhold	if (!nameBuffer)
3309e8dc2a9SIngo Weinhold		return B_BAD_VALUE;
3319e8dc2a9SIngo Weinhold
3329e8dc2a9SIngo Weinhold	strlcpy(nameBuffer, fName, bufferSize);
3339e8dc2a9SIngo Weinhold	return B_OK;
3349e8dc2a9SIngo Weinhold}
3359e8dc2a9SIngo Weinhold
3369e8dc2a9SIngo Weinhold
3379e8dc2a9SIngo Weinhold//	#pragma mark -
3389e8dc2a9SIngo Weinhold
3399e8dc2a9SIngo Weinhold
340f659db05SAxel DörflerDescriptor::Descriptor(Node *node, void *cookie)
341f659db05SAxel Dörfler	:
342f659db05SAxel Dörfler	fNode(node),
343f659db05SAxel Dörfler	fCookie(cookie),
344f659db05SAxel Dörfler	fOffset(0),
345f659db05SAxel Dörfler	fRefCount(1)
346f659db05SAxel Dörfler{
347f659db05SAxel Dörfler}
348f659db05SAxel Dörfler
349f659db05SAxel Dörfler
350f659db05SAxel DörflerDescriptor::~Descriptor()
351f659db05SAxel Dörfler{
352f659db05SAxel Dörfler}
353f659db05SAxel Dörfler
354f659db05SAxel Dörfler
355085cf27bSIngo Weinholdssize_t
356f659db05SAxel DörflerDescriptor::Read(void *buffer, size_t bufferSize)
357f659db05SAxel Dörfler{
358f659db05SAxel Dörfler	ssize_t bytesRead = fNode->ReadAt(fCookie, fOffset, buffer, bufferSize);
359f659db05SAxel Dörfler	if (bytesRead > B_OK)
360f659db05SAxel Dörfler		fOffset += bytesRead;
361f659db05SAxel Dörfler
362f659db05SAxel Dörfler	return bytesRead;
363f659db05SAxel Dörfler}
364f659db05SAxel Dörfler
365f659db05SAxel Dörfler
366085cf27bSIngo Weinholdssize_t
3678de63d24SAxel DörflerDescriptor::ReadAt(off_t pos, void *buffer, size_t bufferSize)
368f659db05SAxel Dörfler{
369f659db05SAxel Dörfler	return fNode->ReadAt(fCookie, pos, buffer, bufferSize);
370f659db05SAxel Dörfler}
371f659db05SAxel Dörfler
372f659db05SAxel Dörfler
373f659db05SAxel Dörflerssize_t
374f659db05SAxel DörflerDescriptor::Write(const void *buffer, size_t bufferSize)
375f659db05SAxel Dörfler{
376f659db05SAxel Dörfler	ssize_t bytesWritten = fNode->WriteAt(fCookie, fOffset, buffer, bufferSize);
377f659db05SAxel Dörfler	if (bytesWritten > B_OK)
378f659db05SAxel Dörfler		fOffset += bytesWritten;
379f659db05SAxel Dörfler
380f659db05SAxel Dörfler	return bytesWritten;
381f659db05SAxel Dörfler}
382f659db05SAxel Dörfler
383f659db05SAxel Dörfler
384f659db05SAxel Dörflerssize_t
3858de63d24SAxel DörflerDescriptor::WriteAt(off_t pos, const void *buffer, size_t bufferSize)
386f659db05SAxel Dörfler{
387f659db05SAxel Dörfler	return fNode->WriteAt(fCookie, pos, buffer, bufferSize);
388f659db05SAxel Dörfler}
389f659db05SAxel Dörfler
390f659db05SAxel Dörfler
39159ae1c81SIngo Weinholdvoid
39216885aacSAxel DörflerDescriptor::Stat(struct stat &stat)
39316885aacSAxel Dörfler{
39459ae1c81SIngo Weinhold	fNode->Stat(stat);
39516885aacSAxel Dörfler}
39616885aacSAxel Dörfler
39716885aacSAxel Dörfler
39801e6d687SIngo Weinholdstatus_t
39901e6d687SIngo WeinholdDescriptor::Seek(off_t position, int mode)
40001e6d687SIngo Weinhold{
40101e6d687SIngo Weinhold	off_t newPosition;
40201e6d687SIngo Weinhold	switch (mode)
40301e6d687SIngo Weinhold	{
40401e6d687SIngo Weinhold		case SEEK_SET:
40501e6d687SIngo Weinhold			newPosition = position;
40601e6d687SIngo Weinhold			break;
40701e6d687SIngo Weinhold		case SEEK_CUR:
40801e6d687SIngo Weinhold			newPosition = fOffset + position;
40901e6d687SIngo Weinhold			break;
41001e6d687SIngo Weinhold		case SEEK_END:
41101e6d687SIngo Weinhold		{
41201e6d687SIngo Weinhold			struct stat st;
41301e6d687SIngo Weinhold			Stat(st);
41401e6d687SIngo Weinhold			newPosition = st.st_size + position;
41501e6d687SIngo Weinhold			break;
41601e6d687SIngo Weinhold		}
41701e6d687SIngo Weinhold		default:
41801e6d687SIngo Weinhold			return B_BAD_VALUE;
41901e6d687SIngo Weinhold	}
42001e6d687SIngo Weinhold
42101e6d687SIngo Weinhold	if (newPosition < 0)
42201e6d687SIngo Weinhold		return B_BAD_VALUE;
42301e6d687SIngo Weinhold
42401e6d687SIngo Weinhold	fOffset = newPosition;
42501e6d687SIngo Weinhold	return B_OK;
42601e6d687SIngo Weinhold}
42701e6d687SIngo Weinhold
42801e6d687SIngo Weinhold
429f659db05SAxel Dörflerstatus_t
430f659db05SAxel DörflerDescriptor::Acquire()
431f659db05SAxel Dörfler{
432f659db05SAxel Dörfler	fRefCount++;
433f659db05SAxel Dörfler	return B_OK;
434f659db05SAxel Dörfler}
435f659db05SAxel Dörfler
436f659db05SAxel Dörfler
437f659db05SAxel Dörflerstatus_t
438f659db05SAxel DörflerDescriptor::Release()
439f659db05SAxel Dörfler{
44016885aacSAxel Dörfler	if (--fRefCount == 0) {
441f659db05SAxel Dörfler		status_t status = fNode->Close(fCookie);
442f659db05SAxel Dörfler		if (status != B_OK)
443f659db05SAxel Dörfler			return status;
444f659db05SAxel Dörfler	}
445f659db05SAxel Dörfler
446f659db05SAxel Dörfler	return B_OK;
447f659db05SAxel Dörfler}
448f659db05SAxel Dörfler
449f659db05SAxel Dörfler
450cd671115SAxel Dörfler//	#pragma mark -
451f659db05SAxel Dörfler
452f659db05SAxel Dörfler
453d11ea2b5SIngo WeinholdBootVolume::BootVolume()
454d11ea2b5SIngo Weinhold	:
455d11ea2b5SIngo Weinhold	fRootDirectory(NULL),
456d11ea2b5SIngo Weinhold	fSystemDirectory(NULL),
4575c0f8450SIngo Weinhold	fPackageVolumeInfo(NULL),
4585c0f8450SIngo Weinhold	fPackageVolumeState(NULL)
459d11ea2b5SIngo Weinhold{
460d11ea2b5SIngo Weinhold}
461d11ea2b5SIngo Weinhold
462d11ea2b5SIngo Weinhold
463d11ea2b5SIngo WeinholdBootVolume::~BootVolume()
464d11ea2b5SIngo Weinhold{
465d11ea2b5SIngo Weinhold	Unset();
466d11ea2b5SIngo Weinhold}
467d11ea2b5SIngo Weinhold
468d11ea2b5SIngo Weinhold
469d11ea2b5SIngo Weinholdstatus_t
4705c0f8450SIngo WeinholdBootVolume::SetTo(Directory* rootDirectory,
4715c0f8450SIngo Weinhold	PackageVolumeInfo* packageVolumeInfo,
4725c0f8450SIngo Weinhold	PackageVolumeState* packageVolumeState)
4735c0f8450SIngo Weinhold{
4745c0f8450SIngo Weinhold	Unset();
4755c0f8450SIngo Weinhold
4765c0f8450SIngo Weinhold	status_t error = _SetTo(rootDirectory, packageVolumeInfo,
4775c0f8450SIngo Weinhold		packageVolumeState);
4785c0f8450SIngo Weinhold	if (error != B_OK)
4795c0f8450SIngo Weinhold		Unset();
4805c0f8450SIngo Weinhold
4815c0f8450SIngo Weinhold	return error;
4825c0f8450SIngo Weinhold}
4835c0f8450SIngo Weinhold
4845c0f8450SIngo Weinhold
4855c0f8450SIngo Weinholdvoid
4865c0f8450SIngo WeinholdBootVolume::Unset()
4875c0f8450SIngo Weinhold{
4885c0f8450SIngo Weinhold	if (fRootDirectory != NULL) {
4895c0f8450SIngo Weinhold		fRootDirectory->Release();
4905c0f8450SIngo Weinhold		fRootDirectory = NULL;
4915c0f8450SIngo Weinhold	}
4925c0f8450SIngo Weinhold
4935c0f8450SIngo Weinhold	if (fSystemDirectory != NULL) {
4945c0f8450SIngo Weinhold		fSystemDirectory->Release();
4955c0f8450SIngo Weinhold		fSystemDirectory = NULL;
4965c0f8450SIngo Weinhold	}
4975c0f8450SIngo Weinhold
4985c0f8450SIngo Weinhold	if (fPackageVolumeInfo != NULL) {
4995c0f8450SIngo Weinhold		fPackageVolumeInfo->ReleaseReference();
5005c0f8450SIngo Weinhold		fPackageVolumeInfo = NULL;
5015c0f8450SIngo Weinhold		fPackageVolumeState = NULL;
5025c0f8450SIngo Weinhold	}
5035c0f8450SIngo Weinhold}
5045c0f8450SIngo Weinhold
5055c0f8450SIngo Weinhold
5065c0f8450SIngo Weinholdstatus_t
5075c0f8450SIngo WeinholdBootVolume::_SetTo(Directory* rootDirectory,
5085c0f8450SIngo Weinhold	PackageVolumeInfo* packageVolumeInfo,
5095c0f8450SIngo Weinhold	PackageVolumeState* packageVolumeState)
510d11ea2b5SIngo Weinhold{
511d11ea2b5SIngo Weinhold	Unset();
512d11ea2b5SIngo Weinhold
513d11ea2b5SIngo Weinhold	if (rootDirectory == NULL)
514d11ea2b5SIngo Weinhold		return B_BAD_VALUE;
515d11ea2b5SIngo Weinhold
516d11ea2b5SIngo Weinhold	fRootDirectory = rootDirectory;
51763d56be3SIngo Weinhold	fRootDirectory->Acquire();
518d11ea2b5SIngo Weinhold
519d11ea2b5SIngo Weinhold	// find the system directory
520d11ea2b5SIngo Weinhold	Node* systemNode = fRootDirectory->Lookup("system", true);
521d11ea2b5SIngo Weinhold	if (systemNode == NULL || !S_ISDIR(systemNode->Type())) {
522d11ea2b5SIngo Weinhold		if (systemNode != NULL)
523d11ea2b5SIngo Weinhold			systemNode->Release();
524d11ea2b5SIngo Weinhold		Unset();
525d11ea2b5SIngo Weinhold		return B_ENTRY_NOT_FOUND;
526d11ea2b5SIngo Weinhold	}
527d11ea2b5SIngo Weinhold
528d11ea2b5SIngo Weinhold	fSystemDirectory = static_cast<Directory*>(systemNode);
529d11ea2b5SIngo Weinhold
5305c0f8450SIngo Weinhold	if (packageVolumeInfo == NULL) {
53135b38c39SJessica Hamilton		// get a package volume info
5325c0f8450SIngo Weinhold		BReference<PackageVolumeInfo> packageVolumeInfoReference(
5335c0f8450SIngo Weinhold			new(std::nothrow) PackageVolumeInfo);
5345c0f8450SIngo Weinhold		status_t error = packageVolumeInfoReference->SetTo(fSystemDirectory,
5355c0f8450SIngo Weinhold			"packages");
5365c0f8450SIngo Weinhold		if (error != B_OK) {
5375c0f8450SIngo Weinhold			// apparently not packaged
5385c0f8450SIngo Weinhold			return B_OK;
5395c0f8450SIngo Weinhold		}
5405c0f8450SIngo Weinhold
5415c0f8450SIngo Weinhold		fPackageVolumeInfo = packageVolumeInfoReference.Detach();
5425c0f8450SIngo Weinhold	} else {
5435c0f8450SIngo Weinhold		fPackageVolumeInfo = packageVolumeInfo;
5445c0f8450SIngo Weinhold		fPackageVolumeInfo->AcquireReference();
5455c0f8450SIngo Weinhold	}
5465c0f8450SIngo Weinhold
5475c0f8450SIngo Weinhold	fPackageVolumeState = packageVolumeState != NULL
5485c0f8450SIngo Weinhold		? packageVolumeState : fPackageVolumeInfo->States().Head();
5495c0f8450SIngo Weinhold
550cbc85916SIngo Weinhold	// try opening the system package
551066d5086SIngo Weinhold	int packageFD = _OpenSystemPackage();
5525c0f8450SIngo Weinhold	if (packageFD < 0)
5535c0f8450SIngo Weinhold		return packageFD;
554d11ea2b5SIngo Weinhold
5555c0f8450SIngo Weinhold	// mount packagefs
556cbc85916SIngo Weinhold	Directory* packageRootDirectory;
5573a7e0b00SIngo Weinhold	status_t error = packagefs_mount_file(packageFD, fSystemDirectory,
5583a7e0b00SIngo Weinhold		packageRootDirectory);
559cbc85916SIngo Weinhold	close(packageFD);
560cbc85916SIngo Weinhold	if (error != B_OK) {
561cbc85916SIngo Weinhold		Unset();
562cbc85916SIngo Weinhold		return error;
563cbc85916SIngo Weinhold	}
564cbc85916SIngo Weinhold
565cbc85916SIngo Weinhold	fSystemDirectory->Release();
566cbc85916SIngo Weinhold	fSystemDirectory = packageRootDirectory;
567cbc85916SIngo Weinhold
568cbc85916SIngo Weinhold	return B_OK;
569d11ea2b5SIngo Weinhold}
570d11ea2b5SIngo Weinhold
571d11ea2b5SIngo Weinhold
572066d5086SIngo Weinholdint
573066d5086SIngo WeinholdBootVolume::_OpenSystemPackage()
574066d5086SIngo Weinhold{
575066d5086SIngo Weinhold	// open the packages directory
576066d5086SIngo Weinhold	Node* packagesNode = fSystemDirectory->Lookup("packages", false);
577066d5086SIngo Weinhold	if (packagesNode == NULL)
578066d5086SIngo Weinhold		return -1;
579066d5086SIngo Weinhold	MethodDeleter<Node, status_t> packagesNodeReleaser(packagesNode,
580066d5086SIngo Weinhold		&Node::Release);
581066d5086SIngo Weinhold
582066d5086SIngo Weinhold	if (!S_ISDIR(packagesNode->Type()))
583066d5086SIngo Weinhold		return -1;
584066d5086SIngo Weinhold	Directory* packageDirectory = (Directory*)packagesNode;
585066d5086SIngo Weinhold
5865c0f8450SIngo Weinhold	// open the system package
5875c0f8450SIngo Weinhold	return open_from(packageDirectory, fPackageVolumeState->SystemPackage(),
5885c0f8450SIngo Weinhold		O_RDONLY);
589066d5086SIngo Weinhold}
590066d5086SIngo Weinhold
591066d5086SIngo Weinhold
592d11ea2b5SIngo Weinhold//	#pragma mark -
593d11ea2b5SIngo Weinhold
594d11ea2b5SIngo Weinhold
595f150614aSAxel Dörflerstatus_t
596f150614aSAxel Dörflervfs_init(stage2_args *args)
597f150614aSAxel Dörfler{
59882029bdaSMarcus Overhagen	gRoot = new(nothrow) RootFileSystem();
5997c198b5dSAxel Dörfler	if (gRoot == NULL)
6007c198b5dSAxel Dörfler		return B_NO_MEMORY;
601f150614aSAxel Dörfler
602f150614aSAxel Dörfler	return B_OK;
603f150614aSAxel Dörfler}
604f150614aSAxel Dörfler
605f150614aSAxel Dörfler
60604b9d56aSAxel Dörflerstatus_t
607533833f6SIngo Weinholdregister_boot_file_system(BootVolume& bootVolume)
6086822f148SAxel Dörfler{
609533833f6SIngo Weinhold	Directory* rootDirectory = bootVolume.RootDirectory();
610533833f6SIngo Weinhold	gRoot->AddLink("boot", rootDirectory);
611085cf27bSIngo Weinhold
61204b9d56aSAxel Dörfler	Partition *partition;
613533833f6SIngo Weinhold	status_t status = gRoot->GetPartitionFor(rootDirectory, &partition);
61404b9d56aSAxel Dörfler	if (status != B_OK) {
615533833f6SIngo Weinhold		dprintf("register_boot_file_system(): could not locate boot volume in "
616533833f6SIngo Weinhold			"root!\n");
61704b9d56aSAxel Dörfler		return status;
61804b9d56aSAxel Dörfler	}
61904b9d56aSAxel Dörfler
62025a7b01dSIngo Weinhold	gBootVolume.SetInt64(BOOT_VOLUME_PARTITION_OFFSET,
6219e8dc2a9SIngo Weinhold		partition->offset);
6225c0f8450SIngo Weinhold
6235c0f8450SIngo Weinhold	if (bootVolume.IsPackaged()) {
62425a7b01dSIngo Weinhold		gBootVolume.SetBool(BOOT_VOLUME_PACKAGED, true);
6255c0f8450SIngo Weinhold		PackageVolumeState* state = bootVolume.GetPackageVolumeState();
6265c0f8450SIngo Weinhold		if (state->Name() != NULL)
627