Fix path parsing - smdev - suckless mdev
 (HTM) git clone git://git.suckless.org/smdev
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 210bd07cd4bb0c41313fda721578a3ddbbd52493
 (DIR) parent 0534a1001fb7990c2837bc4cf76f7f4824a890c1
 (HTM) Author: sin <sin@2f30.org>
       Date:   Thu, 22 Aug 2013 14:06:42 +0100
       
       Fix path parsing
       
       Diffstat:
         M Makefile                            |       3 ++-
         M smdev.c                             |      45 +++++++++++++++++++++++++-------
         M util.h                              |       1 +
         A util/strlcpy.c                      |      14 ++++++++++++++
       
       4 files changed, 53 insertions(+), 10 deletions(-)
       ---
 (DIR) diff --git a/Makefile b/Makefile
       @@ -10,7 +10,8 @@ LIB = \
                util/eprintf.o      \
                util/estrtol.o      \
                util/mkpath.o       \
       -        util/recurse.o
       +        util/recurse.o      \
       +        util/strlcpy.o
        
        SRC = smdev.c
        
 (DIR) diff --git a/smdev.c b/smdev.c
       @@ -11,6 +11,7 @@
        #include <string.h>
        #include <limits.h>
        #include <regex.h>
       +#include <libgen.h>
        #include "config.h"
        #include "mkpath.h"
        #include "util.h"
       @@ -146,17 +147,19 @@ createdev(struct Event *ev)
                struct Rule *Rule;
                struct passwd *pw;
                struct group *gr;
       -        char devpath[PATH_MAX], *devname;
       +        char devpath[PATH_MAX];
       +        char devname[PATH_MAX];
       +        char *dirc, *basec;
                char buf[BUFSIZ];
                int type;
       -        int i;
       +        int i, j;
        
                snprintf(buf, sizeof(buf), "%d:%d", ev->maj, ev->min);
                type = devtype(buf);
                if (type < 0)
                        return -1;
        
       -        devname = ev->devname;
       +        strlcpy(devname, ev->devname, sizeof(devname));
                snprintf(devpath, sizeof(devpath), "/dev/%s", devname);
                for (i = 0; i < LEN(Rules); i++) {
                        Rule = &Rules[i];
       @@ -167,16 +170,40 @@ createdev(struct Event *ev)
                        if (Rule->path) {
                                if (Rule->path[0] != '=' && Rule->path[0] != '>')
                                        eprintf("Invalid path '%s'\n", Rule->path);
       -                        if (Rule->path[strlen(Rule->path) - 1] == '/') {
       -                                snprintf(buf, sizeof(buf), "/dev/%s", &Rule->path[1]);
       +
       +                        for (j = 1; Rule->path[j]; j++) {
       +                                if (Rule->path[j] != '/')
       +                                        continue;
       +                                if (Rule->path[strlen(Rule->path) - 1] == '/') {
       +                                        snprintf(buf, sizeof(buf), "/dev/%s",
       +                                                 &Rule->path[1]);
       +                                        snprintf(devpath, sizeof(devpath), "/dev/%s%s",
       +                                                 &Rule->path[1], devname);
       +                                } else {
       +                                        dirc = strdup(&Rule->path[1]);
       +                                        if (!dirc)
       +                                                eprintf("strdup:");
       +                                        snprintf(buf, sizeof(buf), "/dev/%s", dirname(dirc));
       +                                        free(dirc);
       +
       +                                        basec = strdup(&Rule->path[1]);
       +                                        if (!basec)
       +                                                eprintf("strdup:");
       +                                        strlcpy(devname, basename(basec), sizeof(devname));
       +                                        free(basec);
       +
       +                                        snprintf(devpath, sizeof(devpath), "%s/%s",
       +                                                 buf, devname);
       +                                }
                                        umask(022);
                                        if (mkpath(buf, 0755) < 0)
                                                eprintf("mkdir %s:", buf);
                                        umask(0);
       -                                snprintf(devpath, sizeof(devpath), "/dev/%s%s",
       -                                         &Rule->path[1], devname);
       -                        } else {
       -                                devname = &Rule->path[1];
       +                                break;
       +                        }
       +
       +                        if (!Rule->path[j]) {
       +                                strlcpy(devname, &Rule->path[1], sizeof(devname));
                                        snprintf(devpath, sizeof(devpath), "/dev/%s", devname);
                                }
                        }
 (DIR) diff --git a/util.h b/util.h
       @@ -13,3 +13,4 @@ void enprintf(int, const char *, ...);
        void eprintf(const char *, ...);
        long estrtol(const char *, int);
        void recurse(const char *, void (*)(const char *));
       +size_t strlcpy(char *dest, const char *src, size_t size);
 (DIR) diff --git a/util/strlcpy.c b/util/strlcpy.c
       @@ -0,0 +1,14 @@
       +#include <stdio.h>
       +#include <string.h>
       +
       +size_t strlcpy(char *dest, const char *src, size_t size)
       +{
       +        size_t ret = strlen(src);
       +
       +        if (size) {
       +                size_t len = (ret >= size) ? size - 1 : ret;
       +                memcpy(dest, src, len);
       +                dest[len] = '\0';
       +        }
       +        return ret;
       +}