"Operation not permitted" creating(open)/writing/appending to files

589 views
Skip to first unread message

arritje nof

unread,
Aug 12, 2015, 6:24:27 AM8/12/15
to OSXFUSE
Hello all,

Currently i'm stuck trying to fix a problem that i'm sure must be very simple to solve..
Any pointers that help me get unstuck are greatly appreciated!

My filesystem works like the loopback filesystem, allowing 're-mounting' of a directory,
amongst other things also offering the possibility to create a 'composit' mountpoint out 
of several different directories.

As mentioned the implementration borrows from the loopback example filesystem.
For the directory-contents compositing logic it borrows from the subdir module,
extending that code to support several different sub-directories to appear as 
sub-directories of the main mountpoint.

This is mostly complete and functional, except for the fact that any attempts to create
new files, or write to existing files fail with the Operation Not Permitted error.

I've made sure that the current (mounting) user is owner of and has write permissions to 
both the mountpoint and the actual directory that is mounted on it, as well as any 
additional directories that are composited inside the mountpoint.

Applications using the Cocoa/AppKit API's and performing an atomic save operation will
fail after having deleted the original file, when attempting to move (?) the temporary/new
file in place. So effectively, the file will dissappear. The new/temporary file is nowwhere
to be found either (if it ever actually did exist).

Standard C applications (such as my 4-lines test commandline-app) simply fail with the 
error mentioned, and the original file will dissappear.

The permissions on the mounted fuse-volume appear fine when viewed using ls or stat.
However, Finders' ⌘+I (Info) window reports them as "You have special permissions".
I believe this is common for directories that have ACLs set, but that doesn't seem to be
the case here. I'm also not joined in an AD-domain (or OD-domain) or something.

I'm hoping someone reading this with a little more experience than me can enlighten me
and show me a way to properly debug and finally resolve this issue. Thanks in advance!

Please let me know if you'd like me to provide more info or see actual implementation 
details. I'd be happy to add whatever you'd need to understand what is going on. Thanks!


cheers,
arri

arritje nof

unread,
Aug 12, 2015, 6:49:55 AM8/12/15
to OSXFUSE
Correction: using standard-C, the file does NOT dissappear,
but rather the file is truncated to 0 length.

Additionally, performing (commandline)
cat "blabla" >> /path/to/existing/file.txt
correctly updates the file, appending a newline and "blabla" at the end.


regards,
arri

Vinay K

unread,
Aug 13, 2015, 2:47:00 PM8/13/15
to OSXFUSE
Your create callback is probably return -1.

In errno.h 1 is defined as follows and that is why you are seeing "Operation not permitted"

#define EPERM        1  /* Operation not permitted */

Paste your create callback implementation here.

arritje nof

unread,
Aug 14, 2015, 11:31:53 PM8/14/15
to OSXFUSE
Hi Vinay K. and all,


Thanks for your respons! I've pasted my create-callback below, although create does not seem to be the problem as it is never called. The error seems to already occur before it ever calls open()/create().

The callbacks generating most errors are getxattr(), lookup() and listxattr() - in descending order of severity.
getxattr()and listxattr()mostly just complains about non-existing attriubutes (-93) which should not be causing the described issues if i understand correctly.
lookup()was never implemented, but i'm wondering if i actually need to do this in order for my filesystem to work. It does make sense, since i'm juggling with combining different directory trees under one mountpoint.

Do i need to implement lookup()? Can lowlevel api callback be mixed-in with regular ones? And where do i begin doing this?

Thanks,
Arjen


static int

mxffs_create(const char *path, mode_t mode, struct fuse_file_info *fi)

{

int err = 0, fd;

char * newpath = mxffs_addpath(path);

if(newpath)

{

fd = open(newpath, fi->flags, mode);

err = fd==-1 ? -errno : 0;

fi->fh = fd;

free(newpath);

}

if(err) fprintf(stderr, "ERROR: %s:%d -> err: %d\n", __FUNCTION__, __LINE__, err);

return err;

arritje nof

unread,
Aug 17, 2015, 12:00:22 PM8/17/15
to OSXFUSE
Following-up on my last message;

It definately looks like lookup() is part of the problem, as it seems as if all file-operations never get past initial lookup of the node.
create()is simply never called: lookup()will always 

Interestingly, vim will actually open and save-to an existing file correctly, eventhough it has to fall back to the default (~/tmp) location for creating its' swapfile. 

I'm a bit at loss why lookup throws-up this error. What can possibly be causing this?
Otherwise, the filesystem is almost identical to its' predecessor which still works great.

Thanks for any pointers!

regards,
arri

Vinay K

unread,
Aug 17, 2015, 12:07:49 PM8/17/15
to OSXFUSE
Your create callback looks fine.

I have not implemented lookup either. I think your getattr is returning -1. Instead it should return -ENOATTR.

You can always specifiy the "debug" option in your mount point options and check the sequence of callbacks it calls.

arritje nof

unread,
Aug 18, 2015, 5:05:05 AM8/18/15
to OSXFUSE
Hi Vinay,

Thanks for your comment: You're right, i had found this bug (getattr returning -1 instead of proper/actual error) as well and fixed it, but this didn't resolve my problem.

The debug output is where i've got the idea that i might need to implement lookup(). Below is an excerpt of the debug output. The names in bold (Scratch and first) both are directories that don't really exist in the backing store of the mounted fuse-volume. They actual live elsewhere, and are composited into the mount-point based on arguments passed to my filesystrem.

ACCESS /Pakketje.zip 00

   unique: 0, error: 0 (Undefined error: 0), outsize: 16

unique: 3, opcode: GETATTR (3), nodeid: 14, insize: 40

   unique: 3, error: 0 (Undefined error: 0), outsize: 128

unique: 1, opcode: ACCESS (34), nodeid: 15, insize: 48

ACCESS /RNDTMP.jRoGBH 00

   unique: 1, error: 0 (Undefined error: 0), outsize: 16

unique: 22, opcode: GETATTR (3), nodeid: 15, insize: 40

   unique: 22, error: 0 (Undefined error: 0), outsize: 128

unique: 21, opcode: LOOKUP (1), nodeid: 1, insize: 48

LOOKUP /Scratch

   unique: 21, error: -1 (Operation not permitted), outsize: 16

unique: 4, opcode: ACCESS (34), nodeid: 32, insize: 48

ACCESS /The Unarchiver.app 00

   unique: 4, error: 0 (Undefined error: 0), outsize: 16

unique: 2, opcode: GETATTR (3), nodeid: 32, insize: 40

   unique: 2, error: 0 (Undefined error: 0), outsize: 128

unique: 6, opcode: ACCESS (34), nodeid: 34, insize: 48

ACCESS /Wondershare.plist 00

   unique: 6, error: 0 (Undefined error: 0), outsize: 16

unique: 8, opcode: GETATTR (3), nodeid: 34, insize: 40

   unique: 8, error: 0 (Undefined error: 0), outsize: 128

unique: 7, opcode: LOOKUP (1), nodeid: 1, insize: 46

LOOKUP /first

   unique: 7, error: -1 (Operation not permitted), outsize: 16

unique: 11, opcode: ACCESS (34), nodeid: 6, insize: 48



These directories currently don't show-up in the Finder, but ls displays them like this:

?---------    0 root  wheel         0 Jan  1  1970 Scratch

drwxr-xr-x    3 arri  staff       102 Apr 15  2011 The Unarchiver.app

-rw-rw-rw-    1 arri  staff       331 Jul 15  2013 Wondershare.plist

?---------    0 root  wheel         0 Jan  1  1970 first

-rw-r--r--    1 arri  staff  13892629 Jun  4  2014 mpv.app.zip

-rw-r--r--    1 arri  staff   2217577 Feb 20 16:57 osxfuse-2.7.1.3.zip

-rw-r--r--    1 arri  staff      5452 Aug 17 17:25 root-root.txt

-rw-r--r--@   1 arri  staff     32924 Aug 12 12:42 screencapture.txt

?---------    0 root  wheel         0 Jan  1  1970 second

-rw-r--r--    1 arri  staff        97 Aug 12 06:55 serial_number.txt



The fact that lookup is called is probably caused by the fact that i fill the directory structure to include these directories, but without implementing lookup, this callback will not return the proper paths to the underlying storage objects.

So i'm curious; How would i go about implenting lookup? Or is there another way to approach this problem?

regards
arri

Vinay K

unread,
Aug 18, 2015, 1:46:51 PM8/18/15
to OSXFUSE
I do not think LOOKUP has to be implemented.

If it is not implemented it, you should see -78 (Function not implemented) in the debug logs and not -1 (Operation not permitted).

You should start with the existing loopback example and check if you are able to run it.

arritje nof

unread,
Aug 18, 2015, 6:09:09 PM8/18/15
to OSXFUSE
if i understand correctly (correct me if i'm wrong), if lookup() is not implemented, the default implementation is called instead.

I'm asuming that this is what happens in my case. And since the default implementation does not implement my directory-juggling logic, a call to lookup() for a file called test.txt, with parent-inode 1, will likely end-up evaluating /test.txt instead of /fuse_mounted/pass-through/dir/test.txt  (this a hypothetical directory for the sake of example..dûh)

I wouldn't know why lookup() returns -1 instead of -2: No such file or directory (?) or maybe -13: Permission denied

What i learned up until now (correct me if i'm wrong) is that implementing lookup()can only be done when developing against the lowlevel-API.
Currently, my implementation is actually based on the loopback example you mentioned, using the higher-level API, with additional code that is inspired on the subdir-module. When i started development i thought it'd be easiest and perhaps as a nice bonus also perform better, if i integrated all functionality in the filesystem itsself, instead of loading  multiple, stacking filesystems. the of implementing certain parts in (a fork of) the subdir-module, loading this forked module as stacking filesystem when mounting the filesystem.

But right now i'm starting to wonder if the approach of forking the subdir-module, implementing the directory-juggling logic there, could actually solve the problem without having to rewrite the filesystem against the lowlevel-API, in order implement the lookup() callback...
The simplest lookback-mounted/-passthrough filesystem using the subdir-module seems to suggest that in that scenario the subdir-module-logic is performed before the default implementation of lookup() is called. 

Am i thinking along the right lines? Or is this way off?
Any comment or suggestion is greatly appreciated!

Kind Regards,
arri

Vinay K

unread,
Aug 19, 2015, 4:52:59 PM8/19/15
to OSXFUSE
The file_operations callbacks are different for lowlevel API and high level APIs. I do not know how you plan to mix them as their callback registration structures are different with different interfaces.
(I will let the experts suggest if they know of any way.)

arritje nof

unread,
Aug 20, 2015, 11:06:08 AM8/20/15
to OSXFUSE
Thanks VinayK, 


No, I wasn't planning on mixing the two, but rather i was thinking about re-writing the entire filesystem.. I don't think mixing the two would even be possible.

Anyway, i don't need all that anymore, because by sheer luck i (think i) accidentally found what was causing all the weird errors/problems i was seeing. I'm not sure why, or if it was maybe something else that just happened to coincide with what i did...

What seemed to fix almost all my problems instantly, was including this #define statement:

#ifndef _DARWIN_FEATURE_64_BIT_INODE

#define _DARWIN_FEATURE_64_BIT_INODE    1

#endif


See the stat man-page for more info om this flag.

It seems that when this is not defined, fuse implicitly defines _DARWIN_FEATURE_32_BIT_INODE which causes members of all kind of structs throughout the code to use 32bit data-types. Obviiously causing all sorts of funky effects.

Is this indeed be what was going on? I'm a astounded (also by the fact that i accidentally found this..)


thanks!
Kind regards,

Arjen Keesmaat

Alejandro Exojo

unread,
Aug 20, 2015, 11:58:36 AM8/20/15
to osxfus...@googlegroups.com
On 20 August 2015 at 17:06, arritje nof <arritjepa...@gmail.com> wrote:
> Is this indeed be what was going on? I'm a astounded (also by the fact that
> i accidentally found this..)

Very likely. See:

https://github.com/osxfuse/osxfuse/wiki/FAQ#51-i-am-having-problem-fill-in-problem-here-compiling-a-fuse-file-system-in-the-fuse-for-os-x-environment-what-to-do

If you switch to package-config, you will have the flag right.

arritje nof

unread,
Aug 21, 2015, 11:40:57 AM8/21/15
to OSXFUSE
Hi Alejandro,

Thanks for you respons!

Normally i'm using an elaborate build-script that leverages pkg-config for building the entire package, containing a modified OSXFuse build (kext and libraries) and our filesystem. As this build takes several minutes, during development i'm just compiling/testing the filesystem in Xcode. Your respons has made me aware of the fact that i've forgotten to include pkg-config in that build-process.

Thanks for pointing this out!


kind regards,
arri
Reply all
Reply to author
Forward
0 new messages