]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
Add program to calculate the shortest relative path for symlinks
authorLucas De Marchi <lucas.demarchi@profusion.mobi>
Wed, 18 Jan 2012 18:01:58 +0000 (16:01 -0200)
committerLucas De Marchi <lucas.demarchi@profusion.mobi>
Wed, 18 Jan 2012 21:48:16 +0000 (19:48 -0200)
Makefile.am
tools/.gitignore
tools/shortest-relpath.c [new file with mode: 0644]

index 22ef9eca7503a06e65077c152063e98a6599c776..6eec0d84bd4c9099e01fe08cc0d9805a9df3bf3e 100644 (file)
@@ -124,13 +124,15 @@ tools_kmod_CFLAGS = $(AM_CFLAGS)
 tools_kmod_LDADD = libkmod/libkmod-util.la \
                   libkmod/libkmod.la
 
-noinst_PROGRAMS = tools/kmod-nolib
+noinst_PROGRAMS = tools/kmod-nolib scripts/shortest_relpath
 tools_kmod_nolib_SOURCES = $(tools_kmod_SOURCES)
 tools_kmod_nolib_CPPFLAGS = $(tools_kmod_CPPFLAGS)
 tools_kmod_nolib_CFLAGS = $(tools_kmod_CFLAGS)
 tools_kmod_nolib_LDADD = libkmod/libkmod-util.la \
                         libkmod/libkmod-private.la
 
+scripts_shortest_relpath_SOURCES = scripts/shortest_relpath.c
+
 ${noinst_SCRIPTS}: tools/kmod-nolib
        $(AM_V_GEN) ($(RM) $@; \
                $(LN_S) $(notdir $<) $@)
index 041d7b22fabd9ee3e5c1b285079955865dc4f439..a3a5795f66d95a8ac46a632b57f1e157bd9a4c65 100644 (file)
@@ -7,3 +7,4 @@ modinfo
 depmod
 kmod
 kmod-nolib
+shortest-relpath
diff --git a/tools/shortest-relpath.c b/tools/shortest-relpath.c
new file mode 100644 (file)
index 0000000..5c960bb
--- /dev/null
@@ -0,0 +1,100 @@
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+static void usage(const char *progname)
+{
+       printf("%s <path> <relative-to-path>\n", progname);
+}
+
+/*
+ * path must be absolute path, as the result of calling realpath()
+ */
+static void split_path(const char *path, char d[PATH_MAX], size_t *dlen,
+                                               char n[NAME_MAX], size_t *nlen)
+{
+       size_t dirnamelen, namelen;
+       char *p;
+
+       p = strrchr(path, '/'); /* p is never NULL since path is abs */
+       dirnamelen = p - path;
+       if (dirnamelen > 0)
+               memcpy(d, path, dirnamelen);
+       d[dirnamelen] = '\0';
+
+       namelen = strlen(p + 1);
+       if (namelen > 0)
+               memcpy(n, p + 1, namelen + 1);
+
+       if (dlen)
+               *dlen = dirnamelen;
+       if (nlen)
+               *nlen = namelen;
+}
+
+int main(int argc, char *argv[])
+{
+       size_t sympathlen, namelen, pathlen, i, j;
+       char name[NAME_MAX], path[PATH_MAX];
+       char sympath[PATH_MAX];
+       char buf[PATH_MAX];
+       char *p;
+
+       if (argc < 3) {
+               usage(basename(argv[0]));
+               return EXIT_FAILURE;
+       }
+
+       p = realpath(argv[1], buf);
+       if (p == NULL) {
+               fprintf(stderr, "could not get realpath of %s: %m\n", argv[1]);
+               return EXIT_FAILURE;
+       }
+       split_path(buf, path, &pathlen, name, &namelen);
+
+       p = realpath(argv[2], sympath);
+       if (p == NULL) {
+               fprintf(stderr, "could not get realpath of %s: %m\n", argv[2]);
+               return EXIT_FAILURE;
+       }
+       sympathlen = strlen(sympath);
+
+       for (i = 1; i < sympathlen && i < pathlen; i++) {
+               if (sympath[i] == path[i])
+                       continue;
+               break;
+       }
+
+       if (i < sympathlen) {
+               while (sympath[i - 1] != '/')
+                       i--;
+       }
+
+       p = &path[i];
+
+       j = 0;
+       if (i < sympathlen) {
+               memcpy(buf + j, "../", 3);
+               j += 3;
+       }
+
+       for (; i < sympathlen; i++) {
+               if (sympath[i] != '/')
+                       continue;
+
+               memcpy(buf + j, "../", 3);
+               j += 3;
+       }
+
+       if (p != path + pathlen) {
+               memcpy(buf + j, p, path + pathlen - p);
+               j += path + pathlen - p;;
+               buf[j++] = '/';
+       }
+       memcpy(buf + j, name, namelen + 1);
+
+       printf("%s\n", buf);
+       return 0;
+}