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 32 Volume::Volume(fs_volume* fsVolume) 33 : 34 fFSVolume(fsVolume), 35 fSourceFSVolume(NULL), 36 fSourceVnode(NULL), 37 fRootNode(NULL) 38 { 39 } 40 41 42 Volume::~Volume() 43 { 44 if (fSourceVnode != NULL) 45 vfs_put_vnode(fSourceVnode); 46 } 47 48 49 status_t 50 Volume::Mount(const char* parameterString) 51 { 52 const char* source = NULL; 53 void* parameterHandle = parse_driver_settings_string(parameterString); 54 DriverSettingsUnloader parameterDeleter(parameterHandle); 55 if (parameterHandle != NULL) 56 source = get_driver_parameter(parameterHandle, "source", NULL, NULL); 57 if (source == NULL || source[0] == '\0') { 58 ERROR("need source folder ('source' parameter)!\n"); 59 RETURN_ERROR(B_BAD_VALUE); 60 } 61 62 status_t error = vfs_get_vnode_from_path(source, true, &fSourceVnode); 63 if (error != B_OK) 64 RETURN_ERROR(error); 65 if (fSourceVnode == NULL) 66 RETURN_ERROR(B_ENTRY_NOT_FOUND); 67 fs_vnode* sourceFSNode = vfs_fsnode_for_vnode(fSourceVnode); 68 fSourceFSVolume = volume_for_vnode(sourceFSNode); 69 70 struct stat st; 71 if ((stat(source, &st)) != 0) 72 RETURN_ERROR(B_ERROR); 73 74 strlcpy(fName, "bindfs:", sizeof(fName)); 75 strlcpy(fName, source, sizeof(fName)); 76 77 // create the root node 78 fRootNode = new(std::nothrow) Node(st.st_ino, st.st_mode); 79 if (fRootNode == NULL) 80 RETURN_ERROR(B_NO_MEMORY); 81 82 _InitVnodeOpsFrom(sourceFSNode); 83 84 // publish the root node 85 error = publish_vnode(fFSVolume, fRootNode->ID(), fRootNode, &fVnodeOps, 86 fRootNode->Mode() & S_IFMT, 0); 87 if (error != B_OK) { 88 delete fRootNode; 89 fRootNode = NULL; 90 return error; 91 } 92 93 return B_OK; 94 } 95 96 97 void 98 Volume::Unmount() 99 { 100 } 101 102 103 status_t 104 Volume::_InitVnodeOpsFrom(fs_vnode* sourceNode) 105 { 106 // vnode ops 107 int opsCount = sizeof(fVnodeOps) / sizeof(void*); 108 for (int i = 0; i < opsCount; ++i) { 109 if (((void**)sourceNode->ops)[i] == NULL) 110 ((void**)&fVnodeOps)[i] = NULL; 111 else 112 ((void**)&fVnodeOps)[i] = ((void**)&gBindFSVnodeOps)[i]; 113 } 114 115 return B_OK; 116 } 117