Print this page
    
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libc/port/sys/inotify.c
          +++ new/usr/src/lib/libc/port/sys/inotify.c
   1    1  /*
   2    2   * This file and its contents are supplied under the terms of the
   3    3   * Common Development and Distribution License ("CDDL"), version 1.0.
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13   13   * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
  14   14   */
  15   15  
  16   16  #include <sys/inotify.h>
  17   17  #include <sys/stat.h>
  18   18  #include <unistd.h>
  19   19  #include <errno.h>
  20   20  #include <fcntl.h>
  21   21  #include <strings.h>
  22   22  #include <dirent.h>
  23   23  
  24   24  int
  25   25  inotify_init()
  26   26  {
  27   27          return (open("/dev/inotify", O_RDWR));
  28   28  }
  29   29  
  30   30  int
  31   31  inotify_init1(int flags)
  32   32  {
  33   33          int oflags = O_RDWR;
  34   34  
  35   35          if (flags & IN_NONBLOCK)
  36   36                  oflags |= O_NONBLOCK;
  37   37  
  38   38          if (flags & IN_CLOEXEC)
  39   39                  oflags |= O_CLOEXEC;
  40   40  
  41   41          return (open("/dev/inotify", oflags));
  42   42  }
  43   43  
  44   44  int
  45   45  inotify_add_watch(int fd, const char *pathname, uint32_t mask)
  46   46  {
  47   47          inotify_addwatch_t ioc;
  48   48          inotify_addchild_t cioc;
  49   49          struct stat buf;
  50   50          int dirfd, wd;
  51   51          DIR *dir;
  52   52          struct dirent *dp;
  53   53          int oflags = O_RDONLY;
  54   54  
  55   55          if (mask & IN_DONT_FOLLOW)
  56   56                  oflags |= O_NOFOLLOW;
  57   57  
  58   58          if ((dirfd = open(pathname, oflags)) < 0)
  59   59                  return (-1);
  60   60  
  61   61          if (fstat(dirfd, &buf) != 0) {
  62   62                  (void) close(dirfd);
  63   63                  return (-1);
  64   64          }
  65   65  
  66   66          if ((mask & IN_ONLYDIR) && !(buf.st_mode & S_IFDIR)) {
  67   67                  (void) close(dirfd);
  68   68                  errno = ENOTDIR;
  69   69                  return (-1);
  70   70          }
  71   71  
  72   72          bzero(&ioc, sizeof (ioc));
  73   73          ioc.inaw_fd = dirfd;
  74   74          ioc.inaw_mask = mask;
  75   75  
  76   76          if ((wd = ioctl(fd, INOTIFYIOC_ADD_WATCH, &ioc)) < 0) {
  77   77                  (void) close(dirfd);
  78   78                  return (-1);
  79   79          }
  80   80  
  81   81          if (!(buf.st_mode & S_IFDIR) || !(mask & IN_CHILD_EVENTS)) {
  82   82                  (void) close(dirfd);
  83   83                  (void) ioctl(fd, INOTIFYIOC_ACTIVATE, wd);
  84   84                  return (wd);
  85   85          }
  86   86  
  87   87          /*
  88   88           * If we have a directory and we have a mask that denotes child events,
  89   89           * we need to manually add a child watch to every directory entry.
  90   90           * (Because our watch is in place, it will automatically be added to
  91   91           * files that are newly created after this point.)
  92   92           */
  93   93          if ((dir = fdopendir(dirfd)) == NULL) {
  94   94                  (void) inotify_rm_watch(fd, wd);
  95   95                  (void) close(dirfd);
  96   96                  return (-1);
  97   97          }
  98   98  
  99   99          bzero(&cioc, sizeof (cioc));
 100  100          cioc.inac_fd = dirfd;
 101  101  
 102  102          while ((dp = readdir(dir)) != NULL) {
 103  103                  if (strcmp(dp->d_name, ".") == 0)
 104  104                          continue;
 105  105  
 106  106                  if (strcmp(dp->d_name, "..") == 0)
 107  107                          continue;
 108  108  
 109  109                  cioc.inac_name = dp->d_name;
 110  110  
 111  111                  if (ioctl(fd, INOTIFYIOC_ADD_CHILD, &cioc) != 0) {
 112  112                          /*
 113  113                           * If we get an error that indicates clear internal
 114  114                           * malfunctioning, we propagate the error.  Otherwise
 115  115                           * we eat it:  this could be a file that no longer
 116  116                           * exists or a symlink or something else that we
 117  117                           * can't lookup.
 118  118                           */
 119  119                          switch (errno) {
 120  120                          case ENXIO:
 121  121                          case EFAULT:
 122  122                          case EBADF:
 123  123                                  (void) closedir(dir);
 124  124                                  (void) inotify_rm_watch(fd, wd);
 125  125                                  return (-1);
 126  126                          default:
 127  127                                  break;
 128  128                          }
 129  129                  }
 130  130          }
 131  131  
 132  132          (void) closedir(dir);
 133  133          (void) ioctl(fd, INOTIFYIOC_ACTIVATE, wd);
 134  134  
 135  135          return (wd);
 136  136  }
 137  137  
 138  138  int
 139  139  inotify_rm_watch(int fd, int wd)
 140  140  {
 141  141          return (ioctl(fd, INOTIFYIOC_RM_WATCH, wd));
 142  142  }
  
    | 
      ↓ open down ↓ | 
    142 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX