diff options
| author | Thomas Guyot-Sionnest <dermoth@aei.ca> | 2010-04-07 21:11:46 -0400 |
|---|---|---|
| committer | Thomas Guyot-Sionnest <dermoth@aei.ca> | 2010-04-12 21:26:35 -0400 |
| commit | 74da141e618ef99959d509cb2e7be35a348a39db (patch) | |
| tree | 88ebc38b381a1021fc2d74864a71e230ae591c3d /gl/open.c | |
| parent | c63a4f726a0b6ad8cf6040f947754a81fd4683bb (diff) | |
| download | monitoring-plugins-74da141e618ef99959d509cb2e7be35a348a39db.tar.gz | |
Sync with the latest Gnulib code (177f525)
Signed-off-by: Thomas Guyot-Sionnest <dermoth@aei.ca>
Diffstat (limited to 'gl/open.c')
| -rw-r--r-- | gl/open.c | 76 |
1 files changed, 51 insertions, 25 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* Open a descriptor to a file. | 1 | /* Open a descriptor to a file. |
| 2 | Copyright (C) 2007-2008 Free Software Foundation, Inc. | 2 | Copyright (C) 2007-2010 Free Software Foundation, Inc. |
| 3 | 3 | ||
| 4 | This program is free software: you can redistribute it and/or modify | 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 | 5 | it under the terms of the GNU General Public License as published by |
| @@ -38,6 +38,11 @@ orig_open (const char *filename, int flags, mode_t mode) | |||
| 38 | #include <string.h> | 38 | #include <string.h> |
| 39 | #include <sys/types.h> | 39 | #include <sys/types.h> |
| 40 | #include <sys/stat.h> | 40 | #include <sys/stat.h> |
| 41 | #include <unistd.h> | ||
| 42 | |||
| 43 | #ifndef REPLACE_OPEN_DIRECTORY | ||
| 44 | # define REPLACE_OPEN_DIRECTORY 0 | ||
| 45 | #endif | ||
| 41 | 46 | ||
| 42 | int | 47 | int |
| 43 | open (const char *filename, int flags, ...) | 48 | open (const char *filename, int flags, ...) |
| @@ -51,12 +56,9 @@ open (const char *filename, int flags, ...) | |||
| 51 | va_list arg; | 56 | va_list arg; |
| 52 | va_start (arg, flags); | 57 | va_start (arg, flags); |
| 53 | 58 | ||
| 54 | /* If mode_t is narrower than int, use the promoted type (int), | 59 | /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 |
| 55 | not mode_t. Use sizeof to guess whether mode_t is narrower; | 60 | creates crashing code when 'mode_t' is smaller than 'int'. */ |
| 56 | we don't know of any practical counterexamples. */ | 61 | mode = va_arg (arg, PROMOTED_MODE_T); |
| 57 | mode = (sizeof (mode_t) < sizeof (int) | ||
| 58 | ? va_arg (arg, int) | ||
| 59 | : va_arg (arg, mode_t)); | ||
| 60 | 62 | ||
| 61 | va_end (arg); | 63 | va_end (arg); |
| 62 | } | 64 | } |
| @@ -92,15 +94,38 @@ open (const char *filename, int flags, ...) | |||
| 92 | { | 94 | { |
| 93 | size_t len = strlen (filename); | 95 | size_t len = strlen (filename); |
| 94 | if (len > 0 && filename[len - 1] == '/') | 96 | if (len > 0 && filename[len - 1] == '/') |
| 95 | { | 97 | { |
| 96 | errno = EISDIR; | 98 | errno = EISDIR; |
| 97 | return -1; | 99 | return -1; |
| 98 | } | 100 | } |
| 99 | } | 101 | } |
| 100 | #endif | 102 | #endif |
| 101 | 103 | ||
| 102 | fd = orig_open (filename, flags, mode); | 104 | fd = orig_open (filename, flags, mode); |
| 103 | 105 | ||
| 106 | #if REPLACE_FCHDIR | ||
| 107 | /* Implementing fchdir and fdopendir requires the ability to open a | ||
| 108 | directory file descriptor. If open doesn't support that (as on | ||
| 109 | mingw), we use a dummy file that behaves the same as directories | ||
| 110 | on Linux (ie. always reports EOF on attempts to read()), and | ||
| 111 | override fstat() in fchdir.c to hide the fact that we have a | ||
| 112 | dummy. */ | ||
| 113 | if (REPLACE_OPEN_DIRECTORY && fd < 0 && errno == EACCES | ||
| 114 | && (flags & O_ACCMODE) == O_RDONLY) | ||
| 115 | { | ||
| 116 | struct stat statbuf; | ||
| 117 | if (stat (filename, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) | ||
| 118 | { | ||
| 119 | /* Maximum recursion depth of 1. */ | ||
| 120 | fd = open ("/dev/null", flags, mode); | ||
| 121 | if (0 <= fd) | ||
| 122 | fd = _gl_register_fd (fd, filename); | ||
| 123 | } | ||
| 124 | else | ||
| 125 | errno = EACCES; | ||
| 126 | } | ||
| 127 | #endif | ||
| 128 | |||
| 104 | #if OPEN_TRAILING_SLASH_BUG | 129 | #if OPEN_TRAILING_SLASH_BUG |
| 105 | /* If the filename ends in a slash and fd does not refer to a directory, | 130 | /* If the filename ends in a slash and fd does not refer to a directory, |
| 106 | then fail. | 131 | then fail. |
| @@ -116,24 +141,25 @@ open (const char *filename, int flags, ...) | |||
| 116 | with ENOTDIR. */ | 141 | with ENOTDIR. */ |
| 117 | if (fd >= 0) | 142 | if (fd >= 0) |
| 118 | { | 143 | { |
| 144 | /* We know len is positive, since open did not fail with ENOENT. */ | ||
| 119 | size_t len = strlen (filename); | 145 | size_t len = strlen (filename); |
| 120 | if (len > 0 && filename[len - 1] == '/') | 146 | if (filename[len - 1] == '/') |
| 121 | { | 147 | { |
| 122 | struct stat statbuf; | 148 | struct stat statbuf; |
| 123 | 149 | ||
| 124 | if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) | 150 | if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) |
| 125 | { | 151 | { |
| 126 | close (fd); | 152 | close (fd); |
| 127 | errno = ENOTDIR; | 153 | errno = ENOTDIR; |
| 128 | return -1; | 154 | return -1; |
| 129 | } | 155 | } |
| 130 | } | 156 | } |
| 131 | } | 157 | } |
| 132 | #endif | 158 | #endif |
| 133 | 159 | ||
| 134 | #ifdef FCHDIR_REPLACEMENT | 160 | #if REPLACE_FCHDIR |
| 135 | if (fd >= 0) | 161 | if (!REPLACE_OPEN_DIRECTORY && 0 <= fd) |
| 136 | _gl_register_fd (fd, filename); | 162 | fd = _gl_register_fd (fd, filename); |
| 137 | #endif | 163 | #endif |
| 138 | 164 | ||
| 139 | return fd; | 165 | return fd; |
