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