rework fsnode' into two components;
fsnode' contains the name and tree
information and a link to the appropriate fsinode, and `fsinode' contains the inode information and a reference count. multiple fsnodes may point to the same fsinode. this replaces the 'dup' pointer in the previous code.
This commit is contained in:
parent
20a3ef2b53
commit
ebbf3dddb5
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ffs.c,v 1.4 2001/11/22 02:47:26 lukem Exp $ */
|
||||
/* $NetBSD: ffs.c,v 1.5 2001/12/05 11:08:53 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
@ -71,7 +71,7 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef __lint
|
||||
__RCSID("$NetBSD: ffs.c,v 1.4 2001/11/22 02:47:26 lukem Exp $");
|
||||
__RCSID("$NetBSD: ffs.c,v 1.5 2001/12/05 11:08:53 lukem Exp $");
|
||||
#endif /* !__lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -518,14 +518,16 @@ ffs_size_dir(fsnode *root, fsinfo_t *fsopts)
|
||||
assert(strcmp(node->name, ".") == 0);
|
||||
ADDDIRENT("..");
|
||||
}
|
||||
if (node->dup == NULL) { /* don't count duplicate names */
|
||||
if ((node->inode->flags & FI_SIZED) == 0) {
|
||||
/* don't count duplicate names */
|
||||
node->inode->flags |= FI_SIZED;
|
||||
if (debug & DEBUG_FS_SIZE_DIR_NODE)
|
||||
printf("ffs_size_dir: %s size %lld\n",
|
||||
node->name,
|
||||
(long long)node->statbuf.st_size);
|
||||
(long long)node->inode->st.st_size);
|
||||
fsopts->inodes++;
|
||||
if (node->type == S_IFREG)
|
||||
ADDSIZE(node->statbuf.st_size);
|
||||
ADDSIZE(node->inode->st.st_size);
|
||||
if (node->type == S_IFLNK) {
|
||||
int slen;
|
||||
|
||||
@ -567,23 +569,23 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
* pass 1: allocate inode numbers, build directory `file'
|
||||
*/
|
||||
for (cur = root; cur != NULL; cur = cur->next) {
|
||||
if (cur->dup == NULL) {
|
||||
if (cur == root && cur->parent)
|
||||
cur->ino = cur->parent->ino;
|
||||
if ((cur->inode->flags & FI_ALLOCATED) == 0) {
|
||||
cur->inode->flags |= FI_ALLOCATED;
|
||||
if (cur == root && cur->parent != NULL)
|
||||
cur->inode->ino = cur->parent->inode->ino;
|
||||
else {
|
||||
cur->ino = fsopts->curinode;
|
||||
cur->inode->ino = fsopts->curinode;
|
||||
fsopts->curinode++;
|
||||
}
|
||||
} else
|
||||
cur->ino = cur->dup->ino;
|
||||
}
|
||||
ffs_make_dirbuf(&dirbuf, cur->name, cur, fsopts->needswap);
|
||||
if (cur == root) { /* we're at "."; add ".." */
|
||||
ffs_make_dirbuf(&dirbuf, "..",
|
||||
cur->parent == NULL ? cur : cur->parent->first,
|
||||
fsopts->needswap);
|
||||
root->nlink++; /* count my parent's link */
|
||||
root->inode->nlink++; /* count my parent's link */
|
||||
} else if (cur->child != NULL)
|
||||
root->nlink++; /* count my child's link */
|
||||
root->inode->nlink++; /* count my child's link */
|
||||
|
||||
/*
|
||||
* XXX possibly write file and long symlinks here,
|
||||
@ -601,8 +603,9 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
if (debug & DEBUG_FS_POPULATE)
|
||||
printf("ffs_populate_dir: PASS 2 dir %s\n", dir);
|
||||
for (cur = root; cur != NULL; cur = cur->next) {
|
||||
if (cur->dup != NULL)
|
||||
if (cur->inode->flags & FI_WRITTEN)
|
||||
continue; /* skip hard-linked entries */
|
||||
cur->inode->flags |= FI_WRITTEN;
|
||||
|
||||
if (snprintf(path, sizeof(path), "%s/%s", dir, cur->name)
|
||||
>= sizeof(path))
|
||||
@ -613,19 +616,19 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
|
||||
/* build on-disk inode */
|
||||
memset(&din, 0, sizeof(din));
|
||||
din.di_mode = cur->statbuf.st_mode;
|
||||
din.di_nlink = cur->nlink;
|
||||
din.di_size = cur->statbuf.st_size;
|
||||
din.di_atime = cur->statbuf.st_atime;
|
||||
din.di_atimensec = cur->statbuf.st_atimensec;
|
||||
din.di_mtime = cur->statbuf.st_mtime;
|
||||
din.di_mtimensec = cur->statbuf.st_mtimensec;
|
||||
din.di_ctime = cur->statbuf.st_ctime;
|
||||
din.di_ctimensec = cur->statbuf.st_ctimensec;
|
||||
din.di_flags = cur->statbuf.st_flags;
|
||||
din.di_gen = cur->statbuf.st_gen;
|
||||
din.di_uid = cur->statbuf.st_uid;
|
||||
din.di_gid = cur->statbuf.st_gid;
|
||||
din.di_mode = cur->inode->st.st_mode;
|
||||
din.di_nlink = cur->inode->nlink;
|
||||
din.di_size = cur->inode->st.st_size;
|
||||
din.di_atime = cur->inode->st.st_atime;
|
||||
din.di_atimensec = cur->inode->st.st_atimensec;
|
||||
din.di_mtime = cur->inode->st.st_mtime;
|
||||
din.di_mtimensec = cur->inode->st.st_mtimensec;
|
||||
din.di_ctime = cur->inode->st.st_ctime;
|
||||
din.di_ctimensec = cur->inode->st.st_ctimensec;
|
||||
din.di_flags = cur->inode->st.st_flags;
|
||||
din.di_gen = cur->inode->st.st_gen;
|
||||
din.di_uid = cur->inode->st.st_uid;
|
||||
din.di_gid = cur->inode->st.st_gid;
|
||||
/* not set: di_db, di_ib, di_blocks, di_spare */
|
||||
|
||||
membuf = NULL;
|
||||
@ -635,7 +638,7 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
} else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) {
|
||||
din.di_size = 0; /* a device */
|
||||
din.di_rdev =
|
||||
ufs_rw32(cur->statbuf.st_rdev, fsopts->needswap);
|
||||
ufs_rw32(cur->inode->st.st_rdev, fsopts->needswap);
|
||||
} else if (S_ISLNK(cur->type)) { /* symlink */
|
||||
int slen;
|
||||
|
||||
@ -649,19 +652,19 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
|
||||
if (debug & DEBUG_FS_POPULATE_NODE) {
|
||||
printf("ffs_populate_dir: writing ino %d, %s",
|
||||
cur->ino, inode_type(cur->type));
|
||||
if (cur->nlink > 1)
|
||||
printf(", nlink %d", cur->nlink);
|
||||
cur->inode->ino, inode_type(cur->type));
|
||||
if (cur->inode->nlink > 1)
|
||||
printf(", nlink %d", cur->inode->nlink);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
if (membuf != NULL) {
|
||||
ffs_write_file(&din, cur->ino, membuf, fsopts);
|
||||
ffs_write_file(&din, cur->inode->ino, membuf, fsopts);
|
||||
} else if (S_ISREG(cur->type)) {
|
||||
ffs_write_file(&din, cur->ino, path, fsopts);
|
||||
ffs_write_file(&din, cur->inode->ino, path, fsopts);
|
||||
} else {
|
||||
assert (! S_ISDIR(cur->type));
|
||||
ffs_write_inode(&din, cur->ino, fsopts);
|
||||
ffs_write_inode(&din, cur->inode->ino, fsopts);
|
||||
}
|
||||
}
|
||||
|
||||
@ -788,7 +791,7 @@ ffs_dump_dirbuf(dirbuf_t *dbuf, const char *dir, int needswap)
|
||||
{
|
||||
doff_t i;
|
||||
struct direct *de;
|
||||
u_int16_t reclen;
|
||||
uint16_t reclen;
|
||||
|
||||
assert (dbuf != NULL);
|
||||
assert (dir != NULL);
|
||||
@ -812,16 +815,16 @@ static void
|
||||
ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap)
|
||||
{
|
||||
struct direct de, *dp;
|
||||
u_int16_t llen, reclen;
|
||||
uint16_t llen, reclen;
|
||||
|
||||
assert (dbuf != NULL);
|
||||
assert (name != NULL);
|
||||
assert (node != NULL);
|
||||
/* create direct entry */
|
||||
(void)memset(&de, 0, sizeof(de));
|
||||
de.d_ino = ufs_rw32(node->ino, needswap);
|
||||
de.d_ino = ufs_rw32(node->inode->ino, needswap);
|
||||
de.d_type = IFTODT(node->type);
|
||||
de.d_namlen = (u_int8_t)strlen(name);
|
||||
de.d_namlen = (uint8_t)strlen(name);
|
||||
assert (de.d_namlen < (sizeof(de.d_name)));
|
||||
strcpy(de.d_name, name);
|
||||
reclen = DIRSIZ(0, &de, needswap);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: makefs.c,v 1.6 2001/11/25 11:22:09 lukem Exp $ */
|
||||
/* $NetBSD: makefs.c,v 1.7 2001/12/05 11:08:53 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef __lint
|
||||
__RCSID("$NetBSD: makefs.c,v 1.6 2001/11/25 11:22:09 lukem Exp $");
|
||||
__RCSID("$NetBSD: makefs.c,v 1.7 2001/12/05 11:08:53 lukem Exp $");
|
||||
#endif /* !__lint */
|
||||
|
||||
#include <assert.h>
|
||||
@ -69,7 +69,7 @@ static fstype_t fstypes[] = {
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
u_int debug;
|
||||
uint debug;
|
||||
struct timespec start_time;
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: makefs.h,v 1.3 2001/11/25 11:22:09 lukem Exp $ */
|
||||
/* $NetBSD: makefs.h,v 1.4 2001/12/05 11:08:53 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
@ -39,10 +39,15 @@
|
||||
|
||||
|
||||
/*
|
||||
* fsnode - a component of the tree which contains information about the
|
||||
* file system.
|
||||
* fsnode -
|
||||
* a component of the tree; contains a filename, a pointer to
|
||||
* fsinode, optional symlink name, and tree pointers
|
||||
*
|
||||
* A tree of these looks like this:
|
||||
* fsinode -
|
||||
* equivalent to an inode, containing target file system inode number,
|
||||
* refcount (nlink), and stat buffer
|
||||
*
|
||||
* A tree of fsnodes looks like this:
|
||||
*
|
||||
* name "." "bin" "netbsd"
|
||||
* type S_IFDIR S_IFDIR S_IFREG
|
||||
@ -61,22 +66,32 @@
|
||||
* must be "." when the tree has been built; during build it may
|
||||
* not be if "." hasn't yet been found by readdir(2).
|
||||
*
|
||||
* - if dup is not NULL, it points to an fsnode that this is a
|
||||
* - if dup is not NULL, it points to an fsent that this is a
|
||||
* duplicate of; only relevant for non directories with > 1 link
|
||||
*/
|
||||
|
||||
enum fi_flags {
|
||||
FI_SIZED = 1<<0, /* inode sized */
|
||||
FI_ALLOCATED = 1<<1, /* fsinode->ino allocated */
|
||||
FI_WRITTEN = 1<<2, /* inode written */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t ino; /* inode number used on target fs */
|
||||
uint32_t nlink; /* number of links to this entry */
|
||||
enum fi_flags flags; /* flags used by fs specific code */
|
||||
struct stat st; /* stat entry */
|
||||
} fsinode;
|
||||
|
||||
typedef struct _fsnode {
|
||||
struct _fsnode *parent; /* parent (NULL if root) */
|
||||
struct _fsnode *child; /* child (if type == S_IFDIR) */
|
||||
struct _fsnode *next; /* next */
|
||||
struct _fsnode *first; /* first node of current level (".") */
|
||||
struct stat statbuf; /* stat entry */
|
||||
uint32_t type; /* type of entry */
|
||||
fsinode *inode; /* actual inode data */
|
||||
char *symlink; /* symlink target */
|
||||
char *name; /* file name */
|
||||
struct _fsnode *dup; /* entry this is a duplicate of
|
||||
(when statbuf.st_nlink > 1) */
|
||||
uint32_t nlink; /* number of links to this entry */
|
||||
uint32_t type; /* type of entry */
|
||||
uint32_t ino; /* inode number used on target fs */
|
||||
} fsnode;
|
||||
|
||||
|
||||
@ -151,7 +166,7 @@ void ffs_makefs(const char *, const char *, fsnode *, fsinfo_t *);
|
||||
|
||||
|
||||
|
||||
extern u_int debug;
|
||||
extern uint debug;
|
||||
extern struct timespec start_time;
|
||||
|
||||
#define DEBUG_TIME 0x00000001
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: walk.c,v 1.5 2001/11/02 03:12:48 lukem Exp $ */
|
||||
/* $NetBSD: walk.c,v 1.6 2001/12/05 11:08:53 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
@ -77,7 +77,7 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef __lint
|
||||
__RCSID("$NetBSD: walk.c,v 1.5 2001/11/02 03:12:48 lukem Exp $");
|
||||
__RCSID("$NetBSD: walk.c,v 1.6 2001/12/05 11:08:53 lukem Exp $");
|
||||
#endif /* !__lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -98,7 +98,8 @@ __RCSID("$NetBSD: walk.c,v 1.5 2001/11/02 03:12:48 lukem Exp $");
|
||||
static void apply_specdir(const char *, NODE *, fsnode *);
|
||||
static void apply_specentry(const char *, NODE *, fsnode *);
|
||||
static fsnode *create_fsnode(const char *, struct stat *);
|
||||
static fsnode *link_check(fsnode *);
|
||||
static fsinode *create_fsinode(struct stat *);
|
||||
static fsinode *link_check(fsinode *);
|
||||
|
||||
|
||||
/*
|
||||
@ -141,6 +142,7 @@ walk_dir(const char *dir, fsnode *parent)
|
||||
}
|
||||
|
||||
cur = create_fsnode(dent->d_name, &stbuf);
|
||||
cur->inode = create_fsinode(&stbuf);
|
||||
cur->parent = parent;
|
||||
if (strcmp(dent->d_name, ".") == 0) {
|
||||
/* ensure "." is at the start of the list */
|
||||
@ -159,10 +161,15 @@ walk_dir(const char *dir, fsnode *parent)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (cur->statbuf.st_nlink > 1) {
|
||||
cur->dup = link_check(cur);
|
||||
if (cur->dup)
|
||||
cur->dup->nlink++;
|
||||
if (stbuf.st_nlink > 1) {
|
||||
fsinode *curino;
|
||||
|
||||
curino = link_check(cur->inode);
|
||||
if (curino != NULL) {
|
||||
free(cur->inode);
|
||||
cur->inode = curino;
|
||||
cur->inode->nlink++;
|
||||
}
|
||||
}
|
||||
if (S_ISLNK(cur->type)) {
|
||||
char slink[PATH_MAX+1];
|
||||
@ -184,19 +191,28 @@ walk_dir(const char *dir, fsnode *parent)
|
||||
}
|
||||
|
||||
static fsnode *
|
||||
create_fsnode(const char *name, struct stat *statbuf)
|
||||
create_fsnode(const char *name, struct stat *stbuf)
|
||||
{
|
||||
fsnode *cur;
|
||||
|
||||
if ((cur = calloc(1, sizeof(fsnode))) == NULL ||
|
||||
(cur->name = strdup(name)) == NULL)
|
||||
err(1, "Memory allocation error");
|
||||
cur->statbuf = *statbuf;
|
||||
cur->type = (cur->statbuf.st_mode & S_IFMT);
|
||||
cur->nlink = 1;
|
||||
cur->type = stbuf->st_mode & S_IFMT;
|
||||
return (cur);
|
||||
}
|
||||
|
||||
static fsinode *
|
||||
create_fsinode(struct stat *statbuf)
|
||||
{
|
||||
fsinode *cur;
|
||||
|
||||
if ((cur = calloc(1, sizeof(fsinode))) == NULL)
|
||||
err(1, "Memory allocation error");
|
||||
cur->nlink = 1;
|
||||
cur->st = *statbuf;
|
||||
return (cur);
|
||||
}
|
||||
|
||||
/*
|
||||
* apply_specfile --
|
||||
@ -301,6 +317,7 @@ apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode)
|
||||
/* build minimal fsnode */
|
||||
memset(&stbuf, 0, sizeof(stbuf));
|
||||
stbuf.st_mode = nodetoino(curnode->type);
|
||||
stbuf.st_nlink = 1;
|
||||
stbuf.st_mtime = stbuf.st_atime =
|
||||
stbuf.st_ctime = start_time.tv_sec;
|
||||
stbuf.st_mtimensec = stbuf.st_atimensec =
|
||||
@ -353,16 +370,6 @@ apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode)
|
||||
if (debug & DEBUG_APPLY_SPECENTRY)
|
||||
printf("apply_specentry: %s/%s\n", dir, dirnode->name);
|
||||
|
||||
/*
|
||||
* if this is a duplicate (i.e, an existing hardlink),
|
||||
* change the actual settings.
|
||||
*/
|
||||
if (dirnode->dup != NULL) {
|
||||
if (debug & DEBUG_APPLY_SPECENTRY)
|
||||
printf("\t\t\thard-linked to %s\n", dirnode->dup->name);
|
||||
dirnode = dirnode->dup;
|
||||
}
|
||||
|
||||
#define ASEPRINT(t, b, o, n) \
|
||||
if (debug & DEBUG_APPLY_SPECENTRY) \
|
||||
printf("\t\t\tchanging %s from " b " to " b "\n", \
|
||||
@ -370,21 +377,21 @@ apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode)
|
||||
|
||||
if (specnode->flags & (F_GID | F_GNAME)) {
|
||||
ASEPRINT("gid", "%d",
|
||||
dirnode->statbuf.st_gid, specnode->st_gid);
|
||||
dirnode->statbuf.st_gid = specnode->st_gid;
|
||||
dirnode->inode->st.st_gid, specnode->st_gid);
|
||||
dirnode->inode->st.st_gid = specnode->st_gid;
|
||||
}
|
||||
if (specnode->flags & F_MODE) {
|
||||
ASEPRINT("mode", "%#o",
|
||||
dirnode->statbuf.st_mode & ALLPERMS, specnode->st_mode);
|
||||
dirnode->statbuf.st_mode &= ~ALLPERMS;
|
||||
dirnode->statbuf.st_mode |= (specnode->st_mode & ALLPERMS);
|
||||
dirnode->inode->st.st_mode & ALLPERMS, specnode->st_mode);
|
||||
dirnode->inode->st.st_mode &= ~ALLPERMS;
|
||||
dirnode->inode->st.st_mode |= (specnode->st_mode & ALLPERMS);
|
||||
}
|
||||
/* XXX: ignoring F_NLINK for now */
|
||||
if (specnode->flags & F_SIZE) {
|
||||
ASEPRINT("size", "%lld",
|
||||
(long long)dirnode->statbuf.st_size,
|
||||
(long long)dirnode->inode->st.st_size,
|
||||
(long long)specnode->st_size);
|
||||
dirnode->statbuf.st_size = specnode->st_size;
|
||||
dirnode->inode->st.st_size = specnode->st_size;
|
||||
}
|
||||
if (specnode->flags & F_SLINK) {
|
||||
assert(dirnode->symlink != NULL);
|
||||
@ -396,29 +403,30 @@ apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode)
|
||||
}
|
||||
if (specnode->flags & F_TIME) {
|
||||
ASEPRINT("time", "%ld",
|
||||
(long)dirnode->statbuf.st_mtime, (long)specnode->st_mtime);
|
||||
dirnode->statbuf.st_mtime = specnode->st_mtime;
|
||||
dirnode->statbuf.st_mtimensec = specnode->st_mtimensec;
|
||||
dirnode->statbuf.st_atime = specnode->st_mtime;
|
||||
dirnode->statbuf.st_atimensec = specnode->st_mtimensec;
|
||||
dirnode->statbuf.st_ctime = start_time.tv_sec;
|
||||
dirnode->statbuf.st_ctimensec = start_time.tv_nsec;
|
||||
(long)dirnode->inode->st.st_mtime,
|
||||
(long)specnode->st_mtime);
|
||||
dirnode->inode->st.st_mtime = specnode->st_mtime;
|
||||
dirnode->inode->st.st_mtimensec = specnode->st_mtimensec;
|
||||
dirnode->inode->st.st_atime = specnode->st_mtime;
|
||||
dirnode->inode->st.st_atimensec = specnode->st_mtimensec;
|
||||
dirnode->inode->st.st_ctime = start_time.tv_sec;
|
||||
dirnode->inode->st.st_ctimensec = start_time.tv_nsec;
|
||||
}
|
||||
if (specnode->flags & (F_UID | F_UNAME)) {
|
||||
ASEPRINT("uid", "%d",
|
||||
dirnode->statbuf.st_uid, specnode->st_uid);
|
||||
dirnode->statbuf.st_uid = specnode->st_uid;
|
||||
dirnode->inode->st.st_uid, specnode->st_uid);
|
||||
dirnode->inode->st.st_uid = specnode->st_uid;
|
||||
}
|
||||
if (specnode->flags & F_FLAGS) {
|
||||
ASEPRINT("flags", "%#lX",
|
||||
(u_long)dirnode->statbuf.st_flags,
|
||||
(u_long)specnode->st_flags);
|
||||
dirnode->statbuf.st_flags = specnode->st_flags;
|
||||
(ulong)dirnode->inode->st.st_flags,
|
||||
(ulong)specnode->st_flags);
|
||||
dirnode->inode->st.st_flags = specnode->st_flags;
|
||||
}
|
||||
if (specnode->flags & F_DEV) {
|
||||
ASEPRINT("rdev", "%#x",
|
||||
dirnode->statbuf.st_rdev, specnode->st_rdev);
|
||||
dirnode->statbuf.st_rdev = specnode->st_rdev;
|
||||
dirnode->inode->st.st_rdev, specnode->st_rdev);
|
||||
dirnode->inode->st.st_rdev = specnode->st_rdev;
|
||||
}
|
||||
#undef ASEPRINT
|
||||
}
|
||||
@ -451,11 +459,8 @@ dump_fsnodes(const char *dir, fsnode *root)
|
||||
} else {
|
||||
assert (cur->symlink == NULL);
|
||||
}
|
||||
if (cur->dup != NULL) {
|
||||
printf(", hard-linked to %s", cur->dup->name);
|
||||
}
|
||||
if (cur->nlink > 1)
|
||||
printf(", nlinks=%d", cur->nlink);
|
||||
if (cur->inode->nlink > 1)
|
||||
printf(", nlinks=%d", cur->inode->nlink);
|
||||
putchar('\n');
|
||||
|
||||
if (cur->child) {
|
||||
@ -482,21 +487,19 @@ inode_type(mode_t mode)
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
int32_t dev;
|
||||
int32_t ino;
|
||||
fsnode *dup;
|
||||
} dupnode;
|
||||
|
||||
/*
|
||||
* link_check --
|
||||
* return pointer to fsnode matching `entry's st_ino & st_dev if it exists,
|
||||
* otherwise add `entry' to table and return NULL
|
||||
*/
|
||||
static fsnode *
|
||||
link_check(fsnode *entry)
|
||||
static fsinode *
|
||||
link_check(fsinode *entry)
|
||||
{
|
||||
static dupnode *dups;
|
||||
static struct dupnode {
|
||||
uint32_t dev;
|
||||
uint32_t ino;
|
||||
fsinode *dup;
|
||||
} *dups;
|
||||
static int ndups, maxdups;
|
||||
|
||||
int i;
|
||||
@ -505,27 +508,26 @@ link_check(fsnode *entry)
|
||||
|
||||
/* XXX; maybe traverse in reverse for speed? */
|
||||
for (i = 0; i < ndups; i++) {
|
||||
if (dups[i].dev == entry->statbuf.st_dev &&
|
||||
dups[i].ino == entry->statbuf.st_ino) {
|
||||
if (dups[i].dev == entry->st.st_dev &&
|
||||
dups[i].ino == entry->st.st_ino) {
|
||||
if (debug & DEBUG_WALK_DIR_LINKCHECK)
|
||||
printf(
|
||||
"link_check: %s (%d,%d) linked to %s\n",
|
||||
entry->name, entry->statbuf.st_dev,
|
||||
entry->statbuf.st_ino, dups[i].dup->name);
|
||||
printf("link_check: found [%d,%d]\n",
|
||||
entry->st.st_dev, entry->st.st_ino);
|
||||
return (dups[i].dup);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug & DEBUG_WALK_DIR_LINKCHECK)
|
||||
printf("link_check: no match for %s (%d, %d)\n",
|
||||
entry->name, entry->statbuf.st_dev, entry->statbuf.st_ino);
|
||||
printf("link_check: no match for [%d, %d]\n",
|
||||
entry->st.st_dev, entry->st.st_ino);
|
||||
if (ndups == maxdups) {
|
||||
maxdups += 128;
|
||||
if ((dups = realloc(dups, sizeof(dupnode) * maxdups)) == NULL)
|
||||
if ((dups = realloc(dups, sizeof(struct dupnode) * maxdups))
|
||||
== NULL)
|
||||
err(1, "Memory allocation error");
|
||||
}
|
||||
dups[ndups].dev = entry->statbuf.st_dev;
|
||||
dups[ndups].ino = entry->statbuf.st_ino;
|
||||
dups[ndups].dev = entry->st.st_dev;
|
||||
dups[ndups].ino = entry->st.st_ino;
|
||||
dups[ndups].dup = entry;
|
||||
ndups++;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user