一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語(yǔ)言編程技術(shù)及教程分享平臺(tái)!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - 用Python編寫(xiě)一個(gè)簡(jiǎn)單的FUSE文件系統(tǒng)的教程

用Python編寫(xiě)一個(gè)簡(jiǎn)單的FUSE文件系統(tǒng)的教程

2020-05-29 11:14Stavros Korokithakis Python

這篇文章主要介紹了用Python編寫(xiě)一個(gè)簡(jiǎn)單的FUSE文件系統(tǒng)的教程,對(duì)于數(shù)據(jù)的備份很有幫助,需要的朋友可以參考下

如果你是我的長(zhǎng)期讀者,那么你應(yīng)該知道我在尋找一個(gè)完美備份程序,最后我寫(xiě)了一個(gè)基于bup的我自己的加密層。

在寫(xiě)encbup的時(shí)候,我對(duì)僅僅恢復(fù)一個(gè)文件就必須要下載整個(gè)巨大的檔案文件的做法不甚滿意,但仍然希望能將EncFSrdiff-backup一起使用來(lái)實(shí)現(xiàn)可遠(yuǎn)程掛載、加密、去重、版本化備份的功能。

再次試用obnam 后(啰嗦一句:它還是慢的出奇),我注意到了它有一個(gè)mount命令。深入研究后,我發(fā)現(xiàn)了fuse-pythonfusepy,感覺(jué)用Python寫(xiě)一個(gè)FUSE文件系統(tǒng)應(yīng)該挺簡(jiǎn)單的。

聰明的讀者可能已經(jīng)意識(shí)到了我接下來(lái)要做的事情:我決定用Python寫(xiě)一個(gè)加密文件系統(tǒng)層!它與EncFS會(huì)非常相似,但也有一些重要的區(qū)別:

  •     它默認(rèn)以反向模式運(yùn)行,接收正常的文件并且暴露一個(gè)被加密的目錄。任何備份程序會(huì)發(fā)現(xiàn)(并且備份)這些加密的目錄,不需要任何其它的存儲(chǔ)。
  •     它也能接受由一個(gè)目錄列表組成的配置文件,并且在掛載點(diǎn)將這些目錄暴露出來(lái)。這樣的話,所有的備份腳本就需要將掛載點(diǎn)備份,各種不同的目錄會(huì)立刻得以備份。
  •     它會(huì)更偏重于備份,而不是加密存儲(chǔ)。寫(xiě)起來(lái)應(yīng)該會(huì)挺有意思的。

一個(gè)FUSE文件系統(tǒng)示例

寫(xiě)這個(gè)腳本的第一步是寫(xiě)出一個(gè)純粹的傳遞式的文件系統(tǒng)。它僅僅是接受一個(gè)目錄,并在掛載點(diǎn)將其暴露出來(lái),確保任何在掛載點(diǎn)的修改都會(huì)鏡像到源數(shù)據(jù)中。

fusepy 要求你寫(xiě)一個(gè)類,里面定義了各種操作系統(tǒng)級(jí)別的方法。你可以選擇定義那些你的文件系統(tǒng)想要支持的方法,其他的可以暫時(shí)不予定義,但是我需要定義全部的方法,因?yàn)槲业奈募到y(tǒng)是一個(gè)傳遞式的文件系統(tǒng),它應(yīng)該表現(xiàn)的與原有的文件系統(tǒng)盡可能一致。

寫(xiě)這段代碼會(huì)非常簡(jiǎn)單有趣,因?yàn)榇蟛糠值姆椒ㄖ皇菍?duì)os模塊的一些簡(jiǎn)單封裝(確實(shí),你可以直接給它們賦值,比如 open=os.open 等等,但是我的模塊需要一些路徑擴(kuò)展)。不幸的是,fuse-python有一個(gè)bug(據(jù)我所知)是當(dāng)打開(kāi)和讀文件的時(shí)候,它無(wú)法將文件句柄回傳給文件系統(tǒng)。因而我的腳本不知道某個(gè)應(yīng)用執(zhí)行讀寫(xiě)操作時(shí)對(duì)應(yīng)的是哪個(gè)文件句柄,從而導(dǎo)致了失敗。只需要對(duì)fusepy做極少的改動(dòng),它就可以很好地運(yùn)行。它只有一個(gè)文件,所以你可以把它直接放到你的工程里。
代碼

在這里,我很樂(lè)意給出這段代碼,當(dāng)你打算自己實(shí)現(xiàn)文件系統(tǒng)的時(shí)候可以拿來(lái)參考。這段代碼提供了一個(gè)很好的起點(diǎn),你可以直接把這個(gè)類復(fù)制到你的工程中并且根據(jù)需要重寫(xiě)里面的一些方法。

接下來(lái)是真正的代碼了:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env python
 
from __future__ import with_statement
 
import os
import sys
import errno
 
from fuse import FUSE, FuseOSError, Operations
 
class Passthrough(Operations):
  def __init__(self, root):
    self.root = root
 
  # Helpers
  # =======
 
  def _full_path(self, partial):
    if partial.startswith("/"):
      partial = partial[1:]
    path = os.path.join(self.root, partial)
    return path
 
  # Filesystem methods
  # ==================
 
  def access(self, path, mode):
    full_path = self._full_path(path)
    if not os.access(full_path, mode):
      raise FuseOSError(errno.EACCES)
 
  def chmod(self, path, mode):
    full_path = self._full_path(path)
    return os.chmod(full_path, mode)
 
  def chown(self, path, uid, gid):
    full_path = self._full_path(path)
    return os.chown(full_path, uid, gid)
 
  def getattr(self, path, fh=None):
    full_path = self._full_path(path)
    st = os.lstat(full_path)
    return dict((key, getattr(st, key)) for key in ('st_atime', 'st_ctime',
           'st_gid', 'st_mode', 'st_mtime', 'st_nlink', 'st_size', 'st_uid'))
 
  def readdir(self, path, fh):
    full_path = self._full_path(path)
 
    dirents = ['.', '..']
    if os.path.isdir(full_path):
      dirents.extend(os.listdir(full_path))
    for r in dirents:
      yield r
 
  def readlink(self, path):
    pathname = os.readlink(self._full_path(path))
    if pathname.startswith("/"):
      # Path name is absolute, sanitize it.
      return os.path.relpath(pathname, self.root)
    else:
      return pathname
 
  def mknod(self, path, mode, dev):
    return os.mknod(self._full_path(path), mode, dev)
 
  def rmdir(self, path):
    full_path = self._full_path(path)
    return os.rmdir(full_path)
 
  def mkdir(self, path, mode):
    return os.mkdir(self._full_path(path), mode)
 
  def statfs(self, path):
    full_path = self._full_path(path)
    stv = os.statvfs(full_path)
    return dict((key, getattr(stv, key)) for key in ('f_bavail', 'f_bfree',
      'f_blocks', 'f_bsize', 'f_favail', 'f_ffree', 'f_files', 'f_flag',
      'f_frsize', 'f_namemax'))
 
  def unlink(self, path):
    return os.unlink(self._full_path(path))
 
  def symlink(self, target, name):
    return os.symlink(self._full_path(target), self._full_path(name))
 
  def rename(self, old, new):
    return os.rename(self._full_path(old), self._full_path(new))
 
  def link(self, target, name):
    return os.link(self._full_path(target), self._full_path(name))
 
  def utimens(self, path, times=None):
    return os.utime(self._full_path(path), times)
 
  # File methods
  # ============
 
  def open(self, path, flags):
    full_path = self._full_path(path)
    return os.open(full_path, flags)
 
  def create(self, path, mode, fi=None):
    full_path = self._full_path(path)
    return os.open(full_path, os.O_WRONLY | os.O_CREAT, mode)
 
  def read(self, path, length, offset, fh):
    os.lseek(fh, offset, os.SEEK_SET)
    return os.read(fh, length)
 
  def write(self, path, buf, offset, fh):
    os.lseek(fh, offset, os.SEEK_SET)
    return os.write(fh, buf)
 
  def truncate(self, path, length, fh=None):
    full_path = self._full_path(path)
    with open(full_path, 'r+') as f:
      f.truncate(length)
 
  def flush(self, path, fh):
    return os.fsync(fh)
 
  def release(self, path, fh):
    return os.close(fh)
 
  def fsync(self, path, fdatasync, fh):
    return self.flush(path, fh)
 
def main(mountpoint, root):
  FUSE(Passthrough(root), mountpoint, foreground=True)
 
if __name__ == '__main__':
  main(sys.argv[2], sys.argv[1])

如果你想要運(yùn)行它,只需要安裝fusepy,把這段代碼放進(jìn)一個(gè)文件(比如myfuse.py)然后運(yùn)行 python myfuse.py /你的目錄 /掛載點(diǎn)目錄 。你會(huì)發(fā)現(xiàn) “/你的目錄” 路徑下的所有文件都跑到”/掛載點(diǎn)目錄”,還能像用原生文件系統(tǒng)一樣操作它們。
結(jié)語(yǔ)

總的來(lái)說(shuō),我并不認(rèn)為寫(xiě)一個(gè)文件系統(tǒng)就這么簡(jiǎn)單。接下來(lái)要做的是在腳本里添加加密/解密的功能,以及一些幫助類的方法。我的目標(biāo)是能讓它除了有更好的擴(kuò)展性(因?yàn)槭怯肞ython寫(xiě)的),以及包含一些針對(duì)備份文件的額外特性外,可以成為一個(gè)EncFS的完全替代品。

如果你想跟進(jìn)這個(gè)腳本的開(kāi)發(fā)過(guò)程,請(qǐng)?jiān)谙旅嬗嗛單业泥]件列表,或者在Twitter上關(guān)注我。一如既往的歡迎反饋(在下面評(píng)論就很好)。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美性色老妇人 | 精品一二三区久久AAA片 | 欧美美女一区二区三区 | 国产精品九九久久一区hh | 国产麻豆传媒在线观看 | 亚洲国产精品久久丫 | 亚洲无线一二三四区 | 欧美图片另类小说综合 | 免看一级a一片成人123 | 香蕉久久一区二区三区啪啪 | 探花 在线 | 97视频免费人人观看人人 | 欧美高清videosex极品 | 草莓香蕉绿巨人丝瓜榴莲污在线观看 | 超兴奋朋友的中文字幕下 | 性色AV一区二区三区V视界影院 | 娇妻与公陈峰姚瑶最新版 | 国产精品成人自拍 | 国产福利视频一区二区微拍视频 | 91桃花视频 | 男人疯狂擦进女人下面 | 久久囯产精品777蜜桃传媒 | 桃乃木香奈作品在线 | 999精品视频在线观看热6 | 国产图色| sao虎在线精品永久在线 | 日本三级香港三级久久99 | 97香蕉超级碰碰碰久久兔费 | 亚洲aⅴ男人的天堂在线观看 | 日韩福利网站 | 日本视频在线免费看 | 办公室的秘密在线观看 | 紧身裙女教师波多野结衣 | 91丝袜足控免费网站xx | 欧美日韩国产一区二区三区伦 | 免费成人在线观看视频 | 午夜福利理论片在线播放 | 日韩欧美一区二区三区中文精品 | w7w7w7w7w免费| ipx358cn出差被男上司在线 | 亚州春色|