root/ext/fileinfo/libmagic/fsmagic.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. handle_mime
  2. file_fsmagic

   1 /*
   2  * Copyright (c) Ian F. Darwin 1986-1995.
   3  * Software written by Ian F. Darwin and others;
   4  * maintained 1995-present by Christos Zoulas and others.
   5  * 
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  * 1. Redistributions of source code must retain the above copyright
  10  *    notice immediately at the beginning of the file, without modification,
  11  *    this list of conditions, and the following disclaimer.
  12  * 2. Redistributions in binary form must reproduce the above copyright
  13  *    notice, this list of conditions and the following disclaimer in the
  14  *    documentation and/or other materials provided with the distribution.
  15  *  
  16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26  * SUCH DAMAGE.
  27  */
  28 /*
  29  * fsmagic - magic based on filesystem info - directory, special files, etc.
  30  */
  31 
  32 #include "file.h"
  33 
  34 #ifndef lint
  35 FILE_RCSID("@(#)$File: fsmagic.c,v 1.71 2013/12/01 18:01:07 christos Exp $")
  36 #endif  /* lint */
  37 
  38 #include "magic.h"
  39 #include <string.h>
  40 #ifdef HAVE_UNISTD_H
  41 #include <unistd.h>
  42 #endif
  43 #include <stdlib.h>
  44 /* Since major is a function on SVR4, we cannot use `ifndef major'.  */
  45 #ifdef MAJOR_IN_MKDEV
  46 # include <sys/mkdev.h>
  47 # define HAVE_MAJOR
  48 #endif
  49 #ifdef MAJOR_IN_SYSMACROS
  50 # include <sys/sysmacros.h>
  51 # define HAVE_MAJOR
  52 #endif
  53 #ifdef major                    /* Might be defined in sys/types.h.  */
  54 # define HAVE_MAJOR
  55 #endif
  56   
  57 #ifndef HAVE_MAJOR
  58 # define major(dev)  (((dev) >> 8) & 0xff)
  59 # define minor(dev)  ((dev) & 0xff)
  60 #endif
  61 #undef HAVE_MAJOR
  62 
  63 #ifdef PHP_WIN32
  64 
  65 # undef S_IFIFO
  66 #endif
  67 
  68 
  69 #ifndef S_ISDIR
  70 #define S_ISDIR(mode) ((mode) & _S_IFDIR)
  71 #endif
  72 
  73 #ifndef S_ISREG
  74 #define S_ISREG(mode) ((mode) & _S_IFREG)
  75 #endif
  76 
  77 private int
  78 handle_mime(struct magic_set *ms, int mime, const char *str)
  79 {
  80         if ((mime & MAGIC_MIME_TYPE)) {
  81                 if (file_printf(ms, "inode/%s", str) == -1)
  82                         return -1;
  83                 if ((mime & MAGIC_MIME_ENCODING) && file_printf(ms,
  84                     "; charset=") == -1)
  85                         return -1;
  86         }
  87         if ((mime & MAGIC_MIME_ENCODING) && file_printf(ms, "binary") == -1)
  88                 return -1;
  89         return 0;
  90 }
  91 
  92 protected int
  93 file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *stream)
  94 {
  95         int ret, did = 0;
  96         int mime = ms->flags & MAGIC_MIME;
  97         TSRMLS_FETCH();
  98 
  99         if (ms->flags & MAGIC_APPLE)
 100                 return 0;
 101 
 102         if (fn == NULL && !stream) {
 103                 return 0;
 104         }
 105 
 106 #define COMMA   (did++ ? ", " : "")
 107 
 108         if (stream) {
 109                 php_stream_statbuf ssb;
 110                 if (php_stream_stat(stream, &ssb) < 0) {
 111                         if (ms->flags & MAGIC_ERROR) {
 112                                 file_error(ms, errno, "cannot stat `%s'", fn);
 113                                 return -1;
 114                         }
 115                         return 0;
 116                 }
 117                 memcpy(sb, &ssb.sb, sizeof(struct stat));
 118         } else {
 119                 if (php_sys_stat(fn, sb) != 0) {
 120                         if (ms->flags & MAGIC_ERROR) {
 121                                 file_error(ms, errno, "cannot stat `%s'", fn);
 122                                 return -1;
 123                         }
 124                         return 0;
 125                 }
 126         }
 127 
 128         ret = 1;
 129         if (!mime) {
 130 #ifdef S_ISUID
 131                 if (sb->st_mode & S_ISUID)
 132                         if (file_printf(ms, "%ssetuid", COMMA) == -1)
 133                                 return -1;
 134 #endif
 135 #ifdef S_ISGID
 136                 if (sb->st_mode & S_ISGID) 
 137                         if (file_printf(ms, "%ssetgid", COMMA) == -1)
 138                                 return -1;
 139 #endif
 140 #ifdef S_ISVTX
 141                 if (sb->st_mode & S_ISVTX) 
 142                         if (file_printf(ms, "%ssticky", COMMA) == -1)
 143                                 return -1;
 144 #endif
 145         }
 146         
 147         switch (sb->st_mode & S_IFMT) {
 148 #ifndef PHP_WIN32
 149 # ifdef S_IFCHR
 150                 case S_IFCHR:
 151                         /* 
 152                          * If -s has been specified, treat character special files
 153                          * like ordinary files.  Otherwise, just report that they
 154                          * are block special files and go on to the next file.
 155                          */
 156                         if ((ms->flags & MAGIC_DEVICES) != 0) {
 157                                 ret = 0;
 158                                 break;
 159                         }
 160                         if (mime) {
 161                                 if (handle_mime(ms, mime, "chardevice") == -1)
 162                                         return -1;
 163                         } else {
 164 #  ifdef HAVE_STAT_ST_RDEV
 165 #   ifdef dv_unit
 166                         if (file_printf(ms, "%scharacter special (%d/%d/%d)",
 167                             COMMA, major(sb->st_rdev), dv_unit(sb->st_rdev),
 168                                         dv_subunit(sb->st_rdev)) == -1)
 169                                 return -1;
 170 # else
 171                         if (file_printf(ms, "%scharacter special (%ld/%ld)",
 172                             COMMA, (long)major(sb->st_rdev),
 173                             (long)minor(sb->st_rdev)) == -1)
 174                                 return -1;
 175 # endif
 176 #else
 177                         if (file_printf(ms, "%scharacter special", COMMA) == -1)
 178                                 return -1;
 179 #endif
 180         }
 181                         return 1;
 182 # endif
 183 #endif
 184 
 185 #ifdef  S_IFIFO
 186         case S_IFIFO:
 187                 if((ms->flags & MAGIC_DEVICES) != 0)
 188                         break;
 189                 if (mime) {
 190                         if (handle_mime(ms, mime, "fifo") == -1)
 191                                 return -1;
 192                 } else if (file_printf(ms, "%sfifo (named pipe)", COMMA) == -1)
 193                         return -1;
 194                 break;
 195 #endif
 196 #ifdef  S_IFDOOR
 197         case S_IFDOOR:
 198                 if (mime) {
 199                         if (handle_mime(ms, mime, "door") == -1)
 200                                 return -1;
 201                 } else if (file_printf(ms, "%sdoor", COMMA) == -1)
 202                         return -1;
 203                 break;
 204 #endif
 205 #ifdef  S_IFLNK
 206         case S_IFLNK:
 207                 /* stat is used, if it made here then the link is broken */
 208                         if (ms->flags & MAGIC_ERROR) {
 209                             file_error(ms, errno, "unreadable symlink `%s'", fn);
 210                             return -1;
 211                         }
 212         return 1;
 213 #endif
 214 
 215 #ifdef  S_IFSOCK
 216 #ifndef __COHERENT__
 217         case S_IFSOCK:
 218                 if (mime) {
 219                         if (handle_mime(ms, mime, "socket") == -1)
 220                                 return -1;
 221                 } else if (file_printf(ms, "%ssocket", COMMA) == -1)
 222                         return -1;
 223                 break;
 224 #endif
 225 #endif
 226         case S_IFREG:
 227                 /*
 228                  * regular file, check next possibility
 229                  *
 230                  * If stat() tells us the file has zero length, report here that
 231                  * the file is empty, so we can skip all the work of opening and
 232                  * reading the file.
 233                  * But if the -s option has been given, we skip this
 234                  * optimization, since on some systems, stat() reports zero
 235                  * size for raw disk partitions. (If the block special device
 236                  * really has zero length, the fact that it is empty will be
 237                  * detected and reported correctly when we read the file.)
 238          */
 239         if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) {
 240                 if (mime) {
 241                         if (handle_mime(ms, mime, "x-empty") == -1)
 242                                 return -1;
 243                         } else if (file_printf(ms, "%sempty", COMMA) == -1)
 244                         return -1;
 245                         break;
 246         }
 247                 ret = 0;
 248                 break;
 249 
 250         default:
 251                 file_error(ms, 0, "invalid mode 0%o", sb->st_mode);
 252                 return -1;
 253                 /*NOTREACHED*/
 254         }
 255 
 256         return ret;
 257 }

/* [<][>][^][v][top][bottom][index][help] */