Properly handle recursion in recurse()
The restructuring of recurse() in the last few weeks actually broke the recursion-flags in different tools. As a long-term goal, the recursor should have a field "maxdepth" which should be "1" for the non-Rflag-case. "0" stands for unlimited.
This commit is contained in:
		
							
								
								
									
										7
									
								
								chgrp.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								chgrp.c
									
									
									
									
									
								
							| @@ -9,7 +9,6 @@ | |||||||
| #include "util.h" | #include "util.h" | ||||||
|  |  | ||||||
| static int   hflag = 0; | static int   hflag = 0; | ||||||
| static int   Rflag = 0; |  | ||||||
| static gid_t gid = -1; | static gid_t gid = -1; | ||||||
| static int   ret = 0; | static int   ret = 0; | ||||||
|  |  | ||||||
| @@ -30,7 +29,7 @@ chgrp(const char *path, struct stat *st, void *data, struct recursor *r) | |||||||
| 	if (st && chownf(path, st->st_uid, gid) < 0) { | 	if (st && chownf(path, st->st_uid, gid) < 0) { | ||||||
| 		weprintf("%s %s:", chownf_name, path); | 		weprintf("%s %s:", chownf_name, path); | ||||||
| 		ret = 1; | 		ret = 1; | ||||||
| 	} else if (Rflag && st && S_ISDIR(st->st_mode)) { | 	} else if (!(r->flags & NODIRS) && st && S_ISDIR(st->st_mode)) { | ||||||
| 		recurse(path, NULL, r); | 		recurse(path, NULL, r); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -45,14 +44,14 @@ int | |||||||
| main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||||
| { | { | ||||||
| 	struct group *gr; | 	struct group *gr; | ||||||
| 	struct recursor r = { .fn = chgrp, .hist = NULL, .depth = 0, .follow = 'P', .flags = 0 }; | 	struct recursor r = { .fn = chgrp, .hist = NULL, .depth = 0, .follow = 'P', .flags = NODIRS }; | ||||||
|  |  | ||||||
| 	ARGBEGIN { | 	ARGBEGIN { | ||||||
| 	case 'h': | 	case 'h': | ||||||
| 		hflag = 1; | 		hflag = 1; | ||||||
| 		break; | 		break; | ||||||
| 	case 'R': | 	case 'R': | ||||||
| 		Rflag = 1; | 		r.flags &= ~NODIRS; | ||||||
| 		break; | 		break; | ||||||
| 	case 'H': | 	case 'H': | ||||||
| 	case 'L': | 	case 'L': | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								chmod.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								chmod.c
									
									
									
									
									
								
							| @@ -4,7 +4,6 @@ | |||||||
| #include "fs.h" | #include "fs.h" | ||||||
| #include "util.h" | #include "util.h" | ||||||
|  |  | ||||||
| static int    Rflag   = 0; |  | ||||||
| static char  *modestr = ""; | static char  *modestr = ""; | ||||||
| static mode_t mask    = 0; | static mode_t mask    = 0; | ||||||
| static int    ret     = 0; | static int    ret     = 0; | ||||||
| @@ -18,7 +17,7 @@ chmodr(const char *path, struct stat *st, void *data, struct recursor *r) | |||||||
| 	if (chmod(path, m) < 0) { | 	if (chmod(path, m) < 0) { | ||||||
| 		weprintf("chmod %s:", path); | 		weprintf("chmod %s:", path); | ||||||
| 		ret = 1; | 		ret = 1; | ||||||
| 	} else if (Rflag && st && S_ISDIR(st->st_mode)) { | 	} else if (!(r->flags & NODIRS) && st && S_ISDIR(st->st_mode)) { | ||||||
| 		recurse(path, NULL, r); | 		recurse(path, NULL, r); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -32,7 +31,7 @@ usage(void) | |||||||
| int | int | ||||||
| main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||||
| { | { | ||||||
| 	struct recursor r = { .fn = chmodr, .hist = NULL, .depth = 0, .follow = 'P', .flags = 0}; | 	struct recursor r = { .fn = chmodr, .hist = NULL, .depth = 0, .follow = 'P', .flags = NODIRS}; | ||||||
| 	size_t i; | 	size_t i; | ||||||
|  |  | ||||||
| 	argv0 = argv[0], argc--, argv++; | 	argv0 = argv[0], argc--, argv++; | ||||||
| @@ -43,7 +42,7 @@ main(int argc, char *argv[]) | |||||||
| 		for (i = 1; (*argv)[i]; i++) { | 		for (i = 1; (*argv)[i]; i++) { | ||||||
| 			switch ((*argv)[i]) { | 			switch ((*argv)[i]) { | ||||||
| 			case 'R': | 			case 'R': | ||||||
| 				Rflag = 1; | 				r.flags &= ~NODIRS; | ||||||
| 				break; | 				break; | ||||||
| 			case 'H': | 			case 'H': | ||||||
| 			case 'L': | 			case 'L': | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								chown.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								chown.c
									
									
									
									
									
								
							| @@ -11,7 +11,6 @@ | |||||||
| #include "util.h" | #include "util.h" | ||||||
|  |  | ||||||
| static int   hflag = 0; | static int   hflag = 0; | ||||||
| static int   Rflag = 0; |  | ||||||
| static uid_t uid = -1; | static uid_t uid = -1; | ||||||
| static gid_t gid = -1; | static gid_t gid = -1; | ||||||
| static int   ret = 0; | static int   ret = 0; | ||||||
| @@ -33,7 +32,7 @@ chownpwgr(const char *path, struct stat *st, void *data, struct recursor *r) | |||||||
| 	if (chownf(path, uid, gid) < 0) { | 	if (chownf(path, uid, gid) < 0) { | ||||||
| 		weprintf("%s %s:", chownf_name, path); | 		weprintf("%s %s:", chownf_name, path); | ||||||
| 		ret = 1; | 		ret = 1; | ||||||
| 	} else if (Rflag && st && S_ISDIR(st->st_mode)) { | 	} else if (!(r->flags & NODIRS) && st && S_ISDIR(st->st_mode)) { | ||||||
| 		recurse(path, NULL, r); | 		recurse(path, NULL, r); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -49,7 +48,7 @@ main(int argc, char *argv[]) | |||||||
| { | { | ||||||
| 	struct group *gr; | 	struct group *gr; | ||||||
| 	struct passwd *pw; | 	struct passwd *pw; | ||||||
| 	struct recursor r = { .fn = chownpwgr, .hist = NULL, .depth = 0, .follow = 'P', .flags = 0}; | 	struct recursor r = { .fn = chownpwgr, .hist = NULL, .depth = 0, .follow = 'P', .flags = NODIRS}; | ||||||
| 	char *owner, *group; | 	char *owner, *group; | ||||||
|  |  | ||||||
| 	ARGBEGIN { | 	ARGBEGIN { | ||||||
| @@ -58,7 +57,7 @@ main(int argc, char *argv[]) | |||||||
| 		break; | 		break; | ||||||
| 	case 'r': | 	case 'r': | ||||||
| 	case 'R': | 	case 'R': | ||||||
| 		Rflag = 1; | 		r.flags &= ~NODIRS; | ||||||
| 		break; | 		break; | ||||||
| 	case 'H': | 	case 'H': | ||||||
| 	case 'L': | 	case 'L': | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								fs.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								fs.h
									
									
									
									
									
								
							| @@ -19,6 +19,7 @@ struct recursor { | |||||||
| enum { | enum { | ||||||
| 	SAMEDEV  = 1 << 0, | 	SAMEDEV  = 1 << 0, | ||||||
| 	DIRFIRST = 1 << 1, | 	DIRFIRST = 1 << 1, | ||||||
|  | 	NODIRS   = 1 << 2, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| extern int cp_aflag; | extern int cp_aflag; | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ recurse(const char *path, void *data, struct recursor *r) | |||||||
| 		recurse_status = 1; | 		recurse_status = 1; | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	if (!S_ISDIR(st.st_mode)) { | 	if (!S_ISDIR(st.st_mode) || (S_ISDIR(st.st_mode) && (r->flags & NODIRS))) { | ||||||
| 		(r->fn)(path, &st, data, r); | 		(r->fn)(path, &st, data, r); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								libutil/rm.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								libutil/rm.c
									
									
									
									
									
								
							| @@ -3,22 +3,29 @@ | |||||||
|  |  | ||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  | #include <unistd.h> | ||||||
|  |  | ||||||
| #include "../fs.h" | #include "../fs.h" | ||||||
| #include "../util.h" | #include "../util.h" | ||||||
|  |  | ||||||
| int rm_fflag = 0; | int rm_fflag = 0; | ||||||
| int rm_rflag = 0; |  | ||||||
| int rm_status = 0; | int rm_status = 0; | ||||||
|  |  | ||||||
| void | void | ||||||
| rm(const char *path, struct stat *st, void *data, struct recursor *r) | rm(const char *path, struct stat *st, void *data, struct recursor *r) | ||||||
| { | { | ||||||
| 	if (rm_rflag && st && S_ISDIR(st->st_mode)) | 	if (!(r->flags & NODIRS) && st && S_ISDIR(st->st_mode)) { | ||||||
| 		recurse(path, NULL, r); | 		recurse(path, NULL, r); | ||||||
| 	if (remove(path) < 0) { |  | ||||||
|  | 		if (rmdir(path) < 0) { | ||||||
| 			if (!rm_fflag) | 			if (!rm_fflag) | ||||||
| 			weprintf("remove %s:", path); | 				weprintf("rmdir %s:", path); | ||||||
|  | 			if (!(rm_fflag && errno == ENOENT)) | ||||||
|  | 				rm_status = 1; | ||||||
|  | 		} | ||||||
|  | 	} else if (unlink(path) < 0) { | ||||||
|  | 		if (!rm_fflag) | ||||||
|  | 			weprintf("unlink %s:", path); | ||||||
| 		if (!(rm_fflag && errno == ENOENT)) | 		if (!(rm_fflag && errno == ENOENT)) | ||||||
| 			rm_status = 1; | 			rm_status = 1; | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								mv.c
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								mv.c
									
									
									
									
									
								
							| @@ -19,7 +19,6 @@ mv(const char *s1, const char *s2, int depth) | |||||||
| 	if (errno == EXDEV) { | 	if (errno == EXDEV) { | ||||||
| 		cp_aflag = cp_rflag = cp_pflag = 1; | 		cp_aflag = cp_rflag = cp_pflag = 1; | ||||||
| 		cp_follow = 'P'; | 		cp_follow = 'P'; | ||||||
| 		rm_rflag = 1; |  | ||||||
| 		cp(s1, s2, depth); | 		cp(s1, s2, depth); | ||||||
| 		rm(s1, NULL, NULL, &r); | 		rm(s1, NULL, NULL, &r); | ||||||
| 		return (mv_status = cp_status || rm_status); | 		return (mv_status = cp_status || rm_status); | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								rm.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								rm.c
									
									
									
									
									
								
							| @@ -11,7 +11,7 @@ usage(void) | |||||||
| int | int | ||||||
| main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||||
| { | { | ||||||
| 	struct recursor r = { .fn = rm, .hist = NULL, .depth = 0, .follow = 'P', .flags = 0}; | 	struct recursor r = { .fn = rm, .hist = NULL, .depth = 0, .follow = 'P', .flags = NODIRS }; | ||||||
|  |  | ||||||
| 	ARGBEGIN { | 	ARGBEGIN { | ||||||
| 	case 'f': | 	case 'f': | ||||||
| @@ -19,7 +19,7 @@ main(int argc, char *argv[]) | |||||||
| 		break; | 		break; | ||||||
| 	case 'R': | 	case 'R': | ||||||
| 	case 'r': | 	case 'r': | ||||||
| 		rm_rflag = 1; | 		r.flags &= ~NODIRS; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		usage(); | 		usage(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user