extlinux: handle cases of a single level of directories syslinux-4.00-pre39
authorH. Peter Anvin <hpa@linux.intel.com>
Wed, 28 Apr 2010 22:50:20 +0000 (15:50 -0700)
committerH. Peter Anvin <hpa@linux.intel.com>
Wed, 28 Apr 2010 22:50:20 +0000 (15:50 -0700)
We had a boundary condition error where a single-level directory from
the global root (e.g. /boot) would be incorrectly truncated; fix that.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
extlinux/main.c

index d166671..e1d5596 100644 (file)
@@ -441,7 +441,7 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
     int i, dw, nptrs;
     uint32_t csum;
     int secptroffset, diroffset, dirlen, subvoloffset, subvollen;
-    char *dirpath, *subpath;
+    char *dirpath, *subpath, *xdirpath, *xsubpath;
 
     dirpath = realpath(dir, NULL);
     if (!dirpath || stat(dir, &dirst)) {
@@ -457,10 +457,17 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
     }
 
     subpath = strchr(dirpath, '\0');
-    while (--subpath >= dirpath) {
+    for (;;) {
        if (*subpath == '/') {
-           *subpath = '\0';
-           if (lstat(dirpath, &xdst) || dirst.st_dev != xdst.st_dev) {
+           if (subpath > dirpath) {
+               *subpath = '\0';
+               xsubpath = subpath+1;
+               xdirpath = dirpath;
+           } else {
+               xsubpath = subpath;
+               xdirpath = "/";
+           }
+           if (lstat(xdirpath, &xdst) || dirst.st_dev != xdst.st_dev) {
                subpath = strchr(subpath+1, '/');
                if (!subpath)
                    subpath = "/"; /* It's the root of the filesystem */
@@ -468,6 +475,11 @@ int patch_file_and_bootblock(int fd, const char *dir, int devfd)
            }
            *subpath = '/';
        }
+
+       if (subpath == dirpath)
+           break;
+
+       subpath--;
     }
 
     /* Now subpath should contain the path relative to the fs base */