Refactored recursive directory util functions
This commit is contained in:
		
							parent
							
								
									e9996882cb
								
							
						
					
					
						commit
						a90bd1c833
					
				
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| all: sxiv | ||||
| 
 | ||||
| VERSION=git-20110407 | ||||
| VERSION=git-20110408 | ||||
| 
 | ||||
| CC?=gcc | ||||
| PREFIX?=/usr/local | ||||
|  | ||||
							
								
								
									
										38
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								main.c
									
									
									
									
									
								
							| @ -92,11 +92,15 @@ int load_image(int new) { | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int fncmp(const void *a, const void *b) { | ||||
| 	return strcoll(*((char* const*) a), *((char* const*) b)); | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char **argv) { | ||||
| 	int i, j; | ||||
| 	int i, start; | ||||
| 	const char *filename; | ||||
| 	char **fnames; | ||||
| 	struct stat fstats; | ||||
| 	r_dir_t dir; | ||||
| 
 | ||||
| 	parse_options(argc, argv); | ||||
| 
 | ||||
| @ -121,18 +125,26 @@ int main(int argc, char **argv) { | ||||
| 	} else { | ||||
| 		for (i = 0; i < options->filecnt; ++i) { | ||||
| 			filename = options->filenames[i]; | ||||
| 			if (!stat(filename, &fstats) && S_ISDIR(fstats.st_mode)) { | ||||
| 				if (options->recursive && (fnames = read_dir_rec(filename))) { | ||||
| 					for (j = 0; fnames[j]; ++j) { | ||||
| 						if (!check_append(fnames[j])) | ||||
| 							free(fnames[j]); | ||||
| 					} | ||||
| 					free(fnames); | ||||
| 				} else { | ||||
| 					warn("ignoring directory: %s", filename); | ||||
| 				} | ||||
| 			} else { | ||||
| 
 | ||||
| 			if (stat(filename, &fstats) || !S_ISDIR(fstats.st_mode)) { | ||||
| 				check_append(filename); | ||||
| 			} else { | ||||
| 				if (!options->recursive) { | ||||
| 					warn("ignoring directory: %s", filename); | ||||
| 					continue; | ||||
| 				} | ||||
| 				if (r_opendir(&dir, filename)) { | ||||
| 					warn("could not open directory: %s", filename); | ||||
| 					continue; | ||||
| 				} | ||||
| 				start = fileidx; | ||||
| 				while ((filename = r_readdir(&dir))) { | ||||
| 					if (!check_append(filename)) | ||||
| 						free((void*) filename); | ||||
| 				} | ||||
| 				r_closedir(&dir); | ||||
| 				if (fileidx - start > 1) | ||||
| 					qsort(filenames + start, fileidx - start, sizeof(char*), fncmp); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
							
								
								
									
										178
									
								
								util.c
									
									
									
									
									
								
							
							
						
						
									
										178
									
								
								util.c
									
									
									
									
									
								
							| @ -18,7 +18,6 @@ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <dirent.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <unistd.h> | ||||
| @ -28,7 +27,6 @@ | ||||
| #include "util.h" | ||||
| 
 | ||||
| #define DNAME_CNT 512 | ||||
| #define FNAME_CNT 1024 | ||||
| #define FNAME_LEN 1024 | ||||
| 
 | ||||
| void cleanup(); | ||||
| @ -161,7 +159,105 @@ end: | ||||
| 	return path; | ||||
| } | ||||
| 
 | ||||
| int create_dir_rec(const char *path) { | ||||
| int r_opendir(r_dir_t *rdir, const char *dirname) { | ||||
| 	if (!rdir || !dirname || !*dirname) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	if (!(rdir->dir = opendir(dirname))) { | ||||
| 		rdir->name = NULL; | ||||
| 		rdir->stack = NULL; | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	rdir->stcap = DNAME_CNT; | ||||
| 	rdir->stack = (char**) s_malloc(rdir->stcap * sizeof(char*)); | ||||
| 	rdir->stlen = 0; | ||||
| 
 | ||||
| 	rdir->name = (char*) dirname; | ||||
| 	rdir->d = 0; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int r_closedir(r_dir_t *rdir) { | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	if (!rdir) | ||||
| 		return -1; | ||||
| 	 | ||||
| 	if (rdir->stack) { | ||||
| 		while (rdir->stlen > 0) | ||||
| 			free(rdir->stack[--rdir->stlen]); | ||||
| 		free(rdir->stack); | ||||
| 		rdir->stack = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (rdir->dir) { | ||||
| 		if (!(ret = closedir(rdir->dir))) | ||||
| 			rdir->dir = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (rdir->d && rdir->name) { | ||||
| 		free(rdir->name); | ||||
| 		rdir->name = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| char* r_readdir(r_dir_t *rdir) { | ||||
| 	size_t len; | ||||
| 	char *filename; | ||||
| 	struct dirent *dentry; | ||||
| 	struct stat fstats; | ||||
| 
 | ||||
| 	if (!rdir || !rdir->dir || !rdir->name) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	while (1) { | ||||
| 		if (rdir->dir && (dentry = readdir(rdir->dir))) { | ||||
| 			if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) | ||||
| 				continue; | ||||
| 
 | ||||
| 			len = strlen(rdir->name) + strlen(dentry->d_name) + 2; | ||||
| 			filename = (char*) s_malloc(len); | ||||
| 			snprintf(filename, len, "%s%s%s", rdir->name, | ||||
| 			         rdir->name[strlen(rdir->name)-1] == '/' ? "" : "/", | ||||
| 			         dentry->d_name); | ||||
| 
 | ||||
| 			if (!stat(filename, &fstats) && S_ISDIR(fstats.st_mode)) { | ||||
| 				/* put subdirectory on the stack */ | ||||
| 				if (rdir->stlen == rdir->stcap) { | ||||
| 					rdir->stcap *= 2; | ||||
| 					rdir->stack = (char**) s_realloc(rdir->stack, | ||||
| 					                                 rdir->stcap * sizeof(char*)); | ||||
| 				} | ||||
| 				rdir->stack[rdir->stlen++] = filename; | ||||
| 				continue; | ||||
| 			} | ||||
| 			return filename; | ||||
| 		} | ||||
| 		 | ||||
| 		if (rdir->stlen > 0) { | ||||
| 			/* open next subdirectory */ | ||||
| 			closedir(rdir->dir); | ||||
| 			if (rdir->d) | ||||
| 				free(rdir->name); | ||||
| 			rdir->name = rdir->stack[--rdir->stlen]; | ||||
| 			rdir->d = 1; | ||||
| 			if (!(rdir->dir = opendir(rdir->name))) | ||||
| 				warn("could not open directory: %s", rdir->name); | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		/* no more entries */ | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| int r_mkdir(const char *path) { | ||||
| 	char *dir, *d; | ||||
| 	struct stat stats; | ||||
| 	int err = 0; | ||||
| @ -202,82 +298,6 @@ int create_dir_rec(const char *path) { | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| int fncmp(const void *a, const void *b) { | ||||
| 	return strcoll(*((char* const*) a), *((char* const*) b)); | ||||
| } | ||||
| 
 | ||||
| char** read_dir_rec(const char *dirname) { | ||||
| 	int dcnt, didx, fcnt, fidx; | ||||
| 	char **dnames, **fnames, *filename; | ||||
| 	unsigned char first; | ||||
| 	size_t len; | ||||
| 	DIR *dir; | ||||
| 	struct dirent *dentry; | ||||
| 	struct stat fstats; | ||||
| 
 | ||||
| 	if (!dirname) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	dcnt = DNAME_CNT; | ||||
| 	didx = first = 1; | ||||
| 	dnames = (char**) s_malloc(dcnt * sizeof(char*)); | ||||
| 	dnames[0] = (char*) dirname; | ||||
| 
 | ||||
| 	fcnt = FNAME_CNT; | ||||
| 	fidx = 0; | ||||
| 	fnames = (char**) s_malloc(fcnt * sizeof(char*)); | ||||
| 
 | ||||
| 	while (didx > 0) { | ||||
| 		dirname = dnames[--didx]; | ||||
| 		if (!(dir = opendir(dirname))) { | ||||
| 			warn("could not open directory: %s", dirname); | ||||
| 		} else { | ||||
| 			while ((dentry = readdir(dir))) { | ||||
| 				if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, "..")) | ||||
| 					continue; | ||||
| 
 | ||||
| 				len = strlen(dirname) + strlen(dentry->d_name) + 2; | ||||
| 				filename = (char*) s_malloc(len * sizeof(char)); | ||||
| 				snprintf(filename, len, "%s%s%s", dirname, | ||||
| 				         dirname[strlen(dirname)-1] == '/' ? "" : "/", dentry->d_name); | ||||
| 
 | ||||
| 				if (!stat(filename, &fstats) && S_ISDIR(fstats.st_mode)) { | ||||
| 					if (didx == dcnt) { | ||||
| 						dcnt *= 2; | ||||
| 						dnames = (char**) s_realloc(dnames, dcnt * sizeof(char*)); | ||||
| 					} | ||||
| 					dnames[didx++] = filename; | ||||
| 				} else { | ||||
| 					if (fidx + 1 == fcnt) { | ||||
| 						fcnt *= 2; | ||||
| 						fnames = (char**) s_realloc(fnames, fcnt * sizeof(char*)); | ||||
| 					} | ||||
| 					fnames[fidx++] = filename; | ||||
| 				} | ||||
| 			} | ||||
| 			closedir(dir); | ||||
| 		} | ||||
| 
 | ||||
| 		if (!first) | ||||
| 			free((void*) dirname); | ||||
| 		else | ||||
| 			first = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!fidx) { | ||||
| 		free(fnames); | ||||
| 		fnames = NULL; | ||||
| 	} else { | ||||
| 		if (fidx > 1) | ||||
| 			qsort(fnames, fidx, sizeof(char*), fncmp); | ||||
| 		fnames[fidx] = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	free(dnames); | ||||
| 
 | ||||
| 	return fnames; | ||||
| } | ||||
| 
 | ||||
| char* readline(FILE *stream) { | ||||
| 	size_t len; | ||||
| 	char *buf, *s, *end; | ||||
|  | ||||
							
								
								
									
										17
									
								
								util.h
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								util.h
									
									
									
									
									
								
							| @ -21,6 +21,7 @@ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <dirent.h> | ||||
| 
 | ||||
| #define ABS(a)   ((a) < 0 ? (-(a)) : (a)) | ||||
| #define MIN(a,b) ((a) < (b) ? (a) : (b)) | ||||
| @ -35,6 +36,16 @@ | ||||
| 		(tv)->tv_usec = (ts)->tv_nsec / 1000;  \ | ||||
| } | ||||
| 
 | ||||
| typedef struct { | ||||
| 	DIR *dir; | ||||
| 	char *name; | ||||
| 	int d; | ||||
| 
 | ||||
| 	char **stack; | ||||
| 	int stcap; | ||||
| 	int stlen; | ||||
| } r_dir_t; | ||||
| 
 | ||||
| void* s_malloc(size_t); | ||||
| void* s_realloc(void*, size_t); | ||||
| 
 | ||||
| @ -45,8 +56,10 @@ void size_readable(float*, const char**); | ||||
| 
 | ||||
| char* absolute_path(const char*); | ||||
| 
 | ||||
| int create_dir_rec(const char*); | ||||
| char** read_dir_rec(const char*); | ||||
| int r_opendir(r_dir_t*, const char*); | ||||
| int r_closedir(r_dir_t*); | ||||
| char* r_readdir(r_dir_t*); | ||||
| int r_mkdir(const char *); | ||||
| 
 | ||||
| char* readline(FILE*); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Bert
						Bert