Annotation of embedaddon/libiconv/srclib/stat.c, revision 1.1.1.1

1.1       misho       1: /* Work around platform bugs in stat.
                      2:    Copyright (C) 2009-2011 Free Software Foundation, Inc.
                      3: 
                      4:    This program is free software: you can redistribute it and/or modify
                      5:    it under the terms of the GNU General Public License as published by
                      6:    the Free Software Foundation; either version 3 of the License, or
                      7:    (at your option) any later version.
                      8: 
                      9:    This program is distributed in the hope that it will be useful,
                     10:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     12:    GNU General Public License for more details.
                     13: 
                     14:    You should have received a copy of the GNU General Public License
                     15:    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
                     16: 
                     17: /* written by Eric Blake */
                     18: 
                     19: #include <config.h>
                     20: 
                     21: /* Get the original definition of stat.  It might be defined as a macro.  */
                     22: #define __need_system_sys_stat_h
                     23: #include <sys/types.h>
                     24: #include <sys/stat.h>
                     25: #undef __need_system_sys_stat_h
                     26: 
                     27: static inline int
                     28: orig_stat (const char *filename, struct stat *buf)
                     29: {
                     30:   return stat (filename, buf);
                     31: }
                     32: 
                     33: /* Specification.  */
                     34: #include <sys/stat.h>
                     35: 
                     36: #include <errno.h>
                     37: #include <limits.h>
                     38: #include <stdbool.h>
                     39: #include <string.h>
                     40: #include "dosname.h"
                     41: #include "verify.h"
                     42: 
                     43: /* Store information about NAME into ST.  Work around bugs with
                     44:    trailing slashes.  Mingw has other bugs (such as st_ino always
                     45:    being 0 on success) which this wrapper does not work around.  But
                     46:    at least this implementation provides the ability to emulate fchdir
                     47:    correctly.  */
                     48: 
                     49: int
                     50: rpl_stat (char const *name, struct stat *st)
                     51: {
                     52:   int result = orig_stat (name, st);
                     53: #if REPLACE_FUNC_STAT_FILE
                     54:   /* Solaris 9 mistakenly succeeds when given a non-directory with a
                     55:      trailing slash.  */
                     56:   if (result == 0 && !S_ISDIR (st->st_mode))
                     57:     {
                     58:       size_t len = strlen (name);
                     59:       if (ISSLASH (name[len - 1]))
                     60:         {
                     61:           errno = ENOTDIR;
                     62:           return -1;
                     63:         }
                     64:     }
                     65: #endif /* REPLACE_FUNC_STAT_FILE */
                     66: #if REPLACE_FUNC_STAT_DIR
                     67:   /* The only known systems where REPLACE_FUNC_STAT_DIR is needed also
                     68:      have a constant PATH_MAX.  */
                     69: # ifndef PATH_MAX
                     70: #  error "Please port this replacement to your platform"
                     71: # endif
                     72: 
                     73:   if (result == -1 && errno == ENOENT)
                     74:     {
                     75:       /* Due to mingw's oddities, there are some directories (like
                     76:          c:\) where stat() only succeeds with a trailing slash, and
                     77:          other directories (like c:\windows) where stat() only
                     78:          succeeds without a trailing slash.  But we want the two to be
                     79:          synonymous, since chdir() manages either style.  Likewise, Mingw also
                     80:          reports ENOENT for names longer than PATH_MAX, when we want
                     81:          ENAMETOOLONG, and for stat("file/"), when we want ENOTDIR.
                     82:          Fortunately, mingw PATH_MAX is small enough for stack
                     83:          allocation.  */
                     84:       char fixed_name[PATH_MAX + 1] = {0};
                     85:       size_t len = strlen (name);
                     86:       bool check_dir = false;
                     87:       verify (PATH_MAX <= 4096);
                     88:       if (PATH_MAX <= len)
                     89:         errno = ENAMETOOLONG;
                     90:       else if (len)
                     91:         {
                     92:           strcpy (fixed_name, name);
                     93:           if (ISSLASH (fixed_name[len - 1]))
                     94:             {
                     95:               check_dir = true;
                     96:               while (len && ISSLASH (fixed_name[len - 1]))
                     97:                 fixed_name[--len] = '\0';
                     98:               if (!len)
                     99:                 fixed_name[0] = '/';
                    100:             }
                    101:           else
                    102:             fixed_name[len++] = '/';
                    103:           result = orig_stat (fixed_name, st);
                    104:           if (result == 0 && check_dir && !S_ISDIR (st->st_mode))
                    105:             {
                    106:               result = -1;
                    107:               errno = ENOTDIR;
                    108:             }
                    109:         }
                    110:     }
                    111: #endif /* REPLACE_FUNC_STAT_DIR */
                    112:   return result;
                    113: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>