about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--INSTALL2
-rw-r--r--NEWS6
-rw-r--r--doc/index.html4
-rw-r--r--doc/upgrade.html7
-rw-r--r--package/info2
-rw-r--r--src/mdevd/mdevd-coldplug.c2
-rw-r--r--src/mdevd/mdevd-internal.h2
-rw-r--r--src/mdevd/mdevd.c96
-rw-r--r--src/mdevd/mdevd_uevent_getvar.c2
9 files changed, 73 insertions, 50 deletions
diff --git a/INSTALL b/INSTALL
index 5ab7f15..c09d868 100644
--- a/INSTALL
+++ b/INSTALL
@@ -6,7 +6,7 @@ Build Instructions
 
   - A Linux-based system with a standard C development environment
   - GNU make version 3.81 or later
-  - skalibs version 2.14.2.0 or later: https://skarnet.org/software/skalibs/
+  - skalibs version 2.14.2.1 or later: https://skarnet.org/software/skalibs/
   - optional: nsss version 0.2.0.4 or later: https://skarnet.org/software/nsss/
   - optional: execline version 2.9.6.0 or later: https://skarnet.org/software/execline/
 
diff --git a/NEWS b/NEWS
index e16e018..da9a1ee 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,11 @@
 Changelog for mdevd.
 
+In 0.1.6.5
+----------
+
+ - Bugfixes.
+
+
 In 0.1.6.4
 ----------
 
diff --git a/doc/index.html b/doc/index.html
index 1d3236f..a9ff0f2 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -102,7 +102,7 @@ and does not pull in any unnecessary code. </li>
 The Linux kernel must be 2.6.10 or later. </li>
  <li> GNU make, version 3.81 or later </li>
  <li> <a href="//skarnet.org/software/skalibs/">skalibs</a> version
-2.14.2.0 or later. It's a build-time requirement. It's also a run-time
+2.14.2.1 or later. It's a build-time requirement. It's also a run-time
 requirement if you link against the shared version of the skalibs
 library. </li>
  <li> Optionally: <a href="//skarnet.org/software/execline/">nsss</a>
@@ -127,7 +127,7 @@ if your <tt>mdev.conf</tt> file contains <tt>+</tt>, <tt>-</tt> or
 
 <ul>
  <li> The current released version of mdevd is
-<a href="mdevd-0.1.6.4.tar.gz">0.1.6.4</a>. </li>
+<a href="mdevd-0.1.6.5.tar.gz">0.1.6.5</a>. </li>
  <li> Alternatively, you can checkout a copy of the
 <a href="//git.skarnet.org/cgi-bin/cgit.cgi/mdevd/">mdevd
 git repository</a>:
diff --git a/doc/upgrade.html b/doc/upgrade.html
index aac1c6e..8933613 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -18,6 +18,13 @@
 
 <h1> What has changed in mdevd </h1>
 
+<h2> in 0.1.6.5 </h2>
+
+<ul>
+ <li> <a href="//skarnet.org/software/skalibs/">skalibs</a>
+dependency bumped to 2.14.2.1. </li>
+</ul>
+
 <h2> in 0.1.6.4 </h2>
 
 <ul>
diff --git a/package/info b/package/info
index f7bb7d2..1b5e3f7 100644
--- a/package/info
+++ b/package/info
@@ -1,4 +1,4 @@
 package=mdevd
-version=0.1.6.4
+version=0.1.6.5
 category=admin
 package_macro_name=MDEVD
diff --git a/src/mdevd/mdevd-coldplug.c b/src/mdevd/mdevd-coldplug.c
index 6edf3fc..6b8953f 100644
--- a/src/mdevd/mdevd-coldplug.c
+++ b/src/mdevd/mdevd-coldplug.c
@@ -147,7 +147,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
     struct uevent_s event ;
     for (;;) if (mdevd_uevent_read(nlfd, &event, 0, verbosity))
     {
-      char *x = mdevd_uevent_getvar(&event, "ACTION") ;
+      char const *x = mdevd_uevent_getvar(&event, "ACTION") ;
       if (strcmp(x, "add")) continue ;
       x = mdevd_uevent_getvar(&event, "SUBSYSTEM") ;
       if (strcmp(x, subsystem)) continue ;
diff --git a/src/mdevd/mdevd-internal.h b/src/mdevd/mdevd-internal.h
index cff7cdf..21ec713 100644
--- a/src/mdevd/mdevd-internal.h
+++ b/src/mdevd/mdevd-internal.h
@@ -20,6 +20,6 @@ struct uevent_s
 
 extern int mdevd_netlink_init (unsigned int, unsigned int) ;
 extern int mdevd_uevent_read (int, struct uevent_s *, uint32_t, unsigned int) ;
-extern char *mdevd_uevent_getvar (struct uevent_s *, char const *) ;
+extern char const *mdevd_uevent_getvar (struct uevent_s const *, char const *) ;
 
 #endif
diff --git a/src/mdevd/mdevd.c b/src/mdevd/mdevd.c
index dcd3198..bbef872 100644
--- a/src/mdevd/mdevd.c
+++ b/src/mdevd/mdevd.c
@@ -128,13 +128,14 @@ static scriptelem const scriptelem_catchall =
 typedef struct udata_s udata, *udata_ref ;
 struct udata_s
 {
-  char *devname ;
+  char const *devname ;
   mode_t devtype ;
   unsigned int action ;
   int mmaj ;
   int mmin ;
   pid_t pid ;
   unsigned short i ;
+  char sysdevpath[PATH_MAX] ;
   char buf[UEVENT_MAX_SIZE] ;
 } ;
 #define UDATA_ZERO { .devname = 0, .devtype = 0, .action = 0, .mmaj = -1, .mmin = -1, .pid = 0, .i = 0, .buf = "" }
@@ -151,10 +152,13 @@ static inline void script_free (scriptelem *script, unsigned short scriptlen, st
   for (i = 0 ; i < envmatchlen ; i++) regfree(&envmatch[i].re) ;
 }
 
-static inline int mkdirp (char *s)
+static inline int mkdirp (char const *path)
 {
-  size_t n = strlen(s) ;
+  size_t n = strlen(path) ;
+  if (!n) return 1 ;
+  char s[n + 1] ;
   size_t i = 0 ;
+  memcpy(s, path, n+1) ;
   for (; i < n ; i++)
   {
     if (s[i] == '/')
@@ -170,7 +174,7 @@ static inline int mkdirp (char *s)
   return i >= n ;
 }
 
-static int makesubdirs (char *path)
+static int makesubdirs (char const *path)
 {
   if (strrchr(path, '/') && !mkdirp(path))
   {
@@ -557,12 +561,18 @@ static inline ssize_t alias_format (char *out, size_t outmax, char const *in, ch
   return w ;
 }
 
-static inline void spawn_command (char const *command, struct uevent_s const *event, int isel, udata *ud)
+static inline void spawn_command (char const *command, struct uevent_s const *event, int isel, udata *ud, char const *extra)
 {
   char const *argv[4] = { isel ? "execlineb" : "/bin/sh", isel ? "-Pc" : "-c", command, 0 } ;
   size_t envlen = env_len((char const **)environ) ;
-  char const *envp[envlen + event->varn + 1] ;
-  env_merge(envp, envlen + event->varn + 1, (char const **)environ, envlen, event->buf + event->vars[1], event->len - event->vars[1]) ;
+  size_t n ;
+  char const *envp[envlen + event->varn + 1 + !!extra] ;
+  n = env_merge(envp, envlen + event->varn + 1, (char const **)environ, envlen, event->buf + event->vars[1], event->len - event->vars[1]) ;
+  if (extra)
+  {
+    envp[n - 1] = extra ;
+    envp[n++] = 0 ;
+  }
   ud->pid = cspawn(argv[0], argv, envp, CSPAWN_FLAGS_SELFPIPE_FINISH, 0, 0) ;
   if (!ud->pid)
   {
@@ -570,11 +580,12 @@ static inline void spawn_command (char const *command, struct uevent_s const *ev
   }
 }
 
-static inline int run_scriptelem (struct uevent_s *event, scriptelem const *elem, char const *storage, struct envmatch_s const *envmatch, udata *ud)
+static inline int run_scriptelem (struct uevent_s const *event, scriptelem const *elem, char const *storage, struct envmatch_s const *envmatch, udata *ud)
 {
   size_t devnamelen = strlen(ud->devname) ;
   size_t nodelen = 0 ;
-  char *node = event->buf + event->len + 5 ;
+  char nodebuf[PATH_MAX] = "MDEV=" ;
+  char *node = nodebuf + 5 ;
   regmatch_t off[10] ;
   unsigned short i = 0 ;
   for (; i < elem->envmatchlen ; i++)
@@ -608,27 +619,28 @@ static inline int run_scriptelem (struct uevent_s *event, scriptelem const *elem
     case MOVEINFO_MOVE :
     case MOVEINFO_MOVEANDLINK :
     {
-      ssize_t r = alias_format(node, PATH_MAX, storage + elem->movepath, ud->devname, off) ;
+      ssize_t r = alias_format(node, PATH_MAX - 5, storage + elem->movepath, ud->devname, off) ;
       if (r <= 1)
       {
         if (verbosity) strerr_warnwu5sys("process expression \"", storage + elem->movepath, "\" with devname \"", ud->devname, "\"") ;
         return -1 ;
       }
-      if (node[r - 2] == '/')
+      nodelen = r - 1 ;
+      if (node[nodelen - 1] == '/')
       {
-        if (r + devnamelen >= PATH_MAX)
+        if (nodelen + devnamelen >= PATH_MAX - 6)
         {
           errno = ENAMETOOLONG ;
           if (verbosity) strerr_warnwu2sys("create alias for ", ud->devname) ;
           return -1 ;
         }
-        memcpy(node + r - 1, ud->devname, devnamelen + 1) ;
-        nodelen = r + devnamelen - 1 ;
+        memcpy(node + nodelen, ud->devname, devnamelen + 1) ;
+        nodelen += devnamelen ;
       }
       break ;
     }
   }
-  if (elem->movetype != MOVEINFO_NOCREATE && ud->action == ACTION_ADD && ud->mmaj >= 0)
+  if (nodelen && ud->action == ACTION_ADD && ud->mmaj >= 0)
   {
     if (!makesubdirs(node)) return -1 ;
     if (dryrun)
@@ -684,12 +696,6 @@ static inline int run_scriptelem (struct uevent_s *event, scriptelem const *elem
 
   if (elem->cmdtype == ACTION_ANY || ud->action == elem->cmdtype)
   {
-    if (!mdevd_uevent_getvar(event, "MDEV"))
-    {
-      event->vars[event->varn++] = event->len ;
-      memcpy(event->buf + event->len, "MDEV=", 5) ;
-      event->len += 6 + nodelen ;
-    }
     if (dryrun)
     {
       strerr_warni4x("dry run: spawn ", elem->flagexecline ? "execlineb" : "/bin/sh", " for: ", storage + elem->command) ;
@@ -705,12 +711,16 @@ static inline int run_scriptelem (struct uevent_s *event, scriptelem const *elem
           buf[j+len] = ' ' ;
           j += len+1 ;
         }
+        if (nodelen)
+        {
+          memcpy(buf + j, nodebuf, nodelen + 5) ;
+          j += nodelen + 6 ;
+        }
         buf[j-1] = 0 ;
         strerr_warni2x("dry run: added variables: ", buf) ;
       }
     }
-    else spawn_command(storage + elem->command, event, elem->flagexecline, ud) ;
-    event->varn-- ; event->len -= 6 + nodelen ;
+    else spawn_command(storage + elem->command, event, elem->flagexecline, ud, nodelen ? nodebuf : 0) ;
   }
 
   if (elem->movetype != MOVEINFO_NOCREATE && ud->action == ACTION_REMOVE && ud->mmaj >= 0)
@@ -727,16 +737,17 @@ static inline int run_scriptelem (struct uevent_s *event, scriptelem const *elem
   return !elem->flagcont ;
 }
 
-static int run_script (struct uevent_s *event, scriptelem const *script, unsigned short scriptlen, char const *storage, struct envmatch_s const *envmatch, udata *ud)
+static int run_script (struct uevent_s const *event, scriptelem const *script, unsigned short scriptlen, char const *storage, struct envmatch_s const *envmatch, udata *ud)
 {
   for (; ud->i < scriptlen && !ud->pid ; ud->i++)
     if (run_scriptelem(event, script + ud->i, storage, envmatch, ud)) ud->i = scriptlen - 1 ;
   return ud->i >= scriptlen && !ud->pid ;
 }
 
-static inline int act_on_event (struct uevent_s *event, char *sysdevpath, size_t sysdevpathlen, unsigned int action, scriptelem const *script, unsigned short scriptlen, char const *storage, struct envmatch_s const *envmatch, udata *ud)
+static inline int act_on_event (struct uevent_s const *event, unsigned int action, scriptelem const *script, unsigned short scriptlen, char const *storage, struct envmatch_s const *envmatch, udata *ud)
 {
   ssize_t hasmajmin = 0 ;
+  size_t sysdevpathlen = strlen(ud->sysdevpath) ;
   unsigned int mmaj, mmin ;
   char const *x = mdevd_uevent_getvar(event, "MAJOR") ;
   ud->devtype = S_IFCHR ;
@@ -750,9 +761,9 @@ static inline int act_on_event (struct uevent_s *event, char *sysdevpath, size_t
     }
     if (!hasmajmin)
     {
-      memcpy(sysdevpath + sysdevpathlen, "/dev", 5) ;
-      hasmajmin = openreadnclose(sysdevpath, ud->buf, UINT_FMT << 1) ;
-      sysdevpath[sysdevpathlen] = 0 ;
+      memcpy(ud->sysdevpath + sysdevpathlen, "/dev", 5) ;
+      hasmajmin = openreadnclose(ud->sysdevpath, ud->buf, UINT_FMT << 1) ;
+      ud->sysdevpath[sysdevpathlen] = 0 ;
       if (hasmajmin > 0)
       {
         size_t i = uint_scan(ud->buf, &mmaj) ;
@@ -773,9 +784,9 @@ static inline int act_on_event (struct uevent_s *event, char *sysdevpath, size_t
   if (!ud->devname)
   {
     ssize_t r ;
-    memcpy(sysdevpath + sysdevpathlen, "/uevent", 8) ;
-    r = openreadnclose(sysdevpath, ud->buf, UEVENT_MAX_SIZE-1) ;
-    sysdevpath[sysdevpathlen] = 0 ;
+    memcpy(ud->sysdevpath + sysdevpathlen, "/uevent", 8) ;
+    r = openreadnclose(ud->sysdevpath, ud->buf, UEVENT_MAX_SIZE-1) ;
+    ud->sysdevpath[sysdevpathlen] = 0 ;
     if (r > 0)
     {
       ud->buf[r] = 0 ;
@@ -786,14 +797,14 @@ static inline int act_on_event (struct uevent_s *event, char *sysdevpath, size_t
         *strchr(ud->devname, '\n') = 0 ;
       }
     }
-    if (!ud->devname) ud->devname = basename(sysdevpath) ;
+    if (!ud->devname) ud->devname = basename(ud->sysdevpath) ;
   }
   if (strlen(ud->devname) >= PATH_MAX - 1)
   {
     if (verbosity) strerr_warnwu2x("device name too long: ", ud->devname) ;
     return 1 ;
   }
-  if (strstr(sysdevpath, "/block/")) ud->devtype = S_IFBLK ;
+  if (strstr(ud->sysdevpath, "/block/")) ud->devtype = S_IFBLK ;
   else
   {
     x = mdevd_uevent_getvar(event, "SUBSYSTEM") ;
@@ -803,10 +814,11 @@ static inline int act_on_event (struct uevent_s *event, char *sysdevpath, size_t
   return run_script(event, script, scriptlen, storage, envmatch, ud) ;
 }
 
-static inline int on_event (struct uevent_s *event, scriptelem const *script, unsigned short scriptlen, char const *storage, struct envmatch_s const *envmatch, udata *ud)
+static inline int on_event (struct uevent_s const *event, scriptelem const *script, unsigned short scriptlen, char const *storage, struct envmatch_s const *envmatch, udata *ud)
 {
-  unsigned int action ;
+  int done = 1 ;
   char const *x = mdevd_uevent_getvar(event, "ACTION") ;
+  unsigned int action ;
   if (!x) return 1 ;
   if (!strcmp(x, "add")) action = ACTION_ADD ;
   else if (!strcmp(x, "remove")) action = ACTION_REMOVE ;
@@ -814,17 +826,15 @@ static inline int on_event (struct uevent_s *event, scriptelem const *script, un
   x = mdevd_uevent_getvar(event, "DEVPATH") ;
   if (!x) return 1 ;
   {
-    int done = 1 ;
     size_t devpathlen = strlen(x) ;
     size_t slashsyslen = strlen(slashsys) ;
-    char sysdevpath[devpathlen + slashsyslen + 8] ; /* act_on_event needs the extra storage */
-    memcpy(sysdevpath, slashsys, slashsyslen) ;
-    memcpy(sysdevpath + slashsyslen, x, devpathlen + 1) ;
-    x = mdevd_uevent_getvar(event, "FIRMWARE") ;
-    if (action == ACTION_ADD || !x) done = act_on_event(event, sysdevpath, slashsyslen + devpathlen, action, script, scriptlen, storage, envmatch, ud) ;
-    if (action == ACTION_ADD && x) load_firmware(x, sysdevpath) ;
-    return done ;
+    memcpy(ud->sysdevpath, slashsys, slashsyslen) ;
+    memcpy(ud->sysdevpath + slashsyslen, x, devpathlen + 1) ;
   }
+  x = mdevd_uevent_getvar(event, "FIRMWARE") ;
+  if (action == ACTION_ADD || !x) done = act_on_event(event, action, script, scriptlen, storage, envmatch, ud) ;
+  if (action == ACTION_ADD && x) load_firmware(x, ud->sysdevpath) ;
+  return done ;
 }
 
 
diff --git a/src/mdevd/mdevd_uevent_getvar.c b/src/mdevd/mdevd_uevent_getvar.c
index 8eb8583..0e3fd47 100644
--- a/src/mdevd/mdevd_uevent_getvar.c
+++ b/src/mdevd/mdevd_uevent_getvar.c
@@ -4,7 +4,7 @@
 
 #include "mdevd-internal.h"
 
-char *mdevd_uevent_getvar (struct uevent_s *event, char const *var)
+char const *mdevd_uevent_getvar (struct uevent_s const *event, char const *var)
 {
   size_t varlen = strlen(var) ;
   unsigned short i = 1 ;