1

I'm using C's inotify library, through a wrapper in Swift. The idea is to provide a Swift Package Manager library that gives basic File System events support in Linux.

Almost everything works. Except that here, I can't seem to be able to copy the inotify_event member name:

let bufferLength = Int(MemoryLayout<inotify_event>.size + NAME_MAX + 1)
let buffer = UnsafeMutablePointer<CChar>.allocate(capacity: bufferLength)

var fileSystemEvent : FileSystemEvent?
var currentIndex: Int = 0
let readLength = read(Int32(self.fileDescriptor), buffer, bufferLength)

while currentIndex < readLength {
  var event = withUnsafePointer(to: &buffer[currentIndex]) {
    return $0.withMemoryRebound(to: inotify_event.self, capacity: 1) {
      return $0.pointee
    }
  }
  if event.len > 0 {
     fileSystemEvent = FileSystemEvent(
       watchDescriptor: WatchDescriptor(event.wd),
       name: "", //String(cString: event.name),
       mask: event.mask,
       cookie: event.cookie,
       length: event.len
     )
  }
  currentIndex += MemoryLayout<inotify_event>.stride + Int(event.len)
}

I would want to do:

name: String(cString: event.name), but then the compiler throws an error:

           `value of type 'inotify_event' has no member 'name'`

I can't find any clues as to why this happens, or as to how I can access the name member. Here is the struct's declaration in inotify.h:

/*
 * struct inotify_event - structure read from the inotify device for each event
 *
 * When you are watching a directory, you will receive the filename for events
 * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd.
 */
struct inotify_event {
    __s32       wd;     /* watch descriptor */
    __u32       mask;       /* watch mask */
    __u32       cookie;     /* cookie to synchronize two events */
    __u32       len;        /* length (including nulls) of name */
    char        name[0];    /* stub for possible name */
};

What's going on here?

Thanks in advance :)

PS: here's my full project, if you need more information.

3
  • 1
    Can you include the declaration of the inotify_event struct from its ".h" file in your source example? Commented May 6, 2017 at 4:35
  • You'd better edit your question and include the definition of inotify_event into it. Not all readers try to go inside the link, and the definition of the struct is the key info for your issue. Commented May 6, 2017 at 5:25
  • 1
    @felix91gr great work on your fork of my repo! stumbled upon this problem myself and just left it like that. Commented Nov 7, 2017 at 21:49

1 Answer 1

1

The name field is defined as a zero-length array:

char        name[0];    /* stub for possible name */

and those are not imported into Swift. A possible solution is to compute the offset to the start of the name string within the received buffer:

 fileSystemEvent = FileSystemEvent(
   watchDescriptor: WatchDescriptor(event.wd),
   name: String(cString: buffer + currentIndex + MemoryLayout<inotify_event>.size),
   mask: event.mask,
   cookie: event.cookie,
   length: event.len)
Sign up to request clarification or add additional context in comments.

1 Comment

@martin-r could you point me to the documentation about zero-length arrays not being imported into swift? I'm trying to modify my inotify wrapper so that the name will be accessible as an optional attribute of a swift struct and I'm doing all the research I can to learn about swift c interop

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.