]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - misc-utils/namei.c
1 /*-------------------------------------------------------------
10 Modifications by Steve Tell March 28, 1991
12 usage: namei pathname [pathname ... ]
14 This program reads it's arguments as pathnames to any type
15 of Unix file (symlinks, files, directories, and so forth).
16 The program then follows each pathname until a terminal
17 point is found (a file, directory, char device, etc).
18 If it finds a symbolic link, we show the link, and start
19 following it, indenting the output to show the context.
21 This program is useful for finding a "too many levels of
22 symbolic links" problems.
24 For each line output, the program puts a file type first:
26 f: = the pathname we are currently trying to resolve
28 D = directory that is a mount point
29 l = symbolic link (both the link and it's contents are output)
35 ? = an error of some kind
37 The program prints an informative messages when we exceed
38 the maximum number of symbolic links this system can have.
40 The program exits with a 1 status ONLY if it finds it cannot
41 chdir to /, or if it encounters an unknown file type.
43 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
44 - added Native Language Support
46 2006-12-15 Karel Zak <kzak@redhat.com>
47 - fixed logic; don't follow the path if a component is not directory
48 - fixed infinite loop of symbolic links; stack size is very limited
50 2007-09-10 Li Zefan <lizf@cn.fujitsu.com>
51 - added to identify FIFO
53 -------------------------------------------------------------*/
61 #include <sys/types.h>
63 #include <sys/param.h>
66 #define ERR strerror(errno),errno
73 #define MAXSYMLINKS 256
76 static char *pperm(unsigned short);
77 static void namei(char *, int, mode_t
*);
78 static void usage(void);
81 main(int argc
, char **argv
) {
84 char curdir
[MAXPATHLEN
];
86 setlocale(LC_ALL
, "");
87 bindtextdomain(PACKAGE
, LOCALEDIR
);
93 while((c
= getopt(argc
, argv
, "mx")) != -1){
109 if(getcwd(curdir
, sizeof(curdir
)) == NULL
){
110 (void)fprintf(stderr
,
111 _("namei: unable to get current directory - %s\n"),
117 for(; optind
< argc
; optind
++){
119 (void)printf("f: %s\n", argv
[optind
]);
121 namei(argv
[optind
], 0, &lastmode
);
123 if(chdir(curdir
) == -1){
124 (void)fprintf(stderr
,
125 _("namei: unable to chdir to %s - %s (%d)\n"),
135 (void)fprintf(stderr
,_("usage: namei [-mx] pathname [pathname ...]\n"));
140 #define NODEV (dev_t)(-1)
146 namei(char *file
, int lev
, mode_t
*lastmode
) {
148 char buf
[BUFSIZ
], sym
[BUFSIZ
];
151 dev_t lastdev
= NODEV
;
154 * See if the file has a leading /, and if so cd to root
157 if(file
&& *file
== '/'){
161 if(chdir("/") == -1){
162 (void)fprintf(stderr
,_("namei: could not chdir to root!\n"));
165 for(i
= 0; i
< lev
; i
++)
168 if(stat("/", &stb
) == -1){
169 (void)fprintf(stderr
, _("namei: could not stat root!\n"));
172 lastdev
= stb
.st_dev
;
175 (void)printf(" d%s /\n", pperm(stb
.st_mode
));
177 (void)printf(" d /\n");
180 for(; file
&& *file
;){
182 if (strlen(file
) >= BUFSIZ
) {
183 fprintf(stderr
,_("namei: buf overflow\n"));
188 * Copy up to the next / (or nil) into buf
191 for(cp
= buf
; *file
!= '\0' && *file
!= '/'; cp
++, file
++)
194 while(*file
== '/') /* eat extra /'s */
202 * Buf is empty, so therefore we are done
203 * with this level of file
209 for(i
= 0; i
< lev
; i
++)
214 * We cannot walk on *path* if a previous element, in the path wasn't
215 * directory, because there could be a component with same name. Try:
218 * $ namei a/b <-- "a" is not directory so namei shouldn't
221 if (*lastmode
&& S_ISDIR(*lastmode
)==0 && S_ISLNK(*lastmode
)==0){
222 (void)printf(" ? %s - %s (%d)\n", buf
, strerror(ENOENT
), ENOENT
);
227 * See what type of critter this file is
230 if(lstat(buf
, &stb
) == -1){
231 (void)printf(" ? %s - %s (%d)\n", buf
, ERR
);
235 *lastmode
= stb
.st_mode
;
237 switch(stb
.st_mode
& S_IFMT
){
241 * File is a directory, chdir to it
244 if(chdir(buf
) == -1){
245 (void)printf(_(" ? could not chdir into %s - %s (%d)\n"), buf
, ERR
);
248 if(xflag
&& lastdev
!= stb
.st_dev
&& lastdev
!= NODEV
){
249 /* Across mnt point */
251 (void)printf(" D%s %s\n", pperm(stb
.st_mode
), buf
);
253 (void)printf(" D %s\n", buf
);
257 (void)printf(" d%s %s\n", pperm(stb
.st_mode
), buf
);
259 (void)printf(" d %s\n", buf
);
261 lastdev
= stb
.st_dev
;
263 (void)fflush(stdout
);
268 * Sigh, another symlink. Read its contents and
272 if(readlink(buf
, sym
, BUFSIZ
) == -1){
273 (void)printf(_(" ? problems reading symlink %s - %s (%d)\n"), buf
, ERR
);
278 (void)printf(" l%s %s -> %s", pperm(stb
.st_mode
), buf
, sym
);
280 (void)printf(" l %s -> %s", buf
, sym
);
282 if(symcount
> 0 && symcount
++ > MAXSYMLINKS
){
283 (void)printf(_(" *** EXCEEDED UNIX LIMIT OF SYMLINKS ***\n"));
286 namei(sym
, lev
+ 1, lastmode
);
288 if (symcount
> MAXSYMLINKS
)
294 (void)printf(" c%s %s\n", pperm(stb
.st_mode
), buf
);
296 (void)printf(" c %s\n", buf
);
301 (void)printf(" b%s %s\n", pperm(stb
.st_mode
), buf
);
303 (void)printf(" b %s\n", buf
);
308 (void)printf(" s%s %s\n", pperm(stb
.st_mode
), buf
);
310 (void)printf(" s %s\n", buf
);
315 printf(" p%s %s\n", pperm(stb
.st_mode
), buf
);
317 printf(" p %s\n", buf
);
322 (void)printf(" -%s %s\n", pperm(stb
.st_mode
), buf
);
324 (void)printf(" - %s\n", buf
);
328 (void)fprintf(stderr
,_("namei: unknown file type 0%06o on file %s\n"), stb
.st_mode
, buf
);
336 * Mode word, as from a struct stat, and return
337 * a pointer to a static string containing a printable version like ls.
338 * For example 0755 produces "rwxr-xr-x"
341 pperm(unsigned short mode
) {
345 char *lschars
= "xwrxwrxwr"; /* the complete string backwards */
349 for(i
= 0, cp
= lschars
, m
= mode
, bp
= &buf
[8];
351 i
++, cp
++, m
>>= 1, bp
--) {