ihaveamac / ninfs

FUSE filesystem Python scripts for Nintendo console files
MIT License
436 stars 18 forks source link

Allow copying files directly into the NAND mount #68

Open ihaveamac opened 4 years ago

ihaveamac commented 4 years ago

I don't actually know what blocks this right now so I need to look into it. Will probably happen around the time I make a NAND reader for pyctr.

ihaveamac commented 3 years ago

This requires free space to be large enough, plus truncate and create to be implemented, even if truncate is a no-op and does not actually shrink the file. At least, this worked when trying to copy the file in Windows's File Explorer.

ihaveamac commented 3 years ago

Leaving this here for later as it is not ready to go into the next release:

diff --git a/ninfs/mount/nandtwl.py b/ninfs/mount/nandtwl.py
index 9b8b36f..a7c851a 100644
--- a/ninfs/mount/nandtwl.py
+++ b/ninfs/mount/nandtwl.py
@@ -162,6 +162,26 @@ class TWLNandImageMount(LoggingMixIn, Operations):
         self.fd += 1
         return self.fd

+    def truncate(self, path, length, fh=None):
+        print('attempted truncate:', path, length)
+        pass  # no-op seems to work fine for copying in Windows File Explorer
+
+    def unlink(self, path):
+        print('attempted unlink:', path)
+        pass
+
+    def create(self, path, mode, fi=None):
+        if path not in self.files:
+            raise FuseOSError(EROFS)  # is this the right error to raise?
+        print('create:', path, mode)
+        self.fd += 1
+        return self.fd
+
+    def rename(self, old, new):
+        if new.startswith('/.fuse_hidden'):
+            return
+        raise FuseOSError(EROFS)
+
     @_c.ensure_lower_path
     def readdir(self, path, fh):
         yield from ('.', '..')
@@ -189,7 +209,9 @@ class TWLNandImageMount(LoggingMixIn, Operations):

     @_c.ensure_lower_path
     def statfs(self, path):
-        return {'f_bsize': 4096, 'f_frsize': 4096, 'f_blocks': 0xF000000 // 4096, 'f_bavail': 0, 'f_bfree': 0,
+        bsize = 0x1000
+        size = 0xF000000 // bsize
+        return {'f_bsize': bsize, 'f_frsize': bsize, 'f_blocks': size, 'f_bavail': size, 'f_bfree': size,
                 'f_files': len(self.files)}

     @_c.ensure_lower_path
@@ -250,6 +272,7 @@ def main(prog: str = None, args: list = None):
             if _c.macos:
                 path_to_show = realpath(a.nand).rsplit('/', maxsplit=2)
                 opts['volname'] = f'Nintendo DSi NAND ({path_to_show[-2]}/{path_to_show[-1]})'
+                opts['noappledouble'] = True
             elif _c.windows:
                 # volume label can only be up to 32 chars
                 opts['volname'] = 'Nintendo DSi NAND'
ihaveamac commented 3 years ago

This doesn't work properly with macOS Finder for some reason. I think it has to do with how FUSE handles requests to delete a file that's still in active use, it renames it, but these modules don't allow renaming.