/** Destructor, free all memory used by the vqa. */ VQAMovie::~VQAMovie() { delete[] CBF_LookUp; delete[] CBP_LookUp; delete[] VPT_Table; delete[] offsets; VFS_Close(vqafile); }
/** * \fn void Ext2_Unmount(tVFS_Node *Node) * \brief Close a mounted device */ void Ext2_Unmount(tVFS_Node *Node) { tExt2_Disk *disk = Node->ImplPtr; VFS_Close( disk->FD ); Inode_ClearCache( disk->CacheID ); memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group)); free(disk); }
/** * \fn int VFS_Symlink(const char *Name, const char *Link) * \brief Creates a symlink called \a Name to \a Link * \param Name Name of symbolic link * \param Link Destination of symbolic link */ int VFS_Symlink(const char *Name, const char *Link) { char *realLink; int fp; ENTER("sName sLink", Name, Link); // Get absolue path name realLink = VFS_GetAbsPath( Link ); if(!realLink) { Log_Warning("VFS", "Path '%s' is badly formed", Link); errno = EINVAL; LEAVE('i', -1); return -1; } LOG("realLink = '%s'", realLink); // Make node if( VFS_MkNod(Name, VFS_FFLAG_SYMLINK) != 0 ) { Log_Warning("VFS", "Unable to create link node '%s'", Name); free(realLink); // errno is set by VFS_MkNod LEAVE('i', -2); return -2; // Make link node } // Write link address fp = VFS_Open(Name, VFS_OPENFLAG_WRITE|VFS_OPENFLAG_NOLINK); if( fp == -1 ) { Log_Warning("VFS", "Unable to open newly created symlink '%s'", Name); free(realLink); LEAVE('i', -3); return -3; } VFS_Write(fp, strlen(realLink), realLink); VFS_Close(fp); free(realLink); LEAVE('i', 1); return 1; }
/** * \brief Mount a device * \param Device Device string to mount * \param MountPoint Destination for the mount * \param Filesystem Filesystem to use for the mount * \param Options Options to be passed to the filesystem * \return -1 on Invalid FS, -2 on No Mem, 0 on success * * Mounts the filesystem on \a Device at \a MountPoint using the driver * \a Filesystem. The options in the string \a Options is passed to the * driver's mount. */ int VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem, const char *Options) { tVFS_Mount *mnt, *parent_mnt; tVFS_Driver *fs; int deviceLen = strlen(Device); int mountLen = strlen(MountPoint); int argLen = strlen(Options); // Get the filesystem if( Filesystem && Filesystem[0] ) { fs = VFS_GetFSByName(Filesystem); if(!fs) { Log_Warning("VFS", "VFS_Mount - Unknown FS Type '%s'", Filesystem); return -ENOENT; } } else { int fd = VFS_Open(Device, VFS_OPENFLAG_READ); if( fd == -1 ) { Log_Warning("VFS", "VFS_Mount - Unable to open '%s' for autodetect", Device); return -ENOENT; } tVFS_Driver *bestfs = NULL; int bestrank = 0, rank; for( fs = gVFS_Drivers; fs; fs = fs->Next ) { if(!fs->Detect) continue ; rank = fs->Detect(fd); if(!rank) continue ; if(!bestfs || rank > bestrank) { bestfs = fs; bestrank = rank; } } VFS_Close(fd); if( bestfs == NULL ) { Log_Warning("VFS", "VFS_Mount - Filesystem autodetection failed"); return -1; } fs = bestfs; } // Validate the mountpoint target // - Only if / is mounted if( gVFS_Mounts ) { tVFS_Node *mpnode = VFS_ParsePath(MountPoint, NULL, &parent_mnt); if( !mpnode ) { Log_Warning("VFS", "VFS_Mount - Mountpoint '%s' does not exist", MountPoint); return -1; } if( mpnode->Type->Close ) mpnode->Type->Close(mpnode); if( parent_mnt->RootNode == mpnode ) { Log_Warning("VFS", "VFS_Mount - Attempt to mount over '%s' (%s)", MountPoint, parent_mnt->MountPoint); return -1; } } // Create mount information mnt = malloc( sizeof(tVFS_Mount)+deviceLen+1+mountLen+1+argLen+1 ); if(!mnt) { ASSERT(parent_mnt->OpenHandleCount > 0); parent_mnt->OpenHandleCount --; return -2; } // HACK: Forces VFS_ParsePath to fall back on root if(mountLen == 1 && MountPoint[0] == '/') mnt->MountPointLen = 0; else mnt->MountPointLen = mountLen; // Fill Structure mnt->Filesystem = fs; mnt->OpenHandleCount = 0; mnt->Device = &mnt->StrData[0]; memcpy( mnt->Device, Device, deviceLen+1 ); mnt->MountPoint = &mnt->StrData[deviceLen+1]; memcpy( mnt->MountPoint, MountPoint, mountLen+1 ); mnt->Options = &mnt->StrData[deviceLen+1+mountLen+1]; memcpy( mnt->Options, Options, argLen+1 ); // Parse options string char *str = mnt->Options; int nArg = 0; do { nArg ++; } while( (str = strchr(str, ',')) ); char *args[nArg + 1]; str = mnt->Options; nArg = 0; do { args[nArg++] = str; str = strchr(str, ','); if(str) *str = '\0'; } while( str ); args[nArg] = 0; // NULL terminal // Initialise Volume mnt->RootNode = fs->InitDevice(Device, (const char **)args); if(!mnt->RootNode) { free(mnt); ASSERT(parent_mnt->OpenHandleCount>0); parent_mnt->OpenHandleCount --; return -2; } // Repair the options string while( nArg -- > 1 ) args[nArg][-1] = ','; mnt->Identifier = giVFS_NextMountIdent++; #if 0 // Ensure identifiers don't repeat // - Only a problem if there have been 4 billion mounts while( giVFS_NextMountIdent == 0 || VFS_GetMountByIdent(giVFS_NextMountIdent) ) giVFS_NextMountIdent ++; #endif // Set root if(!gVFS_RootMount) gVFS_RootMount = mnt; // Add to mount list RWLock_AcquireWrite( &glVFS_MountList ); { mnt->Next = NULL; if(gVFS_Mounts) { tVFS_Mount *tmp; for( tmp = gVFS_Mounts; tmp->Next; tmp = tmp->Next ); tmp->Next = mnt; } else { gVFS_Mounts = mnt; } } RWLock_Release( &glVFS_MountList ); Log_Log("VFS", "Mounted '%s' to '%s' ('%s')", Device, MountPoint, fs->Name); VFS_UpdateMountFile(); return 0; }
/** \brief Initializes a device to be read by by the driver \param Device String - Device to read from \param Options NULL Terminated array of option strings \return Root Node */ tVFS_Node *Ext2_InitDevice(const char *Device, const char **Options) { tExt2_Disk *disk = NULL; int fd; int groupCount; tExt2_SuperBlock sb; ENTER("sDevice pOptions", Device, Options); // Open Disk fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE); //Open Device if(fd == -1) { Log_Warning("EXT2", "Unable to open '%s'", Device); LEAVE('n'); return NULL; } // Read Superblock at offset 1024 VFS_ReadAt(fd, 1024, 1024, &sb); // Read Superblock // Sanity Check Magic value if(sb.s_magic != 0xEF53) { Log_Warning("EXT2", "Volume '%s' is not an EXT2 volume (0x%x != 0xEF53)", Device, sb.s_magic); goto _error; } if( sb.s_blocks_per_group < MIN_BLOCKS_PER_GROUP ) { Log_Warning("Ext2", "Blocks per group is too small (%i < %i)", sb.s_blocks_per_group, MIN_BLOCKS_PER_GROUP); goto _error; } // Get Group count groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group); LOG("groupCount = %i", groupCount); // Allocate Disk Information disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount); if(!disk) { Log_Warning("EXT2", "Unable to allocate disk structure"); goto _error; } disk->FD = fd; memcpy(&disk->SuperBlock, &sb, 1024); disk->GroupCount = groupCount; // Get an inode cache handle disk->CacheID = Inode_GetHandle(NULL); // Get Block Size if( sb.s_log_block_size > MAX_BLOCK_LOG_SIZE ) { Log_Warning("Ext2", "Block size (log2) too large (%i > %i)", sb.s_log_block_size, MAX_BLOCK_LOG_SIZE); goto _error; } disk->BlockSize = 1024 << sb.s_log_block_size; LOG("Disk->BlockSie = 0x%x (1024 << %i)", disk->BlockSize, sb.s_log_block_size); // Read Group Information LOG("sb,s_first_data_block = %x", sb.s_first_data_block); VFS_ReadAt( disk->FD, sb.s_first_data_block * disk->BlockSize + 1024, sizeof(tExt2_Group)*groupCount, disk->Groups ); LOG("Block Group 0"); LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap); LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap); LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table); LOG("Block Group 1"); LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap); LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap); LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table); // Get root Inode Ext2_int_ReadInode(disk, 2, &disk->RootInode); // Create Root Node memset(&disk->RootNode, 0, sizeof(tVFS_Node)); disk->RootNode.Inode = 2; // Root inode ID disk->RootNode.ImplPtr = disk; // Save disk pointer disk->RootNode.Size = -1; // Fill in later (on readdir) disk->RootNode.Flags = VFS_FFLAG_DIRECTORY; disk->RootNode.Type = &gExt2_DirType; // Complete root node disk->RootNode.UID = disk->RootInode.i_uid; disk->RootNode.GID = disk->RootInode.i_gid; disk->RootNode.NumACLs = 1; disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW; #if DEBUG LOG("inode.i_size = 0x%x", disk->RootInode.i_size); LOG("inode.i_block[0] = 0x%x", disk->RootInode.i_block[0]); #endif LEAVE('p', &disk->RootNode); return &disk->RootNode; _error: if( disk ) free(disk); VFS_Close(fd); LEAVE('n'); return NULL; }