Annotation of embedaddon/libiconv/srclib/stat.c, revision 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>