Using a FUSE filesystem (Filesystem in Userspace), you can write a program using the libfuse library to implement most file operations. You effectively mount a program on a directory, and any operations you do in the directory are passed via the kernel to the program which provides a reply.
There are several Perl and Python packages with example programs that can be fairly simple to modify to your requirements.
In particular, for my Fedora 25 there is a fuse-python
rpm that provides an example program xmp.py that "simply" duplicates every operation done under the mount point, to a real directory you specify at the start.
For example, if you run (not as root, but as an ordinary user)
mkdir -p /tmp/myfs/under /tmp/myfs/write
xmp.py /tmp/myfs/write -o root=/tmp/myfs/under
then everything you do to a file under the mount point /tmp/myfs/write
, will also be seen in the real duplicate "root" directory /tmp/myfs/under
. Eg
echo abc >/tmp/myfs/write/file1
creates file1
in the real directory. Of course, if you ls /tmp/myfs/*/file1
the file appears in both, since xmp.py
shows you the real directory too:
-rw-r--r-- 1 4 Aug 1 18:43 /tmp/myfs/under/file1
-rw-r--r-- 1 4 Aug 1 18:43 /tmp/myfs/write/file1
If you look at the Python example code, it is quite short. You can see the implentation of the system call write()
here:
def write(self, buf, offset):
self.file.seek(offset)
self.file.write(buf)
return len(buf)
To suppress the actual write to the file you only need to comment out the third line:
def write(self, buf, offset):
self.file.seek(offset)
# self.file.write(buf)
return len(buf)
Unmount the fuse filesystem with
fusermount -u /tmp/myfs/write
then run the new xmp.py
and now when you write to a file, it appears to succeed, but no data is written to the underlying real directory. It is probably wise to not try stubbing out other file operations, such as creating directories and so on, as your program may see spurious problems.
Note, I used the xmp.py
provided with the package I installed on my system. The links to the github code are just for browsing. You should have no problems repeating this experiment if you find and use the appropriate package for your system. Note, there are several Python libraries for FUSE. Make sure you install the one with the above example code.
Your login must be in group fuse to be able to use the program. You should see this listed in the output of command id
. If the group isn't there add it with sudo usermod -a -G fuse $USER
(where $USER is your login), and login again.
On Ubuntu the package is python-fuse
. My tests in 18.04.2 LTS however did not work. The example xmp.py
, unchanged, would create a file but not write into it, saying Invalid argument
. It seems this is due to an incompatibility in the versions of this and libfuse. When I ran xmp.py
with the extra debug option -o debug
I saw the errors
AttributeError: 'XmpFile' object has no attribute 'direct_io'
AttributeError: 'XmpFile' object has no attribute 'keep_cache'
You may want to try other means to fix this, but I simply added the missing attributes to xmp.py
by adding to class XmpFile
, function def __init__
, after the line self.fd = self.file.fileno()
the following 2 lines:
self.direct_io = None
self.keep_cache = None
Make sure you keep exactly the same indentation for these lines, using spaces only, not tabs.
ptrace
it, use a fuse or kernel module to implement a fake filesystem,seccomp
it. The key point is make thewrite
syscall return succeed but actually do nothing. – 炸鱼薯条德里克 Aug 01 '19 at 05:18chmod
on the file and so. Are you sure your software does not have a "dummy run" mode that will provide output without trying to copy files? Alternatively, if you provide it a read-only directory will it just produce error messages but continue nonetheless so you can get the output. – meuh Aug 01 '19 at 06:05tmpfs
? Your requirements are not entirely clear to me. – frostschutz Aug 02 '19 at 08:10