P3:文件系统
概述
你在蜥蜴军团的掩护被揭穿了,你被揭露为双重间谍并被驱逐出去!是的都很“詹姆斯·邦德”,如果你自己这么说的话,那是多么大胆的地下直升机逃生……但是你感到很幸运能带着你的皮肤逃脱。(从字面上看……他们会用你做一套“人体服”!)现在你又回到了“外部”,你的任务是创建一个方案来允许剩余的阻力仍在蜥蜴军团中的战士可以秘密地将信息传回你的组织,而不需要筹集怀疑最近,蜥蜴军团的成员发现了PC经典游戏“DOOM”,它已经成为在总部为它建造新的MOD,所以你的团队决定使用这个标题的MOD作为用于排气的车辆。通过将加密比特埋在纹理和其他游戏数据块中,信息可以隐藏在无害的“WAD”(所有数据在哪里)文件中。
在这个项目中,您将使用FUSE(userspace中的filesystem)实现一个用户空间文件系统守护进程API访问WAD格式的数据,WAD格式是许多经典PC游戏(包括DOOM)中使用的标准和Hexen)。在这个关键的早期原型中,您的任务是实现对的读写访问WAD文件中的文件和目录作为概念证明。因此,您需要实现read和在基于FUSE的程序中为文件和目录编写功能。作为您的战友,我们将提供WAD样本文件,以展示您的功能实施(抵抗力量指望着你!)抵抗力量利用大学课程作为掩护标准操作,因此您将通过Canvas提交项目。
结构
该项目分为三个主要部分:
1) 开发一个用于读取和写入WAD文件的库,并从中创建目录和文件结构。2) 实现一个用户空间守护进程(通过FUSE),以便在安装后访问目录结构。3) 通过导航装载的目录、检查名称和文件内容来测试您的实现,以及添加自己的目录和文件。虽然具体实现可能有所不同,但守护进程的参数必须与本文档中列出的参数相匹配,并且目录结构、命名和文件内容必须通过文件系统正确呈现。文件格式WAD文件格式包含三个部分的信息:提供基本布局信息的标题,描述文件中元素的描述符和包含数据本身的块。注意:所有数字都是小的Endian格式,在适用的情况下,以字节为单位指定!自从爬行动物商店它在内存中的变量也是小Endian格式的,不需要执行任何字节顺序反转在读取或写入数据时,但这仍然是需要了解的重要信息。文件头标头包含文件魔力、描述符计数和描述符在文件中的位置(偏移量):代 写COP4600 文件系统实现细节wad文件的魔力通常是ASCII,并且总是以后缀“wad”(例如,“IWAD”或“PWAD”)结尾。同样重要的是要注意描述符列表,从描述符指示的位置开始偏移量总是位于WAD文件的末尾。
描述符
文件的描述符包含有关WAD文件中元素的信息——文件偏移量、长度和名称某些元素将具有特定的命名约定,以区别于常规内容文件夹。这些“标记”元素将被守护进程解释为目录,并且应该显示相应地在文件系统中(见下文)。
肿块
WAD格式中的元素存储为描述符所描述的“块”。这些结块会在文件系统中由守护进程表示为可以打开、读取和关闭的单个文件。您不能写入现有的块,但您将创建空文件,其块将为您所拥有写信给。
标记元素
WAD文件中有两种主要类型的标记元素,每种标记元素都应解释为目录。类型包括映射标记和命名空间标记。地图标记名称的格式为“E#M#”,其中#表示一个十进制数字(例如“E1M9”)。它们后面跟着十(10)个地图元素描述符。接下来的10个描述符的元素应该是放置在具有地图名称的目录中。映射标记目录不能有文件或目录添加到它们中命名空间标记成对出现。命名空间的开头用描述符标记,该描述符的名称具有后缀“_START”(例如“F1_START”),其结尾用描述符标记,该描述符的名称具有后缀“_END(例如“F1_END”)。位于开头和结尾之间的元素的任何描述符命名空间的标记应放置在具有命名空间名称的目录中(例如,“F1”)。命名空间标记的名称(不包括后缀)永远不会超过两个字符。这些将是您将负责创建的目录类型。
例如,在描述符列表中,以下描述符按顺序应产生此组织:图书馆
您的库将包含一个类来表示WAD数据,如本节所述。
Wad类
Wad类用于表示Wad数据,应具有以下功能。所有路径的根WAD中的数据应为“/”,每个目录应以“/”分隔(例如,“/F/F1/LOLWUT”)。公共静态Wad*loadW(常量字符串和路径)对象分配器;动态创建Wad对象,并将Wad文件数据从路径加载到内存中。调用方必须使用delete关键字解除分配内存。
公共字符串getMagic()返回此WAD数据的魔力。
public bool isContent(const字符串和路径)如果path表示内容(数据),则返回true,否则返回false。public bool isDirectory(const字符串和路径)如果path表示目录,则返回true,否则返回false。public int getSize(const字符串和路径)如果path表示内容,则返回其数据中的字节数;否则,返回-1。public int getContents(const string&path,char*buffer,int length,int offset=0)如果路径表示内容,则将尽可能多的可用字节(最大长度)的内容数据复制到预先存在的缓冲区中。如果提供了偏移量,则应从内容中的该字节开始复制数据。退换商品复制到缓冲区的字节数,如果路径不表示内容(例如,如果它表示目录),则为-1。public int getDirectory(const string&path,vector<string>*目录)若path表示一个目录,那个么将立即包含的元素的条目放在目录中。元素应按照与WAD文件中相同的顺序放置在目录中。返回的数量目录中的元素,或者-1,如果路径不表示目录(例如,如果它表示内容)。偏移长度名称
0 0 F_START
0 0 F1_启动
67500 0 E1M1
67500 1380件东西
68880 6650 LINEDEFS
75532 19440侧定义
94972 1868个顶点
96840 8784段
105624 948名检查员
106572 6608个节点
113180 2210个扇区
115392904拒绝
116296 6922块图
42 9001 LOLWUT
0 0 F1_END
0 0结束
E1M1
东西
LINEDEFS
SIDEDEFS
顶点
SEGS
SSECTORS
节点
扇区
拒绝
块图
LOLWUT
目录结构
public void createDirectory(const字符串和路径)路径包括要创建的新目录的名称。如果给定有效路径,则创建一个新目录在路径处使用命名空间标记。这两个新的名称空间标记将添加到“_END”之前其父目录的标记。无法在地图标记内创建新目录。
public void createFile(const字符串和路径)路径包括要创建的新文件的名称。如果给定有效路径,则在路径处创建一个空文件,偏移量和长度为0。文件将在“_END”标记之前添加到描述符列表中的父目录。无法在地图标记内创建新文件。
public int writeToFile(const string&path,const char*buffer,int length,int offset=0)如果给定一个空文件的有效路径,则增大文件大小并生成块偏移量,然后写入长度量从缓冲区到文件的块数据的字节数。如果提供了偏移量,则应从该偏移量开始写入数据块内容中的字节。返回从缓冲区复制的字节数,如果路径不表示内容,则返回-1(例如,如果它表示一个目录)。
精灵命令和参数
您的守护进程应该具有名称wadfs,并且应该至少接受三个参数——单线程标志“-s”、目标WAD文件和装载目录。例如,这个命令应该挂载TINY。WAD在/home/retilian/mountdir…$ ./wadfs-s TINY。WAD/home/retilian/mountdir$
…这应该是由于执行ls命令来显示其部分内容:
$ls/home/retilian/mountdir/F/F1-al总计0
drwxrwxrwx。2根1970年1月1日0。
drwxrwxrwx。2根
drwxrwxrwx。2根
1970年1月1日。。
1970年1月1日E1M1
-rwxrwxrwx。2根9001 1970年1月1日LOLWUT您的守护程序应该在后台运行。不要硬编码调试(-d)或前台(-f)标志!我们将使用以下命令卸载您的文件系统:
$fusermount-u/home/retilian/mountdir额外信贷
您可能会注意到,在使用守护进程进行测试时,您在中创建的文件的大小有一个上限您的文件系统可以是。您的任务是配置库和守护进程,以便能够创建文件系统中的大文件(例如,使用“cp”复制到200KB的映像文件中)。运行您的调试模式下的守护进程(-d)可能会提示您某些调用的行为。注意:如果文件或目录是在根目录中创建的,它将被放置在描述符列表,而不是在“_END”命名空间标记之前
带保险丝的建筑
FUSE是一个用户空间文件系统API,由Linux内核直接支持。它允许用户空间程序
要向内核提供有关内核无法自行解释的文件系统的信息。
安装和设置
要使用FUSE库,您需要在Reptilian中安装它,并更改FUSE权限:
$sudo apt-install libfuse dev-fuse
$sudo chmod 666/dev/fuse
注意:如果重新启动虚拟机,则需要重新添加FUSE权限,因为它们将被重置!
生成指令
为了使用FUSE库系统构建程序,您需要将文件偏移位指定为64和
识别FUSE版本。我们建议指定FUSE版本26(尽管这是可选的):
$g++-D_FILE_OFFSET_BITS=64-DFUSE_USE_VERSION=26 myproggy.cpp-o myproggy-lfuse
提交的资料
您将在本项目结束时提交以下内容:
Canvas上的手册页格式的报告(p3.txt),包括未列出的放映视频的链接
Canvas上libWad库和wadfs守护进程的压缩tar存档(wad.tar.gz)
汇报
您的报告将解释您是如何实现守护进程的,包括您的通用体系结构/程序
结构它必须包括如何将WAD文件元素表示为目录结构的说明
内存中,以及运行时守护进程如何使用此结构。它将包括
关于如何执行测试以及任何已知错误的描述。报告不应超过600
单词,涵盖项目的所有相关方面,并以专业的方式组织和格式化——这不是
备忘文件和目录要求您的守护进程必须至少实现以下文件系统功能才能提供读写功能
通道
1) 正在检索文件和目录属性
2) 从现有文件中读取,并写入新文件
3) 从现有目录中读取,并写入新目录
文件和目录应具有完全的读取、写入和执行权限。至少使用以下六个保险丝回调函数来实现上述要求:get_attr、mknod、mkdir、读取、写入和读取dir
强烈建议密切关注此pdf底部的链接资源,以帮助您FUSE实现。对文件系统的所有更改(如目录和文件创建)都必须在
安装和拆卸。要构建库和守护进程,我们将执行以下命令:
$tar zxvf wad.tar.gz
$cd libWad
制作
$cd。。
$cd wadfs
制作
$cd。。
要运行您的守护程序,我们将执行以下命令:
$ ./wadfs/wadfs somewadfile.wad/some/mount/目录
要使用您的库构建另一个程序,我们将执行以下命令:
$c++-o程序名称源文件.cpp-L/libWad-lWad