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

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

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

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

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

2020-05-29 11:14Stavros Korokithakis Python

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

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

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

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

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

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

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

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

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

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

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

接下來是真正的代碼了:

?
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ǔ)

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

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 免费人成黄页在线观看69 | 蜜桃久久久亚洲精品成人 | 欧美日韩国产在线人成 | w7w7w7w7w免费 | 四虎影视永久在线精品免费 | 9191精品国产观看 | 国产精品自在线 | 羞羞视频污 | 精品夜夜澡人妻无码AV蜜桃 | 热99这里只有精品 | 日日草视频 | 天堂资源8中文最新版 | 日本亚欧乱色视频在线观看 | 成人网址大全 | 亚洲高清在线天堂精品 | 国产精品久久久久久久久久久威 | 美女张开双腿让男人捅 | 国产肥女bbwbbw | 欧美视频一区二区专区 | tolove第一季动画在线看 | 性做久久久久久久久浪潮 | 俄罗斯一级淫片 | 亚洲精品免费在线观看 | 亚洲精品国产一区二区第一页 | 教室里老师好紧h | 亚欧综合 | 亚洲六月丁香婷婷综合 | 能播放的欧美同性videos | 国内精品久久久久影院网站 | 亚洲天堂网站在线 | 操国产美女 | 日本乱中文字幕系列在线观看 | 波多野结衣伦理在线观看 | 国产偷啪| 草草免费观看视频在线 | 精品视频在线免费看 | 超h 超重口 高h 污肉1v1 | 交换年轻夫妇HD中文字幕 | 国产第一福利 | 免费高清资源黄网站在线观看 | 99re最新网址 |