2

On OSX 10.8.x, I am using FSEvents to detect changes in a directory. The problem is that when a file is copied via sftp, the FSEvents callback is not called.
When I am using cp to copy a file (or touch to simulate a change), the callback is called. Am I doing something stupid ? Is sshd using some sort of low level API to create the file ? Should I file a bug to Apple ?

eventQueue = dispatch_queue_create(EVENT_QUEUE_NAME, DISPATCH_QUEUE_SERIAL);

//Watch the data/apns directory (for .json files)
NSString *pathToWatch = ...
NSArray  *pathsToWatch = @[pathToWatch];
CFAbsoluteTime latency = 1.0; /* Latency in seconds */

// Create the FileSystem events stream, passing in a callback
streamRef = FSEventStreamCreate(NULL,
                                &fscallback,
                                NULL,
                                (__bridge CFArrayRef)(pathsToWatch),
                                kFSEventStreamEventIdSinceNow,
                                latency,
                                kFSEventStreamCreateFlagIgnoreSelf);
if (streamRef)
{
    FSEventStreamSetDispatchQueue(streamRef, eventQueue);
    if (NO == FSEventStreamStart(streamRef))
    {
        DDLogError(@"FSEventStreamStart error");
    }
    else
    {
        DDLogError(@"FSEventStreamStart ok");
    }
}
else
{
    DDLogError(@"FSEventStreamCreate error");
}

I am using internal-sftp in the sshd config:

...
Subsystem sftp internal-sftp

Match Group users
PasswordAuthentication yes
AllowTCPForwarding no
X11Forwarding no
ForceCommand internal-sftp
Match User user
ChrootDirectory /vhosts/web/user
FKDev
  • 2,266
  • 1
  • 20
  • 23

1 Answers1

1

No, you're not doing anything wrong. The problem relates to your use of a chroot; I was able to reproduce this without involving sshd at all, just by running touch in a chroot.

FSEvents is recording the events as occurring on the path in the chroot, e.g., /foo rather than /vhosts/web/user/foo.

This is almost certainly an OS X bug; whether you're going to get Apple to fix it any time soon is another matter. Your best bet is probably to use Apple's sandboxing (run sftp-server with sandbox-exec) rather than a chroot.

Nicholas Riley
  • 43,532
  • 6
  • 101
  • 124
  • It makes sense (kind of). But how do you know that the event is occuring on the chrooted path ? If that were the case, shouldn't I be able to get the events by watching the /foo path ? But it does not work. – FKDev Jul 21 '13 at 10:04
  • /foo also has to exist in the base filesystem or the events won't be delivered. Really, I don't think it's worth the effort to work around this bug. – Nicholas Riley Jul 21 '13 at 10:55
  • You are right but now that you have put this idea in my mind, I would like to validate it so that all the time wasted on this would at least yield a logical explanation of twhat is going on. I have created the /foo directory and I have gave it the right permissions and it still doesn't work. So my guess is it's just a weird edge case in Apple implementation. – FKDev Jul 21 '13 at 12:21
  • Now I am heading to server fault because I have questions about sftp+sandbox-exec, although I should probably use kqueue. – FKDev Jul 21 '13 at 12:23
  • All I can say is it worked for me on 10.8.4 (the exact directories I tried with are /private/var/tmp/net and /net). Good luck :-) – Nicholas Riley Jul 21 '13 at 17:26
  • I have several virtual hosts with the same directory structure, it may explain why it's not working for me. – FKDev Jul 21 '13 at 19:42