Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/diff/diffdir.c
| Show First 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| RB_HEAD(inodetree, inode); | RB_HEAD(inodetree, inode); | ||||
| static struct inodetree v1 = RB_INITIALIZER(&v1); | static struct inodetree v1 = RB_INITIALIZER(&v1); | ||||
| static struct inodetree v2 = RB_INITIALIZER(&v2); | static struct inodetree v2 = RB_INITIALIZER(&v2); | ||||
| RB_GENERATE_STATIC(inodetree, inode, entry, inodecmp); | RB_GENERATE_STATIC(inodetree, inode, entry, inodecmp); | ||||
| static int | static int | ||||
| vscandir(struct inodetree *tree, const char *path, struct dirent ***dirp, | vscandir(struct inodetree *tree, struct inode **inop, | ||||
| const char *path, struct dirent ***dirp, | |||||
| int (*selectf)(const struct dirent *), | int (*selectf)(const struct dirent *), | ||||
| int (*comparf)(const struct dirent **, const struct dirent **)) | int (*comparf)(const struct dirent **, const struct dirent **)) | ||||
| { | { | ||||
| struct stat sb; | struct stat sb; | ||||
| struct inode *ino = NULL; | struct inode *ino = NULL; | ||||
| int fd = -1, ret, serrno; | int fd = -1, ret, serrno; | ||||
| if ((fd = open(path, O_DIRECTORY | O_RDONLY)) < 0 || | if ((fd = open(path, O_DIRECTORY | O_RDONLY)) < 0 || | ||||
| (ino = calloc(1, sizeof(*ino))) == NULL || | (ino = calloc(1, sizeof(*ino))) == NULL || | ||||
| fstat(fd, &sb) != 0) | fstat(fd, &sb) != 0) | ||||
| goto fail; | goto fail; | ||||
| ino->dev = sb.st_dev; | ino->dev = sb.st_dev; | ||||
| ino->ino = sb.st_ino; | ino->ino = sb.st_ino; | ||||
| if (RB_FIND(inodetree, tree, ino)) { | if (RB_FIND(inodetree, tree, ino)) { | ||||
| free(ino); | free(ino); | ||||
| close(fd); | close(fd); | ||||
| warnx("%s: Directory loop detected", path); | warnx("%s: Directory loop detected", path); | ||||
| *dirp = NULL; | *dirp = NULL; | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| if ((ret = fdscandir(fd, dirp, selectf, comparf)) < 0) | if ((ret = fdscandir(fd, dirp, selectf, comparf)) < 0) | ||||
| goto fail; | goto fail; | ||||
| RB_INSERT(inodetree, tree, ino); | RB_INSERT(inodetree, tree, ino); | ||||
| close(fd); | close(fd); | ||||
| *inop = ino; | |||||
| return (ret); | return (ret); | ||||
| fail: | fail: | ||||
| serrno = errno; | serrno = errno; | ||||
| if (ino != NULL) | if (ino != NULL) | ||||
| free(ino); | free(ino); | ||||
| if (fd >= 0) | if (fd >= 0) | ||||
| close(fd); | close(fd); | ||||
| errno = serrno; | errno = serrno; | ||||
| return (-1); | return (-1); | ||||
| } | } | ||||
| static void | |||||
| leavedir(struct inodetree *tree, struct inode *ino) | |||||
| { | |||||
| RB_REMOVE(inodetree, tree, ino); | |||||
| free(ino); | |||||
| } | |||||
| /* | /* | ||||
| * Diff directory traversal. Will be called recursively if -r was specified. | * Diff directory traversal. Will be called recursively if -r was specified. | ||||
| */ | */ | ||||
| void | void | ||||
| diffdir(char *p1, char *p2, int flags) | diffdir(char *p1, char *p2, int flags) | ||||
| { | { | ||||
| struct dirent *dent1, **dp1, **edp1, **dirp1 = NULL; | struct dirent *dent1, **dp1, **edp1, **dirp1 = NULL; | ||||
| struct dirent *dent2, **dp2, **edp2, **dirp2 = NULL; | struct dirent *dent2, **dp2, **edp2, **dirp2 = NULL; | ||||
| struct inode *ino1 = NULL, *ino2 = NULL; | |||||
| size_t dirlen1, dirlen2; | size_t dirlen1, dirlen2; | ||||
| char path1[PATH_MAX], path2[PATH_MAX]; | char path1[PATH_MAX], path2[PATH_MAX]; | ||||
| int pos; | int pos; | ||||
| edp1 = edp2 = NULL; | edp1 = edp2 = NULL; | ||||
| dirlen1 = strlcpy(path1, *p1 ? p1 : ".", sizeof(path1)); | dirlen1 = strlcpy(path1, *p1 ? p1 : ".", sizeof(path1)); | ||||
| if (dirlen1 >= sizeof(path1) - 1) { | if (dirlen1 >= sizeof(path1) - 1) { | ||||
| Show All 11 Lines | diffdir(char *p1, char *p2, int flags) | ||||
| } | } | ||||
| while (dirlen2 > 1 && path2[dirlen2 - 1] == '/') | while (dirlen2 > 1 && path2[dirlen2 - 1] == '/') | ||||
| path2[--dirlen2] = '\0'; | path2[--dirlen2] = '\0'; | ||||
| /* | /* | ||||
| * Get a list of entries in each directory, skipping "excluded" files | * Get a list of entries in each directory, skipping "excluded" files | ||||
| * and sorting alphabetically. | * and sorting alphabetically. | ||||
| */ | */ | ||||
| pos = vscandir(&v1, path1, &dirp1, selectfile, alphasort); | pos = vscandir(&v1, &ino1, path1, &dirp1, selectfile, alphasort); | ||||
| if (pos == -1) { | if (pos == -1) { | ||||
| if (errno == ENOENT && (Nflag || Pflag)) { | if (errno == ENOENT && (Nflag || Pflag)) { | ||||
| pos = 0; | pos = 0; | ||||
| } else { | } else { | ||||
| warn("%s", path1); | warn("%s", path1); | ||||
| goto closem; | goto closem; | ||||
| } | } | ||||
| } | } | ||||
| dp1 = dirp1; | dp1 = dirp1; | ||||
| edp1 = dirp1 + pos; | edp1 = dirp1 + pos; | ||||
| pos = vscandir(&v2, path2, &dirp2, selectfile, alphasort); | pos = vscandir(&v2, &ino2, path2, &dirp2, selectfile, alphasort); | ||||
| if (pos == -1) { | if (pos == -1) { | ||||
| if (errno == ENOENT && Nflag) { | if (errno == ENOENT && Nflag) { | ||||
| pos = 0; | pos = 0; | ||||
| } else { | } else { | ||||
| warn("%s", path2); | warn("%s", path2); | ||||
| goto closem; | goto closem; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | if (pos == 0) { | ||||
| status |= 1; | status |= 1; | ||||
| } | } | ||||
| dp2++; | dp2++; | ||||
| } | } | ||||
| } | } | ||||
| closem: | closem: | ||||
| if (dirp1 != NULL) { | if (dirp1 != NULL) { | ||||
| if (ino1 != NULL) | |||||
| leavedir(&v1, ino1); | |||||
| for (dp1 = dirp1; dp1 < edp1; dp1++) | for (dp1 = dirp1; dp1 < edp1; dp1++) | ||||
| free(*dp1); | free(*dp1); | ||||
| free(dirp1); | free(dirp1); | ||||
| } | } | ||||
| if (dirp2 != NULL) { | if (dirp2 != NULL) { | ||||
| if (ino2 != NULL) | |||||
| leavedir(&v2, ino2); | |||||
| for (dp2 = dirp2; dp2 < edp2; dp2++) | for (dp2 = dirp2; dp2 < edp2; dp2++) | ||||
| free(*dp2); | free(*dp2); | ||||
| free(dirp2); | free(dirp2); | ||||
| } | } | ||||
| } | } | ||||
| /* | /* | ||||
| * Do the actual diff by calling either diffreg() or diffdir(). | * Do the actual diff by calling either diffreg() or diffdir(). | ||||
| ▲ Show 20 Lines • Show All 147 Lines • Show Last 20 Lines | |||||