home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / file39a.zip / src / fsmagic.c < prev    next >
C/C++ Source or Header  |  1993-04-05  |  5KB  |  210 lines

  1. /*
  2.  * fsmagic - magic based on filesystem info - directory, special files, etc.
  3.  *
  4.  * Copyright (c) Ian F. Darwin, 1987.
  5.  * Written by Ian F. Darwin.
  6.  *
  7.  * This software is not subject to any license of the American Telephone
  8.  * and Telegraph Company or of the Regents of the University of California.
  9.  *
  10.  * Permission is granted to anyone to use this software for any purpose on
  11.  * any computer system, and to alter it and redistribute it freely, subject
  12.  * to the following restrictions:
  13.  *
  14.  * 1. The author is not responsible for the consequences of use of this
  15.  *    software, no matter how awful, even if they arise from flaws in it.
  16.  *
  17.  * 2. The origin of this software must not be misrepresented, either by
  18.  *    explicit claim or by omission.  Since few users ever read sources,
  19.  *    credits must appear in the documentation.
  20.  *
  21.  * 3. Altered versions must be plainly marked as such, and must not be
  22.  *    misrepresented as being the original software.  Since few users
  23.  *    ever read sources, credits must appear in the documentation.
  24.  *
  25.  * 4. This notice may not be removed or altered.
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <sys/types.h>
  31. #include <sys/stat.h>
  32. #ifndef MSC
  33. #include <unistd.h>
  34. #endif
  35. #include <stdlib.h>
  36. #ifndef    major            /* if `major' not defined in types.h, */
  37. #ifdef OS2              /* These will always return 0 in EMX */
  38. #define major(x) ((int) x & 0xffff) /* will return driver in MSC */
  39. #define minor(x) ((int) x >> 16)
  40. #else
  41. #include <sys/sysmacros.h>    /* try this one. */
  42. #endif
  43. #endif
  44. #ifndef    major    /* still not defined? give up, manual intervention needed */
  45.         /* If cc tries to compile this, read and act on it. */
  46.         /* On most systems cpp will discard it automatically */
  47.         Congratulations, you have found a portability bug.
  48.         Please grep /usr/include/sys and edit the above #include 
  49.         to point at the file that defines the "major" macro.
  50. #endif    /*major*/
  51.  
  52. #include "file.h"
  53.  
  54. #ifndef    lint
  55. static char *moduleid = 
  56.     "@(#)$Id: fsmagic.c,v 1.22 93/02/19 12:09:04 ian Exp $";
  57. #endif    /* lint */
  58.  
  59.  
  60. #ifdef MSC            /* MSC stat() is broken on directories ending with '/' */
  61. int    Stat(fn, sb)
  62. const char *fn;
  63. struct stat *sb;
  64. {
  65.     char    path[_MAX_PATH], dir[_MAX_DIR], fname[_MAX_FNAME];
  66.     char     *p;
  67.  
  68.     strcpy(path, fn);
  69.     _splitpath(path, NULL, dir, fname, NULL);
  70.     if (*fname == '\0') 
  71.         if (strlen(dir) > 1)
  72.             if ( *(p = path + strlen(path) -1) == '/' || *p == '\\')
  73.                 *p = '\0';
  74.     return(stat(path, sb));
  75. }
  76. #endif
  77.  
  78.  
  79. int
  80. fsmagic(fn, sb)
  81. const char *fn;
  82. struct stat *sb;
  83. {
  84.     int ret = 0;
  85.  
  86.     /*
  87.      * Fstat is cheaper but fails for files you don't have read perms on.
  88.      * On 4.2BSD and similar systems, use lstat() to identify symlinks.
  89.      */
  90. #ifdef    S_IFLNK
  91.     if (!lflag)
  92.         ret = lstat(fn, sb);
  93.     else
  94. #endif
  95. #ifdef MSC
  96.     ret = Stat(fn, sb);    /* don't merge into if; see "ret =" above */
  97. #else
  98.     ret = stat(fn, sb);    /* don't merge into if; see "ret =" above */
  99. #endif
  100.  
  101.     if (ret) {
  102.         ckfprintf(stdout,
  103.             /* Yes, I do mean stdout. */
  104.             /* No \n, caller will provide. */
  105.             "can't stat `%s' (%s).", fn, strerror(errno));
  106.         return 1;
  107.     }
  108.  
  109. #ifdef S_ISUID
  110.     if (sb->st_mode & S_ISUID) ckfputs("setuid ", stdout);
  111.     if (sb->st_mode & S_ISGID) ckfputs("setgid ", stdout);
  112.     if (sb->st_mode & S_ISVTX) ckfputs("sticky ", stdout);
  113. #endif
  114.     
  115.     switch (sb->st_mode & S_IFMT) {
  116.     case S_IFDIR:
  117.         ckfputs("directory", stdout);
  118.         return 1;
  119.     case S_IFCHR:
  120.         (void) printf("character special (%d/%d)",
  121.             major(sb->st_rdev), minor(sb->st_rdev));
  122.         return 1;
  123. #ifdef S_IFBLK
  124.     case S_IFBLK:
  125.         (void) printf("block special (%d/%d)",
  126.             major(sb->st_rdev), minor(sb->st_rdev));
  127.         return 1;
  128. #endif
  129.     /* TODO add code to handle V7 MUX and Blit MUX files */
  130. #ifdef    S_IFIFO
  131.     case S_IFIFO:
  132.         ckfputs("fifo (named pipe)", stdout);
  133.         return 1;
  134. #endif
  135. #ifdef    S_IFLNK
  136.     case S_IFLNK:
  137.         {
  138.             char buf[BUFSIZ+4];
  139.             register int nch;
  140.             struct stat tstatbuf;
  141.  
  142.             if ((nch = readlink(fn, buf, BUFSIZ-1)) <= 0) {
  143.                 ckfprintf(stdout, "unreadable symlink (%s).", 
  144.                       strerror(errno));
  145.                 return 1;
  146.             }
  147.             buf[nch] = '\0';    /* readlink(2) forgets this */
  148.  
  149.             /* If broken symlink, say so and quit early. */
  150.             if (*buf == '/') {
  151.                 if (stat(buf, &tstatbuf) < 0) {
  152.                 ckfprintf(stdout,
  153.                     "broken symbolic link to %s", buf);
  154.                 return 1;
  155.                 }
  156.             }
  157.             else {
  158.                 char *tmp;
  159.                 char buf2[BUFSIZ+BUFSIZ+4];
  160.  
  161.                 if ((tmp = strrchr(fn,  '/')) == NULL) {
  162.                 tmp = buf; /* in current directory anyway */
  163.                 }
  164.                 else {
  165.                 strcpy (buf2, fn);  /* take directory part */
  166.                 buf2[tmp-fn+1] = '\0';
  167.                 strcat (buf2, buf); /* plus (relative) symlink */
  168.                 tmp = buf2;
  169.                 }
  170.                 if (stat(tmp, &tstatbuf) < 0) {
  171.                 ckfprintf(stdout,
  172.                     "broken symbolic link to %s", buf);
  173.                 return 1;
  174.                 }
  175.                         }
  176.  
  177.             /* Otherwise, handle it. */
  178.             if (lflag) {
  179.                 process(buf, strlen(buf));
  180.                 return 1;
  181.             } else { /* just print what it points to */
  182.                 ckfputs("symbolic link to ", stdout);
  183.                 ckfputs(buf, stdout);
  184.             }
  185.         }
  186.         return 1;
  187. #endif
  188. #ifdef    S_IFSOCK
  189.     case S_IFSOCK:
  190.         ckfputs("socket", stdout);
  191.         return 1;
  192. #endif
  193.     case S_IFREG:
  194.         break;
  195.     default:
  196.         error("invalid mode 0%o.\n", sb->st_mode);
  197.         /*NOTREACHED*/
  198.     }
  199.  
  200.     /*
  201.      * regular file, check next possibility
  202.      */
  203.     if (sb->st_size == 0) {
  204.         ckfputs("empty", stdout);
  205.         return 1;
  206.     }
  207.     return 0;
  208. }
  209.  
  210.