xref: /openbmc/qemu/scripts/qmp/qom-fuse (revision ddda3748)
1#!/usr/bin/env python3
2##
3# QEMU Object Model test tools
4#
5# Copyright IBM, Corp. 2012
6#
7# Authors:
8#  Anthony Liguori   <aliguori@us.ibm.com>
9#
10# This work is licensed under the terms of the GNU GPL, version 2 or later.  See
11# the COPYING file in the top-level directory.
12##
13
14import fuse, stat
15from fuse import Fuse
16import os, posix
17from errno import *
18from qmp import QEMUMonitorProtocol
19
20fuse.fuse_python_api = (0, 2)
21
22class QOMFS(Fuse):
23    def __init__(self, qmp, *args, **kwds):
24        Fuse.__init__(self, *args, **kwds)
25        self.qmp = qmp
26        self.qmp.connect()
27        self.ino_map = {}
28        self.ino_count = 1
29
30    def get_ino(self, path):
31        if path in self.ino_map:
32            return self.ino_map[path]
33        self.ino_map[path] = self.ino_count
34        self.ino_count += 1
35        return self.ino_map[path]
36
37    def is_object(self, path):
38        try:
39            items = self.qmp.command('qom-list', path=path)
40            return True
41        except:
42            return False
43
44    def is_property(self, path):
45        try:
46            path, prop = path.rsplit('/', 1)
47            for item in self.qmp.command('qom-list', path=path):
48                if item['name'] == prop:
49                    return True
50            return False
51        except:
52            return False
53
54    def is_link(self, path):
55        try:
56            path, prop = path.rsplit('/', 1)
57            for item in self.qmp.command('qom-list', path=path):
58                if item['name'] == prop:
59                    if item['type'].startswith('link<'):
60                        return True
61                    return False
62            return False
63        except:
64            return False
65
66    def read(self, path, length, offset):
67        if not self.is_property(path):
68            return -ENOENT
69
70        path, prop = path.rsplit('/', 1)
71        try:
72            data = str(self.qmp.command('qom-get', path=path, property=prop))
73            data += '\n' # make values shell friendly
74        except:
75            return -EPERM
76
77        if offset > len(data):
78            return ''
79
80        return str(data[offset:][:length])
81
82    def readlink(self, path):
83        if not self.is_link(path):
84            return False
85        path, prop = path.rsplit('/', 1)
86        prefix = '/'.join(['..'] * (len(path.split('/')) - 1))
87        return prefix + str(self.qmp.command('qom-get', path=path,
88                                             property=prop))
89
90    def getattr(self, path):
91        if self.is_link(path):
92            value = posix.stat_result((0o755 | stat.S_IFLNK,
93                                       self.get_ino(path),
94                                       0,
95                                       2,
96                                       1000,
97                                       1000,
98                                       4096,
99                                       0,
100                                       0,
101                                       0))
102        elif self.is_object(path):
103            value = posix.stat_result((0o755 | stat.S_IFDIR,
104                                       self.get_ino(path),
105                                       0,
106                                       2,
107                                       1000,
108                                       1000,
109                                       4096,
110                                       0,
111                                       0,
112                                       0))
113        elif self.is_property(path):
114            value = posix.stat_result((0o644 | stat.S_IFREG,
115                                       self.get_ino(path),
116                                       0,
117                                       1,
118                                       1000,
119                                       1000,
120                                       4096,
121                                       0,
122                                       0,
123                                       0))
124        else:
125            value = -ENOENT
126        return value
127
128    def readdir(self, path, offset):
129        yield fuse.Direntry('.')
130        yield fuse.Direntry('..')
131        for item in self.qmp.command('qom-list', path=path):
132            yield fuse.Direntry(str(item['name']))
133
134if __name__ == '__main__':
135    import sys, os
136
137    fs = QOMFS(QEMUMonitorProtocol(os.environ['QMP_SOCKET']))
138    fs.main(sys.argv)
139