1327e51cbSPeter Avalos /*
2327e51cbSPeter Avalos * Copyright (c) Ian F. Darwin 1986-1995.
3327e51cbSPeter Avalos * Software written by Ian F. Darwin and others;
4327e51cbSPeter Avalos * maintained 1995-present by Christos Zoulas and others.
5327e51cbSPeter Avalos *
6327e51cbSPeter Avalos * Redistribution and use in source and binary forms, with or without
7327e51cbSPeter Avalos * modification, are permitted provided that the following conditions
8327e51cbSPeter Avalos * are met:
9327e51cbSPeter Avalos * 1. Redistributions of source code must retain the above copyright
10327e51cbSPeter Avalos * notice immediately at the beginning of the file, without modification,
11327e51cbSPeter Avalos * this list of conditions, and the following disclaimer.
12327e51cbSPeter Avalos * 2. Redistributions in binary form must reproduce the above copyright
13327e51cbSPeter Avalos * notice, this list of conditions and the following disclaimer in the
14327e51cbSPeter Avalos * documentation and/or other materials provided with the distribution.
15327e51cbSPeter Avalos *
16327e51cbSPeter Avalos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17327e51cbSPeter Avalos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18327e51cbSPeter Avalos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19327e51cbSPeter Avalos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20327e51cbSPeter Avalos * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21327e51cbSPeter Avalos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22327e51cbSPeter Avalos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23327e51cbSPeter Avalos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24327e51cbSPeter Avalos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25327e51cbSPeter Avalos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26327e51cbSPeter Avalos * SUCH DAMAGE.
27327e51cbSPeter Avalos */
28327e51cbSPeter Avalos /*
29327e51cbSPeter Avalos * fsmagic - magic based on filesystem info - directory, special files, etc.
30327e51cbSPeter Avalos */
31327e51cbSPeter Avalos
32327e51cbSPeter Avalos #include "file.h"
3379343712SPeter Avalos
3479343712SPeter Avalos #ifndef lint
35*3b9cdfa3SAntonio Huete Jimenez FILE_RCSID("@(#)$File: fsmagic.c,v 1.82 2022/04/11 18:14:41 christos Exp $")
3679343712SPeter Avalos #endif /* lint */
3779343712SPeter Avalos
38327e51cbSPeter Avalos #include "magic.h"
39327e51cbSPeter Avalos #include <string.h>
40327e51cbSPeter Avalos #ifdef HAVE_UNISTD_H
41327e51cbSPeter Avalos #include <unistd.h>
42327e51cbSPeter Avalos #endif
43327e51cbSPeter Avalos #include <stdlib.h>
44327e51cbSPeter Avalos /* Since major is a function on SVR4, we cannot use `ifndef major'. */
45327e51cbSPeter Avalos #ifdef MAJOR_IN_MKDEV
46327e51cbSPeter Avalos # include <sys/mkdev.h>
47327e51cbSPeter Avalos # define HAVE_MAJOR
48327e51cbSPeter Avalos #endif
496fca56fbSSascha Wildner #ifdef HAVE_SYS_SYSMACROS_H
50327e51cbSPeter Avalos # include <sys/sysmacros.h>
516fca56fbSSascha Wildner #endif
526fca56fbSSascha Wildner #ifdef MAJOR_IN_SYSMACROS
53327e51cbSPeter Avalos # define HAVE_MAJOR
54327e51cbSPeter Avalos #endif
556fca56fbSSascha Wildner #if defined(major) && !defined(HAVE_MAJOR)
566fca56fbSSascha Wildner /* Might be defined in sys/types.h. */
57327e51cbSPeter Avalos # define HAVE_MAJOR
58327e51cbSPeter Avalos #endif
5982c5fa3eSPeter Avalos #ifdef WIN32
6082c5fa3eSPeter Avalos # define WIN32_LEAN_AND_MEAN
6182c5fa3eSPeter Avalos # include <windows.h>
6282c5fa3eSPeter Avalos #endif
63327e51cbSPeter Avalos
64327e51cbSPeter Avalos #ifndef HAVE_MAJOR
65327e51cbSPeter Avalos # define major(dev) (((dev) >> 8) & 0xff)
66327e51cbSPeter Avalos # define minor(dev) ((dev) & 0xff)
67327e51cbSPeter Avalos #endif
68327e51cbSPeter Avalos #undef HAVE_MAJOR
69e4d4ce0cSPeter Avalos #ifdef S_IFLNK
7079343712SPeter Avalos private int
bad_link(struct magic_set * ms,int err,char * buf)7179343712SPeter Avalos bad_link(struct magic_set *ms, int err, char *buf)
7279343712SPeter Avalos {
7379343712SPeter Avalos int mime = ms->flags & MAGIC_MIME;
7479343712SPeter Avalos if ((mime & MAGIC_MIME_TYPE) &&
75a96e001bSPeter Avalos file_printf(ms, "inode/symlink")
7679343712SPeter Avalos == -1)
7779343712SPeter Avalos return -1;
7879343712SPeter Avalos else if (!mime) {
7979343712SPeter Avalos if (ms->flags & MAGIC_ERROR) {
80a96e001bSPeter Avalos file_error(ms, err,
8182c5fa3eSPeter Avalos "broken symbolic link to %s", buf);
8279343712SPeter Avalos return -1;
8379343712SPeter Avalos }
8482c5fa3eSPeter Avalos if (file_printf(ms, "broken symbolic link to %s", buf) == -1)
8579343712SPeter Avalos return -1;
8679343712SPeter Avalos }
8779343712SPeter Avalos return 1;
8879343712SPeter Avalos }
89e4d4ce0cSPeter Avalos #endif
9079343712SPeter Avalos private int
handle_mime(struct magic_set * ms,int mime,const char * str)9179343712SPeter Avalos handle_mime(struct magic_set *ms, int mime, const char *str)
9279343712SPeter Avalos {
9379343712SPeter Avalos if ((mime & MAGIC_MIME_TYPE)) {
94a96e001bSPeter Avalos if (file_printf(ms, "inode/%s", str) == -1)
9579343712SPeter Avalos return -1;
9679343712SPeter Avalos if ((mime & MAGIC_MIME_ENCODING) && file_printf(ms,
9779343712SPeter Avalos "; charset=") == -1)
9879343712SPeter Avalos return -1;
9979343712SPeter Avalos }
10079343712SPeter Avalos if ((mime & MAGIC_MIME_ENCODING) && file_printf(ms, "binary") == -1)
10179343712SPeter Avalos return -1;
10279343712SPeter Avalos return 0;
10379343712SPeter Avalos }
104327e51cbSPeter Avalos
105327e51cbSPeter Avalos protected int
file_fsmagic(struct magic_set * ms,const char * fn,struct stat * sb)106327e51cbSPeter Avalos file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
107327e51cbSPeter Avalos {
108e8af9738SPeter Avalos int ret, did = 0;
109327e51cbSPeter Avalos int mime = ms->flags & MAGIC_MIME;
110c30bd091SSascha Wildner int silent = ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION);
111327e51cbSPeter Avalos #ifdef S_IFLNK
112327e51cbSPeter Avalos char buf[BUFSIZ+4];
113f72f8299SJan Lentfer ssize_t nch;
114327e51cbSPeter Avalos struct stat tstatbuf;
115327e51cbSPeter Avalos #endif
116327e51cbSPeter Avalos
117327e51cbSPeter Avalos if (fn == NULL)
118327e51cbSPeter Avalos return 0;
119327e51cbSPeter Avalos
120e8af9738SPeter Avalos #define COMMA (did++ ? ", " : "")
121327e51cbSPeter Avalos /*
122327e51cbSPeter Avalos * Fstat is cheaper but fails for files you don't have read perms on.
123327e51cbSPeter Avalos * On 4.2BSD and similar systems, use lstat() to identify symlinks.
124327e51cbSPeter Avalos */
125327e51cbSPeter Avalos #ifdef S_IFLNK
126327e51cbSPeter Avalos if ((ms->flags & MAGIC_SYMLINK) == 0)
127327e51cbSPeter Avalos ret = lstat(fn, sb);
128327e51cbSPeter Avalos else
129327e51cbSPeter Avalos #endif
130327e51cbSPeter Avalos ret = stat(fn, sb); /* don't merge into if; see "ret =" above */
131327e51cbSPeter Avalos
13282c5fa3eSPeter Avalos #ifdef WIN32
13382c5fa3eSPeter Avalos {
13482c5fa3eSPeter Avalos HANDLE hFile = CreateFile((LPCSTR)fn, 0, FILE_SHARE_DELETE |
13582c5fa3eSPeter Avalos FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0,
13682c5fa3eSPeter Avalos NULL);
13782c5fa3eSPeter Avalos if (hFile != INVALID_HANDLE_VALUE) {
13882c5fa3eSPeter Avalos /*
13982c5fa3eSPeter Avalos * Stat failed, but we can still open it - assume it's
14082c5fa3eSPeter Avalos * a block device, if nothing else.
14182c5fa3eSPeter Avalos */
14282c5fa3eSPeter Avalos if (ret) {
14382c5fa3eSPeter Avalos sb->st_mode = S_IFBLK;
14482c5fa3eSPeter Avalos ret = 0;
14582c5fa3eSPeter Avalos }
14682c5fa3eSPeter Avalos switch (GetFileType(hFile)) {
14782c5fa3eSPeter Avalos case FILE_TYPE_CHAR:
14882c5fa3eSPeter Avalos sb->st_mode |= S_IFCHR;
14982c5fa3eSPeter Avalos sb->st_mode &= ~S_IFREG;
15082c5fa3eSPeter Avalos break;
15182c5fa3eSPeter Avalos case FILE_TYPE_PIPE:
15282c5fa3eSPeter Avalos sb->st_mode |= S_IFIFO;
15382c5fa3eSPeter Avalos sb->st_mode &= ~S_IFREG;
15482c5fa3eSPeter Avalos break;
15582c5fa3eSPeter Avalos }
15682c5fa3eSPeter Avalos CloseHandle(hFile);
15782c5fa3eSPeter Avalos }
15882c5fa3eSPeter Avalos }
15982c5fa3eSPeter Avalos #endif
16082c5fa3eSPeter Avalos
161327e51cbSPeter Avalos if (ret) {
162327e51cbSPeter Avalos if (ms->flags & MAGIC_ERROR) {
163327e51cbSPeter Avalos file_error(ms, errno, "cannot stat `%s'", fn);
164327e51cbSPeter Avalos return -1;
165327e51cbSPeter Avalos }
166327e51cbSPeter Avalos if (file_printf(ms, "cannot open `%s' (%s)",
167327e51cbSPeter Avalos fn, strerror(errno)) == -1)
168327e51cbSPeter Avalos return -1;
169e8af9738SPeter Avalos return 0;
170327e51cbSPeter Avalos }
171327e51cbSPeter Avalos
172e8af9738SPeter Avalos ret = 1;
173c30bd091SSascha Wildner if (!mime && !silent) {
174327e51cbSPeter Avalos #ifdef S_ISUID
175327e51cbSPeter Avalos if (sb->st_mode & S_ISUID)
176e8af9738SPeter Avalos if (file_printf(ms, "%ssetuid", COMMA) == -1)
177327e51cbSPeter Avalos return -1;
178327e51cbSPeter Avalos #endif
179327e51cbSPeter Avalos #ifdef S_ISGID
180327e51cbSPeter Avalos if (sb->st_mode & S_ISGID)
181e8af9738SPeter Avalos if (file_printf(ms, "%ssetgid", COMMA) == -1)
182327e51cbSPeter Avalos return -1;
183327e51cbSPeter Avalos #endif
184327e51cbSPeter Avalos #ifdef S_ISVTX
185327e51cbSPeter Avalos if (sb->st_mode & S_ISVTX)
186e8af9738SPeter Avalos if (file_printf(ms, "%ssticky", COMMA) == -1)
187327e51cbSPeter Avalos return -1;
188327e51cbSPeter Avalos #endif
189327e51cbSPeter Avalos }
190327e51cbSPeter Avalos
191327e51cbSPeter Avalos switch (sb->st_mode & S_IFMT) {
192327e51cbSPeter Avalos case S_IFDIR:
19379343712SPeter Avalos if (mime) {
194a96e001bSPeter Avalos if (handle_mime(ms, mime, "directory") == -1)
19579343712SPeter Avalos return -1;
196c30bd091SSascha Wildner } else if (silent) {
197e8af9738SPeter Avalos } else if (file_printf(ms, "%sdirectory", COMMA) == -1)
198327e51cbSPeter Avalos return -1;
199e8af9738SPeter Avalos break;
200327e51cbSPeter Avalos #ifdef S_IFCHR
201327e51cbSPeter Avalos case S_IFCHR:
202327e51cbSPeter Avalos /*
203327e51cbSPeter Avalos * If -s has been specified, treat character special files
204327e51cbSPeter Avalos * like ordinary files. Otherwise, just report that they
205327e51cbSPeter Avalos * are block special files and go on to the next file.
206327e51cbSPeter Avalos */
207e8af9738SPeter Avalos if ((ms->flags & MAGIC_DEVICES) != 0) {
208e8af9738SPeter Avalos ret = 0;
209327e51cbSPeter Avalos break;
210e8af9738SPeter Avalos }
21179343712SPeter Avalos if (mime) {
212a96e001bSPeter Avalos if (handle_mime(ms, mime, "chardevice") == -1)
21379343712SPeter Avalos return -1;
214c30bd091SSascha Wildner } else if (silent) {
21579343712SPeter Avalos } else {
21682c5fa3eSPeter Avalos #ifdef HAVE_STRUCT_STAT_ST_RDEV
217327e51cbSPeter Avalos # ifdef dv_unit
218e8af9738SPeter Avalos if (file_printf(ms, "%scharacter special (%d/%d/%d)",
219e8af9738SPeter Avalos COMMA, major(sb->st_rdev), dv_unit(sb->st_rdev),
220327e51cbSPeter Avalos dv_subunit(sb->st_rdev)) == -1)
221327e51cbSPeter Avalos return -1;
222327e51cbSPeter Avalos # else
223e8af9738SPeter Avalos if (file_printf(ms, "%scharacter special (%ld/%ld)",
224e8af9738SPeter Avalos COMMA, (long)major(sb->st_rdev),
225e8af9738SPeter Avalos (long)minor(sb->st_rdev)) == -1)
226327e51cbSPeter Avalos return -1;
227327e51cbSPeter Avalos # endif
228327e51cbSPeter Avalos #else
229e8af9738SPeter Avalos if (file_printf(ms, "%scharacter special", COMMA) == -1)
230327e51cbSPeter Avalos return -1;
231327e51cbSPeter Avalos #endif
23279343712SPeter Avalos }
233e8af9738SPeter Avalos break;
234327e51cbSPeter Avalos #endif
235327e51cbSPeter Avalos #ifdef S_IFBLK
236327e51cbSPeter Avalos case S_IFBLK:
237327e51cbSPeter Avalos /*
238327e51cbSPeter Avalos * If -s has been specified, treat block special files
239327e51cbSPeter Avalos * like ordinary files. Otherwise, just report that they
240327e51cbSPeter Avalos * are block special files and go on to the next file.
241327e51cbSPeter Avalos */
242e8af9738SPeter Avalos if ((ms->flags & MAGIC_DEVICES) != 0) {
243e8af9738SPeter Avalos ret = 0;
244327e51cbSPeter Avalos break;
245e8af9738SPeter Avalos }
24679343712SPeter Avalos if (mime) {
247a96e001bSPeter Avalos if (handle_mime(ms, mime, "blockdevice") == -1)
24879343712SPeter Avalos return -1;
249c30bd091SSascha Wildner } else if (silent) {
25079343712SPeter Avalos } else {
25182c5fa3eSPeter Avalos #ifdef HAVE_STRUCT_STAT_ST_RDEV
252327e51cbSPeter Avalos # ifdef dv_unit
253e8af9738SPeter Avalos if (file_printf(ms, "%sblock special (%d/%d/%d)",
254e8af9738SPeter Avalos COMMA, major(sb->st_rdev), dv_unit(sb->st_rdev),
255327e51cbSPeter Avalos dv_subunit(sb->st_rdev)) == -1)
256327e51cbSPeter Avalos return -1;
257327e51cbSPeter Avalos # else
258e8af9738SPeter Avalos if (file_printf(ms, "%sblock special (%ld/%ld)",
259e8af9738SPeter Avalos COMMA, (long)major(sb->st_rdev),
260e8af9738SPeter Avalos (long)minor(sb->st_rdev)) == -1)
261327e51cbSPeter Avalos return -1;
262327e51cbSPeter Avalos # endif
263327e51cbSPeter Avalos #else
264e8af9738SPeter Avalos if (file_printf(ms, "%sblock special", COMMA) == -1)
265327e51cbSPeter Avalos return -1;
266327e51cbSPeter Avalos #endif
26779343712SPeter Avalos }
268e8af9738SPeter Avalos break;
269327e51cbSPeter Avalos #endif
270327e51cbSPeter Avalos /* TODO add code to handle V7 MUX and Blit MUX files */
271327e51cbSPeter Avalos #ifdef S_IFIFO
272327e51cbSPeter Avalos case S_IFIFO:
273327e51cbSPeter Avalos if((ms->flags & MAGIC_DEVICES) != 0)
274327e51cbSPeter Avalos break;
27579343712SPeter Avalos if (mime) {
276a96e001bSPeter Avalos if (handle_mime(ms, mime, "fifo") == -1)
27779343712SPeter Avalos return -1;
278c30bd091SSascha Wildner } else if (silent) {
279e8af9738SPeter Avalos } else if (file_printf(ms, "%sfifo (named pipe)", COMMA) == -1)
280327e51cbSPeter Avalos return -1;
281e8af9738SPeter Avalos break;
282327e51cbSPeter Avalos #endif
283327e51cbSPeter Avalos #ifdef S_IFDOOR
284327e51cbSPeter Avalos case S_IFDOOR:
28579343712SPeter Avalos if (mime) {
286a96e001bSPeter Avalos if (handle_mime(ms, mime, "door") == -1)
28779343712SPeter Avalos return -1;
288c30bd091SSascha Wildner } else if (silent) {
289e8af9738SPeter Avalos } else if (file_printf(ms, "%sdoor", COMMA) == -1)
290327e51cbSPeter Avalos return -1;
291e8af9738SPeter Avalos break;
292327e51cbSPeter Avalos #endif
293327e51cbSPeter Avalos #ifdef S_IFLNK
294327e51cbSPeter Avalos case S_IFLNK:
295327e51cbSPeter Avalos if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
296327e51cbSPeter Avalos if (ms->flags & MAGIC_ERROR) {
297327e51cbSPeter Avalos file_error(ms, errno, "unreadable symlink `%s'",
298327e51cbSPeter Avalos fn);
299327e51cbSPeter Avalos return -1;
300327e51cbSPeter Avalos }
30179343712SPeter Avalos if (mime) {
302a96e001bSPeter Avalos if (handle_mime(ms, mime, "symlink") == -1)
30379343712SPeter Avalos return -1;
304c30bd091SSascha Wildner } else if (silent) {
30579343712SPeter Avalos } else if (file_printf(ms,
306e8af9738SPeter Avalos "%sunreadable symlink `%s' (%s)", COMMA, fn,
307327e51cbSPeter Avalos strerror(errno)) == -1)
308327e51cbSPeter Avalos return -1;
309e8af9738SPeter Avalos break;
310327e51cbSPeter Avalos }
31179343712SPeter Avalos buf[nch] = '\0'; /* readlink(2) does not do this */
312327e51cbSPeter Avalos
313327e51cbSPeter Avalos /* If broken symlink, say so and quit early. */
3146fca56fbSSascha Wildner #ifdef __linux__
3156fca56fbSSascha Wildner /*
3166fca56fbSSascha Wildner * linux procfs/devfs makes symlinks like pipe:[3515864880]
3176fca56fbSSascha Wildner * that we can't stat their readlink output, so stat the
3186fca56fbSSascha Wildner * original filename instead.
3196fca56fbSSascha Wildner */
3206fca56fbSSascha Wildner if (stat(fn, &tstatbuf) < 0)
3216fca56fbSSascha Wildner return bad_link(ms, errno, buf);
3226fca56fbSSascha Wildner #else
323327e51cbSPeter Avalos if (*buf == '/') {
32479343712SPeter Avalos if (stat(buf, &tstatbuf) < 0)
32579343712SPeter Avalos return bad_link(ms, errno, buf);
32679343712SPeter Avalos } else {
327327e51cbSPeter Avalos char *tmp;
328327e51cbSPeter Avalos char buf2[BUFSIZ+BUFSIZ+4];
329327e51cbSPeter Avalos
330*3b9cdfa3SAntonio Huete Jimenez if ((tmp = CCAST(char *, strrchr(fn, '/'))) == NULL) {
331327e51cbSPeter Avalos tmp = buf; /* in current directory anyway */
332327e51cbSPeter Avalos } else {
333327e51cbSPeter Avalos if (tmp - fn + 1 > BUFSIZ) {
334327e51cbSPeter Avalos if (ms->flags & MAGIC_ERROR) {
335327e51cbSPeter Avalos file_error(ms, 0,
336327e51cbSPeter Avalos "path too long: `%s'", buf);
337327e51cbSPeter Avalos return -1;
338327e51cbSPeter Avalos }
33979343712SPeter Avalos if (mime) {
34079343712SPeter Avalos if (handle_mime(ms, mime,
34179343712SPeter Avalos "x-path-too-long") == -1)
34279343712SPeter Avalos return -1;
343c30bd091SSascha Wildner } else if (silent) {
34479343712SPeter Avalos } else if (file_printf(ms,
345e8af9738SPeter Avalos "%spath too long: `%s'", COMMA,
346e8af9738SPeter Avalos fn) == -1)
347327e51cbSPeter Avalos return -1;
348e8af9738SPeter Avalos break;
349327e51cbSPeter Avalos }
35079343712SPeter Avalos /* take dir part */
35179343712SPeter Avalos (void)strlcpy(buf2, fn, sizeof buf2);
352327e51cbSPeter Avalos buf2[tmp - fn + 1] = '\0';
35379343712SPeter Avalos /* plus (rel) link */
35479343712SPeter Avalos (void)strlcat(buf2, buf, sizeof buf2);
355327e51cbSPeter Avalos tmp = buf2;
356327e51cbSPeter Avalos }
35779343712SPeter Avalos if (stat(tmp, &tstatbuf) < 0)
35879343712SPeter Avalos return bad_link(ms, errno, buf);
359327e51cbSPeter Avalos }
3606fca56fbSSascha Wildner #endif
361327e51cbSPeter Avalos
362327e51cbSPeter Avalos /* Otherwise, handle it. */
363327e51cbSPeter Avalos if ((ms->flags & MAGIC_SYMLINK) != 0) {
364327e51cbSPeter Avalos const char *p;
365327e51cbSPeter Avalos ms->flags &= MAGIC_SYMLINK;
366327e51cbSPeter Avalos p = magic_file(ms, buf);
367327e51cbSPeter Avalos ms->flags |= MAGIC_SYMLINK;
368e8af9738SPeter Avalos if (p == NULL)
369e8af9738SPeter Avalos return -1;
370327e51cbSPeter Avalos } else { /* just print what it points to */
37179343712SPeter Avalos if (mime) {
372a96e001bSPeter Avalos if (handle_mime(ms, mime, "symlink") == -1)
37379343712SPeter Avalos return -1;
374c30bd091SSascha Wildner } else if (silent) {
37582c5fa3eSPeter Avalos } else if (file_printf(ms, "%ssymbolic link to %s",
376e8af9738SPeter Avalos COMMA, buf) == -1)
377327e51cbSPeter Avalos return -1;
378327e51cbSPeter Avalos }
379e8af9738SPeter Avalos break;
380327e51cbSPeter Avalos #endif
381327e51cbSPeter Avalos #ifdef S_IFSOCK
382327e51cbSPeter Avalos #ifndef __COHERENT__
383327e51cbSPeter Avalos case S_IFSOCK:
38479343712SPeter Avalos if (mime) {
385a96e001bSPeter Avalos if (handle_mime(ms, mime, "socket") == -1)
38679343712SPeter Avalos return -1;
387c30bd091SSascha Wildner } else if (silent) {
388e8af9738SPeter Avalos } else if (file_printf(ms, "%ssocket", COMMA) == -1)
389327e51cbSPeter Avalos return -1;
390e8af9738SPeter Avalos break;
391327e51cbSPeter Avalos #endif
392327e51cbSPeter Avalos #endif
393327e51cbSPeter Avalos case S_IFREG:
394327e51cbSPeter Avalos /*
395327e51cbSPeter Avalos * regular file, check next possibility
396327e51cbSPeter Avalos *
397327e51cbSPeter Avalos * If stat() tells us the file has zero length, report here that
398327e51cbSPeter Avalos * the file is empty, so we can skip all the work of opening and
399327e51cbSPeter Avalos * reading the file.
400e8af9738SPeter Avalos * But if the -s option has been given, we skip this
401e8af9738SPeter Avalos * optimization, since on some systems, stat() reports zero
402e8af9738SPeter Avalos * size for raw disk partitions. (If the block special device
403e8af9738SPeter Avalos * really has zero length, the fact that it is empty will be
404e8af9738SPeter Avalos * detected and reported correctly when we read the file.)
405327e51cbSPeter Avalos */
406327e51cbSPeter Avalos if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) {
40779343712SPeter Avalos if (mime) {
40879343712SPeter Avalos if (handle_mime(ms, mime, "x-empty") == -1)
40979343712SPeter Avalos return -1;
410c30bd091SSascha Wildner } else if (silent) {
411e8af9738SPeter Avalos } else if (file_printf(ms, "%sempty", COMMA) == -1)
412327e51cbSPeter Avalos return -1;
413e8af9738SPeter Avalos break;
414327e51cbSPeter Avalos }
415e8af9738SPeter Avalos ret = 0;
416e8af9738SPeter Avalos break;
417e8af9738SPeter Avalos
418e8af9738SPeter Avalos default:
419e8af9738SPeter Avalos file_error(ms, 0, "invalid mode 0%o", sb->st_mode);
420e8af9738SPeter Avalos return -1;
421e8af9738SPeter Avalos /*NOTREACHED*/
422e8af9738SPeter Avalos }
423e8af9738SPeter Avalos
424c30bd091SSascha Wildner if (!silent && !mime && did && ret == 0) {
425e8af9738SPeter Avalos if (file_printf(ms, " ") == -1)
426e8af9738SPeter Avalos return -1;
427e8af9738SPeter Avalos }
4286fca56fbSSascha Wildner /*
4296fca56fbSSascha Wildner * If we were looking for extensions or apple (silent) it is not our
4306fca56fbSSascha Wildner * job to print here, so don't count this as a match.
4316fca56fbSSascha Wildner */
4326fca56fbSSascha Wildner if (ret == 1 && silent)
4336fca56fbSSascha Wildner return 0;
434e8af9738SPeter Avalos return ret;
435327e51cbSPeter Avalos }
436