Back to index

php5  5.3.10
fsmagic.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) Ian F. Darwin 1986-1995.
00003  * Software written by Ian F. Darwin and others;
00004  * maintained 1995-present by Christos Zoulas and others.
00005  * 
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice immediately at the beginning of the file, without modification,
00011  *    this list of conditions, and the following disclaimer.
00012  * 2. Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in the
00014  *    documentation and/or other materials provided with the distribution.
00015  *  
00016  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
00017  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00019  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
00020  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00022  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00023  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00024  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00025  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00026  * SUCH DAMAGE.
00027  */
00028 /*
00029  * fsmagic - magic based on filesystem info - directory, special files, etc.
00030  */
00031 
00032 #include "file.h"
00033 
00034 #ifndef       lint
00035 FILE_RCSID("@(#)$File: fsmagic.c,v 1.59 2009/02/03 20:27:51 christos Exp $")
00036 #endif /* lint */
00037 
00038 #include "magic.h"
00039 #include <string.h>
00040 #ifdef HAVE_UNISTD_H
00041 #include <unistd.h>
00042 #endif
00043 #include <stdlib.h>
00044 /* Since major is a function on SVR4, we cannot use `ifndef major'.  */
00045 #ifdef MAJOR_IN_MKDEV
00046 # include <sys/mkdev.h>
00047 # define HAVE_MAJOR
00048 #endif
00049 #ifdef MAJOR_IN_SYSMACROS
00050 # include <sys/sysmacros.h>
00051 # define HAVE_MAJOR
00052 #endif
00053 #ifdef major                /* Might be defined in sys/types.h.  */
00054 # define HAVE_MAJOR
00055 #endif
00056   
00057 #ifndef HAVE_MAJOR
00058 # define major(dev)  (((dev) >> 8) & 0xff)
00059 # define minor(dev)  ((dev) & 0xff)
00060 #endif
00061 #undef HAVE_MAJOR
00062 
00063 #ifdef PHP_WIN32
00064 
00065 # undef S_IFIFO
00066 #endif
00067 
00068 
00069 #ifndef S_ISDIR
00070 #define S_ISDIR(mode) ((mode) & _S_IFDIR)
00071 #endif
00072 
00073 #ifndef S_ISREG
00074 #define S_ISREG(mode) ((mode) & _S_IFREG)
00075 #endif
00076 
00077 private int
00078 handle_mime(struct magic_set *ms, int mime, const char *str)
00079 {
00080        if ((mime & MAGIC_MIME_TYPE)) {
00081               if (file_printf(ms, "application/%s", str) == -1)
00082                      return -1;
00083               if ((mime & MAGIC_MIME_ENCODING) && file_printf(ms,
00084                   "; charset=") == -1)
00085                      return -1;
00086        }
00087        if ((mime & MAGIC_MIME_ENCODING) && file_printf(ms, "binary") == -1)
00088               return -1;
00089        return 0;
00090 }
00091 
00092 protected int
00093 file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb, php_stream *stream)
00094 {
00095        int mime = ms->flags & MAGIC_MIME;
00096        TSRMLS_FETCH();
00097 
00098        if (ms->flags & MAGIC_APPLE)
00099               return 0;
00100 
00101        if (!fn && !stream) {
00102               return 0;
00103        }
00104 
00105        if (stream) {
00106               php_stream_statbuf ssb;
00107               if (php_stream_stat(stream, &ssb) < 0) {
00108                      if (ms->flags & MAGIC_ERROR) {
00109                             file_error(ms, errno, "cannot stat `%s'", fn);
00110                             return -1;
00111                      }
00112                      return 1;
00113               }
00114               memcpy(sb, &ssb.sb, sizeof(struct stat));
00115        } else {
00116               if (php_sys_stat(fn, sb) != 0) {
00117                      if (ms->flags & MAGIC_ERROR) {
00118                             file_error(ms, errno, "cannot stat `%s'", fn);
00119                             return -1;
00120                      }
00121                      return 1;
00122               }
00123        }
00124 
00125        if (!mime) {
00126 #ifdef S_ISUID
00127               if (sb->st_mode & S_ISUID) 
00128                      if (file_printf(ms, "setuid ") == -1)
00129                             return -1;
00130 #endif
00131 #ifdef S_ISGID
00132               if (sb->st_mode & S_ISGID) 
00133                      if (file_printf(ms, "setgid ") == -1)
00134                             return -1;
00135 #endif
00136 #ifdef S_ISVTX
00137               if (sb->st_mode & S_ISVTX) 
00138                      if (file_printf(ms, "sticky ") == -1)
00139                             return -1;
00140 #endif
00141        }
00142 
00143        switch (sb->st_mode & S_IFMT) {
00144 #ifndef PHP_WIN32
00145 # ifdef S_IFCHR
00146               case S_IFCHR:
00147                      /* 
00148                       * If -s has been specified, treat character special files
00149                       * like ordinary files.  Otherwise, just report that they
00150                       * are block special files and go on to the next file.
00151                       */
00152                      if ((ms->flags & MAGIC_DEVICES) != 0) {
00153                             break;
00154                      }
00155                      if (mime) {
00156                             if (handle_mime(ms, mime, "x-character-device") == -1)
00157                                    return -1;
00158                      } else {
00159 #  ifdef HAVE_STAT_ST_RDEV
00160 #   ifdef dv_unit
00161                             if (file_printf(ms, "character special (%d/%d/%d)",
00162                                 major(sb->st_rdev), dv_unit(sb->st_rdev),
00163                                           dv_subunit(sb->st_rdev)) == -1)
00164                                    return -1;
00165 #   else
00166                             if (file_printf(ms, "character special (%ld/%ld)",
00167                                 (long)major(sb->st_rdev), (long)minor(sb->st_rdev))
00168                                 == -1)
00169                                    return -1;
00170 #   endif
00171 #  else
00172                             if (file_printf(ms, "character special") == -1)
00173                                    return -1;
00174 #  endif
00175                      }
00176                      return 1;
00177 # endif
00178 #endif
00179 
00180 #ifdef S_IFIFO
00181                      case S_IFIFO:
00182                             if((ms->flags & MAGIC_DEVICES) != 0)
00183                                    break;
00184                             if (mime) {
00185                                    if (handle_mime(ms, mime, "x-fifo") == -1)
00186                                           return -1;
00187                             } else if (file_printf(ms, "fifo (named pipe)") == -1)
00188                                    return -1;
00189                             return 1;
00190 #endif
00191 #ifdef S_IFDOOR
00192                             case S_IFDOOR:
00193                                    if (mime) {
00194                                           if (handle_mime(ms, mime, "x-door") == -1)
00195                                                  return -1;
00196                                    } else if (file_printf(ms, "door") == -1)
00197                                           return -1;
00198                                    return 1;
00199 #endif
00200 
00201 #ifdef S_IFLNK
00202        case S_IFLNK:
00203               /* stat is used, if it made here then the link is broken */
00204                      if (ms->flags & MAGIC_ERROR) {
00205                          file_error(ms, errno, "unreadable symlink `%s'", fn);
00206                          return -1;
00207                      }
00208        return 1;
00209 #endif
00210 
00211 #ifdef S_IFSOCK
00212 #ifndef __COHERENT__
00213        case S_IFSOCK:
00214               if (mime) {
00215                      if (handle_mime(ms, mime, "x-socket") == -1)
00216                             return -1;
00217               } else if (file_printf(ms, "socket") == -1)
00218                      return -1;
00219               return 1;
00220 #endif
00221 #endif
00222 
00223               case S_IFREG:
00224                      break;
00225 
00226               default:
00227                      file_error(ms, 0, "invalid mode 0%o", sb->st_mode);
00228                      return -1;
00229                      /*NOTREACHED*/
00230        }
00231 
00232        /*
00233         * regular file, check next possibility
00234         *
00235         * If stat() tells us the file has zero length, report here that
00236         * the file is empty, so we can skip all the work of opening and 
00237         * reading the file.
00238         * But if the -s option has been given, we skip this optimization,
00239         * since on some systems, stat() reports zero size for raw disk
00240         * partitions.  (If the block special device really has zero length,
00241         * the fact that it is empty will be detected and reported correctly
00242         * when we read the file.)
00243         */
00244        if ((ms->flags & MAGIC_DEVICES) == 0 && sb->st_size == 0) {
00245               if (mime) {
00246                      if (handle_mime(ms, mime, "x-empty") == -1)
00247                             return -1;
00248               } else if (file_printf(ms, "empty") == -1)
00249                      return -1;
00250               return 1;
00251        }
00252        return 0;
00253 }