]> Zhao Yanbai Git Server - minix.git/commitdiff
backup: bug fix for improper struct dirent usage 29/729/3
authorThomas Cort <tcort@minix3.org>
Sat, 10 Aug 2013 05:22:48 +0000 (05:22 +0000)
committerGerrit Code Review <gerrit@gerrit>
Mon, 12 Aug 2013 09:19:10 +0000 (11:19 +0200)
Between Minix 3.1.2 and Minix 3.1.3, the d_name member of struct
dirent was reduced from 61 characters to 1 character. backup(8)
blindly copies the result of readdir() into an array of dirent
structs. As a consequence, the structs in the array only contain
the first letter of the name and the name string was not null
terminated. This caused the backup utility to always fail.

Remedy the situation by adding room for the full d_name.

Change-Id: I2a7b4630f1bb727825a95a6095a7a543fc2f08f6

commands/backup/backup.c

index f953c56ba2266a26a0ade4bec449b22eea653898..116278f5626b6d6667bfcd03bcca5f4db1db9ca9 100644 (file)
 #define NO_SAVINGS 512         /* compress can return code 2 */
 #define OUT_OF_SPACE 2
 
-struct dirent dir_ent[MAX_ENTRIES];
+struct dirent_full {
+       struct dirent de;
+       char d_name[MAXNAMLEN+1];
+} dir_ent[MAX_ENTRIES];
 int entries = 0;
 
 struct sorted {
@@ -138,8 +141,10 @@ char *argv[];
        perror(dir1);
        return 1;
   }
-  while(entries < MAX_ENTRIES && (e=readdir(DIR1)))
-       memcpy(&dir_ent[entries++], e, sizeof(*e));
+  for(entries = 0; entries < MAX_ENTRIES && (e=readdir(DIR1)); entries++) {
+       memcpy(&dir_ent[entries].de, e, sizeof(*e));
+       snprintf(dir_ent[entries].d_name, MAXNAMLEN, "%s", e->d_name);
+  }
   closedir(DIR1);
   if (entries == MAX_ENTRIES)
        error(FATAL, "directory ", dir1, " is too large");
@@ -222,15 +227,15 @@ int n;
 
   for (i = 0; i < n; i++) {
        /* Mark "." and ".." as null entries, as well as unstatable ones. */
-       if (strcmp(dir_ent[i].d_name, ".") == 0) dir_ent[i].d_ino = 0;
-       if (strcmp(dir_ent[i].d_name, "..") == 0) dir_ent[i].d_ino = 0;
-       if (dir_ent[i].d_ino == 0) continue;
+       if (strcmp(dir_ent[i].d_name, ".") == 0) dir_ent[i].de.d_ino = 0;
+       if (strcmp(dir_ent[i].d_name, "..") == 0) dir_ent[i].de.d_ino = 0;
+       if (dir_ent[i].de.d_ino == 0) continue;
 
        /* Stat the file. */
        snprintf(cbuf, sizeof(cbuf), "%s/%s", dir1, dir_ent[i].d_name);
        if (stat(cbuf, &s) < 0) {
                error(NONFATAL, "cannot stat ", cbuf, "");
-               dir_ent[i].d_ino = 0;   /* mark as unusable */
+               dir_ent[i].de.d_ino = 0;        /* mark as unusable */
                continue;
        }
        sorted[i].mode = s.st_mode;
@@ -243,7 +248,7 @@ int n;
   /* Squeeze out all the entries whose ino field is 0. */
   j = 0;
   for (i = 0; i < n; i++) {
-       if (dir_ent[i].d_ino != 0) {
+       if (dir_ent[i].de.d_ino != 0) {
                sorted[j] = sorted[i];
                j++;
        }