Implemented hardlink detection
Этот коммит содержится в:
родитель
188265c594
Коммит
757bdff7ed
56
src/calc.c
56
src/calc.c
@ -53,7 +53,12 @@ struct dir *root; /* root directory struct we're calculating */
|
||||
struct dir *orig; /* original directory, when recalculating */
|
||||
dev_t curdev; /* current device we're calculating on */
|
||||
int anpos; /* position of the animation string */
|
||||
int curpathl = 0, lasterrl = 0;
|
||||
struct link_inode { /* list of all non-dirs with nlink > 1 */
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
} *links = NULL;
|
||||
int curpathl = 0, lasterrl = 0, linksl = 0, linkst = 0;
|
||||
|
||||
|
||||
|
||||
/* adds name to curpath */
|
||||
@ -86,6 +91,7 @@ void calc_leavepath() {
|
||||
int calc_item(struct dir *par, char *name) {
|
||||
struct dir *t, *d;
|
||||
struct stat fs;
|
||||
int i;
|
||||
|
||||
if(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
|
||||
return 0;
|
||||
@ -130,6 +136,31 @@ int calc_item(struct dir *par, char *name) {
|
||||
for(t=d->parent; t!=NULL; t=t->parent)
|
||||
t->items++;
|
||||
|
||||
/* check for hard links.
|
||||
An item is only considered a hard link if it's not a directory,
|
||||
has st_nlink > 1, and is already present in the links array */
|
||||
if(!S_ISDIR(fs.st_mode) && fs.st_nlink > 1) {
|
||||
for(i=0; i<linkst; i++)
|
||||
if(links[i].dev == fs.st_dev && links[i].ino == fs.st_ino)
|
||||
break;
|
||||
/* found in the list, set size = 0 */
|
||||
if(i != linkst)
|
||||
fs.st_blocks = fs.st_size = 0;
|
||||
/* not found, add to the list */
|
||||
else {
|
||||
if(++linkst > linksl) {
|
||||
linksl *= 2;
|
||||
if(!linksl) {
|
||||
linksl = 64;
|
||||
links = malloc(linksl);
|
||||
} else
|
||||
links = realloc(links, linksl);
|
||||
}
|
||||
links[i].dev = fs.st_dev;
|
||||
links[i].ino = fs.st_ino;
|
||||
}
|
||||
}
|
||||
|
||||
/* count the size */
|
||||
if(!(d->flags & FF_EXL || d->flags & FF_OTHFS)) {
|
||||
d->size = fs.st_blocks * S_BLKSIZE;
|
||||
@ -297,6 +328,7 @@ void calc_process() {
|
||||
char *path, *name;
|
||||
struct stat fs;
|
||||
struct dir *t;
|
||||
int n;
|
||||
|
||||
/* check root directory */
|
||||
if((path = path_real(curpath)) == NULL) {
|
||||
@ -365,11 +397,20 @@ void calc_process() {
|
||||
} else
|
||||
curpath[0] = 0;
|
||||
|
||||
/* start calculating */
|
||||
if(!calc_dir(root, name) && !failed) {
|
||||
if(!path[1] && strcmp(name, "."))
|
||||
free(name);
|
||||
free(path);
|
||||
/* calculate */
|
||||
n = calc_dir(root, name);
|
||||
|
||||
/* free some resources */
|
||||
if(!path[1] && strcmp(name, "."))
|
||||
free(name);
|
||||
free(path);
|
||||
if(linksl) {
|
||||
linksl = linkst = 0;
|
||||
free(links);
|
||||
}
|
||||
|
||||
/* success */
|
||||
if(!n && !failed) {
|
||||
if(root->sub == NULL) {
|
||||
freedir(root);
|
||||
failed = 1;
|
||||
@ -403,9 +444,6 @@ void calc_process() {
|
||||
}
|
||||
|
||||
/* something went wrong... */
|
||||
if(!path[1] && strcmp(name, "."))
|
||||
free(name);
|
||||
free(path);
|
||||
freedir(root);
|
||||
calc_fail:
|
||||
while(failed && !input_handle(0))
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user