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 14Volume::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 23Volume::~Volume() 24{ 25 mutex_destroy(&fLock); 26 TRACE("Volume::Destructor : Removing Volume"); 27} 28 29 30bool 31Volume::IsValidSuperBlock() const 32{ 33 return fSuperBlock.IsValid(); 34} 35 36 37status_t 38Volume::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, XfsSuperBlock::Offset_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 76status_t 77Volume::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 141status_t 142Volume::Unmount() 143{ 144 TRACE("Volume::Unmount(): Unmounting"); 145 146 TRACE("Volume::Unmount(): Closing device"); 147 close(fDevice); 148 149 return B_OK; 150} 151