1 /* 2 * Copyright 2001 - 2017, Axel Dörfler, axeld @pinc - software.de. 3 * Copyright 2020, Shubham Bhagat, shubhambhagat111@yahoo.com 4 * All rights reserved. Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "Volume.h" 9 10 #include "Checksum.h" 11 #include "Inode.h" 12 13 14 Volume::Volume(fs_volume *volume) 15 : fFSVolume(volume) 16 { 17 fFlags = 0; 18 mutex_init(&fLock, "xfs volume"); 19 TRACE("Volume::Volume() : Initialising volume"); 20 } 21 22 23 Volume::~Volume() 24 { 25 mutex_destroy(&fLock); 26 TRACE("Volume::Destructor : Removing Volume"); 27 } 28 29 30 bool 31 Volume::IsValidSuperBlock() const 32 { 33 return fSuperBlock.IsValid(); 34 } 35 36 37 status_t 38 Volume::Identify(int fd, XfsSuperBlock *superBlock) 39 { 40 41 TRACE("Volume::Identify() : Identifying Volume in progress"); 42 43 //Create a buffer of 512 bytes for Crc verification 44 char buf[512]; 45 46 if(read_pos(fd, 0, buf, 512) != 512) 47 return B_IO_ERROR; 48 49 memcpy(superBlock, buf, sizeof(XfsSuperBlock)); 50 51 int version = B_BENDIAN_TO_HOST_INT16(superBlock->Version()) & XFS_SB_VERSION_NUMBITS; 52 53 // if its V5 filesystem check for superblock checksum 54 if (superBlock->MagicNum() == B_HOST_TO_BENDIAN_INT32(XFS_SB_MAGIC) 55 && (version == 5 || superBlock->Crc() != 0)) { 56 57 TRACE("Superblock Crc: (%" B_PRIu32 ")\n", superBlock->Crc()); 58 59 if(!xfs_verify_cksum(buf, 512, offsetof(XfsSuperBlock, sb_crc))) { 60 ERROR("Filesystem is corrupted"); 61 return B_BAD_VALUE; 62 } 63 64 } 65 66 superBlock->SwapEndian(); 67 68 if (!superBlock->IsValid()) { 69 ERROR("Volume::Identify(): Invalid Superblock!\n"); 70 return B_BAD_VALUE; 71 } 72 return B_OK; 73 } 74 75 76 status_t 77 Volume::Mount(const char *deviceName, uint32 flags) 78 { 79 TRACE("Volume::Mount() : Mounting in progress"); 80 81 flags |= B_MOUNT_READ_ONLY; 82 83 if ((flags & B_MOUNT_READ_ONLY) != 0) { 84 TRACE("Volume::Mount(): Read only\n"); 85 } else { 86 TRACE("Volume::Mount(): Read write\n"); 87 } 88 89 DeviceOpener opener(deviceName, (flags & B_MOUNT_READ_ONLY) != 0 90 ? O_RDONLY 91 : O_RDWR); 92 fDevice = opener.Device(); 93 if (fDevice < B_OK) { 94 ERROR("Volume::Mount(): couldn't open device\n"); 95 return fDevice; 96 } 97 98 if (opener.IsReadOnly()) 99 fFlags |= VOLUME_READ_ONLY; 100 101 // read the superblock 102 status_t status = Identify(fDevice, &fSuperBlock); 103 if (status != B_OK) { 104 ERROR("Volume::Mount(): Invalid super block!\n"); 105 return B_BAD_VALUE; 106 } 107 108 if ((fSuperBlock.Version() & XFS_SB_VERSION_NUMBITS) == 5) 109 TRACE("Volume::Mount(): Valid Version 5 SuperBlock.\n"); 110 else 111 TRACE("Volume::Mount(): Valid Version 4 SuperBlock.\n"); 112 113 114 // check if the device size is large enough to hold the file system 115 off_t diskSize; 116 if (opener.GetSize(&diskSize) != B_OK) { 117 ERROR("Volume:Mount() Unable to get diskSize"); 118 return B_ERROR; 119 } 120 121 opener.Keep(); 122 123 //publish the root inode 124 Inode* rootInode = new(std::nothrow) Inode(this, Root()); 125 if (rootInode == NULL) 126 return B_NO_MEMORY; 127 128 status = rootInode->Init(); 129 if (status != B_OK) 130 return status; 131 132 status = publish_vnode(FSVolume(), Root(), 133 (void*)rootInode, &gxfsVnodeOps, rootInode->Mode(), 0); 134 if (status != B_OK) 135 return B_BAD_VALUE; 136 137 return B_OK; 138 } 139 140 141 status_t 142 Volume::Unmount() 143 { 144 TRACE("Volume::Unmount(): Unmounting"); 145 146 TRACE("Volume::Unmount(): Closing device"); 147 close(fDevice); 148 149 return B_OK; 150 } 151