diff --git a/ext/extfs.cpp b/ext/extfs.cpp index 78fa7248..acb60eca 100644 --- a/ext/extfs.cpp +++ b/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 #include #include @@ -49,6 +50,7 @@ #endif #if defined(__sortix__) +#include #include #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__) diff --git a/kernel/descriptor.cpp b/kernel/descriptor.cpp index 0e6d4a32..3fff557c 100644 --- a/kernel/descriptor.cpp +++ b/kernel/descriptor.cpp @@ -26,14 +26,17 @@ #include #include +#include #include #include #include #include +#include #include #include +#include #include #include #include @@ -109,17 +112,40 @@ Ref OpenDirContainingPath(ioctx_t* ctx, // TODO: Add security checks. +Descriptor::Descriptor() +{ + current_offset_lock = KTHREAD_MUTEX_INITIALIZER; + this->vnode = Ref(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, int dflags) { current_offset_lock = KTHREAD_MUTEX_INITIALIZER; + this->vnode = Ref(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, 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 dir = + OpenDirContainingPath(ctx, Ref(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 target, int flags) +{ + return vnode->fsm_fsbind(ctx, target->vnode, flags); +} + +Ref 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(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 dir = + OpenDirContainingPath(ctx, Ref(this), filename, &final); + if ( !dir ) + return errno = EINVAL, Ref(NULL); + if ( !(flags & FSM_MOUNT_NOFOLLOW) ) + { + // TODO: Potentially follow a symlink here! + } + Ref result(new Descriptor()); + if ( !result ) + return Ref(NULL); + Ref result_vnode = dir->vnode->fsm_mount(ctx, final, rootst, subflags); + delete[] final; + if ( !result_vnode ) + return Ref(NULL); + result->LateConstruct(result_vnode, result_dflags); + return result; +} + } // namespace Sortix diff --git a/kernel/fs/user.cpp b/kernel/fs/user.cpp index c1cd4098..8d19546a 100644 --- a/kernel/fs/user.cpp +++ b/kernel/fs/user.cpp @@ -158,8 +158,9 @@ public: Server(); virtual ~Server(); void Disconnect(); + void Unmount(); Channel* Connect(); - Channel* Listen(); + Channel* Accept(); Ref BootstrapNode(ino_t ino, mode_t type); Ref 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); virtual ~ServerNode(); - virtual Ref open(ioctx_t* ctx, const char* filename, int flags, - mode_t mode); + virtual Ref accept(ioctx_t* ctx, uint8_t* addr, size_t* addrlen, + int flags); private: Ref 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) { 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 ServerNode::open(ioctx_t* /*ctx*/, const char* filename, int flags, - mode_t mode) +Ref 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(NULL); - ino_t ino = (ino_t) ull_ino; - return server->BootstrapNode(ino, mode & S_IFMT); - } - errno = saved_errno; - if ( !strcmp(filename, "listen") ) - { - Ref node(new ChannelNode); - if ( !node ) - return Ref(NULL); - Channel* channel = server->Listen(); - if ( !channel ) - return Ref(NULL); - node->Construct(channel); - return node; - } - return errno = ENOENT, Ref(NULL); + (void) addr; + (void) flags; + size_t out_addrlen = 0; + if ( addrlen && !ctx->copy_to_dest(addrlen, &out_addrlen, sizeof(out_addrlen)) ) + return Ref(NULL); + Ref node(new ChannelNode); + if ( !node ) + return Ref(NULL); + Channel* channel = server->Accept(); + if ( !channel ) + return Ref(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 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 FactoryNode::open(ioctx_t* /*ctx*/, const char* filename, - int /*flags*/, mode_t /*mode*/) +bool Bootstrap(Ref* out_root, + Ref* out_server, + const struct stat* rootst) { - if ( !strcmp(filename, "new") ) - { - Ref server(new Server()); - if ( !server ) - return Ref(NULL); - Ref node(new ServerNode(server)); - if ( !node ) - return Ref(NULL); - return node; - } - return errno = ENOENT, Ref(NULL); -} - -} // namespace UserFS -} // namespace Sortix - -namespace Sortix { - -int sys_fsm_fsbind(int rootfd, int mpointfd, int /*flags*/) -{ - Ref desc = CurrentProcess()->GetDescriptor(rootfd); - if ( !desc ) { return -1; } - Ref mpoint = CurrentProcess()->GetDescriptor(mpointfd); - if ( !mpoint ) { return -1; } - Ref mtable = CurrentProcess()->GetMTable(); - Ref 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 slashdev) -{ - ioctx_t ctx; SetupKernelIOCtx(&ctx); - Ref 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 mpoint = slashdev->open(&ctx, "fs", O_READ | O_WRITE, 0); - if ( !mpoint ) - PanicF("Could not open the %s/fs directory", devpath); - Ref 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(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 root_inode = server->OpenNode(root_inode_ino, root_inode_type); + if ( !root_inode ) + return false; + + Ref server_inode(new ServerNode(server)); + if ( !server_inode ) + return false; + + return *out_root = root_inode, *out_server = server_inode, true; } } // namespace UserFS diff --git a/kernel/fs/user.h b/kernel/fs/user.h index e32ae579..c680c7e9 100644 --- a/kernel/fs/user.h +++ b/kernel/fs/user.h @@ -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 + +#include +#include + namespace Sortix { namespace UserFS { -void Init(const char* devpath, Ref slashdev); +bool Bootstrap(Ref* out_root, Ref* out_server, const struct stat* rootst); } // namespace UserFS } // namespace Sortix diff --git a/kernel/include/sortix/kernel/descriptor.h b/kernel/include/sortix/kernel/descriptor.h index 88036666..5f06d9b3 100644 --- a/kernel/include/sortix/kernel/descriptor.h +++ b/kernel/include/sortix/kernel/descriptor.h @@ -50,6 +50,10 @@ typedef struct ioctx_struct ioctx_t; class Descriptor : public Refcountable { +private: + Descriptor(); + void LateConstruct(Ref vnode, int dflags); + public: Descriptor(Ref 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 target, int flags); + Ref fsm_mount(ioctx_t* ctx, const char* filename, + const struct stat* rootst, int flags); private: Ref open_elem(ioctx_t* ctx, const char* filename, int flags, diff --git a/kernel/include/sortix/kernel/inode.h b/kernel/include/sortix/kernel/inode.h index dfbf2535..da447051 100644 --- a/kernel/include/sortix/kernel/inode.h +++ b/kernel/include/sortix/kernel/inode.h @@ -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); }; diff --git a/kernel/include/sortix/kernel/mtable.h b/kernel/include/sortix/kernel/mtable.h index 6ede7f62..1bf6274a 100644 --- a/kernel/include/sortix/kernel/mtable.h +++ b/kernel/include/sortix/kernel/mtable.h @@ -39,6 +39,7 @@ typedef struct Ref inode; ino_t ino; dev_t dev; + bool fsbind; } mountpoint_t; class MountTable : public Refcountable @@ -47,7 +48,8 @@ public: MountTable(); virtual ~MountTable(); Ref Fork(); - bool AddMount(ino_t ino, dev_t dev, Ref inode); + bool AddMount(ino_t ino, dev_t dev, Ref inode, bool fsbind); + bool AddMountUnlocked(ino_t ino, dev_t dev, Ref inode, bool fsbind); public: // Consider these read-only. kthread_mutex_t mtablelock; diff --git a/kernel/include/sortix/kernel/syscall.h b/kernel/include/sortix/kernel/syscall.h index 7eaf68bd..0e9d781f 100644 --- a/kernel/include/sortix/kernel/syscall.h +++ b/kernel/include/sortix/kernel/syscall.h @@ -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); diff --git a/kernel/include/sortix/kernel/vnode.h b/kernel/include/sortix/kernel/vnode.h index 549b39ee..10165168 100644 --- a/kernel/include/sortix/kernel/vnode.h +++ b/kernel/include/sortix/kernel/vnode.h @@ -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 target, int flags); + Ref fsm_mount(ioctx_t* ctx, const char* filename, const struct stat* rootst, int flags); public /*TODO: private*/: Ref inode; diff --git a/kernel/include/sortix/mount.h b/kernel/include/sortix/mount.h index ac1c6933..9b899999 100644 --- a/kernel/include/sortix/mount.h +++ b/kernel/include/sortix/mount.h @@ -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 diff --git a/kernel/include/sortix/syscall.h b/kernel/include/sortix/syscall.h index 79acfd55..7832700b 100644 --- a/kernel/include/sortix/syscall.h +++ b/kernel/include/sortix/syscall.h @@ -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 diff --git a/kernel/inode.cpp b/kernel/inode.cpp index 17852eea..37307411 100644 --- a/kernel/inode.cpp +++ b/kernel/inode.cpp @@ -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 diff --git a/kernel/io.cpp b/kernel/io.cpp index 6bf58789..9ed7b76f 100644 --- a/kernel/io.cpp +++ b/kernel/io.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -174,7 +175,13 @@ int sys_openat(int dirfd, const char* path, int flags, mode_t mode) if ( !desc ) return -1; Ref 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 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 desc = CurrentProcess()->GetDescriptor(rootfd); + if ( !desc ) + return -1; + Ref 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 from = PrepareLookup(&relpath, dirfd); + if ( !from ) + return delete[] pathcopy, -1; + Ref desc = from->fsm_mount(&ctx, relpath, rootst, flags); + delete[] pathcopy; + Ref 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 diff --git a/kernel/kernel.cpp b/kernel/kernel.cpp index f69c6d0a..2df77eb1 100644 --- a/kernel/kernel.cpp +++ b/kernel/kernel.cpp @@ -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") // diff --git a/kernel/mtable.cpp b/kernel/mtable.cpp index 4569b9ed..881ca367 100644 --- a/kernel/mtable.cpp +++ b/kernel/mtable.cpp @@ -61,9 +61,14 @@ Ref MountTable::Fork() return clone; } -bool MountTable::AddMount(ino_t ino, dev_t dev, Ref inode) +bool MountTable::AddMount(ino_t ino, dev_t dev, Ref inode, bool fsbind) { ScopedLock lock(&mtablelock); + return AddMountUnlocked(ino, dev, inode, fsbind); +} + +bool MountTable::AddMountUnlocked(ino_t ino, dev_t dev, Ref 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) mp->ino = ino; mp->dev = dev; mp->inode = inode; + mp->fsbind = fsbind; return true; } diff --git a/kernel/net/fs.cpp b/kernel/net/fs.cpp index 95c3ee31..259ab5aa 100644 --- a/kernel/net/fs.cpp +++ b/kernel/net/fs.cpp @@ -536,7 +536,7 @@ void Init(const char* devpath, Ref slashdev) Ref 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); } diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp index ba47c745..5085bdae 100644 --- a/kernel/syscall.cpp +++ b/kernel/syscall.cpp @@ -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" diff --git a/kernel/vnode.cpp b/kernel/vnode.cpp index e3624552..1aaad4da 100644 --- a/kernel/vnode.cpp +++ b/kernel/vnode.cpp @@ -25,7 +25,9 @@ #include #include +#include #include +#include #include #include @@ -36,20 +38,31 @@ #include #include +#include "fs/user.h" + namespace Sortix { -static Ref LookupMount(Ref inode) +static Ref LookupMountUnlocked(Ref inode, size_t* out_index = NULL) { + Ref result_inode(NULL); Ref 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(NULL); + return result_inode; +} + +static Ref LookupMount(Ref inode) +{ + Ref mtable = CurrentProcess()->GetMTable(); + ScopedLock mtable_lock(&mtable->mtablelock); + return LookupMountUnlocked(inode); } Vnode::Vnode(Ref inode, Ref mountedat, ino_t rootino, dev_t rootdev) @@ -88,7 +101,8 @@ Ref Vnode::open(ioctx_t* ctx, const char* filename, int flags, mode_t mod // Move within the current filesystem. Ref retinode = inode->open(ctx, filename, flags, mode); - if ( !retinode ) { return Ref(NULL); } + if ( !retinode ) + return Ref(NULL); Ref retmountedat = mountedat; ino_t retrootino = rootino; dev_t retrootdev = rootdev; @@ -106,6 +120,102 @@ Ref Vnode::open(ioctx_t* ctx, const char* filename, int flags, mode_t mod return Ref(new Vnode(retinode, retmountedat, retrootino, retrootdev)); } +int Vnode::fsm_fsbind(ioctx_t* ctx, Ref target, int flags) +{ + (void) ctx; + if ( flags & ~(0) ) + return errno = EINVAL, -1; + Ref mtable = CurrentProcess()->GetMTable(); + if ( !mtable->AddMount(ino, dev, target->inode, true) ) + return -1; + return 0; +} + +Ref Vnode::fsm_mount(ioctx_t* ctx, + const char* filename, + const struct stat* rootst_ptr, + int flags) +{ + if ( flags & ~(0) ) + return Ref(NULL); + + if ( !strcmp(filename, ".") || !strcmp(filename, "..") ) + return errno = EINVAL, Ref(NULL); + + struct stat rootst; + if ( !ctx->copy_from_src(&rootst, rootst_ptr, sizeof(struct stat)) ) + return Ref(NULL); + + Ref normal_inode = inode->open(ctx, filename, O_READ, 0); + if ( !normal_inode ) + return Ref(NULL); + + Ref root_inode; + Ref server_inode; + if ( !UserFS::Bootstrap(&root_inode, &server_inode, &rootst) ) + return Ref(NULL); + + Ref server_vnode(new Vnode(server_inode, Ref(NULL), 0, 0)); + if ( !server_vnode ) + return Ref(NULL); + + Ref mtable = CurrentProcess()->GetMTable(); + ScopedLock lock(&mtable->mtablelock); + if ( Ref mounted = LookupMountUnlocked(normal_inode) ) + normal_inode = mounted; + + if ( !mtable->AddMountUnlocked(normal_inode->ino, normal_inode->dev, root_inode, false) ) + return Ref(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 normal_inode = inode->open(ctx, filename, O_READ, 0); + if ( !normal_inode ) + return -1; + + Ref 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 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); diff --git a/libc/Makefile b/libc/Makefile index 071ee81b..7b27a8c9 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -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 \ diff --git a/libc/fsmarshall/fsm_bootstraprootfd.cpp b/libc/fsmarshall/fsm_bootstraprootfd.cpp deleted file mode 100644 index 413435fe..00000000 --- a/libc/fsmarshall/fsm_bootstraprootfd.cpp +++ /dev/null @@ -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 . - - fsmarshall/fsm_bootstraprootfd.cpp - Creates a root file descriptor associated with a user-space filesystem. - -*******************************************************************************/ - -#include -#include -#include -#include - -#include - -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); -} diff --git a/libc/fsmarshall/fsm_listen.cpp b/libc/fsmarshall/fsm_mountat.cpp similarity index 69% rename from libc/fsmarshall/fsm_listen.cpp rename to libc/fsmarshall/fsm_mountat.cpp index 46ad4f07..9b44f198 100644 --- a/libc/fsmarshall/fsm_listen.cpp +++ b/libc/fsmarshall/fsm_mountat.cpp @@ -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 . - 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 +#include #include -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); } diff --git a/libc/fsmarshall/fsm_recv.cpp b/libc/fsmarshall/fsm_recv.cpp deleted file mode 100644 index d0fb55f9..00000000 --- a/libc/fsmarshall/fsm_recv.cpp +++ /dev/null @@ -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 . - - fsmarshall/fsm_recv.cpp - Reads a message from a filesystem communication channel. - -*******************************************************************************/ - -#include - -#include - -extern "C" ssize_t fsm_recv(int /*server*/, int channel, void* ptr, size_t count) -{ - return read(channel, ptr, count); -} diff --git a/libc/fsmarshall/fsm_send.cpp b/libc/fsmarshall/fsm_send.cpp deleted file mode 100644 index f8c6618c..00000000 --- a/libc/fsmarshall/fsm_send.cpp +++ /dev/null @@ -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 . - - fsmarshall/fsm_send.cpp - Send a message to a filesystem communication channel. - -*******************************************************************************/ - -#include - -#include - -extern "C" ssize_t fsm_send(int /*server*/, int channel, const void* ptr, - size_t count) -{ - return write(channel, ptr, count); -} diff --git a/libc/include/fsmarshall-msg.h b/libc/include/fsmarshall-msg.h index b53426e6..df0b576a 100644 --- a/libc/include/fsmarshall-msg.h +++ b/libc/include/fsmarshall-msg.h @@ -25,6 +25,8 @@ #ifndef INCLUDE_FSMARSHALL_MSG_H #define INCLUDE_FSMARSHALL_MSG_H +#include + #include #include @@ -32,9 +34,12 @@ #include #include -#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 diff --git a/libc/include/fsmarshall.h b/libc/include/fsmarshall.h index 1ae16ca1..63709662 100644 --- a/libc/include/fsmarshall.h +++ b/libc/include/fsmarshall.h @@ -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 - -#include -#include -#include +#include #include -#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 diff --git a/libc/fsmarshall/fsm_closechannel.cpp b/libc/include/sys/mount.h similarity index 74% rename from libc/fsmarshall/fsm_closechannel.cpp rename to libc/include/sys/mount.h index 7ec21ae2..54e81a5a 100644 --- a/libc/fsmarshall/fsm_closechannel.cpp +++ b/libc/include/sys/mount.h @@ -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 . - fsmarshall/fsm_closechannel.cpp - Closes a user-space filesystem communication channel. + sys/mount.h + Filesystem mount functionality. *******************************************************************************/ -#include +#ifndef INCLUDE_SYS_MOUNT_H +#define INCLUDE_SYS_MOUNT_H -#include +#include -extern "C" int fsm_closechannel(int /*server*/, int channel) -{ - return close(channel); -} +#include + +__BEGIN_DECLS + +int unmount(const char*, int); +int unmountat(int, const char*, int); + +__END_DECLS + +#endif diff --git a/libc/fsmarshall/fsm_mkserver.cpp b/libc/sys/mount/unmount.cpp similarity index 80% rename from libc/fsmarshall/fsm_mkserver.cpp rename to libc/sys/mount/unmount.cpp index ec3342e6..5e7cb9cb 100644 --- a/libc/fsmarshall/fsm_mkserver.cpp +++ b/libc/sys/mount/unmount.cpp @@ -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 . - fsmarshall/fsm_mkserver.cpp - Creates a user-space filesystem server. + sys/mount/unmount.cpp + Unmount filesystem at path. *******************************************************************************/ +#include + #include -#include - -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); } diff --git a/libc/fsmarshall/fsm_closeserver.cpp b/libc/sys/mount/unmountat.cpp similarity index 72% rename from libc/fsmarshall/fsm_closeserver.cpp rename to libc/sys/mount/unmountat.cpp index 463eac0f..300152f6 100644 --- a/libc/fsmarshall/fsm_closeserver.cpp +++ b/libc/sys/mount/unmountat.cpp @@ -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 . - fsmarshall/fsm_closeserver.cpp - Destroys a user-space filesystem server. + sys/mount/unmountat.cpp + Unmount filesystem at path. *******************************************************************************/ -#include +#include +#include -#include +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); }