inotify and recursion

Artur Skawina art.08.09 at gmail.com
Fri Dec 27 09:05:42 PST 2013


On 12/27/13 15:13, Artur Skawina wrote:
>    struct MyInotifyEvent(size_t BS) {
>       inotify_event event;
>       char[BS] buffer;
>       alias event this;
>    }
>    [...]
>    enum bufsiz = inotify_event.sizeof + PATH_MAX + 1;
>    auto event = cast(MyInotifyEvent!bufsiz*)malloc(bufsiz);
>    [...]
>    writeln("Name:", event.buffer[0..event.len-1]); // 2do: strip any extra trailing \0s.

Well, that could get awkward, as the inotify api doesn't really support disabling
event batching. A saner design would be something like the code below.

artur

struct INotify {
   Fd fd;
   
   import std.exception;
   import core.sys.posix.unistd;
   
   this(cint flags) {
      fd = inotify_init(flags);
      errnoEnforce(fd!=-1);
   }
   ~this() {
      close(fd);
   }
   
   Wd add(const char* name, uint mask) { return inotify_add_watch(fd, name, mask); }
   Fd remove(Wd wd)                    { return inotify_rm_watch(fd, wd); }
   
   bool get(CB)(CB cb) {
      void[4*1024] buffer = void;
      
      auto got = read(fd, &buffer, buffer.sizeof);
      
      if (got<=inotify_event.sizeof)
         return false;
         
      size_t off = 0;
         
      while (off<=got-inotify_event.sizeof) {
         auto evp = cast(inotify_event*)&buffer[off];
         auto namebuf = evp.len ? (cast(char*)&evp.name)[0..evp.len-1] : null;

         while (namebuf.length && !namebuf[namebuf.length-1])
            --namebuf.length;

         cb(evp, namebuf);
         
         off += inotify_event.sizeof + evp.len;
      }
      
      assert(off==got);
      return true;
   }
}

void main(string argv[]) {
   import std.string;
   auto ntf = INotify(0);
   
   foreach (arg; argv[1..$])
      ntf.add(toStringz(arg), IN_MODIFY);
   
   void myCallback(/*scope*/ const inotify_event* ev, /*scope*/ char[] name) {
      /* Don't even think about escaping any of the args. Dup if necessary. */
      import std.stdio;
      writeln(*ev, " \"", name, "\"");
   }
   
   while (1)
      ntf.get(&myCallback);
}


// libc i/f follows:

alias uint32_t = uint;
alias cint = int;
alias Fd = cint;

extern(C) {
   Fd inotify_init();
   Fd inotify_init1(cint flags);
   Wd inotify_add_watch(Fd fd, const char* pathname, uint mask);
   Fd inotify_rm_watch(Fd fd, Wd wd);
}

Fd inotify_init(cint flags) { return inotify_init1(flags); }

enum IN_MODIFY = 0x00000002; /* DEFINEME */

struct Wd { Fd fd; alias fd this; }

struct inotify_event {
   Wd       wd;       /* Watch descriptor */
   uint32_t mask;     /* Mask of events */
   uint32_t cookie;   /* Unique cookie associating related events (for rename(2)) */
   uint32_t len;      /* Size of name field */
   char     name[0];   /* Optional null-terminated name */
   
   void toString(DG, FT)(scope DG sink, FT fmt) const @trusted {
      import std.format;
      foreach (I, E; this.tupleof)
         static if (I<this.tupleof.length-1)
            formatValue(sink, E, fmt), sink(" ");
   }
}




More information about the Digitalmars-d-learn mailing list