A tutorial on writing a simple fuse file system in Python _python

Source: Internet
Author: User
Tags chmod flush mkdir passthrough symlink

If you are my long-time reader, then you should know that I am looking for a perfect backup program, and finally I wrote a bup based on my own encryption layer.

When I wrote Encbup, I was not satisfied with the idea that I had to download the entire huge archive file just to recover a single file, but I still wanted to be able to use ENCFS and rdiff-backup to implement the ability to remotely mount, encrypt, go heavy, and version the backup.

After trying Obnam again (wordy: It's still surprisingly slow), I noticed that it had a mount command. After a thorough study, I found Fuse-python and fusepy, and it would be easy to write a fuse file system in Python.

Smart readers may already be aware of what I'm going to do: I've decided to use Python to write an encrypted file system layer! It's very similar to ENCFS, but there are some important differences:

    • It runs in reverse mode by default, receives normal files, and exposes an encrypted directory. Any backup program discovers (and backs up) these encrypted directories and does not require any other storage.
    • It can also accept configuration files made up of a list of directories, and these directories are exposed at mount points. In this way, all backup scripts need to back up the mount point, and the various directories will be backed up immediately.
    • It tends to be more focused on backup than encrypted storage. It should be fun to write.

An example of a fuse file system

The first step in writing this script is to write a purely transitive file system. It simply accepts a directory and exposes it at Mount point to ensure that any modifications to the mount points are mirrored to the source data.

Fusepy requires you to write a class that defines the various operating system-level methods. You can choose to define the methods that your file system would like to support, others can be temporarily undefined, but I need to define all the methods, because my filesystem is a transitive file system that should behave as closely as possible with the original file system.

Writing this code can be very simple and interesting, because most of the methods are simple encapsulation of the OS module (yes, you can assign values directly to them, such as open=os.open, etc., but my module needs some path extensions). Unfortunately, Fuse-python has a bug (as far as I know) that it cannot pass the file handle back to the file system when it is opened and read. My script, therefore, does not know which file handle is corresponding to the read-write operation of an application, resulting in a failure. You just need to make minimal changes to the fusepy and it works well. It has only one file, so you can put it directly into your project.
Code

Here, I am happy to give this code, when you intend to implement the file system, you can refer to. This code provides a good starting point where you can copy the class directly into your project and rewrite some of the methods as needed.

The next step is the real code:

#!/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.P Ath.join (self.root, partial) return path # filesystem methods # ================== def access (self, path, MO DE): 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) de F Chown (self, path, UID, gid): Full_path = Self._full_path (path) return Os.chown (Full_path, UID, GID) def Geta TTR (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 Readl Ink (self, path): pathname = Os.readlink (Self._full_path (path)) if Pathname.startswith ("/"): # path name is a
      Bsolute, sanitize it. Return Os.path.relpath (pathname, Self.root) Else:return pathname def mknod (self, path, mode, dev): Retu RN 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), 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 (SE LF, PATH, flags: Full_path = Self._full_path (path) return Os.open (Full_path, Flags) def create (self, path, MO DE, 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 the 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])

If you want to run it, just install fusepy, put the code into a file (such as myfuse.py) and run Python myfuse.py/your directory/mount point directory. You will find that all files under the "/Your Directory" path go to the/mount point directory, and you can manipulate them like you would with a native file system.
Conclusion

Overall, I don't think it's as simple as writing a file system. The next thing to do is to add the encryption/decryption functionality to the script, as well as some help-class methods. My goal is to make it a complete alternative to ENCFS, in addition to having better scalability (written in Python) and including some extra features for backup files.

If you want to follow up on the development of this script, please subscribe to my mailing list below or follow me on Twitter. As always welcome feedback (in the comments below is very good).

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.