diff --git a/src/calc.c b/src/calc.c index 7a738787c0c1ef7c450464a3acaea6121edd4ad8..4a0bc7df15417d3f65d45ea5bd1e41f337388f5b 100644 --- a/src/calc.c +++ b/src/calc.c @@ -168,13 +168,12 @@ int calc_item(struct dir *par, char *name) { return 0; /* allocate dir and fix references */ - d = calloc(sizeof(struct dir), 1); + d = calloc(SDIRSIZE+strlen(name), 1); d->parent = par; d->next = par->sub; par->sub = d; if(d->next) d->next->prev = d; - d->name = malloc(strlen(name)+1); strcpy(d->name, name); #ifdef __CYGWIN__ @@ -434,16 +433,15 @@ int calc_process() { } /* initialize parent dir */ - t = (struct dir *) calloc(1, sizeof(struct dir)); + n = orig ? strlen(orig->name) : strlen(path)+strlen(name)+1; + t = (struct dir *) calloc(1, SDIRSIZE+n); t->size = fs.st_blocks * S_BLKSIZE; t->asize = fs.st_size; t->flags |= FF_DIR; if(orig) { - t->name = malloc(strlen(orig->name)+1); strcpy(t->name, orig->name); t->parent = orig->parent; } else { - t->name = malloc(strlen(path)+strlen(name)+2); t->name[0] = 0; if(strcmp(path, "/")) strcpy(t->name, path); diff --git a/src/dirlist.c b/src/dirlist.c index 2239914a9734d2adc4c847893fa2db526c61a867..db0bd0dbe2870d7c1656a2c9304dd988645efbe4 100644 --- a/src/dirlist.c +++ b/src/dirlist.c @@ -197,7 +197,7 @@ void dirlist_open(struct dir *d) { dirlist_parent_alloc.flags &= ~FF_BSEL; if(head->parent->parent) { dirlist_parent = &dirlist_parent_alloc; - dirlist_parent->name = ".."; + strcpy(dirlist_parent->name, ".."); dirlist_parent->next = head; dirlist_parent->parent = head->parent; dirlist_parent->sub = head->parent; diff --git a/src/global.h b/src/global.h index e48a58bbdc75eb5ede2634625fb91f9b63bcce92..ceb1a2b59ba8eced5568a2ac6794dbdf9b06a42c 100644 --- a/src/global.h +++ b/src/global.h @@ -53,13 +53,21 @@ * fixed-size integers instead, which are much more predictable */ struct dir { struct dir *parent, *next, *prev, *sub, *hlnk; - char *name; off_t size, asize; + ino_t ino; unsigned long items; - unsigned char flags; dev_t dev; - ino_t ino; + unsigned char flags; + char name[3]; /* must be large enough to hold ".." */ }; +/* sizeof(total dir) = SDIRSIZE + strlen(name) = sizeof(struct dir) - 3 + strlen(name) + 1 */ +#define SDIRSIZE (sizeof(struct dir)-2) + +/* Ideally, the name array should be as large as the padding added to the end of + * the struct, but I can't figure out a portable way to calculate this. We can + * be sure that it's at least 3 bytes, though, as the struct is aligned to at + * least 4 bytes and the flags field is a single byte. */ + /* program state */ extern int pstate; diff --git a/src/util.c b/src/util.c index a0dc92dd056397efcd71715e1f642395a91f727e..bea2483c4fbf0f195a38149d55b35ba8f7cc6b3b 100644 --- a/src/util.c +++ b/src/util.c @@ -211,7 +211,6 @@ void freedir_rec(struct dir *dr) { freedir_hlnk(tmp); /* remove item */ if(tmp->sub) freedir_rec(tmp->sub); - free(tmp->name); tmp2 = tmp->next; free(tmp); } @@ -245,7 +244,6 @@ void freedir(struct dir *dr) { tmp->items -= dr->items+1; } - free(dr->name); free(dr); }