mirror of
				https://gitlab.com/sortix/sortix.git
				synced 2023-02-13 20:55:38 -05:00 
			
		
		
		
	Add umount(2) and unmountat(2).
This commit is contained in:
		
							parent
							
								
									e88a3ef654
								
							
						
					
					
						commit
						d890d3082d
					
				
					 28 changed files with 599 additions and 477 deletions
				
			
		
							
								
								
									
										346
									
								
								ext/extfs.cpp
									
										
									
									
									
								
							
							
						
						
									
										346
									
								
								ext/extfs.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2013.
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2013, 2014.
 | 
			
		||||
 | 
			
		||||
    This program is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU General Public License as published by the Free
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +23,7 @@
 | 
			
		|||
#define __STDC_CONSTANT_MACROS
 | 
			
		||||
#define __STDC_LIMIT_MACROS
 | 
			
		||||
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +50,7 @@
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__sortix__)
 | 
			
		||||
#include <ioleast.h>
 | 
			
		||||
#include <timespec.h>
 | 
			
		||||
#else
 | 
			
		||||
struct timespec timespec_make(time_t sec, long nsec)
 | 
			
		||||
| 
						 | 
				
			
			@ -80,6 +82,8 @@ struct timespec timespec_make(time_t sec, long nsec)
 | 
			
		|||
#include "ioleast.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
static volatile bool should_terminate = false;
 | 
			
		||||
 | 
			
		||||
const uint32_t EXT2_FEATURE_COMPAT_SUPPORTED = 0;
 | 
			
		||||
const uint32_t EXT2_FEATURE_INCOMPAT_SUPPORTED = \
 | 
			
		||||
               EXT2_FEATURE_INCOMPAT_FILETYPE;
 | 
			
		||||
| 
						 | 
				
			
			@ -146,105 +150,103 @@ void StatInode(Inode* inode, struct stat* st)
 | 
			
		|||
 | 
			
		||||
#if defined(__sortix__)
 | 
			
		||||
 | 
			
		||||
bool RespondData(int svr, int chl, const void* ptr, size_t count)
 | 
			
		||||
bool RespondData(int chl, const void* ptr, size_t count)
 | 
			
		||||
{
 | 
			
		||||
	return fsm_send(svr, chl, ptr, count) == (ssize_t) count;
 | 
			
		||||
	return writeall(chl, ptr, count) == count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RespondHeader(int svr, int chl, size_t type, size_t size)
 | 
			
		||||
bool RespondHeader(int chl, size_t type, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	struct fsm_msg_header hdr;
 | 
			
		||||
	hdr.msgtype = type;
 | 
			
		||||
	hdr.msgsize = size;
 | 
			
		||||
	return RespondData(svr, chl, &hdr, sizeof(hdr));
 | 
			
		||||
	return RespondData(chl, &hdr, sizeof(hdr));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RespondMessage(int svr, int chl, unsigned int type, const void* ptr,
 | 
			
		||||
                    size_t count)
 | 
			
		||||
bool RespondMessage(int chl, unsigned int type, const void* ptr, size_t count)
 | 
			
		||||
{
 | 
			
		||||
	return RespondHeader(svr, chl, type, count) &&
 | 
			
		||||
	       RespondData(svr, chl, ptr, count);
 | 
			
		||||
	return RespondHeader(chl, type, count) &&
 | 
			
		||||
	       RespondData(chl, ptr, count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RespondError(int svr, int chl, int errnum)
 | 
			
		||||
bool RespondError(int chl, int errnum)
 | 
			
		||||
{
 | 
			
		||||
	struct fsm_resp_error body;
 | 
			
		||||
	body.errnum = errnum;
 | 
			
		||||
	//fprintf(stderr, "extfs: sending error %i (%s)\n", errnum, strerror(errnum));
 | 
			
		||||
	return RespondMessage(svr, chl, FSM_RESP_ERROR, &body, sizeof(body));
 | 
			
		||||
	return RespondMessage(chl, FSM_RESP_ERROR, &body, sizeof(body));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RespondSuccess(int svr, int chl)
 | 
			
		||||
bool RespondSuccess(int chl)
 | 
			
		||||
{
 | 
			
		||||
	struct fsm_resp_success body;
 | 
			
		||||
	return RespondMessage(svr, chl, FSM_RESP_SUCCESS, &body, sizeof(body));
 | 
			
		||||
	return RespondMessage(chl, FSM_RESP_SUCCESS, &body, sizeof(body));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RespondStat(int svr, int chl, struct stat* st)
 | 
			
		||||
bool RespondStat(int chl, struct stat* st)
 | 
			
		||||
{
 | 
			
		||||
	struct fsm_resp_stat body;
 | 
			
		||||
	body.st = *st;
 | 
			
		||||
	return RespondMessage(svr, chl, FSM_RESP_STAT, &body, sizeof(body));
 | 
			
		||||
	return RespondMessage(chl, FSM_RESP_STAT, &body, sizeof(body));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RespondSeek(int svr, int chl, off_t offset)
 | 
			
		||||
bool RespondSeek(int chl, off_t offset)
 | 
			
		||||
{
 | 
			
		||||
	struct fsm_resp_lseek body;
 | 
			
		||||
	body.offset = offset;
 | 
			
		||||
	return RespondMessage(svr, chl, FSM_RESP_LSEEK, &body, sizeof(body));
 | 
			
		||||
	return RespondMessage(chl, FSM_RESP_LSEEK, &body, sizeof(body));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RespondRead(int svr, int chl, const uint8_t* buf, size_t count)
 | 
			
		||||
bool RespondRead(int chl, const uint8_t* buf, size_t count)
 | 
			
		||||
{
 | 
			
		||||
	struct fsm_resp_read body;
 | 
			
		||||
	body.count = count;
 | 
			
		||||
	return RespondMessage(svr, chl, FSM_RESP_READ, &body, sizeof(body)) &&
 | 
			
		||||
	       RespondData(svr, chl, buf, count);
 | 
			
		||||
	return RespondMessage(chl, FSM_RESP_READ, &body, sizeof(body)) &&
 | 
			
		||||
	       RespondData(chl, buf, count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RespondReadlink(int svr, int chl, const uint8_t* buf, size_t count)
 | 
			
		||||
bool RespondReadlink(int chl, const uint8_t* buf, size_t count)
 | 
			
		||||
{
 | 
			
		||||
	struct fsm_resp_readlink body;
 | 
			
		||||
	body.targetlen = count;
 | 
			
		||||
	return RespondMessage(svr, chl, FSM_RESP_READLINK, &body, sizeof(body)) &&
 | 
			
		||||
	       RespondData(svr, chl, buf, count);
 | 
			
		||||
	return RespondMessage(chl, FSM_RESP_READLINK, &body, sizeof(body)) &&
 | 
			
		||||
	       RespondData(chl, buf, count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RespondWrite(int svr, int chl, size_t count)
 | 
			
		||||
bool RespondWrite(int chl, size_t count)
 | 
			
		||||
{
 | 
			
		||||
	struct fsm_resp_write body;
 | 
			
		||||
	body.count = count;
 | 
			
		||||
	return RespondMessage(svr, chl, FSM_RESP_WRITE, &body, sizeof(body));
 | 
			
		||||
	return RespondMessage(chl, FSM_RESP_WRITE, &body, sizeof(body));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RespondOpen(int svr, int chl, ino_t ino, mode_t type)
 | 
			
		||||
bool RespondOpen(int chl, ino_t ino, mode_t type)
 | 
			
		||||
{
 | 
			
		||||
	struct fsm_resp_open body;
 | 
			
		||||
	body.ino = ino;
 | 
			
		||||
	body.type = type;
 | 
			
		||||
	return RespondMessage(svr, chl, FSM_RESP_OPEN, &body, sizeof(body));
 | 
			
		||||
	return RespondMessage(chl, FSM_RESP_OPEN, &body, sizeof(body));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RespondMakeDir(int svr, int chl, ino_t ino)
 | 
			
		||||
bool RespondMakeDir(int chl, ino_t ino)
 | 
			
		||||
{
 | 
			
		||||
	struct fsm_resp_mkdir body;
 | 
			
		||||
	body.ino = ino;
 | 
			
		||||
	return RespondMessage(svr, chl, FSM_RESP_MKDIR, &body, sizeof(body));
 | 
			
		||||
	return RespondMessage(chl, FSM_RESP_MKDIR, &body, sizeof(body));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RespondReadDir(int svr, int chl, struct kernel_dirent* dirent)
 | 
			
		||||
bool RespondReadDir(int chl, struct kernel_dirent* dirent)
 | 
			
		||||
{
 | 
			
		||||
	struct fsm_resp_readdirents body;
 | 
			
		||||
	body.ino = dirent->d_ino;
 | 
			
		||||
	body.type = dirent->d_type;
 | 
			
		||||
	body.namelen = dirent->d_namlen;
 | 
			
		||||
	return RespondMessage(svr, chl, FSM_RESP_READDIRENTS, &body, sizeof(body)) &&
 | 
			
		||||
	       RespondData(svr, chl, dirent->d_name, dirent->d_namlen);
 | 
			
		||||
	return RespondMessage(chl, FSM_RESP_READDIRENTS, &body, sizeof(body)) &&
 | 
			
		||||
	       RespondData(chl, dirent->d_name, dirent->d_namlen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleRefer(int svr, int chl, struct fsm_req_refer* msg, Filesystem* fs)
 | 
			
		||||
void HandleRefer(int chl, struct fsm_req_refer* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	(void) svr;
 | 
			
		||||
	(void) chl;
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino )
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -252,9 +254,8 @@ void HandleRefer(int svr, int chl, struct fsm_req_refer* msg, Filesystem* fs)
 | 
			
		|||
		inode->RemoteRefer();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleUnref(int svr, int chl, struct fsm_req_unref* msg, Filesystem* fs)
 | 
			
		||||
void HandleUnref(int chl, struct fsm_req_unref* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	(void) svr;
 | 
			
		||||
	(void) chl;
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino )
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -262,32 +263,32 @@ void HandleUnref(int svr, int chl, struct fsm_req_unref* msg, Filesystem* fs)
 | 
			
		|||
		inode->RemoteUnref();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleSync(int svr, int chl, struct fsm_req_sync* msg, Filesystem* fs)
 | 
			
		||||
void HandleSync(int chl, struct fsm_req_sync* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->ino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
	inode->Sync();
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
	RespondSuccess(svr, chl);
 | 
			
		||||
	RespondSuccess(chl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleStat(int svr, int chl, struct fsm_req_stat* msg, Filesystem* fs)
 | 
			
		||||
void HandleStat(int chl, struct fsm_req_stat* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->ino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
	struct stat st;
 | 
			
		||||
	StatInode(inode, &st);
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
	RespondStat(svr, chl, &st);
 | 
			
		||||
	RespondStat(chl, &st);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleChangeMode(int svr, int chl, struct fsm_req_chmod* msg, Filesystem* fs)
 | 
			
		||||
void HandleChangeMode(int chl, struct fsm_req_chmod* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->ino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
	uint32_t req_mode = ExtModeFromHostMode(msg->mode);
 | 
			
		||||
	uint32_t old_mode = inode->Mode();
 | 
			
		||||
	uint32_t new_mode = (old_mode & ~S_SETABLE) | (req_mode & S_SETABLE);
 | 
			
		||||
| 
						 | 
				
			
			@ -295,96 +296,96 @@ void HandleChangeMode(int svr, int chl, struct fsm_req_chmod* msg, Filesystem* f
 | 
			
		|||
	inode->Unref();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleChangeOwner(int svr, int chl, struct fsm_req_chown* msg, Filesystem* fs)
 | 
			
		||||
void HandleChangeOwner(int chl, struct fsm_req_chown* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->ino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
	inode->SetUserId((uint32_t) msg->uid);
 | 
			
		||||
	inode->SetGroupId((uint32_t) msg->gid);
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
	RespondSuccess(svr, chl);
 | 
			
		||||
	RespondSuccess(chl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleUTimens(int svr, int chl, struct fsm_req_utimens* msg, Filesystem* fs)
 | 
			
		||||
void HandleUTimens(int chl, struct fsm_req_utimens* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->ino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
	inode->data->i_atime = msg->times[0].tv_sec;
 | 
			
		||||
	inode->data->i_mtime = msg->times[1].tv_sec;
 | 
			
		||||
	inode->Dirty();
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
	RespondSuccess(svr, chl);
 | 
			
		||||
	RespondSuccess(chl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleTruncate(int svr, int chl, struct fsm_req_truncate* msg, Filesystem* fs)
 | 
			
		||||
void HandleTruncate(int chl, struct fsm_req_truncate* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if( msg->size < 0 ) { RespondError(svr, chl, EINVAL); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if( msg->size < 0 ) { RespondError(chl, EINVAL); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->ino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
	inode->Truncate((uint64_t) msg->size);
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
	RespondSuccess(svr, chl);
 | 
			
		||||
	RespondSuccess(chl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleSeek(int svr, int chl, struct fsm_req_lseek* msg, Filesystem* fs)
 | 
			
		||||
void HandleSeek(int chl, struct fsm_req_lseek* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->ino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
	if ( msg->whence == SEEK_SET )
 | 
			
		||||
		RespondSeek(svr, chl, msg->offset);
 | 
			
		||||
		RespondSeek(chl, msg->offset);
 | 
			
		||||
	else if ( msg->whence == SEEK_END )
 | 
			
		||||
	{
 | 
			
		||||
		off_t inode_size = inode->Size();
 | 
			
		||||
		if ( (msg->offset < 0 && inode_size + msg->offset < 0) ||
 | 
			
		||||
		     (0 <= msg->offset && OFF_MAX - inode_size < msg->offset) )
 | 
			
		||||
			RespondError(svr, chl, EOVERFLOW);
 | 
			
		||||
			RespondError(chl, EOVERFLOW);
 | 
			
		||||
		else
 | 
			
		||||
			RespondSeek(svr, chl, msg->offset + inode_size);
 | 
			
		||||
			RespondSeek(chl, msg->offset + inode_size);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		RespondError(svr, chl, EINVAL);
 | 
			
		||||
		RespondError(chl, EINVAL);
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleReadAt(int svr, int chl, struct fsm_req_pread* msg, Filesystem* fs)
 | 
			
		||||
void HandleReadAt(int chl, struct fsm_req_pread* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->ino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
	uint8_t* buf = (uint8_t*) malloc(msg->count);
 | 
			
		||||
	if ( !buf ) { inode->Unref(); RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !buf ) { inode->Unref(); RespondError(chl, errno); return; }
 | 
			
		||||
	ssize_t amount = inode->ReadAt(buf, msg->count, msg->offset);
 | 
			
		||||
	RespondRead(svr, chl, buf, amount);
 | 
			
		||||
	RespondRead(chl, buf, amount);
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
	free(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleWriteAt(int svr, int chl, struct fsm_req_pread* msg, Filesystem* fs)
 | 
			
		||||
void HandleWriteAt(int chl, struct fsm_req_pread* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->ino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
	const uint8_t* buf = (const uint8_t*) &msg[1];
 | 
			
		||||
	ssize_t amount = inode->WriteAt(buf, msg->count, msg->offset);
 | 
			
		||||
	RespondWrite(svr, chl, amount);
 | 
			
		||||
	RespondWrite(chl, amount);
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleOpen(int svr, int chl, struct fsm_req_open* msg, Filesystem* fs)
 | 
			
		||||
void HandleOpen(int chl, struct fsm_req_open* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->dirino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->dirino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->dirino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
 | 
			
		||||
	char* pathraw = (char*) &(msg[1]);
 | 
			
		||||
	char* path = (char*) malloc(msg->namelen+1);
 | 
			
		||||
	if ( !path )
 | 
			
		||||
	{
 | 
			
		||||
		RespondError(svr, chl, errno);
 | 
			
		||||
		RespondError(chl, errno);
 | 
			
		||||
		inode->Unref();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -396,23 +397,23 @@ void HandleOpen(int svr, int chl, struct fsm_req_open* msg, Filesystem* fs)
 | 
			
		|||
	free(path);
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
 | 
			
		||||
	if ( !result ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !result ) { RespondError(chl, errno); return; }
 | 
			
		||||
 | 
			
		||||
	RespondOpen(svr, chl, result->inode_id, result->Mode() & S_IFMT);
 | 
			
		||||
	RespondOpen(chl, result->inode_id, result->Mode() & S_IFMT);
 | 
			
		||||
	result->Unref();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleMakeDir(int svr, int chl, struct fsm_req_open* msg, Filesystem* fs)
 | 
			
		||||
void HandleMakeDir(int chl, struct fsm_req_open* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->dirino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->dirino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->dirino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
 | 
			
		||||
	char* pathraw = (char*) &(msg[1]);
 | 
			
		||||
	char* path = (char*) malloc(msg->namelen+1);
 | 
			
		||||
	if ( !path )
 | 
			
		||||
	{
 | 
			
		||||
		RespondError(svr, chl, errno);
 | 
			
		||||
		RespondError(chl, errno);
 | 
			
		||||
		inode->Unref();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -424,21 +425,21 @@ void HandleMakeDir(int svr, int chl, struct fsm_req_open* msg, Filesystem* fs)
 | 
			
		|||
	free(path);
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
 | 
			
		||||
	if ( !result ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !result ) { RespondError(chl, errno); return; }
 | 
			
		||||
 | 
			
		||||
	RespondMakeDir(svr, chl, result->inode_id);
 | 
			
		||||
	RespondMakeDir(chl, result->inode_id);
 | 
			
		||||
	result->Unref();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleReadDir(int svr, int chl, struct fsm_req_readdirents* msg, Filesystem* fs)
 | 
			
		||||
void HandleReadDir(int chl, struct fsm_req_readdirents* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->ino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
	if ( !S_ISDIR(inode->Mode()) )
 | 
			
		||||
	{
 | 
			
		||||
		inode->Unref();
 | 
			
		||||
		RespondError(svr, chl, ENOTDIR);
 | 
			
		||||
		RespondError(chl, ENOTDIR);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	union
 | 
			
		||||
| 
						 | 
				
			
			@ -462,7 +463,7 @@ void HandleReadDir(int svr, int chl, struct fsm_req_readdirents* msg, Filesystem
 | 
			
		|||
		if ( !block && !(block = inode->GetBlock(block_id = entry_block_id)) )
 | 
			
		||||
		{
 | 
			
		||||
			inode->Unref();
 | 
			
		||||
			RespondError(svr, chl, errno);
 | 
			
		||||
			RespondError(chl, errno);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		const uint8_t* block_data = block->block_data + entry_block_offset;
 | 
			
		||||
| 
						 | 
				
			
			@ -480,7 +481,7 @@ void HandleReadDir(int svr, int chl, struct fsm_req_readdirents* msg, Filesystem
 | 
			
		|||
			padding[dname_offset + kernel_entry.d_namlen] = '\0';
 | 
			
		||||
			block->Unref();
 | 
			
		||||
			inode->Unref();
 | 
			
		||||
			RespondReadDir(svr, chl, &kernel_entry);
 | 
			
		||||
			RespondReadDir(chl, &kernel_entry);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		offset += entry->reclen;
 | 
			
		||||
| 
						 | 
				
			
			@ -489,29 +490,29 @@ void HandleReadDir(int svr, int chl, struct fsm_req_readdirents* msg, Filesystem
 | 
			
		|||
		block->Unref();
 | 
			
		||||
 | 
			
		||||
	kernel_entry.d_reclen = sizeof(kernel_entry);
 | 
			
		||||
	RespondReadDir(svr, chl, &kernel_entry);
 | 
			
		||||
	RespondReadDir(chl, &kernel_entry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleIsATTY(int svr, int chl, struct fsm_req_isatty* msg, Filesystem* fs)
 | 
			
		||||
void HandleIsATTY(int chl, struct fsm_req_isatty* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->ino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	RespondError(svr, chl, ENOTTY);
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
	RespondError(chl, ENOTTY);
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleUnlink(int svr, int chl, struct fsm_req_unlink* msg, Filesystem* fs)
 | 
			
		||||
void HandleUnlink(int chl, struct fsm_req_unlink* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->dirino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->dirino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->dirino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
 | 
			
		||||
	char* pathraw = (char*) &(msg[1]);
 | 
			
		||||
	char* path = (char*) malloc(msg->namelen+1);
 | 
			
		||||
	if ( !path )
 | 
			
		||||
	{
 | 
			
		||||
		RespondError(svr, chl, errno);
 | 
			
		||||
		RespondError(chl, errno);
 | 
			
		||||
		inode->Unref();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -522,24 +523,24 @@ void HandleUnlink(int svr, int chl, struct fsm_req_unlink* msg, Filesystem* fs)
 | 
			
		|||
	free(path);
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
 | 
			
		||||
	if ( !result ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !result ) { RespondError(chl, errno); return; }
 | 
			
		||||
 | 
			
		||||
	result->Unref();
 | 
			
		||||
 | 
			
		||||
	RespondSuccess(svr, chl);
 | 
			
		||||
	RespondSuccess(chl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleRemoveDir(int svr, int chl, struct fsm_req_unlink* msg, Filesystem* fs)
 | 
			
		||||
void HandleRemoveDir(int chl, struct fsm_req_unlink* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->dirino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->dirino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->dirino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
 | 
			
		||||
	char* pathraw = (char*) &(msg[1]);
 | 
			
		||||
	char* path = (char*) malloc(msg->namelen+1);
 | 
			
		||||
	if ( !path )
 | 
			
		||||
	{
 | 
			
		||||
		RespondError(svr, chl, errno);
 | 
			
		||||
		RespondError(chl, errno);
 | 
			
		||||
		inode->Unref();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -547,28 +548,28 @@ void HandleRemoveDir(int svr, int chl, struct fsm_req_unlink* msg, Filesystem* f
 | 
			
		|||
	path[msg->namelen] = '\0';
 | 
			
		||||
 | 
			
		||||
	if ( inode->RemoveDirectory(path) )
 | 
			
		||||
		RespondSuccess(svr, chl);
 | 
			
		||||
		RespondSuccess(chl);
 | 
			
		||||
	else
 | 
			
		||||
		RespondError(svr, chl, errno);
 | 
			
		||||
		RespondError(chl, errno);
 | 
			
		||||
 | 
			
		||||
	free(path);
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleLink(int svr, int chl, struct fsm_req_link* msg, Filesystem* fs)
 | 
			
		||||
void HandleLink(int chl, struct fsm_req_link* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->dirino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->linkino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->dirino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->linkino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->dirino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
	Inode* dest = fs->GetInode((uint32_t) msg->linkino);
 | 
			
		||||
	if ( !dest ) { inode->Unref(); RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !dest ) { inode->Unref(); RespondError(chl, errno); return; }
 | 
			
		||||
 | 
			
		||||
	char* pathraw = (char*) &(msg[1]);
 | 
			
		||||
	char* path = (char*) malloc(msg->namelen+1);
 | 
			
		||||
	if ( !path )
 | 
			
		||||
	{
 | 
			
		||||
		RespondError(svr, chl, errno);
 | 
			
		||||
		RespondError(chl, errno);
 | 
			
		||||
		inode->Unref();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -576,26 +577,26 @@ void HandleLink(int svr, int chl, struct fsm_req_link* msg, Filesystem* fs)
 | 
			
		|||
	path[msg->namelen] = '\0';
 | 
			
		||||
 | 
			
		||||
	if ( inode->Link(path, dest, false) )
 | 
			
		||||
		RespondSuccess(svr, chl);
 | 
			
		||||
		RespondSuccess(chl);
 | 
			
		||||
	else
 | 
			
		||||
		RespondError(svr, chl, errno);
 | 
			
		||||
		RespondError(chl, errno);
 | 
			
		||||
 | 
			
		||||
	free(path);
 | 
			
		||||
	dest->Unref();
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleSymlink(int svr, int chl, struct fsm_req_symlink* msg, Filesystem* fs)
 | 
			
		||||
void HandleSymlink(int chl, struct fsm_req_symlink* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->dirino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->dirino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->dirino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
 | 
			
		||||
	char* dest_raw = (char*) &(msg[1]);
 | 
			
		||||
	char* dest = (char*) malloc(msg->targetlen + 1);
 | 
			
		||||
	if ( !dest )
 | 
			
		||||
	{
 | 
			
		||||
		RespondError(svr, chl, errno);
 | 
			
		||||
		RespondError(chl, errno);
 | 
			
		||||
		inode->Unref();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -606,7 +607,7 @@ void HandleSymlink(int svr, int chl, struct fsm_req_symlink* msg, Filesystem* fs
 | 
			
		|||
	char* path = (char*) malloc(msg->namelen + 1);
 | 
			
		||||
	if ( !path )
 | 
			
		||||
	{
 | 
			
		||||
		RespondError(svr, chl, errno);
 | 
			
		||||
		RespondError(chl, errno);
 | 
			
		||||
		inode->Unref();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -614,38 +615,38 @@ void HandleSymlink(int svr, int chl, struct fsm_req_symlink* msg, Filesystem* fs
 | 
			
		|||
	path[msg->namelen] = '\0';
 | 
			
		||||
 | 
			
		||||
	if ( inode->Symlink(path, dest) )
 | 
			
		||||
		RespondSuccess(svr, chl);
 | 
			
		||||
		RespondSuccess(chl);
 | 
			
		||||
	else
 | 
			
		||||
		RespondError(svr, chl, errno);
 | 
			
		||||
		RespondError(chl, errno);
 | 
			
		||||
 | 
			
		||||
	free(path);
 | 
			
		||||
	free(dest);
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleReadlink(int svr, int chl, struct fsm_req_readlink* msg, Filesystem* fs)
 | 
			
		||||
void HandleReadlink(int chl, struct fsm_req_readlink* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	Inode* inode = fs->GetInode((uint32_t) msg->ino);
 | 
			
		||||
	if ( !inode ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !EXT2_S_ISLNK(inode->Mode()) ) { RespondError(svr, chl, EINVAL); return; }
 | 
			
		||||
	if ( !inode ) { RespondError(chl, errno); return; }
 | 
			
		||||
	if ( !EXT2_S_ISLNK(inode->Mode()) ) { RespondError(chl, EINVAL); return; }
 | 
			
		||||
	size_t count = inode->Size();
 | 
			
		||||
	uint8_t* buf = (uint8_t*) malloc(count);
 | 
			
		||||
	if ( !buf ) { inode->Unref(); RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !buf ) { inode->Unref(); RespondError(chl, errno); return; }
 | 
			
		||||
	ssize_t amount = inode->ReadAt(buf, count, 0);
 | 
			
		||||
	RespondReadlink(svr, chl, buf, amount);
 | 
			
		||||
	RespondReadlink(chl, buf, amount);
 | 
			
		||||
	inode->Unref();
 | 
			
		||||
	free(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleRename(int svr, int chl, struct fsm_req_rename* msg, Filesystem* fs)
 | 
			
		||||
void HandleRename(int chl, struct fsm_req_rename* msg, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( fs->num_inodes <= msg->olddirino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->newdirino ) { RespondError(svr, chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->olddirino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
	if ( fs->num_inodes <= msg->newdirino ) { RespondError(chl, EBADF); return; }
 | 
			
		||||
 | 
			
		||||
	char* pathraw = (char*) &(msg[1]);
 | 
			
		||||
	char* path = (char*) malloc(msg->oldnamelen+1 + msg->newnamelen+1);
 | 
			
		||||
	if ( !path ) { RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !path ) { RespondError(chl, errno); return; }
 | 
			
		||||
	memcpy(path, pathraw, msg->oldnamelen);
 | 
			
		||||
	path[msg->oldnamelen] = '\0';
 | 
			
		||||
	memcpy(path + msg->oldnamelen + 1, pathraw + msg->oldnamelen, msg->newnamelen);
 | 
			
		||||
| 
						 | 
				
			
			@ -655,24 +656,23 @@ void HandleRename(int svr, int chl, struct fsm_req_rename* msg, Filesystem* fs)
 | 
			
		|||
	const char* newname = path + msg->oldnamelen + 1;
 | 
			
		||||
 | 
			
		||||
	Inode* olddir = fs->GetInode((uint32_t) msg->olddirino);
 | 
			
		||||
	if ( !olddir ) { free(path); RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !olddir ) { free(path); RespondError(chl, errno); return; }
 | 
			
		||||
	Inode* newdir = fs->GetInode((uint32_t) msg->newdirino);
 | 
			
		||||
	if ( !newdir ) { olddir->Unref(); free(path); RespondError(svr, chl, errno); return; }
 | 
			
		||||
	if ( !newdir ) { olddir->Unref(); free(path); RespondError(chl, errno); return; }
 | 
			
		||||
 | 
			
		||||
	if ( newdir->Rename(olddir, oldname, newname) )
 | 
			
		||||
		RespondSuccess(svr, chl);
 | 
			
		||||
		RespondSuccess(chl);
 | 
			
		||||
	else
 | 
			
		||||
		RespondError(svr, chl, errno);
 | 
			
		||||
		RespondError(chl, errno);
 | 
			
		||||
 | 
			
		||||
	newdir->Unref();
 | 
			
		||||
	olddir->Unref();
 | 
			
		||||
	free(path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HandleIncomingMessage(int svr, int chl, struct fsm_msg_header* hdr,
 | 
			
		||||
                           Filesystem* fs)
 | 
			
		||||
void HandleIncomingMessage(int chl, struct fsm_msg_header* hdr, Filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	typedef void (*handler_t)(int, int, void*, Filesystem*);
 | 
			
		||||
	typedef void (*handler_t)(int, void*, Filesystem*);
 | 
			
		||||
	handler_t handlers[FSM_MSG_NUM] = { NULL };
 | 
			
		||||
	handlers[FSM_REQ_SYNC] = (handler_t) HandleSync;
 | 
			
		||||
	handlers[FSM_REQ_STAT] = (handler_t) HandleStat;
 | 
			
		||||
| 
						 | 
				
			
			@ -700,25 +700,25 @@ void HandleIncomingMessage(int svr, int chl, struct fsm_msg_header* hdr,
 | 
			
		|||
	if ( FSM_MSG_NUM <= hdr->msgtype || !handlers[hdr->msgtype] )
 | 
			
		||||
	{
 | 
			
		||||
		fprintf(stderr, "extfs: message type %zu not supported!\n", hdr->msgtype);
 | 
			
		||||
		RespondError(svr, chl, ENOTSUP);
 | 
			
		||||
		RespondError(chl, ENOTSUP);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	uint8_t* body = (uint8_t*) malloc(hdr->msgsize);
 | 
			
		||||
	if ( !body )
 | 
			
		||||
	{
 | 
			
		||||
		fprintf(stderr, "extfs: message of type %zu too large: %zu bytes\n", hdr->msgtype, hdr->msgsize);
 | 
			
		||||
		RespondError(svr, chl, errno);
 | 
			
		||||
		RespondError(chl, errno);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	ssize_t amount = fsm_recv(svr, chl, body, hdr->msgsize);
 | 
			
		||||
	if ( amount < (ssize_t) hdr->msgsize )
 | 
			
		||||
	size_t amount = readall(chl, body, hdr->msgsize);
 | 
			
		||||
	if ( amount < hdr->msgsize )
 | 
			
		||||
	{
 | 
			
		||||
		fprintf(stderr, "extfs: incomplete message of type %zu: got %zi of %zu bytes\n", hdr->msgtype, amount, hdr->msgsize);
 | 
			
		||||
		RespondError(svr, chl, errno);
 | 
			
		||||
		RespondError(chl, errno);
 | 
			
		||||
		free(body);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	handlers[hdr->msgtype](svr, chl, body, fs);
 | 
			
		||||
	handlers[hdr->msgtype](chl, body, fs);
 | 
			
		||||
	free(body);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -726,7 +726,6 @@ void AlarmHandler(int)
 | 
			
		|||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static volatile bool should_terminate = false;
 | 
			
		||||
void TerminationHandler(int)
 | 
			
		||||
{
 | 
			
		||||
	should_terminate = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -1471,32 +1470,22 @@ int main(int argc, char* argv[])
 | 
			
		|||
	for ( size_t i = 0; i < fs->num_groups; i++ )
 | 
			
		||||
		fs->block_groups[i] = NULL;
 | 
			
		||||
 | 
			
		||||
#if defined(__sortix__)
 | 
			
		||||
	if ( !mount_path )
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	// Open the mount point.
 | 
			
		||||
	int mountfd = open(mount_path, O_RDWR | O_DIRECTORY);
 | 
			
		||||
	if ( mountfd < 0 )
 | 
			
		||||
		error(1, errno, "%s", mount_path);
 | 
			
		||||
#if defined(__sortix__)
 | 
			
		||||
	// Stat the root inode.
 | 
			
		||||
	struct stat root_inode_st;
 | 
			
		||||
	Inode* root_inode = fs->GetInode((uint32_t) EXT2_ROOT_INO);
 | 
			
		||||
	if ( !root_inode )
 | 
			
		||||
		error(1, errno, "GetInode(%u)", EXT2_ROOT_INO);
 | 
			
		||||
	StatInode(root_inode, &root_inode_st);
 | 
			
		||||
	root_inode->Unref();
 | 
			
		||||
 | 
			
		||||
	// Create a filesystem server connected to the kernel that we'll listen on.
 | 
			
		||||
	int serverfd = fsm_mkserver();
 | 
			
		||||
	int serverfd = fsm_mountat(AT_FDCWD, mount_path, &root_inode_st, 0);
 | 
			
		||||
	if ( serverfd < 0 )
 | 
			
		||||
		error(1, errno, "fsm_mkserver");
 | 
			
		||||
 | 
			
		||||
	// Create a file descriptor for our root directory. The kernel won't send
 | 
			
		||||
	// a message to this file descriptor so we can mount it before starting to
 | 
			
		||||
	// listen for messages.
 | 
			
		||||
	int rootfd = fsm_bootstraprootfd(serverfd, EXT2_ROOT_INO, O_RDWR | O_CREAT,
 | 
			
		||||
	                                 S_IFDIR);
 | 
			
		||||
	if ( rootfd < 0 )
 | 
			
		||||
		error(1, errno, "fsm_bootstraprootfd");
 | 
			
		||||
 | 
			
		||||
	if ( fsm_fsbind(rootfd, mountfd, 0) < 0 )
 | 
			
		||||
		error(1, errno, "fsm_fsbind");
 | 
			
		||||
 | 
			
		||||
	close(mountfd);
 | 
			
		||||
		error(1, errno, "%s", mount_path);
 | 
			
		||||
 | 
			
		||||
	// Make sure the server isn't unexpectedly killed and data is lost.
 | 
			
		||||
	signal(SIGINT, TerminationHandler);
 | 
			
		||||
| 
						 | 
				
			
			@ -1506,7 +1495,10 @@ int main(int argc, char* argv[])
 | 
			
		|||
	// Become a background process in its own process group by default.
 | 
			
		||||
	if ( !foreground )
 | 
			
		||||
	{
 | 
			
		||||
		if ( fork() )
 | 
			
		||||
		pid_t child_pid = fork();
 | 
			
		||||
		if ( child_pid < 0 )
 | 
			
		||||
			error(1, errno, "fork");
 | 
			
		||||
		if ( child_pid )
 | 
			
		||||
			exit(0);
 | 
			
		||||
		setpgid(0, 0);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1515,20 +1507,20 @@ int main(int argc, char* argv[])
 | 
			
		|||
	struct timespec last_sync_at;
 | 
			
		||||
	clock_gettime(CLOCK_MONOTONIC, &last_sync_at);
 | 
			
		||||
	int channel;
 | 
			
		||||
	while ( 0 <= (channel = fsm_listen(serverfd)) )
 | 
			
		||||
	while ( 0 <= (channel = accept(serverfd, NULL, NULL)) )
 | 
			
		||||
	{
 | 
			
		||||
		if ( should_terminate )
 | 
			
		||||
			break;
 | 
			
		||||
		struct fsm_msg_header hdr;
 | 
			
		||||
		ssize_t amount;
 | 
			
		||||
		if ( (amount = fsm_recv(serverfd, channel, &hdr, sizeof(hdr))) != sizeof(hdr) )
 | 
			
		||||
		size_t amount;
 | 
			
		||||
		if ( (amount = readall(channel, &hdr, sizeof(hdr))) != sizeof(hdr) )
 | 
			
		||||
		{
 | 
			
		||||
			error(0, errno, "incomplete header: got %zi of %zu bytes", amount, sizeof(hdr));
 | 
			
		||||
			errno = 0;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		HandleIncomingMessage(serverfd, channel, &hdr, fs);
 | 
			
		||||
		fsm_closechannel(serverfd, channel);
 | 
			
		||||
		HandleIncomingMessage(channel, &hdr, fs);
 | 
			
		||||
		close(channel);
 | 
			
		||||
 | 
			
		||||
		struct timespec now;
 | 
			
		||||
		clock_gettime(CLOCK_MONOTONIC, &now);
 | 
			
		||||
| 
						 | 
				
			
			@ -1549,7 +1541,7 @@ int main(int argc, char* argv[])
 | 
			
		|||
		fprintf(stderr, " done.\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fsm_closeserver(serverfd);
 | 
			
		||||
	close(serverfd);
 | 
			
		||||
 | 
			
		||||
#elif defined(__linux__)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,14 +26,17 @@
 | 
			
		|||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fsmarshall-msg.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <sortix/dirent.h>
 | 
			
		||||
#include <sortix/fcntl.h>
 | 
			
		||||
#include <sortix/mount.h>
 | 
			
		||||
#include <sortix/seek.h>
 | 
			
		||||
#include <sortix/stat.h>
 | 
			
		||||
 | 
			
		||||
#include <sortix/kernel/copy.h>
 | 
			
		||||
#include <sortix/kernel/descriptor.h>
 | 
			
		||||
#include <sortix/kernel/fsfunc.h>
 | 
			
		||||
#include <sortix/kernel/inode.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -109,17 +112,40 @@ Ref<Descriptor> OpenDirContainingPath(ioctx_t* ctx,
 | 
			
		|||
 | 
			
		||||
// TODO: Add security checks.
 | 
			
		||||
 | 
			
		||||
Descriptor::Descriptor()
 | 
			
		||||
{
 | 
			
		||||
	current_offset_lock = KTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
	this->vnode = Ref<Vnode>(NULL);
 | 
			
		||||
	this->ino = 0;
 | 
			
		||||
	this->dev = 0;
 | 
			
		||||
	this->type = 0;
 | 
			
		||||
	this->dflags = 0;
 | 
			
		||||
	checked_seekable = false;
 | 
			
		||||
	seekable = false /* unused */;
 | 
			
		||||
	current_offset = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Descriptor::Descriptor(Ref<Vnode> vnode, int dflags)
 | 
			
		||||
{
 | 
			
		||||
	current_offset_lock = KTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
	this->vnode = Ref<Vnode>(NULL);
 | 
			
		||||
	this->ino = 0;
 | 
			
		||||
	this->dev = 0;
 | 
			
		||||
	this->type = 0;
 | 
			
		||||
	this->dflags = 0;
 | 
			
		||||
	checked_seekable = false;
 | 
			
		||||
	seekable = false /* unused */;
 | 
			
		||||
	current_offset = 0;
 | 
			
		||||
	LateConstruct(vnode, dflags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Descriptor::LateConstruct(Ref<Vnode> vnode, int dflags)
 | 
			
		||||
{
 | 
			
		||||
	this->vnode = vnode;
 | 
			
		||||
	this->ino = vnode->ino;
 | 
			
		||||
	this->dev = vnode->dev;
 | 
			
		||||
	this->type = vnode->type;
 | 
			
		||||
	this->dflags = dflags;
 | 
			
		||||
	checked_seekable = false;
 | 
			
		||||
	seekable = false /* unused */;
 | 
			
		||||
	current_offset = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Descriptor::~Descriptor()
 | 
			
		||||
| 
						 | 
				
			
			@ -749,4 +775,60 @@ ssize_t Descriptor::tcsetblob(ioctx_t* ctx, const char* name, const void* buffer
 | 
			
		|||
	return vnode->tcsetblob(ctx, name, buffer, count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Descriptor::unmount(ioctx_t* ctx, const char* filename, int flags)
 | 
			
		||||
{
 | 
			
		||||
	if ( flags & ~(UNMOUNT_FORCE | UNMOUNT_DETACH | UNMOUNT_NOFOLLOW) )
 | 
			
		||||
		return errno = EINVAL, -1;
 | 
			
		||||
	int subflags = flags & ~(UNMOUNT_NOFOLLOW);
 | 
			
		||||
	char* final;
 | 
			
		||||
	// TODO: This may follow a symlink when not supposed to!
 | 
			
		||||
	Ref<Descriptor> dir =
 | 
			
		||||
		OpenDirContainingPath(ctx, Ref<Descriptor>(this), filename, &final);
 | 
			
		||||
	if ( !dir )
 | 
			
		||||
		return -1;
 | 
			
		||||
	if ( !(flags & UNMOUNT_NOFOLLOW) )
 | 
			
		||||
	{
 | 
			
		||||
		// TODO: Potentially follow a symlink here!
 | 
			
		||||
	}
 | 
			
		||||
	int ret = dir->vnode->unmount(ctx, final, subflags);
 | 
			
		||||
	delete[] final;
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Descriptor::fsm_fsbind(ioctx_t* ctx, Ref<Descriptor> target, int flags)
 | 
			
		||||
{
 | 
			
		||||
	return vnode->fsm_fsbind(ctx, target->vnode, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ref<Descriptor> Descriptor::fsm_mount(ioctx_t* ctx,
 | 
			
		||||
                                      const char* filename,
 | 
			
		||||
                                      const struct stat* rootst,
 | 
			
		||||
                                      int flags)
 | 
			
		||||
{
 | 
			
		||||
	if ( flags & ~(FSM_MOUNT_NOFOLLOW | FSM_MOUNT_NONBLOCK) )
 | 
			
		||||
		return errno = EINVAL, Ref<Descriptor>(NULL);
 | 
			
		||||
	int result_dflags = O_READ | O_WRITE;
 | 
			
		||||
	if ( flags & FSM_MOUNT_NOFOLLOW ) result_dflags |= O_NONBLOCK;
 | 
			
		||||
	int subflags = flags & ~(FSM_MOUNT_NOFOLLOW | FSM_MOUNT_NONBLOCK);
 | 
			
		||||
	char* final;
 | 
			
		||||
	// TODO: This may follow a symlink when not supposed to!
 | 
			
		||||
	Ref<Descriptor> dir =
 | 
			
		||||
		OpenDirContainingPath(ctx, Ref<Descriptor>(this), filename, &final);
 | 
			
		||||
	if ( !dir )
 | 
			
		||||
		return errno = EINVAL, Ref<Descriptor>(NULL);
 | 
			
		||||
	if ( !(flags & FSM_MOUNT_NOFOLLOW) )
 | 
			
		||||
	{
 | 
			
		||||
		// TODO: Potentially follow a symlink here!
 | 
			
		||||
	}
 | 
			
		||||
	Ref<Descriptor> result(new Descriptor());
 | 
			
		||||
	if ( !result )
 | 
			
		||||
		return Ref<Descriptor>(NULL);
 | 
			
		||||
	Ref<Vnode> result_vnode = dir->vnode->fsm_mount(ctx, final, rootst, subflags);
 | 
			
		||||
	delete[] final;
 | 
			
		||||
	if ( !result_vnode )
 | 
			
		||||
		return Ref<Descriptor>(NULL);
 | 
			
		||||
	result->LateConstruct(result_vnode, result_dflags);
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Sortix
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -158,8 +158,9 @@ public:
 | 
			
		|||
	Server();
 | 
			
		||||
	virtual ~Server();
 | 
			
		||||
	void Disconnect();
 | 
			
		||||
	void Unmount();
 | 
			
		||||
	Channel* Connect();
 | 
			
		||||
	Channel* Listen();
 | 
			
		||||
	Channel* Accept();
 | 
			
		||||
	Ref<Inode> BootstrapNode(ino_t ino, mode_t type);
 | 
			
		||||
	Ref<Inode> OpenNode(ino_t ino, mode_t type);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -171,6 +172,7 @@ private:
 | 
			
		|||
	uintptr_t connecter_system_tid;
 | 
			
		||||
	Channel* connecting;
 | 
			
		||||
	bool disconnected;
 | 
			
		||||
	bool unmounted;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -179,8 +181,8 @@ class ServerNode : public AbstractInode
 | 
			
		|||
public:
 | 
			
		||||
	ServerNode(Ref<Server> server);
 | 
			
		||||
	virtual ~ServerNode();
 | 
			
		||||
	virtual Ref<Inode> open(ioctx_t* ctx, const char* filename, int flags,
 | 
			
		||||
	                        mode_t mode);
 | 
			
		||||
	virtual Ref<Inode> accept(ioctx_t* ctx, uint8_t* addr, size_t* addrlen,
 | 
			
		||||
	                          int flags);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	Ref<Server> server;
 | 
			
		||||
| 
						 | 
				
			
			@ -248,6 +250,7 @@ public:
 | 
			
		|||
	                       const void* option_value, size_t option_size);
 | 
			
		||||
	virtual ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count);
 | 
			
		||||
	virtual ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count);
 | 
			
		||||
	virtual int unmounted(ioctx_t* ctx);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	bool SendMessage(Channel* channel, size_t type, void* ptr, size_t size,
 | 
			
		||||
| 
						 | 
				
			
			@ -527,6 +530,7 @@ Server::Server()
 | 
			
		|||
	listener_system_tid = 0;
 | 
			
		||||
	connecting = NULL;
 | 
			
		||||
	disconnected = false;
 | 
			
		||||
	unmounted = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Server::~Server()
 | 
			
		||||
| 
						 | 
				
			
			@ -540,6 +544,13 @@ void Server::Disconnect()
 | 
			
		|||
	kthread_cond_signal(&connectable_cond);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Server::Unmount()
 | 
			
		||||
{
 | 
			
		||||
	ScopedLock lock(&connect_lock);
 | 
			
		||||
	unmounted = true;
 | 
			
		||||
	kthread_cond_signal(&connecting_cond);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Channel* Server::Connect()
 | 
			
		||||
{
 | 
			
		||||
	Channel* channel = new Channel();
 | 
			
		||||
| 
						 | 
				
			
			@ -565,13 +576,15 @@ Channel* Server::Connect()
 | 
			
		|||
	return channel;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Channel* Server::Listen()
 | 
			
		||||
Channel* Server::Accept()
 | 
			
		||||
{
 | 
			
		||||
	ScopedLock lock(&connect_lock);
 | 
			
		||||
	listener_system_tid = CurrentThread()->system_tid;
 | 
			
		||||
	while ( !connecting )
 | 
			
		||||
	while ( !connecting && !unmounted )
 | 
			
		||||
		if ( !kthread_cond_wait_signal(&connecting_cond, &connect_lock) )
 | 
			
		||||
			return errno = EINTR, (Channel*) NULL;
 | 
			
		||||
	if ( unmounted )
 | 
			
		||||
		return errno = ECONNRESET, (Channel*) NULL;
 | 
			
		||||
	Channel* result = connecting;
 | 
			
		||||
	connecting = NULL;
 | 
			
		||||
	kthread_cond_signal(&connectable_cond);
 | 
			
		||||
| 
						 | 
				
			
			@ -596,7 +609,7 @@ ServerNode::ServerNode(Ref<Server> server)
 | 
			
		|||
{
 | 
			
		||||
	inode_type = INODE_TYPE_UNKNOWN;
 | 
			
		||||
	this->server = server;
 | 
			
		||||
	this->type = S_IFDIR;
 | 
			
		||||
	this->type = S_IFSOCK;
 | 
			
		||||
	this->dev = (dev_t) this;
 | 
			
		||||
	this->ino = 0;
 | 
			
		||||
	// TODO: Set uid, gid, mode.
 | 
			
		||||
| 
						 | 
				
			
			@ -607,36 +620,22 @@ ServerNode::~ServerNode()
 | 
			
		|||
	server->Disconnect();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ref<Inode> ServerNode::open(ioctx_t* /*ctx*/, const char* filename, int flags,
 | 
			
		||||
                            mode_t mode)
 | 
			
		||||
Ref<Inode> ServerNode::accept(ioctx_t* ctx, uint8_t* addr, size_t* addrlen,
 | 
			
		||||
                              int flags)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long long ull_ino;
 | 
			
		||||
	char* end;
 | 
			
		||||
	int saved_errno = errno; errno = 0;
 | 
			
		||||
	if ( !isspace(*filename) &&
 | 
			
		||||
	     0 < (ull_ino = strtoull(filename, &end, 10)) &&
 | 
			
		||||
	     *end == '\0' &&
 | 
			
		||||
	     errno != ERANGE )
 | 
			
		||||
	{
 | 
			
		||||
		errno = saved_errno;
 | 
			
		||||
		if ( !(flags & O_CREATE) )
 | 
			
		||||
			return errno = ENOENT, Ref<Inode>(NULL);
 | 
			
		||||
		ino_t ino = (ino_t) ull_ino;
 | 
			
		||||
		return server->BootstrapNode(ino, mode & S_IFMT);
 | 
			
		||||
	}
 | 
			
		||||
	errno = saved_errno;
 | 
			
		||||
	if ( !strcmp(filename, "listen") )
 | 
			
		||||
	{
 | 
			
		||||
		Ref<ChannelNode> node(new ChannelNode);
 | 
			
		||||
		if ( !node )
 | 
			
		||||
			return Ref<Inode>(NULL);
 | 
			
		||||
		Channel* channel = server->Listen();
 | 
			
		||||
		if ( !channel )
 | 
			
		||||
			return Ref<Inode>(NULL);
 | 
			
		||||
		node->Construct(channel);
 | 
			
		||||
		return node;
 | 
			
		||||
	}
 | 
			
		||||
	return errno = ENOENT, Ref<Inode>(NULL);
 | 
			
		||||
	(void) addr;
 | 
			
		||||
	(void) flags;
 | 
			
		||||
	size_t out_addrlen = 0;
 | 
			
		||||
	if ( addrlen && !ctx->copy_to_dest(addrlen, &out_addrlen, sizeof(out_addrlen)) )
 | 
			
		||||
		return Ref<Inode>(NULL);
 | 
			
		||||
	Ref<ChannelNode> node(new ChannelNode);
 | 
			
		||||
	if ( !node )
 | 
			
		||||
		return Ref<Inode>(NULL);
 | 
			
		||||
	Channel* channel = server->Accept();
 | 
			
		||||
	if ( !channel )
 | 
			
		||||
		return Ref<Inode>(NULL);
 | 
			
		||||
	node->Construct(channel);
 | 
			
		||||
	return node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
| 
						 | 
				
			
			@ -1443,86 +1442,31 @@ ssize_t Unode::tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, siz
 | 
			
		|||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Initialization.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
class FactoryNode : public AbstractInode
 | 
			
		||||
int Unode::unmounted(ioctx_t* /*ctx*/)
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	FactoryNode(uid_t owner, gid_t group, mode_t mode);
 | 
			
		||||
	virtual ~FactoryNode() { }
 | 
			
		||||
	virtual Ref<Inode> open(ioctx_t* ctx, const char* filename, int flags,
 | 
			
		||||
	                        mode_t mode);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
FactoryNode::FactoryNode(uid_t owner, gid_t group, mode_t mode)
 | 
			
		||||
{
 | 
			
		||||
	inode_type = INODE_TYPE_UNKNOWN;
 | 
			
		||||
	dev = (dev_t) this;
 | 
			
		||||
	ino = 0;
 | 
			
		||||
	this->type = S_IFDIR;
 | 
			
		||||
	this->stat_uid = owner;
 | 
			
		||||
	this->stat_gid = group;
 | 
			
		||||
	this->stat_mode = (mode & S_SETABLE) | this->type;
 | 
			
		||||
	server->Unmount();
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ref<Inode> FactoryNode::open(ioctx_t* /*ctx*/, const char* filename,
 | 
			
		||||
                             int /*flags*/, mode_t /*mode*/)
 | 
			
		||||
bool Bootstrap(Ref<Inode>* out_root,
 | 
			
		||||
               Ref<Inode>* out_server,
 | 
			
		||||
               const struct stat* rootst)
 | 
			
		||||
{
 | 
			
		||||
	if ( !strcmp(filename, "new") )
 | 
			
		||||
	{
 | 
			
		||||
		Ref<Server> server(new Server());
 | 
			
		||||
		if ( !server )
 | 
			
		||||
			return Ref<Inode>(NULL);
 | 
			
		||||
		Ref<ServerNode> node(new ServerNode(server));
 | 
			
		||||
		if ( !node )
 | 
			
		||||
			return Ref<Inode>(NULL);
 | 
			
		||||
		return node;
 | 
			
		||||
	}
 | 
			
		||||
	return errno = ENOENT, Ref<Inode>(NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace UserFS
 | 
			
		||||
} // namespace Sortix
 | 
			
		||||
 | 
			
		||||
namespace Sortix {
 | 
			
		||||
 | 
			
		||||
int sys_fsm_fsbind(int rootfd, int mpointfd, int /*flags*/)
 | 
			
		||||
{
 | 
			
		||||
	Ref<Descriptor> desc = CurrentProcess()->GetDescriptor(rootfd);
 | 
			
		||||
	if ( !desc ) { return -1; }
 | 
			
		||||
	Ref<Descriptor> mpoint = CurrentProcess()->GetDescriptor(mpointfd);
 | 
			
		||||
	if ( !mpoint ) { return -1; }
 | 
			
		||||
	Ref<MountTable> mtable = CurrentProcess()->GetMTable();
 | 
			
		||||
	Ref<Inode> node = desc->vnode->inode;
 | 
			
		||||
	return mtable->AddMount(mpoint->ino, mpoint->dev, node) ? 0 : -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Sortix
 | 
			
		||||
 | 
			
		||||
namespace Sortix {
 | 
			
		||||
namespace UserFS {
 | 
			
		||||
 | 
			
		||||
void Init(const char* devpath, Ref<Descriptor> slashdev)
 | 
			
		||||
{
 | 
			
		||||
	ioctx_t ctx; SetupKernelIOCtx(&ctx);
 | 
			
		||||
	Ref<Inode> node(new FactoryNode(0, 0, 0666));
 | 
			
		||||
	if ( !node )
 | 
			
		||||
		PanicF("Unable to allocate %s/fs inode.", devpath);
 | 
			
		||||
	// TODO: Race condition! Create a mkdir function that returns what it
 | 
			
		||||
	// created, possibly with a O_MKDIR flag to open.
 | 
			
		||||
	if ( slashdev->mkdir(&ctx, "fs", 0755) < 0 && errno != EEXIST )
 | 
			
		||||
		PanicF("Could not create a %s/fs directory", devpath);
 | 
			
		||||
	Ref<Descriptor> mpoint = slashdev->open(&ctx, "fs", O_READ | O_WRITE, 0);
 | 
			
		||||
	if ( !mpoint )
 | 
			
		||||
		PanicF("Could not open the %s/fs directory", devpath);
 | 
			
		||||
	Ref<MountTable> mtable = CurrentProcess()->GetMTable();
 | 
			
		||||
	// TODO: Make sure that the mount point is *empty*! Add a proper function
 | 
			
		||||
	// for this on the file descriptor class!
 | 
			
		||||
	if ( !mtable->AddMount(mpoint->ino, mpoint->dev, node) )
 | 
			
		||||
		PanicF("Unable to mount filesystem on %s/fs", devpath);
 | 
			
		||||
	Ref<Server> server(new Server());
 | 
			
		||||
	if ( !server )
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	ino_t root_inode_ino = rootst->st_ino;
 | 
			
		||||
	mode_t root_inode_type = rootst->st_mode & S_IFMT;
 | 
			
		||||
	Ref<Inode> root_inode = server->OpenNode(root_inode_ino, root_inode_type);
 | 
			
		||||
	if ( !root_inode )
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	Ref<ServerNode> server_inode(new ServerNode(server));
 | 
			
		||||
	if ( !server_inode )
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	return *out_root = root_inode, *out_server = server_inode, true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace UserFS
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2012, 2013.
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,10 +25,15 @@
 | 
			
		|||
#ifndef SORTIX_FS_USER_H
 | 
			
		||||
#define SORTIX_FS_USER_H
 | 
			
		||||
 | 
			
		||||
#include <sortix/stat.h>
 | 
			
		||||
 | 
			
		||||
#include <sortix/kernel/refcount.h>
 | 
			
		||||
#include <sortix/kernel/vnode.h>
 | 
			
		||||
 | 
			
		||||
namespace Sortix {
 | 
			
		||||
namespace UserFS {
 | 
			
		||||
 | 
			
		||||
void Init(const char* devpath, Ref<Descriptor> slashdev);
 | 
			
		||||
bool Bootstrap(Ref<Inode>* out_root, Ref<Inode>* out_server, const struct stat* rootst);
 | 
			
		||||
 | 
			
		||||
} // namespace UserFS
 | 
			
		||||
} // namespace Sortix
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,6 +50,10 @@ typedef struct ioctx_struct ioctx_t;
 | 
			
		|||
 | 
			
		||||
class Descriptor : public Refcountable
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
	Descriptor();
 | 
			
		||||
	void LateConstruct(Ref<Vnode> vnode, int dflags);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	Descriptor(Ref<Vnode> vnode, int dflags);
 | 
			
		||||
	virtual ~Descriptor();
 | 
			
		||||
| 
						 | 
				
			
			@ -102,6 +106,10 @@ public:
 | 
			
		|||
	               const void* option_value, size_t option_size);
 | 
			
		||||
	ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count);
 | 
			
		||||
	ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count);
 | 
			
		||||
	int unmount(ioctx_t* ctx, const char* filename, int flags);
 | 
			
		||||
	int fsm_fsbind(ioctx_t* ctx, Ref<Descriptor> target, int flags);
 | 
			
		||||
	Ref<Descriptor> fsm_mount(ioctx_t* ctx, const char* filename,
 | 
			
		||||
	                          const struct stat* rootst, int flags);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	Ref<Descriptor> open_elem(ioctx_t* ctx, const char* filename, int flags,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -112,6 +112,7 @@ public:
 | 
			
		|||
	                       const void* option_value, size_t option_size) = 0;
 | 
			
		||||
	virtual ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count) = 0;
 | 
			
		||||
	virtual ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count) = 0;
 | 
			
		||||
	virtual int unmounted(ioctx_t* ctx) = 0;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -199,6 +200,7 @@ public:
 | 
			
		|||
	                       const void* option_value, size_t option_size);
 | 
			
		||||
	virtual ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count);
 | 
			
		||||
	virtual ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count);
 | 
			
		||||
	virtual int unmounted(ioctx_t* ctx);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,6 +39,7 @@ typedef struct
 | 
			
		|||
	Ref<Inode> inode;
 | 
			
		||||
	ino_t ino;
 | 
			
		||||
	dev_t dev;
 | 
			
		||||
	bool fsbind;
 | 
			
		||||
} mountpoint_t;
 | 
			
		||||
 | 
			
		||||
class MountTable : public Refcountable
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +48,8 @@ public:
 | 
			
		|||
	MountTable();
 | 
			
		||||
	virtual ~MountTable();
 | 
			
		||||
	Ref<MountTable> Fork();
 | 
			
		||||
	bool AddMount(ino_t ino, dev_t dev, Ref<Inode> inode);
 | 
			
		||||
	bool AddMount(ino_t ino, dev_t dev, Ref<Inode> inode, bool fsbind);
 | 
			
		||||
	bool AddMountUnlocked(ino_t ino, dev_t dev, Ref<Inode> inode, bool fsbind);
 | 
			
		||||
 | 
			
		||||
public: // Consider these read-only.
 | 
			
		||||
	kthread_mutex_t mtablelock;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,6 +78,7 @@ int sys_fchroot(int);
 | 
			
		|||
int sys_fchrootat(int, const char*);
 | 
			
		||||
int sys_fcntl(int, int, uintptr_t);
 | 
			
		||||
int sys_fsm_fsbind(int, int, int);
 | 
			
		||||
int sys_fsm_mountat(int, const char*, const struct stat*, int flags);
 | 
			
		||||
int sys_fstat(int, struct stat*);
 | 
			
		||||
int sys_fstatat(int, const char*, struct stat*, int);
 | 
			
		||||
int sys_fstatvfs(int, struct statvfs*);
 | 
			
		||||
| 
						 | 
				
			
			@ -166,6 +167,7 @@ int sys_timer_settime(timer_t, int, const struct itimerspec*, struct itimerspec*
 | 
			
		|||
int sys_truncateat(int, const char*, off_t);
 | 
			
		||||
mode_t sys_umask(mode_t);
 | 
			
		||||
int sys_unlinkat(int, const char*, int);
 | 
			
		||||
int sys_unmountat(int, const char*, int);
 | 
			
		||||
int sys_utimensat(int, const char*, const struct timespec [2], int);
 | 
			
		||||
pid_t sys_waitpid(pid_t, int*, int);
 | 
			
		||||
ssize_t sys_write(int, const void*, size_t);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -102,6 +102,9 @@ public:
 | 
			
		|||
	               const void* option_value, size_t option_size);
 | 
			
		||||
	ssize_t tcgetblob(ioctx_t* ctx, const char* name, void* buffer, size_t count);
 | 
			
		||||
	ssize_t tcsetblob(ioctx_t* ctx, const char* name, const void* buffer, size_t count);
 | 
			
		||||
	int unmount(ioctx_t* ctx, const char* filename, int flags);
 | 
			
		||||
	int fsm_fsbind(ioctx_t* ctx, Ref<Vnode> target, int flags);
 | 
			
		||||
	Ref<Vnode> fsm_mount(ioctx_t* ctx, const char* filename, const struct stat* rootst, int flags);
 | 
			
		||||
 | 
			
		||||
public /*TODO: private*/:
 | 
			
		||||
	Ref<Inode> inode;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2012.
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2014.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -29,10 +29,9 @@
 | 
			
		|||
 | 
			
		||||
__BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define MREPL   (0<<0) /* Replace binding. */
 | 
			
		||||
#define MBEFORE (1<<0) /* Add to start of directory union. */
 | 
			
		||||
#define MAFTER  (2<<0) /* Add to end of directory union. */
 | 
			
		||||
#define MCREATE (1<<2) /* Create files here, otherwise try next in union. */
 | 
			
		||||
#define UNMOUNT_FORCE (1 << 0)
 | 
			
		||||
#define UNMOUNT_DETACH (1 << 1)
 | 
			
		||||
#define UNMOUNT_NOFOLLOW (1 << 2)
 | 
			
		||||
 | 
			
		||||
__END_DECLS
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -175,6 +175,8 @@
 | 
			
		|||
#define SYSCALL_GETENTROPY 147
 | 
			
		||||
#define SYSCALL_GETHOSTNAME 148
 | 
			
		||||
#define SYSCALL_SETHOSTNAME 149
 | 
			
		||||
#define SYSCALL_MAX_NUM 150 /* index of highest constant + 1 */
 | 
			
		||||
#define SYSCALL_UNMOUNTAT 150
 | 
			
		||||
#define SYSCALL_FSM_MOUNTAT 151
 | 
			
		||||
#define SYSCALL_MAX_NUM 152 /* index of highest constant + 1 */
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -406,4 +406,9 @@ ssize_t AbstractInode::tcsetblob(ioctx_t* /*ctx*/, const char* /*name*/, const v
 | 
			
		|||
	return errno = ENOTTY, -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int AbstractInode::unmounted(ioctx_t* /*ctx*/)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Sortix
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@
 | 
			
		|||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fsmarshall-msg.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -174,7 +175,13 @@ int sys_openat(int dirfd, const char* path, int flags, mode_t mode)
 | 
			
		|||
	if ( !desc )
 | 
			
		||||
		return -1;
 | 
			
		||||
	Ref<DescriptorTable> dtable = CurrentProcess()->GetDTable();
 | 
			
		||||
	return dtable->Allocate(desc, fdflags);
 | 
			
		||||
	int ret = dtable->Allocate(desc, fdflags);
 | 
			
		||||
	if ( ret < 0 )
 | 
			
		||||
	{
 | 
			
		||||
		// TODO: We should use a fail-safe dtable reservation mechanism that
 | 
			
		||||
		//       causes this error earlier before we have side effects.
 | 
			
		||||
	}
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: This is a hack! Stat the file in some manner and check permissions.
 | 
			
		||||
| 
						 | 
				
			
			@ -1079,4 +1086,65 @@ int sys_shutdown(int fd, int how)
 | 
			
		|||
	return errno = ENOSYS, -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int sys_unmountat(int dirfd, const char* path, int flags)
 | 
			
		||||
{
 | 
			
		||||
	char* pathcopy = GetStringFromUser(path);
 | 
			
		||||
	if ( !pathcopy )
 | 
			
		||||
		return -1;
 | 
			
		||||
	ioctx_t ctx; SetupUserIOCtx(&ctx);
 | 
			
		||||
	const char* relpath = pathcopy;
 | 
			
		||||
	Ref<Descriptor> from = PrepareLookup(&relpath, dirfd);
 | 
			
		||||
	if ( !from )
 | 
			
		||||
		return delete[] pathcopy, -1;
 | 
			
		||||
	int ret = from->unmount(&ctx, relpath, flags);
 | 
			
		||||
	delete[] pathcopy;
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int sys_fsm_fsbind(int rootfd, int mpointfd, int flags)
 | 
			
		||||
{
 | 
			
		||||
	if ( flags & ~(0) )
 | 
			
		||||
		return errno = EINVAL, -1;
 | 
			
		||||
	Ref<Descriptor> desc = CurrentProcess()->GetDescriptor(rootfd);
 | 
			
		||||
	if ( !desc )
 | 
			
		||||
		return -1;
 | 
			
		||||
	Ref<Descriptor> mpoint = CurrentProcess()->GetDescriptor(mpointfd);
 | 
			
		||||
	if ( !mpoint )
 | 
			
		||||
		return -1;
 | 
			
		||||
	ioctx_t ctx; SetupUserIOCtx(&ctx);
 | 
			
		||||
	return mpoint->fsm_fsbind(&ctx, desc, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int sys_fsm_mountat(int dirfd, const char* path, const struct stat* rootst, int flags)
 | 
			
		||||
{
 | 
			
		||||
	if ( flags & ~(FSM_MOUNT_CLOEXEC | FSM_MOUNT_CLOFORK |
 | 
			
		||||
	               FSM_MOUNT_NOFOLLOW | FSM_MOUNT_NONBLOCK) )
 | 
			
		||||
		return -1;
 | 
			
		||||
	int fdflags = 0;
 | 
			
		||||
	if ( flags & FSM_MOUNT_CLOEXEC ) fdflags |= FD_CLOEXEC;
 | 
			
		||||
	if ( flags & FSM_MOUNT_CLOFORK ) fdflags |= FD_CLOFORK;
 | 
			
		||||
	flags &= ~(FSM_MOUNT_CLOEXEC | FSM_MOUNT_CLOFORK);
 | 
			
		||||
	char* pathcopy = GetStringFromUser(path);
 | 
			
		||||
	if ( !pathcopy )
 | 
			
		||||
		return -1;
 | 
			
		||||
	ioctx_t ctx; SetupUserIOCtx(&ctx);
 | 
			
		||||
	const char* relpath = pathcopy;
 | 
			
		||||
	Ref<Descriptor> from = PrepareLookup(&relpath, dirfd);
 | 
			
		||||
	if ( !from )
 | 
			
		||||
		return delete[] pathcopy, -1;
 | 
			
		||||
	Ref<Descriptor> desc = from->fsm_mount(&ctx, relpath, rootst, flags);
 | 
			
		||||
	delete[] pathcopy;
 | 
			
		||||
	Ref<DescriptorTable> dtable = CurrentProcess()->GetDTable();
 | 
			
		||||
	int ret = dtable->Allocate(desc, fdflags);
 | 
			
		||||
	if ( ret < 0 )
 | 
			
		||||
	{
 | 
			
		||||
		// TODO: We should use a fail-safe dtable reservation mechanism that
 | 
			
		||||
		//       causes this error earlier before we have side effects.
 | 
			
		||||
		int errnum = errno;
 | 
			
		||||
		from->unmount(&ctx, relpath, 0);
 | 
			
		||||
		return errno = errnum, -1;
 | 
			
		||||
	}
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Sortix
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,7 +73,6 @@
 | 
			
		|||
#include "fs/full.h"
 | 
			
		||||
#include "fs/kram.h"
 | 
			
		||||
#include "fs/null.h"
 | 
			
		||||
#include "fs/user.h"
 | 
			
		||||
#include "fs/zero.h"
 | 
			
		||||
#include "gpu/bga/bga.h"
 | 
			
		||||
#include "initrd.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -601,9 +600,6 @@ static void BootThread(void* /*user*/)
 | 
			
		|||
	// Initialize the filesystem network-
 | 
			
		||||
	NetFS::Init("/dev", slashdev);
 | 
			
		||||
 | 
			
		||||
	// Initialize the user-space filesystem framework.
 | 
			
		||||
	UserFS::Init("/dev", slashdev);
 | 
			
		||||
 | 
			
		||||
	//
 | 
			
		||||
	// Stage 6. Executing Hosted Environment ("User-Space")
 | 
			
		||||
	//
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,9 +61,14 @@ Ref<MountTable> MountTable::Fork()
 | 
			
		|||
	return clone;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MountTable::AddMount(ino_t ino, dev_t dev, Ref<Inode> inode)
 | 
			
		||||
bool MountTable::AddMount(ino_t ino, dev_t dev, Ref<Inode> inode, bool fsbind)
 | 
			
		||||
{
 | 
			
		||||
	ScopedLock lock(&mtablelock);
 | 
			
		||||
	return AddMountUnlocked(ino, dev, inode, fsbind);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool MountTable::AddMountUnlocked(ino_t ino, dev_t dev, Ref<Inode> inode, bool fsbind)
 | 
			
		||||
{
 | 
			
		||||
	if ( nummounts == mountsalloced )
 | 
			
		||||
	{
 | 
			
		||||
		size_t newalloced = mountsalloced ? 2UL * mountsalloced : 4UL;
 | 
			
		||||
| 
						 | 
				
			
			@ -80,6 +85,7 @@ bool MountTable::AddMount(ino_t ino, dev_t dev, Ref<Inode> inode)
 | 
			
		|||
	mp->ino = ino;
 | 
			
		||||
	mp->dev = dev;
 | 
			
		||||
	mp->inode = inode;
 | 
			
		||||
	mp->fsbind = fsbind;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -536,7 +536,7 @@ void Init(const char* devpath, Ref<Descriptor> slashdev)
 | 
			
		|||
	Ref<MountTable> mtable = CurrentProcess()->GetMTable();
 | 
			
		||||
	// TODO: Make sure that the mount point is *empty*! Add a proper function
 | 
			
		||||
	// for this on the file descriptor class!
 | 
			
		||||
	if ( !mtable->AddMount(mpoint->ino, mpoint->dev, node) )
 | 
			
		||||
	if ( !mtable->AddMount(mpoint->ino, mpoint->dev, node, false) )
 | 
			
		||||
		PanicF("Unable to mount filesystem on %s/net/fs", devpath);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -185,6 +185,8 @@ void* syscall_list[SYSCALL_MAX_NUM + 1] =
 | 
			
		|||
	[SYSCALL_GETENTROPY] = (void*) sys_getentropy,
 | 
			
		||||
	[SYSCALL_GETHOSTNAME] = (void*) sys_gethostname,
 | 
			
		||||
	[SYSCALL_SETHOSTNAME] = (void*) sys_sethostname,
 | 
			
		||||
	[SYSCALL_UNMOUNTAT] = (void*) sys_unmountat,
 | 
			
		||||
	[SYSCALL_FSM_MOUNTAT] = (void*) sys_fsm_mountat,
 | 
			
		||||
	[SYSCALL_MAX_NUM] = (void*) sys_bad_syscall,
 | 
			
		||||
};
 | 
			
		||||
} // extern "C"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										120
									
								
								kernel/vnode.cpp
									
										
									
									
									
								
							
							
						
						
									
										120
									
								
								kernel/vnode.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -25,7 +25,9 @@
 | 
			
		|||
#include <assert.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
#include <sortix/fcntl.h>
 | 
			
		||||
#include <sortix/mount.h>
 | 
			
		||||
#include <sortix/stat.h>
 | 
			
		||||
 | 
			
		||||
#include <sortix/kernel/kernel.h>
 | 
			
		||||
#include <sortix/kernel/refcount.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -36,20 +38,31 @@
 | 
			
		|||
#include <sortix/kernel/mtable.h>
 | 
			
		||||
#include <sortix/kernel/process.h>
 | 
			
		||||
 | 
			
		||||
#include "fs/user.h"
 | 
			
		||||
 | 
			
		||||
namespace Sortix {
 | 
			
		||||
 | 
			
		||||
static Ref<Inode> LookupMount(Ref<Inode> inode)
 | 
			
		||||
static Ref<Inode> LookupMountUnlocked(Ref<Inode> inode, size_t* out_index = NULL)
 | 
			
		||||
{
 | 
			
		||||
	Ref<Inode> result_inode(NULL);
 | 
			
		||||
	Ref<MountTable> mtable = CurrentProcess()->GetMTable();
 | 
			
		||||
	ScopedLock lock(&mtable->mtablelock);
 | 
			
		||||
	for ( size_t i = 0; i < mtable->nummounts; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		mountpoint_t* mp = mtable->mounts + i;
 | 
			
		||||
		if ( mp->ino != inode->ino || mp->dev != inode->dev )
 | 
			
		||||
			continue;
 | 
			
		||||
		return mp->inode;
 | 
			
		||||
		if ( out_index )
 | 
			
		||||
			*out_index = i;
 | 
			
		||||
		result_inode = mp->inode;
 | 
			
		||||
	}
 | 
			
		||||
	return Ref<Inode>(NULL);
 | 
			
		||||
	return result_inode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Ref<Inode> LookupMount(Ref<Inode> inode)
 | 
			
		||||
{
 | 
			
		||||
	Ref<MountTable> mtable = CurrentProcess()->GetMTable();
 | 
			
		||||
	ScopedLock mtable_lock(&mtable->mtablelock);
 | 
			
		||||
	return LookupMountUnlocked(inode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Vnode::Vnode(Ref<Inode> inode, Ref<Vnode> mountedat, ino_t rootino, dev_t rootdev)
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +101,8 @@ Ref<Vnode> Vnode::open(ioctx_t* ctx, const char* filename, int flags, mode_t mod
 | 
			
		|||
 | 
			
		||||
	// Move within the current filesystem.
 | 
			
		||||
	Ref<Inode> retinode = inode->open(ctx, filename, flags, mode);
 | 
			
		||||
	if ( !retinode ) { return Ref<Vnode>(NULL); }
 | 
			
		||||
	if ( !retinode )
 | 
			
		||||
		return Ref<Vnode>(NULL);
 | 
			
		||||
	Ref<Vnode> retmountedat = mountedat;
 | 
			
		||||
	ino_t retrootino = rootino;
 | 
			
		||||
	dev_t retrootdev = rootdev;
 | 
			
		||||
| 
						 | 
				
			
			@ -106,6 +120,102 @@ Ref<Vnode> Vnode::open(ioctx_t* ctx, const char* filename, int flags, mode_t mod
 | 
			
		|||
	return Ref<Vnode>(new Vnode(retinode, retmountedat, retrootino, retrootdev));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Vnode::fsm_fsbind(ioctx_t* ctx, Ref<Vnode> target, int flags)
 | 
			
		||||
{
 | 
			
		||||
	(void) ctx;
 | 
			
		||||
	if ( flags & ~(0) )
 | 
			
		||||
		return errno = EINVAL, -1;
 | 
			
		||||
	Ref<MountTable> mtable = CurrentProcess()->GetMTable();
 | 
			
		||||
	if ( !mtable->AddMount(ino, dev, target->inode, true) )
 | 
			
		||||
		return -1;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Ref<Vnode> Vnode::fsm_mount(ioctx_t* ctx,
 | 
			
		||||
                            const char* filename,
 | 
			
		||||
                            const struct stat* rootst_ptr,
 | 
			
		||||
                            int flags)
 | 
			
		||||
{
 | 
			
		||||
	if ( flags & ~(0) )
 | 
			
		||||
		return Ref<Vnode>(NULL);
 | 
			
		||||
 | 
			
		||||
	if ( !strcmp(filename, ".") || !strcmp(filename, "..") )
 | 
			
		||||
		return errno = EINVAL, Ref<Vnode>(NULL);
 | 
			
		||||
 | 
			
		||||
	struct stat rootst;
 | 
			
		||||
	if ( !ctx->copy_from_src(&rootst, rootst_ptr, sizeof(struct stat)) )
 | 
			
		||||
		return Ref<Vnode>(NULL);
 | 
			
		||||
 | 
			
		||||
	Ref<Inode> normal_inode = inode->open(ctx, filename, O_READ, 0);
 | 
			
		||||
	if ( !normal_inode )
 | 
			
		||||
		return Ref<Vnode>(NULL);
 | 
			
		||||
 | 
			
		||||
	Ref<Inode> root_inode;
 | 
			
		||||
	Ref<Inode> server_inode;
 | 
			
		||||
	if ( !UserFS::Bootstrap(&root_inode, &server_inode, &rootst) )
 | 
			
		||||
		return Ref<Vnode>(NULL);
 | 
			
		||||
 | 
			
		||||
	Ref<Vnode> server_vnode(new Vnode(server_inode, Ref<Vnode>(NULL), 0, 0));
 | 
			
		||||
	if ( !server_vnode )
 | 
			
		||||
		return Ref<Vnode>(NULL);
 | 
			
		||||
 | 
			
		||||
	Ref<MountTable> mtable = CurrentProcess()->GetMTable();
 | 
			
		||||
	ScopedLock lock(&mtable->mtablelock);
 | 
			
		||||
	if ( Ref<Inode> mounted = LookupMountUnlocked(normal_inode) )
 | 
			
		||||
		normal_inode = mounted;
 | 
			
		||||
 | 
			
		||||
	if ( !mtable->AddMountUnlocked(normal_inode->ino, normal_inode->dev, root_inode, false) )
 | 
			
		||||
		return Ref<Vnode>(NULL);
 | 
			
		||||
 | 
			
		||||
	return server_vnode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Vnode::unmount(ioctx_t* ctx, const char* filename, int flags)
 | 
			
		||||
{
 | 
			
		||||
	if ( flags & ~(UNMOUNT_FORCE | UNMOUNT_DETACH) )
 | 
			
		||||
		return errno = EINVAL, -1;
 | 
			
		||||
 | 
			
		||||
	if ( !strcmp(filename, ".") || !strcmp(filename, "..") )
 | 
			
		||||
		return errno = EINVAL, -1;
 | 
			
		||||
 | 
			
		||||
	Ref<Inode> normal_inode = inode->open(ctx, filename, O_READ, 0);
 | 
			
		||||
	if ( !normal_inode )
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	Ref<MountTable> mtable = CurrentProcess()->GetMTable();
 | 
			
		||||
	ScopedLock mtable_lock(&mtable->mtablelock);
 | 
			
		||||
 | 
			
		||||
	size_t mp_index;
 | 
			
		||||
	if ( !LookupMountUnlocked(normal_inode, &mp_index) )
 | 
			
		||||
		return errno = EINVAL, -1;
 | 
			
		||||
	mountpoint_t* mp = mtable->mounts + mp_index;
 | 
			
		||||
 | 
			
		||||
	Ref<Inode> mp_inode = mp->inode;
 | 
			
		||||
	bool mp_fsbind = mp->fsbind;
 | 
			
		||||
 | 
			
		||||
	mp->inode.Reset();
 | 
			
		||||
	for ( size_t n = mp_index; n < mtable->nummounts - 1; n++ )
 | 
			
		||||
	{
 | 
			
		||||
		mtable->mounts[n].inode.Reset();
 | 
			
		||||
		mtable->mounts[n] = mtable->mounts[n+1];
 | 
			
		||||
	}
 | 
			
		||||
	if ( mp_index + 1 != mtable->nummounts )
 | 
			
		||||
		mtable->mounts[mtable->nummounts].inode.Reset();
 | 
			
		||||
	mtable->nummounts--;
 | 
			
		||||
 | 
			
		||||
	mtable_lock.Reset();
 | 
			
		||||
 | 
			
		||||
	if ( !mp_fsbind )
 | 
			
		||||
	{
 | 
			
		||||
		// TODO: Implement the !UNMOUNT_DETACH case.
 | 
			
		||||
		// TODO: Implement the UNMOUNT_FORCE case.
 | 
			
		||||
		mp_inode->unmounted(ctx);
 | 
			
		||||
	}
 | 
			
		||||
	mp_inode.Reset();
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Vnode::sync(ioctx_t* ctx)
 | 
			
		||||
{
 | 
			
		||||
	return inode->sync(ctx);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -333,14 +333,8 @@ fcntl/creat.o \
 | 
			
		|||
fcntl/fcntl.o \
 | 
			
		||||
fcntl/openat.o \
 | 
			
		||||
fcntl/open.o \
 | 
			
		||||
fsmarshall/fsm_bootstraprootfd.o \
 | 
			
		||||
fsmarshall/fsm_closechannel.o \
 | 
			
		||||
fsmarshall/fsm_closeserver.o \
 | 
			
		||||
fsmarshall/fsm_fsbind.o \
 | 
			
		||||
fsmarshall/fsm_listen.o \
 | 
			
		||||
fsmarshall/fsm_mkserver.o \
 | 
			
		||||
fsmarshall/fsm_recv.o \
 | 
			
		||||
fsmarshall/fsm_send.o \
 | 
			
		||||
fsmarshall/fsm_mountat.o \
 | 
			
		||||
getopt/getopt_long.o \
 | 
			
		||||
getopt/getopt.o \
 | 
			
		||||
grp/endgrent.o \
 | 
			
		||||
| 
						 | 
				
			
			@ -476,6 +470,8 @@ syslog/vsyslog.o \
 | 
			
		|||
sys/mman/mmap.o \
 | 
			
		||||
sys/mman/mprotect.o \
 | 
			
		||||
sys/mman/munmap.o \
 | 
			
		||||
sys/mount/unmountat.o \
 | 
			
		||||
sys/mount/unmount.o \
 | 
			
		||||
sys/readdirents/readdirents.o \
 | 
			
		||||
sys/resource/getpriority.o \
 | 
			
		||||
sys/resource/getrlimit.o \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,38 +0,0 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2012.
 | 
			
		||||
 | 
			
		||||
    This file is part of the Sortix C Library.
 | 
			
		||||
 | 
			
		||||
    The Sortix C Library is free software: you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
    the Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    The Sortix C Library is distributed in the hope that it will be useful, but
 | 
			
		||||
    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 | 
			
		||||
    or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    fsmarshall/fsm_bootstraprootfd.cpp
 | 
			
		||||
    Creates a root file descriptor associated with a user-space filesystem.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <fsmarshall.h>
 | 
			
		||||
 | 
			
		||||
extern "C" int fsm_bootstraprootfd(int server, ino_t ino, int open_flags,
 | 
			
		||||
                                   mode_t mode)
 | 
			
		||||
{
 | 
			
		||||
	char name[sizeof(uintmax_t)*3];
 | 
			
		||||
	snprintf(name, sizeof(name), "%ju", (uintmax_t) ino);
 | 
			
		||||
	return openat(server, name, open_flags, mode);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2012.
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2014.
 | 
			
		||||
 | 
			
		||||
    This file is part of the Sortix C Library.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,16 +17,18 @@
 | 
			
		|||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    fsmarshall/fsm_listen.cpp
 | 
			
		||||
    Listens for a new channel on a given filesystem server.
 | 
			
		||||
    fsmarshall/fsm_mountat.cpp
 | 
			
		||||
    Attaches a user-space filesystem at the specified mount point.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <sys/syscall.h>
 | 
			
		||||
 | 
			
		||||
#include <fsmarshall.h>
 | 
			
		||||
 | 
			
		||||
extern "C" int fsm_listen(int server)
 | 
			
		||||
DEFN_SYSCALL4(int, sys_fsm_mountat, SYSCALL_FSM_MOUNTAT, int, const char*, const struct stat*, int);
 | 
			
		||||
 | 
			
		||||
extern "C" int fsm_mountat(int dirfd, const char* path, const struct stat* rootst, int flags)
 | 
			
		||||
{
 | 
			
		||||
	return openat(server, "listen", O_RDWR);
 | 
			
		||||
	return sys_fsm_mountat(dirfd, path, rootst, flags);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,32 +0,0 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2012.
 | 
			
		||||
 | 
			
		||||
    This file is part of the Sortix C Library.
 | 
			
		||||
 | 
			
		||||
    The Sortix C Library is free software: you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
    the Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    The Sortix C Library is distributed in the hope that it will be useful, but
 | 
			
		||||
    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 | 
			
		||||
    or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    fsmarshall/fsm_recv.cpp
 | 
			
		||||
    Reads a message from a filesystem communication channel.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <fsmarshall.h>
 | 
			
		||||
 | 
			
		||||
extern "C" ssize_t fsm_recv(int /*server*/, int channel, void* ptr, size_t count)
 | 
			
		||||
{
 | 
			
		||||
	return read(channel, ptr, count);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,33 +0,0 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2012.
 | 
			
		||||
 | 
			
		||||
    This file is part of the Sortix C Library.
 | 
			
		||||
 | 
			
		||||
    The Sortix C Library is free software: you can redistribute it and/or modify
 | 
			
		||||
    it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
    the Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    The Sortix C Library is distributed in the hope that it will be useful, but
 | 
			
		||||
    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 | 
			
		||||
    or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    fsmarshall/fsm_send.cpp
 | 
			
		||||
    Send a message to a filesystem communication channel.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <fsmarshall.h>
 | 
			
		||||
 | 
			
		||||
extern "C" ssize_t fsm_send(int /*server*/, int channel, const void* ptr,
 | 
			
		||||
                            size_t count)
 | 
			
		||||
{
 | 
			
		||||
	return write(channel, ptr, count);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +25,8 @@
 | 
			
		|||
#ifndef INCLUDE_FSMARSHALL_MSG_H
 | 
			
		||||
#define INCLUDE_FSMARSHALL_MSG_H
 | 
			
		||||
 | 
			
		||||
#include <sys/cdefs.h>
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
 | 
			
		||||
#include <sortix/stat.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -32,9 +34,12 @@
 | 
			
		|||
#include <sortix/termios.h>
 | 
			
		||||
#include <sortix/timespec.h>
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
__BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define FSM_MOUNT_CLOEXEC (1 << 0)
 | 
			
		||||
#define FSM_MOUNT_CLOFORK (1 << 1)
 | 
			
		||||
#define FSM_MOUNT_NOFOLLOW (1 << 2)
 | 
			
		||||
#define FSM_MOUNT_NONBLOCK (1 << 3)
 | 
			
		||||
 | 
			
		||||
struct fsm_msg_header
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -427,8 +432,6 @@ struct fsm_resp_tcsetblob
 | 
			
		|||
 | 
			
		||||
#define FSM_MSG_NUM 53
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
__END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2013.
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2013, 2014.
 | 
			
		||||
 | 
			
		||||
    This file is part of the Sortix C Library.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,29 +25,17 @@
 | 
			
		|||
#ifndef INCLUDE_FSMARSHALL_H
 | 
			
		||||
#define INCLUDE_FSMARSHALL_H
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
 | 
			
		||||
#include <sortix/stat.h>
 | 
			
		||||
#include <sortix/termios.h>
 | 
			
		||||
#include <sortix/timespec.h>
 | 
			
		||||
#include <sys/cdefs.h>
 | 
			
		||||
 | 
			
		||||
#include <fsmarshall-msg.h>
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
__BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
int fsm_mkserver();
 | 
			
		||||
int fsm_closeserver(int server);
 | 
			
		||||
int fsm_bootstraprootfd(int server, ino_t ino, int open_flags, mode_t mode);
 | 
			
		||||
int fsm_fsbind(int rootfd, int mountpoint, int flags);
 | 
			
		||||
int fsm_listen(int server);
 | 
			
		||||
int fsm_closechannel(int server, int channel);
 | 
			
		||||
ssize_t fsm_recv(int server, int channel, void* ptr, size_t count);
 | 
			
		||||
ssize_t fsm_send(int server, int channel, const void* ptr, size_t count);
 | 
			
		||||
struct stat;
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
int fsm_fsbind(int, int, int);
 | 
			
		||||
int fsm_mountat(int, const char*, const struct stat*, int);
 | 
			
		||||
 | 
			
		||||
__END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2012.
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2014.
 | 
			
		||||
 | 
			
		||||
    This file is part of the Sortix C Library.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,16 +17,23 @@
 | 
			
		|||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    fsmarshall/fsm_closechannel.cpp
 | 
			
		||||
    Closes a user-space filesystem communication channel.
 | 
			
		||||
    sys/mount.h
 | 
			
		||||
    Filesystem mount functionality.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#ifndef INCLUDE_SYS_MOUNT_H
 | 
			
		||||
#define INCLUDE_SYS_MOUNT_H
 | 
			
		||||
 | 
			
		||||
#include <fsmarshall.h>
 | 
			
		||||
#include <sys/cdefs.h>
 | 
			
		||||
 | 
			
		||||
extern "C" int fsm_closechannel(int /*server*/, int channel)
 | 
			
		||||
{
 | 
			
		||||
	return close(channel);
 | 
			
		||||
}
 | 
			
		||||
#include <sortix/mount.h>
 | 
			
		||||
 | 
			
		||||
__BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
int unmount(const char*, int);
 | 
			
		||||
int unmountat(int, const char*, int);
 | 
			
		||||
 | 
			
		||||
__END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2012.
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2014.
 | 
			
		||||
 | 
			
		||||
    This file is part of the Sortix C Library.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,16 +17,16 @@
 | 
			
		|||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    fsmarshall/fsm_mkserver.cpp
 | 
			
		||||
    Creates a user-space filesystem server.
 | 
			
		||||
    sys/mount/unmount.cpp
 | 
			
		||||
    Unmount filesystem at path.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <sys/mount.h>
 | 
			
		||||
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
#include <fsmarshall.h>
 | 
			
		||||
 | 
			
		||||
extern "C" int fsm_mkserver()
 | 
			
		||||
extern "C" int unmount(const char* path, int flags)
 | 
			
		||||
{
 | 
			
		||||
	return open("/dev/fs/new", O_RDWR | O_CREAT, 0666);
 | 
			
		||||
	return unmountat(AT_FDCWD, path, flags);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2012.
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2014.
 | 
			
		||||
 | 
			
		||||
    This file is part of the Sortix C Library.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,16 +17,17 @@
 | 
			
		|||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    fsmarshall/fsm_closeserver.cpp
 | 
			
		||||
    Destroys a user-space filesystem server.
 | 
			
		||||
    sys/mount/unmountat.cpp
 | 
			
		||||
    Unmount filesystem at path.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/mount.h>
 | 
			
		||||
#include <sys/syscall.h>
 | 
			
		||||
 | 
			
		||||
#include <fsmarshall.h>
 | 
			
		||||
DEFN_SYSCALL3(int, sys_unmountat, SYSCALL_UNMOUNTAT, int, const char*, int);
 | 
			
		||||
 | 
			
		||||
extern "C" int fsm_closeserver(int server)
 | 
			
		||||
extern "C" int unmountat(int dirfd, const char* path, int flags)
 | 
			
		||||
{
 | 
			
		||||
	return close(server);
 | 
			
		||||
	return sys_unmountat(dirfd, path, flags);
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue