1e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define _FILE_OFFSET_BITS 64 2e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define _LARGEFILE_SOURCE 3e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define _LARGEFILE64_SOURCE 4e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 5e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <unistd.h> 6e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef _POSIX_SOURCE 7e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define _POSIX_SOURCE 8e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 9e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <stdio.h> 10e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <stdlib.h> 11e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef HAVE_MALLOC_H 12e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <malloc.h> 13e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 14e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <string.h> 15e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <fcntl.h> 16e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/param.h> 17e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/types.h> 18e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/stat.h> 19e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <dirent.h> 20e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <time.h> 21e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <stddef.h> 22e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <errno.h> 23e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 24e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef S_ISLNK 25e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define S_ISLNK(mode) (((mode) & (_S_IFMT)) == (_S_IFLNK)) 26e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 27e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 28e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifndef PATH_MAX 29e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define PATH_MAX 1024 30e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 31e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 32e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define progver "%s: scan/change symbolic links - v1.3 - by Mark Lord\n\n" 33e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic char *progname; 34e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int verbose = 0, fix_links = 0, recurse = 0, delete = 0, shorten = 0, 35e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall testing = 0, single_fs = 1; 36e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 37e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 38e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * tidypath removes excess slashes and "." references from a path string 39e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 40e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int substr (char *s, char *old, char *new) 42e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 43e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *tmp = NULL; 44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int oldlen = strlen(old), newlen = 0; 45e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 46e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (NULL == strstr(s, old)) 47e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 48e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 49e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (new) 50e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall newlen = strlen(new); 51e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 52e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (newlen > oldlen) { 53e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((tmp = malloc(strlen(s))) == NULL) { 54e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, "no memory\n"); 55e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall exit (1); 56e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 57e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 58e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (NULL != (s = strstr(s, old))) { 60e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *p, *old_s = s; 61e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 62e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (new) { 63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (newlen > oldlen) 64e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall old_s = strcpy(tmp, s); 65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall p = new; 66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (*p) 67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *s++ = *p++; 68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 69e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall p = old_s + oldlen; 70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while ((*s++ = *p++)); 71e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 72e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (tmp) 73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free(tmp); 74e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 1; 75e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 76e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 77e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 78e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int tidy_path (char *path) 79e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int tidied = 0; 81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *s, *p; 82e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 83e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall s = path + strlen(path) - 1; 84e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (s[0] != '/') { /* tmp trailing slash simplifies things */ 85e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall s[1] = '/'; 86e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall s[2] = '\0'; 87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 88e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (substr(path, "/./", "/")) 89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall tidied = 1; 90e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (substr(path, "//", "/")) 91e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall tidied = 1; 92e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 93e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while ((p = strstr(path,"/../")) != NULL) { 94e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall s = p+3; 95e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (p--; p != path; p--) if (*p == '/') break; 96e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*p != '/') 97e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 98e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while ((*p++ = *s++)); 99e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall tidied = 1; 100e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*path == '\0') 102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strcpy(path,"/"); 103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall p = path + strlen(path) - 1; 104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (p != path && *p == '/') 105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *p-- = '\0'; /* remove tmp trailing slash */ 106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (p != path && *p == '/') { /* remove any others */ 107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *p-- = '\0'; 108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall tidied = 1; 109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (!strncmp(path,"./",2)) { 111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (p = path, s = path+2; (*p++ = *s++);); 112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall tidied = 1; 113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 114e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return tidied; 115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int shorten_path (char *path, char *abspath) 118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 119e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall static char dir[PATH_MAX]; 120e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int shortened = 0; 121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *p; 122e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 123e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* get rid of unnecessary "../dir" sequences */ 124e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (abspath && strlen(abspath) > 1 && (p = strstr(path,"../"))) { 125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* find innermost occurance of "../dir", and save "dir" */ 126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int slashes = 2; 127e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *a, *s, *d = dir; 128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while ((s = strstr(p+3, "../"))) { 129e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ++slashes; 130e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall p = s; 131e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 132e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall s = p+3; 133e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *d++ = '/'; 134e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (*s && *s != '/') 135e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *d++ = *s++; 136e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *d++ = '/'; 137e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *d = '\0'; 138e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!strcmp(dir,"//")) 139e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* note: p still points at ../dir */ 141e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*s != '/' || !*++s) 142e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 143e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall a = abspath + strlen(abspath) - 1; 144e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (slashes-- > 0) { 145e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (a <= abspath) 146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto ughh; 147e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (*--a != '/') { 148e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (a <= abspath) 149e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto ughh; 150e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 151e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 152e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (strncmp(dir, a, strlen(dir))) 153e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 154e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while ((*p++ = *s++)); /* delete the ../dir */ 155e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall shortened = 1; 156e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 157e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallughh: 158e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return shortened; 159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 161e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 162e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void fix_symlink (char *path, dev_t my_dev) 163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 164e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall static char lpath[PATH_MAX], new[PATH_MAX], abspath[PATH_MAX]; 165e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *p, *np, *lp, *tail, *msg; 166e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct stat stbuf, lstbuf; 167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int c, fix_abs = 0, fix_messy = 0, fix_long = 0; 168e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((c = readlink(path, lpath, sizeof(lpath))) == -1) { 170e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror(path); 171e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall lpath[c] = '\0'; /* readlink does not null terminate it */ 174e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* construct the absolute address of the link */ 176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall abspath[0] = '\0'; 177e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (lpath[0] != '/') { 178e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strcat(abspath,path); 179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall c = strlen(abspath); 180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((c > 0) && (abspath[c-1] == '/')) 181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall abspath[c-1] = '\0'; /* cut trailing / */ 182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((p = strrchr(abspath,'/')) != NULL) 183e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *p = '\0'; /* cut last component */ 184e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strcat(abspath,"/"); 185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 186e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strcat(abspath,lpath); 187e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (void) tidy_path(abspath); 188e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 189e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* check for various things */ 190e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (stat(abspath, &stbuf) == -1) { 191e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("dangling: %s -> %s\n", path, lpath); 192e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (delete) { 193e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (unlink (path)) { 194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror(path); 195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else 196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("deleted: %s -> %s\n", path, lpath); 197e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 198e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 199e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 200e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 201e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (single_fs) 202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall lstat(abspath, &lstbuf); /* if the above didn't fail, then this shouldn't */ 203e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (single_fs && lstbuf.st_dev != my_dev) { 205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall msg = "other_fs:"; 206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (lpath[0] == '/') { 207e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall msg = "absolute:"; 208e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fix_abs = 1; 209e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (verbose) { 210e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall msg = "relative:"; 211e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else 212e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall msg = NULL; 213e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fix_messy = tidy_path(strcpy(new,lpath)); 214e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (shorten) 215e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fix_long = shorten_path(new, path); 216e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!fix_abs) { 217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fix_messy) 218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall msg = "messy: "; 219e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (fix_long) 220e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall msg = "lengthy: "; 221e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (msg != NULL) 223e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("%s %s -> %s\n", msg, path, lpath); 224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!(fix_links || testing) || !(fix_messy || fix_abs || fix_long)) 225e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 226e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 227e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fix_abs) { 228e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* convert an absolute link to relative: */ 229e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* point tail at first part of lpath that differs from path */ 230e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* point p at first part of path that differs from lpath */ 231e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (void) tidy_path(lpath); 232e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall tail = lp = lpath; 233e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall p = path; 234e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (*p && (*p == *lp)) { 235e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*lp++ == '/') { 236e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall tail = lp; 237e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (*++p == '/'); 238e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* now create new, with "../"s followed by tail */ 242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall np = new; 243e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (*p) { 244e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*p++ == '/') { 245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *np++ = '.'; 246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *np++ = '.'; 247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *np++ = '/'; 248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (*p == '/') ++p; 249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 251e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strcpy (np, tail); 252e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (void) tidy_path(new); 253e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (shorten) (void) shorten_path(new, path); 254e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 255e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall shorten_path(new,path); 256e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!testing) { 257e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (unlink (path)) { 258e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror(path); 259e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 260e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (symlink(new, path)) { 262e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror(path); 263e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 264e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("changed: %s -> %s\n", path, new); 267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 268e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 269e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void dirwalk (char *path, int pathlen, dev_t dev) 270e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 271e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *name; 272e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall DIR *dfd; 273e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall static struct stat st; 274e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall static struct dirent *dp; 275e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 276e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((dfd = opendir(path)) == NULL) { 277e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror(path); 278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 279e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 280e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 281e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall name = path + pathlen; 282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*(name-1) != '/') 283e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *name++ = '/'; 284e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 285e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while ((dp = readdir(dfd)) != NULL ) { 286e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strcpy(name, dp->d_name); 287e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (strcmp(name, ".") && strcmp(name,"..")) { 288e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (lstat(path, &st) == -1) { 289e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror(path); 290e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (st.st_dev == dev) { 291e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (S_ISLNK(st.st_mode)) { 292e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fix_symlink (path, dev); 293e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (recurse && S_ISDIR(st.st_mode)) { 294e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dirwalk(path, strlen(path), dev); 295e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 296e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 298e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 299e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall closedir(dfd); 300e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall path[pathlen] = '\0'; 301e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 303e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void usage_error (void) 304e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 305e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, progver, progname); 306e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, "Usage:\t%s [-cdorstv] LINK|DIR ...\n\n", progname); 307e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, "Flags:" 308e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "\t-c == change absolute/messy links to relative\n" 309e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "\t-d == delete dangling links\n" 310e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "\t-o == warn about links across file systems\n" 311e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "\t-r == recurse into subdirs\n" 312e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "\t-s == shorten lengthy links (displayed in output only when -c not specified)\n" 313e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "\t-t == show what would be done by -c\n" 314e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "\t-v == verbose (show all symlinks)\n\n"); 315e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall exit(1); 316e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 317e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 318e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallint main(int argc, char **argv) 319e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 320e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#if defined (_GNU_SOURCE) && defined (__GLIBC__) 321e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall static char path[PATH_MAX+2]; 322e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char* cwd = get_current_dir_name(); 323e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#else 324e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall static char path[PATH_MAX+2], cwd[PATH_MAX+2]; 325e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 326e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int dircount = 0; 327e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char c, *p; 328e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 329e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((progname = (char *) strrchr(*argv, '/')) == NULL) 330e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall progname = *argv; 331e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 332e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall progname++; 333e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 334e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#if defined (_GNU_SOURCE) && defined (__GLIBC__) 335e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (NULL == cwd) { 336e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr,"get_current_dir_name() failed\n"); 337e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#else 338e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (NULL == getcwd(cwd,PATH_MAX)) { 339e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr,"getcwd() failed\n"); 340e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 341e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall exit (1); 342e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 343e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#if defined (_GNU_SOURCE) && defined (__GLIBC__) 344e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall cwd = realloc(cwd, strlen(cwd)+2); 345e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (cwd == NULL) { 346e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, "realloc() failed\n"); 347e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall exit (1); 348e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 349e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 350e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!*cwd || cwd[strlen(cwd)-1] != '/') 351e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strcat(cwd,"/"); 352e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 353e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (--argc) { 354e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall p = *++argv; 355e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*p == '-') { 356e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*++p == '\0') 357e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall usage_error(); 358e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while ((c = *p++)) { 359e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (c == 'c') fix_links = 1; 360e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (c == 'd') delete = 1; 361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (c == 'o') single_fs = 0; 362e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (c == 'r') recurse = 1; 363e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (c == 's') shorten = 1; 364e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (c == 't') testing = 1; 365e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (c == 'v') verbose = 1; 366e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else usage_error(); 367e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 368e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 369e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct stat st; 370e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*p == '/') 371e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *path = '\0'; 372e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 373e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strcpy(path,cwd); 374e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall tidy_path(strcat(path, p)); 375e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (lstat(path, &st) == -1) 376e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall perror(path); 377e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (S_ISLNK(st.st_mode)) 378e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fix_symlink(path, st.st_dev); 379e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 380e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dirwalk(path, strlen(path), st.st_dev); 381e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ++dircount; 382e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 383e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 384e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (dircount == 0) 385e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall usage_error(); 386e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall exit (0); 387e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 388