Back to index

nagios-plugins  1.4.16
stat.c
Go to the documentation of this file.
00001 /* Work around platform bugs in stat.
00002    Copyright (C) 2009, 2010 Free Software Foundation, Inc.
00003 
00004    This program is free software: you can redistribute it and/or modify
00005    it under the terms of the GNU General Public License as published by
00006    the Free Software Foundation; either version 3 of the License, or
00007    (at your option) any later version.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012    GNU General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License
00015    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00016 
00017 /* written by Eric Blake */
00018 
00019 #include <config.h>
00020 
00021 /* Get the original definition of stat.  It might be defined as a macro.  */
00022 #define __need_system_sys_stat_h
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #undef __need_system_sys_stat_h
00026 
00027 static inline int
00028 orig_stat (const char *filename, struct stat *buf)
00029 {
00030   return stat (filename, buf);
00031 }
00032 
00033 /* Specification.  */
00034 #include <sys/stat.h>
00035 
00036 #include <errno.h>
00037 #include <limits.h>
00038 #include <stdbool.h>
00039 #include <string.h>
00040 
00041 /* Store information about NAME into ST.  Work around bugs with
00042    trailing slashes.  Mingw has other bugs (such as st_ino always
00043    being 0 on success) which this wrapper does not work around.  But
00044    at least this implementation provides the ability to emulate fchdir
00045    correctly.  */
00046 
00047 int
00048 rpl_stat (char const *name, struct stat *st)
00049 {
00050   int result = orig_stat (name, st);
00051 #if REPLACE_FUNC_STAT_FILE
00052   /* Solaris 9 mistakenly succeeds when given a non-directory with a
00053      trailing slash.  */
00054   if (result == 0 && !S_ISDIR (st->st_mode))
00055     {
00056       size_t len = strlen (name);
00057       if (ISSLASH (name[len - 1]))
00058         {
00059           errno = ENOTDIR;
00060           return -1;
00061         }
00062     }
00063 #endif /* REPLACE_FUNC_STAT_FILE */
00064 #if REPLACE_FUNC_STAT_DIR
00065   if (result == -1 && errno == ENOENT)
00066     {
00067       /* Due to mingw's oddities, there are some directories (like
00068          c:\) where stat() only succeeds with a trailing slash, and
00069          other directories (like c:\windows) where stat() only
00070          succeeds without a trailing slash.  But we want the two to be
00071          synonymous, since chdir() manages either style.  Likewise, Mingw also
00072          reports ENOENT for names longer than PATH_MAX, when we want
00073          ENAMETOOLONG, and for stat("file/"), when we want ENOTDIR.
00074          Fortunately, mingw PATH_MAX is small enough for stack
00075          allocation.  */
00076       char fixed_name[PATH_MAX + 1] = {0};
00077       size_t len = strlen (name);
00078       bool check_dir = false;
00079       if (PATH_MAX <= len)
00080         errno = ENAMETOOLONG;
00081       else if (len)
00082         {
00083           strcpy (fixed_name, name);
00084           if (ISSLASH (fixed_name[len - 1]))
00085             {
00086               check_dir = true;
00087               while (len && ISSLASH (fixed_name[len - 1]))
00088                 fixed_name[--len] = '\0';
00089               if (!len)
00090                 fixed_name[0] = '/';
00091             }
00092           else
00093             fixed_name[len++] = '/';
00094           result = orig_stat (fixed_name, st);
00095           if (result == 0 && check_dir && !S_ISDIR (st->st_mode))
00096             {
00097               result = -1;
00098               errno = ENOTDIR;
00099             }
00100         }
00101     }
00102 #endif /* REPLACE_FUNC_STAT_DIR */
00103   return result;
00104 }