1/* 2 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de> 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "Volume.h" 8 9#include <dirent.h> 10#include <errno.h> 11#include <fcntl.h> 12#include <string.h> 13#include <sys/stat.h> 14 15#include <new> 16 17#include <driver_settings.h> 18#include <KernelExport.h> 19#include <vfs.h> 20 21#include <AutoDeleter.h> 22#include <AutoDeleterDrivers.h> 23 24#include "DebugSupport.h" 25#include "kernel_interface.h" 26#include "Node.h" 27 28 29// #pragma mark - Volume 30 31 32Volume::Volume(fs_volume* fsVolume) 33 : 34 fFSVolume(fsVolume), 35 fSourceFSVolume(NULL), 36 fSourceVnode(NULL), 37 fRootNode(NULL) 38{ 39} 40 41 42Volume::~Volume() 43{ 44 if (fSourceVnode != NULL) 45 vfs_put_vnode(fSourceVnode); 46} 47 48 49status_t 50Volume::Mount(const char* parameterString) 51{ 52 const char* source = NULL; 53 DriverSettingsUnloader parametersHandle( 54 parse_driver_settings_string(parameterString)); 55 if (parametersHandle.IsSet()) 56 source = get_driver_parameter( 57 parametersHandle.Get(), "source", NULL, NULL); 58 if (source == NULL || source[0] == '\0') { 59 ERROR("need source folder ('source' parameter)!\n"); 60 RETURN_ERROR(B_BAD_VALUE); 61 } 62 63 status_t error = vfs_get_vnode_from_path(source, true, &fSourceVnode); 64 if (error != B_OK) 65 RETURN_ERROR(error); 66 if (fSourceVnode == NULL) 67 RETURN_ERROR(B_ENTRY_NOT_FOUND); 68 fs_vnode* sourceFSNode = vfs_fsnode_for_vnode(fSourceVnode); 69 fSourceFSVolume = volume_for_vnode(sourceFSNode); 70 71 struct stat st; 72 if ((stat(source, &st)) != 0) 73 RETURN_ERROR(B_ERROR); 74 75 strlcpy(fName, "bindfs:", sizeof(fName)); 76 strlcpy(fName, source, sizeof(fName)); 77 78 // create the root node 79 fRootNode = new(std::nothrow) Node(st.st_ino, st.st_mode); 80 if (fRootNode == NULL) 81 RETURN_ERROR(B_NO_MEMORY); 82 83 _InitVnodeOpsFrom(sourceFSNode); 84 85 // publish the root node 86 error = publish_vnode(fFSVolume, fRootNode->ID(), fRootNode, &fVnodeOps, 87 fRootNode->Mode() & S_IFMT, 0); 88 if (error != B_OK) { 89 delete fRootNode; 90 fRootNode = NULL; 91 return error; 92 } 93 94 return B_OK; 95} 96 97 98void 99Volume::Unmount() 100{ 101} 102 103 104status_t 105Volume::_InitVnodeOpsFrom(fs_vnode* sourceNode) 106{ 107 // vnode ops 108 int opsCount = sizeof(fVnodeOps) / sizeof(void*); 109 for (int i = 0; i < opsCount; ++i) { 110 if (((void**)sourceNode->ops)[i] == NULL) 111 ((void**)&fVnodeOps)[i] = NULL; 112 else 113 ((void**)&fVnodeOps)[i] = ((void**)&gBindFSVnodeOps)[i]; 114 } 115 116 return B_OK; 117} 118