0

I am using SKQueue to monitor some folders in the mac filesystem. As per the documentation, I have added the directory paths to the queues but I noticed that while adding the path, the following line of code in SKQueue is returning -1 and hence it is unable to monitor my folder.

This is the SKQueue Documentation.

The following is code from the documentation, written in the controller class.

import SKQueue

class SomeClass: SKQueueDelegate {
  func receivedNotification(_ notification: SKQueueNotification, path: String, queue: SKQueue) {
    print("\(notification.toStrings().map { $0.rawValue }) @ \(path)")
  }
}

let delegate = SomeClass()
let queue = SKQueue(delegate: delegate)!

queue.addPath("/Users/steve/Documents")
queue.addPath("/Users/steve/Documents/dog.jpg")

The following is code inside SKQueue dependency.

  public func addPath(_ path: String, notifyingAbout notification: SKQueueNotification = SKQueueNotification.Default) {
    var fileDescriptor: Int32! = watchedPaths[path]
    if fileDescriptor == nil {
      fileDescriptor = open(FileManager.default.fileSystemRepresentation(withPath: path), O_EVTONLY)
      guard fileDescriptor >= 0 else { return }
      watchedPaths[path] = fileDescriptor
    }

fileDescriptor = open(FileManager.default.fileSystemRepresentation(withPath: path), O_EVTONLY)

The above code is returning -1 and hence it is failing.

halfer
  • 19,824
  • 17
  • 99
  • 186
  • 1
    Without looking to hard, I'd say "you aren't allowed to nominate random pathnames any more" - the user has to have explicitly selected any directory/file you want to access. – Jeff Laing Mar 03 '20 at 02:16

2 Answers2

0

The call to open() failed, likely due to insufficient permissions. Since macOS 10.15, apps can't access certain files and folders without permission (the user's home directory, for example). Read more here.

dape
  • 162
  • 6
0

I was getting the same -1 return code and couldn't understand why. Whilst looking for a solution I stumbled upon SwiftFolderMonitor at https://github.com/MartinJNash/SwiftFolderMonitor. This class worked so I knew it wasn't a permission problem.

SwiftFolderMonitor uses DispatchSource.makeFileSystemObjectSource rather than kevent, but it also takes a URL parameter rather than a String path. I amended SKQueue to take a URL instead of a String and it works.

Here's my amended addPath:

public func addPath(url: URL, notifyingAbout notification: SKQueueNotification = SKQueueNotification.Default) {
    let path = url.absoluteString
    var fileDescriptor: Int32! = watchedPaths[path]
    if fileDescriptor == nil {
        fileDescriptor = open((url as NSURL).fileSystemRepresentation, O_EVTONLY)
        guard fileDescriptor >= 0 else { return }
        watchedPaths[path] = fileDescriptor
    }

    var edit = kevent(
        ident: UInt(fileDescriptor),
        filter: Int16(EVFILT_VNODE),
        flags: UInt16(EV_ADD | EV_CLEAR),
        fflags: notification.rawValue,
        data: 0,
        udata: nil
    )
    kevent(kqueueId, &edit, 1, nil, 0, nil)

    if !keepWatcherThreadRunning {
        keepWatcherThreadRunning = true
        DispatchQueue.global().async(execute: watcherThread)
    }
}

I don't know why this works, perhaps someone else can shed some light on this.

I'm still playing with both solutions but it looks like SwiftFolderMonitor does all I need (I just need to know when a specific file has changed) and it's code is clean and minimal so I think I'll use it over SKQueue.

I hope this helps.

gjerman
  • 46
  • 1
  • Ok, just found the answer to my own question. When using SKQueue.addPath I had a URL property so was passing url.absoluteString as the path String parameter. This was failing and returning a fileDescriptor of -1 and so monitoring failed. I am now passing url.path as the path String parameter and it all works. FYI I've also found another useful file monitoring class DAFileMonitor at https://github.com/dagostini/DAFileMonitor and https://agostini.tech/2017/08/06/monitoring-files-using-dispatch-sources/. I think this is the one I'm going to use. – gjerman May 12 '20 at 08:51