readlink: add -m and -f flags
This commit is contained in:
		
				
					committed by
					
						 sin
						sin
					
				
			
			
				
	
			
			
			
						parent
						
							0fcad66c75
						
					
				
				
					commit
					28e26bc688
				
			
							
								
								
									
										68
									
								
								readlink.c
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								readlink.c
									
									
									
									
									
								
							| @@ -5,6 +5,7 @@ | |||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
|  | #include <sys/stat.h> | ||||||
|  |  | ||||||
| #include "util.h" | #include "util.h" | ||||||
|  |  | ||||||
| @@ -17,17 +18,18 @@ usage(void) | |||||||
| int | int | ||||||
| main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||||
| { | { | ||||||
| 	char buf[PATH_MAX]; | 	char buf1[PATH_MAX], buf2[PATH_MAX], arg[PATH_MAX]; | ||||||
| 	int nflag = 0; | 	int nflag = 0; | ||||||
| 	int fflag = 0; | 	int mefflag = 0; | ||||||
| 	ssize_t n; | 	ssize_t n; | ||||||
|  | 	struct stat st; | ||||||
|  | 	char *p = arg, *lp = NULL, *b = buf1; | ||||||
|  |  | ||||||
| 	ARGBEGIN { | 	ARGBEGIN { | ||||||
| 	case 'e': |  | ||||||
| 	case 'm': | 	case 'm': | ||||||
| 		eprintf("not implemented\n"); | 	case 'e': | ||||||
| 	case 'f': | 	case 'f': | ||||||
| 		fflag = 1; | 		mefflag = ARGC(); | ||||||
| 		break; | 		break; | ||||||
| 	case 'n': | 	case 'n': | ||||||
| 		nflag = 1; | 		nflag = 1; | ||||||
| @@ -42,16 +44,54 @@ main(int argc, char *argv[]) | |||||||
| 	if (strlen(argv[0]) > PATH_MAX - 1) | 	if (strlen(argv[0]) > PATH_MAX - 1) | ||||||
| 		eprintf("path too long\n"); | 		eprintf("path too long\n"); | ||||||
|  |  | ||||||
| 	if (fflag) { | #define SWAP_BUF() (b = (b == buf1 ? buf2 : buf1)); | ||||||
| 		if (!realpath(argv[0], buf)) | 	switch (mefflag) { | ||||||
| 			exit(1); | 		case 'm': | ||||||
| 	} else { | 			if (argv[0][0] == '/') { /* case when path is on '/' */ | ||||||
| 		if ((n = readlink(argv[0], buf, sizeof(buf) - 1)) < 0) | 				arg[0] = '/'; | ||||||
| 			exit(1); | 				arg[1] = '\0'; | ||||||
| 		buf[n] = '\0'; | 				p++; | ||||||
|  | 			} else if (!strchr(argv[0], '/')) { /* relative path */ | ||||||
|  | 				arg[0] = '.'; | ||||||
|  | 				arg[1] = '/'; | ||||||
|  | 				arg[2] = '\0'; | ||||||
|  | 			} else | ||||||
|  | 				arg[0] = '\0'; | ||||||
|  | 			strncat(arg, argv[0], PATH_MAX); | ||||||
|  | 			while ((p = strchr(p, '/'))) { | ||||||
|  | 				*p = '\0'; | ||||||
|  | 				if (!realpath(arg, b)) { | ||||||
|  | 					*p = '/'; | ||||||
|  | 					goto mdone; | ||||||
| 				} | 				} | ||||||
|  | 				SWAP_BUF(); | ||||||
| 	printf("%s", buf); | 				lp = p; | ||||||
|  | 				*p++ = '/'; | ||||||
|  | 			} | ||||||
|  | 			if (!realpath(arg, b)) { | ||||||
|  | mdone: | ||||||
|  | 				SWAP_BUF(); | ||||||
|  | 				if (lp) { | ||||||
|  | 					/* drop the extra '/' on root */ | ||||||
|  | 					lp += (argv[0][0] == '/' && | ||||||
|  | 					       lp - arg == 1); | ||||||
|  | 					strncat(b, lp, PATH_MAX); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			break; | ||||||
|  | 		case 'e': | ||||||
|  | 			if (stat(argv[0], &st) < 0) | ||||||
|  | 				exit(1); | ||||||
|  | 		case 'f': | ||||||
|  | 			if (!realpath(argv[0], b)) | ||||||
|  | 				exit(1); | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			if ((n = readlink(argv[0], b, PATH_MAX - 1)) < 0) | ||||||
|  | 				exit(1); | ||||||
|  | 			b[n] = '\0'; | ||||||
|  | 	} | ||||||
|  | 	printf("%s", b); | ||||||
| 	if (!nflag) | 	if (!nflag) | ||||||
| 		putchar('\n'); | 		putchar('\n'); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user