ait/os/bin/mirrorfuse/mirrorfuse.py
author om
Tue, 12 Nov 2013 11:31:34 +0100
branchom
changeset 2 c9bf2537109a
permissions -rwxr-xr-x
added C/C++ and Python sources
om@2
     1
#!/bin/env python
om@2
     2
# -*- coding: utf-8 -*-
om@2
     3
om@2
     4
# ------------------------------------------------------------
om@2
     5
# mirrorfuse
om@2
     6
# 
om@2
     7
# create a mirror filesystem folder as a new filesystem to mount
om@2
     8
#
om@2
     9
# This is directly based on xmp.py of the 
om@2
    10
# dev-python/fuse-python example
om@2
    11
#
om@2
    12
# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
om@2
    13
#
om@2
    14
# Copyright (C) 2013 AIT Austrian Institute of Technology
om@2
    15
# AIT Austrian Institute of Technology GmbH
om@2
    16
# Donau-City-Strasse 1 | 1220 Vienna | Austria
om@2
    17
# http://www.ait.ac.at
om@2
    18
#
om@2
    19
# This program is free software; you can redistribute it and/or
om@2
    20
# modify it under the terms of the GNU General Public License
om@2
    21
# as published by the Free Software Foundation version 2.
om@2
    22
# 
om@2
    23
# This program is distributed in the hope that it will be useful,
om@2
    24
# but WITHOUT ANY WARRANTY; without even the implied warranty of
om@2
    25
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
om@2
    26
# GNU General Public License for more details.
om@2
    27
# 
om@2
    28
# You should have received a copy of the GNU General Public License
om@2
    29
# along with this program; if not, write to the Free Software
om@2
    30
# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
om@2
    31
# Boston, MA  02110-1301, USA.
om@2
    32
# ------------------------------------------------------------
om@2
    33
om@2
    34
om@2
    35
# ------------------------------------------------------------
om@2
    36
# imports
om@2
    37
om@2
    38
import errno
om@2
    39
import fcntl
om@2
    40
import fuse
om@2
    41
import os
om@2
    42
import sys
om@2
    43
om@2
    44
from fuse import Fuse
om@2
    45
om@2
    46
# ------------------------------------------------------------
om@2
    47
# const
om@2
    48
om@2
    49
om@2
    50
__version__ = "0.1"
om@2
    51
om@2
    52
om@2
    53
# ------------------------------------------------------------
om@2
    54
# code
om@2
    55
om@2
    56
om@2
    57
class MirrorFuse(Fuse):
om@2
    58
    
om@2
    59
    """This is the Mirror FUSE in python.
om@2
    60
    
om@2
    61
    This is to represnt a file hierarchy elsewhere (and intercept each file system call)
om@2
    62
    """
om@2
    63
om@2
    64
    def __init__(self, *args, **kw):
om@2
    65
        fuse.fuse_python_api = (0, 2)
om@2
    66
        super(MirrorFuse, self).__init__(*args, **kw)
om@2
    67
        self.root = '/'
om@2
    68
        self.os_server_url = ''
om@2
    69
        
om@2
    70
    def getattr(self, path):
om@2
    71
        return os.lstat("." + path)
om@2
    72
    
om@2
    73
om@2
    74
    #
om@2
    75
    # links are not allowed for a mirrored FS
om@2
    76
    #
om@2
    77
    def readlink(self, path):
om@2
    78
        eturn -errno.EACCES
om@2
    79
    
om@2
    80
om@2
    81
    def readdir(self, path, offset):
om@2
    82
        for e in os.listdir("." + path):
om@2
    83
            yield fuse.Direntry(e)
om@2
    84
            
om@2
    85
om@2
    86
    def unlink(self, path):
om@2
    87
        sys.stdout.write("===\nInsert Hook here! Deleting file %s\n===\n" % path)
om@2
    88
        os.unlink("." + path)
om@2
    89
        
om@2
    90
om@2
    91
    def rmdir(self, path):
om@2
    92
        sys.stdout.write("===\nInsert Hook here! Deleting folder %s\n===\n" % path)
om@2
    93
        os.rmdir("." + path)
om@2
    94
        
om@2
    95
om@2
    96
    #
om@2
    97
    # links are not allowed for a mirrored FS
om@2
    98
    #
om@2
    99
    def symlink(self, path, path1):
om@2
   100
        eturn -errno.EACCES
om@2
   101
        
om@2
   102
om@2
   103
    def rename(self, path, path1):
om@2
   104
        sys.stdout.write("===\nInsert Hook here! Moving file %s --> %s\n===\n" % path % path1)
om@2
   105
        os.rename("." + path, "." + path1)
om@2
   106
        
om@2
   107
om@2
   108
    #
om@2
   109
    # links are not allowed for a mirrored FS
om@2
   110
    #
om@2
   111
    def link(self, path, path1):
om@2
   112
        return -errno.EACCES
om@2
   113
        
om@2
   114
om@2
   115
    #
om@2
   116
    # changing access mode is not allowed in mirrored FS
om@2
   117
    #
om@2
   118
    def chmod(self, path, mode):
om@2
   119
        return -errno.EACCES
om@2
   120
        
om@2
   121
om@2
   122
    #
om@2
   123
    # changing ownership is not allowed in mirrored FS
om@2
   124
    #
om@2
   125
    def chown(self, path, user, group):
om@2
   126
        return -errno.EACCES
om@2
   127
        
om@2
   128
om@2
   129
    def truncate(self, path, len):
om@2
   130
        f = open("." + path, "a")
om@2
   131
        f.truncate(len)
om@2
   132
        f.close()
om@2
   133
        
om@2
   134
om@2
   135
    def mknod(self, path, mode, dev):
om@2
   136
        sys.stdout.write("===\nInsert Hook here! Creating file %s\n===\n" % path)
om@2
   137
        os.mknod("." + path, mode, dev)
om@2
   138
        
om@2
   139
om@2
   140
    def mkdir(self, path, mode):
om@2
   141
        sys.stdout.write("===\nInsert Hook here! Creating folder %s\n===\n" % path)
om@2
   142
        os.mkdir("." + path, mode)
om@2
   143
        
om@2
   144
om@2
   145
    def utime(self, path, times):
om@2
   146
        os.utime("." + path, times)
om@2
   147
    
om@2
   148
om@2
   149
    def access(self, path, mode):
om@2
   150
        if not os.access("." + path, mode):
om@2
   151
            return -errno.EACCES
om@2
   152
om@2
   153
om@2
   154
    def statfs(self):
om@2
   155
        return os.statvfs(".")
om@2
   156
om@2
   157
om@2
   158
    def fsinit(self):
om@2
   159
        os.chdir(self.root)
om@2
   160
om@2
   161
om@2
   162
    def main(self, *a, **kw):
om@2
   163
        self.file_class = MirrorFuseFile
om@2
   164
        return Fuse.main(self, *a, **kw)
om@2
   165
om@2
   166
om@2
   167
class MirrorFuseFile(object):
om@2
   168
    
om@2
   169
    """This is a single "File" in the Mirror FUSE"""
om@2
   170
om@2
   171
    def __init__(self, path, flags, *mode):
om@2
   172
        sys.stdout.write("===\nInsert Hook here! Opening file %s\n===\n" % path)
om@2
   173
        self.file = os.fdopen(os.open("." + path, flags, *mode), flag2mode(flags))
om@2
   174
        self.fd = self.file.fileno()
om@2
   175
        
om@2
   176
om@2
   177
    def read(self, length, offset):
om@2
   178
        self.file.seek(offset)
om@2
   179
        return self.file.read(length)
om@2
   180
    
om@2
   181
om@2
   182
    def write(self, buf, offset):
om@2
   183
        self.file.seek(offset)
om@2
   184
        self.file.write(buf)
om@2
   185
        return len(buf)
om@2
   186
    
om@2
   187
om@2
   188
    def release(self, flags):
om@2
   189
        self.file.close()
om@2
   190
        
om@2
   191
om@2
   192
    def _fflush(self):
om@2
   193
        if 'w' in self.file.mode or 'a' in self.file.mode:
om@2
   194
            self.file.flush()
om@2
   195
om@2
   196
    def fsync(self, isfsyncfile):
om@2
   197
        self._fflush()
om@2
   198
        if isfsyncfile and hasattr(os, 'fdatasync'):
om@2
   199
            os.fdatasync(self.fd)
om@2
   200
        else:
om@2
   201
            os.fsync(self.fd)
om@2
   202
            
om@2
   203
om@2
   204
    def flush(self):
om@2
   205
        self._fflush()
om@2
   206
        os.close(os.dup(self.fd))
om@2
   207
        
om@2
   208
om@2
   209
    def fgetattr(self):
om@2
   210
        return os.fstat(self.fd)
om@2
   211
    
om@2
   212
om@2
   213
    def ftruncate(self, len):
om@2
   214
        self.file.truncate(len)
om@2
   215
        
om@2
   216
om@2
   217
    def lock(self, cmd, owner, **kw):
om@2
   218
        op = {fcntl.F_UNLCK : fcntl.LOCK_UN, fcntl.F_RDLCK : fcntl.LOCK_SH, fcntl.F_WRLCK : fcntl.LOCK_EX}[kw['l_type']]
om@2
   219
        if cmd == fcntl.F_GETLK:
om@2
   220
            return -EOPNOTSUPP
om@2
   221
        elif cmd == fcntl.F_SETLK:
om@2
   222
            if op != fcntl.LOCK_UN:
om@2
   223
                op |= fcntl.LOCK_NB
om@2
   224
        elif cmd == fcntl.F_SETLKW:
om@2
   225
            pass
om@2
   226
        else:
om@2
   227
            return -errno.EINVAL
om@2
   228
om@2
   229
        fcntl.lockf(self.fd, op, kw['l_start'], kw['l_len'])
om@2
   230
om@2
   231
om@2
   232
def flag2mode(flags):
om@2
   233
    
om@2
   234
    """Turn os flags into mode chars"""
om@2
   235
    
om@2
   236
    md = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'}
om@2
   237
    m = md[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)]
om@2
   238
    if flags | os.O_APPEND:
om@2
   239
        m = m.replace('w', 'a', 1)
om@2
   240
    return m
om@2
   241
om@2
   242
om@2
   243
def main():             
om@2
   244
            
om@2
   245
    usage = """
om@2
   246
mirror the a file tree from some point on.
om@2
   247
om@2
   248
""" + Fuse.fusage
om@2
   249
om@2
   250
    # launch the Fuse server
om@2
   251
    server = MirrorFuse(version = "%prog " + __version__, usage = usage, dash_s_do = 'setsingle')
om@2
   252
    server.parser.add_option(mountopt = "root", metavar = "PATH", default='/',  help="mirror filesystem from under PATH [default: %default]")
om@2
   253
    server.parser.add_option(mountopt = "os_server_url", metavar = "URL", default='http://localhost:8080',  help="URL to OpenSecurity Server [default: %default]")
om@2
   254
    server.parse(values=server, errex=1)
om@2
   255
om@2
   256
    try:
om@2
   257
        if server.fuse_args.mount_expected():
om@2
   258
            os.chdir(server.root)
om@2
   259
    except OSError:
om@2
   260
        print >> sys.stderr, "can't enter root of underlying filesystem"
om@2
   261
        sys.exit(1)
om@2
   262
om@2
   263
    server.main()
om@2
   264
    
om@2
   265
om@2
   266
# start
om@2
   267
if __name__ == "__main__":
om@2
   268
    main()
om@2
   269
om@2
   270