filestat.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2. * contributor license agreements. See the NOTICE file distributed with
  3. * this work for additional information regarding copyright ownership.
  4. * The ASF licenses this file to You under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "fspr_arch_file_io.h"
  17. #include "fspr_file_io.h"
  18. #include "fspr_general.h"
  19. #include "fspr_strings.h"
  20. #include "fspr_errno.h"
  21. #ifdef HAVE_UTIME
  22. #include <utime.h>
  23. #endif
  24. static fspr_filetype_e filetype_from_mode(mode_t mode)
  25. {
  26. fspr_filetype_e type;
  27. switch (mode & S_IFMT) {
  28. case S_IFREG:
  29. type = APR_REG; break;
  30. case S_IFDIR:
  31. type = APR_DIR; break;
  32. case S_IFLNK:
  33. type = APR_LNK; break;
  34. case S_IFCHR:
  35. type = APR_CHR; break;
  36. case S_IFBLK:
  37. type = APR_BLK; break;
  38. #if defined(S_IFFIFO)
  39. case S_IFFIFO:
  40. type = APR_PIPE; break;
  41. #endif
  42. #if !defined(BEOS) && defined(S_IFSOCK)
  43. case S_IFSOCK:
  44. type = APR_SOCK; break;
  45. #endif
  46. default:
  47. /* Work around missing S_IFxxx values above
  48. * for Linux et al.
  49. */
  50. #if !defined(S_IFFIFO) && defined(S_ISFIFO)
  51. if (S_ISFIFO(mode)) {
  52. type = APR_PIPE;
  53. } else
  54. #endif
  55. #if !defined(BEOS) && !defined(S_IFSOCK) && defined(S_ISSOCK)
  56. if (S_ISSOCK(mode)) {
  57. type = APR_SOCK;
  58. } else
  59. #endif
  60. type = APR_UNKFILE;
  61. }
  62. return type;
  63. }
  64. static void fill_out_finfo(fspr_finfo_t *finfo, struct_stat *info,
  65. fspr_int32_t wanted)
  66. {
  67. finfo->valid = APR_FINFO_MIN | APR_FINFO_IDENT | APR_FINFO_NLINK
  68. | APR_FINFO_OWNER | APR_FINFO_PROT;
  69. finfo->protection = fspr_unix_mode2perms(info->st_mode);
  70. finfo->filetype = filetype_from_mode(info->st_mode);
  71. finfo->user = info->st_uid;
  72. finfo->group = info->st_gid;
  73. finfo->size = info->st_size;
  74. finfo->inode = info->st_ino;
  75. finfo->device = info->st_dev;
  76. finfo->nlink = info->st_nlink;
  77. fspr_time_ansi_put(&finfo->atime, info->st_atime);
  78. fspr_time_ansi_put(&finfo->mtime, info->st_mtime);
  79. fspr_time_ansi_put(&finfo->ctime, info->st_ctime);
  80. /* ### needs to be revisited
  81. * if (wanted & APR_FINFO_CSIZE) {
  82. * finfo->csize = info->st_blocks * 512;
  83. * finfo->valid |= APR_FINFO_CSIZE;
  84. * }
  85. */
  86. }
  87. APR_DECLARE(fspr_status_t) fspr_file_info_get(fspr_finfo_t *finfo,
  88. fspr_int32_t wanted,
  89. fspr_file_t *thefile)
  90. {
  91. struct_stat info;
  92. if (thefile->buffered) {
  93. fspr_status_t rv = fspr_file_flush(thefile);
  94. if (rv != APR_SUCCESS)
  95. return rv;
  96. }
  97. if (fstat(thefile->filedes, &info) == 0) {
  98. finfo->pool = thefile->pool;
  99. finfo->fname = thefile->fname;
  100. fill_out_finfo(finfo, &info, wanted);
  101. return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
  102. }
  103. else {
  104. return errno;
  105. }
  106. }
  107. APR_DECLARE(fspr_status_t) fspr_file_perms_set(const char *fname,
  108. fspr_fileperms_t perms)
  109. {
  110. mode_t mode = fspr_unix_perms2mode(perms);
  111. if (chmod(fname, mode) == -1)
  112. return errno;
  113. return APR_SUCCESS;
  114. }
  115. APR_DECLARE(fspr_status_t) fspr_file_attrs_set(const char *fname,
  116. fspr_fileattrs_t attributes,
  117. fspr_fileattrs_t attr_mask,
  118. fspr_pool_t *pool)
  119. {
  120. fspr_status_t status;
  121. fspr_finfo_t finfo = {0};
  122. /* Don't do anything if we can't handle the requested attributes */
  123. if (!(attr_mask & (APR_FILE_ATTR_READONLY
  124. | APR_FILE_ATTR_EXECUTABLE)))
  125. return APR_SUCCESS;
  126. status = fspr_stat(&finfo, fname, APR_FINFO_PROT, pool);
  127. if (status)
  128. return status;
  129. /* ### TODO: should added bits be umask'd? */
  130. if (attr_mask & APR_FILE_ATTR_READONLY)
  131. {
  132. if (attributes & APR_FILE_ATTR_READONLY)
  133. {
  134. finfo.protection &= ~APR_UWRITE;
  135. finfo.protection &= ~APR_GWRITE;
  136. finfo.protection &= ~APR_WWRITE;
  137. }
  138. else
  139. {
  140. /* ### umask this! */
  141. finfo.protection |= APR_UWRITE;
  142. finfo.protection |= APR_GWRITE;
  143. finfo.protection |= APR_WWRITE;
  144. }
  145. }
  146. if (attr_mask & APR_FILE_ATTR_EXECUTABLE)
  147. {
  148. if (attributes & APR_FILE_ATTR_EXECUTABLE)
  149. {
  150. /* ### umask this! */
  151. finfo.protection |= APR_UEXECUTE;
  152. finfo.protection |= APR_GEXECUTE;
  153. finfo.protection |= APR_WEXECUTE;
  154. }
  155. else
  156. {
  157. finfo.protection &= ~APR_UEXECUTE;
  158. finfo.protection &= ~APR_GEXECUTE;
  159. finfo.protection &= ~APR_WEXECUTE;
  160. }
  161. }
  162. return fspr_file_perms_set(fname, finfo.protection);
  163. }
  164. APR_DECLARE(fspr_status_t) fspr_file_mtime_set(const char *fname,
  165. fspr_time_t mtime,
  166. fspr_pool_t *pool)
  167. {
  168. fspr_status_t status;
  169. fspr_finfo_t finfo = {0};
  170. status = fspr_stat(&finfo, fname, APR_FINFO_ATIME, pool);
  171. if (status) {
  172. return status;
  173. }
  174. #ifdef HAVE_UTIMES
  175. {
  176. struct timeval tvp[2];
  177. tvp[0].tv_sec = fspr_time_sec(finfo.atime);
  178. tvp[0].tv_usec = fspr_time_usec(finfo.atime);
  179. tvp[1].tv_sec = fspr_time_sec(mtime);
  180. tvp[1].tv_usec = fspr_time_usec(mtime);
  181. if (utimes(fname, tvp) == -1) {
  182. return errno;
  183. }
  184. }
  185. #elif defined(HAVE_UTIME)
  186. {
  187. struct utimbuf buf;
  188. buf.actime = (time_t) (finfo.atime / APR_USEC_PER_SEC);
  189. buf.modtime = (time_t) (mtime / APR_USEC_PER_SEC);
  190. if (utime(fname, &buf) == -1) {
  191. return errno;
  192. }
  193. }
  194. #else
  195. return APR_ENOTIMPL;
  196. #endif
  197. return APR_SUCCESS;
  198. }
  199. APR_DECLARE(fspr_status_t) fspr_stat(fspr_finfo_t *finfo,
  200. const char *fname,
  201. fspr_int32_t wanted, fspr_pool_t *pool)
  202. {
  203. struct_stat info;
  204. int srv;
  205. if (wanted & APR_FINFO_LINK)
  206. srv = lstat(fname, &info);
  207. else
  208. srv = stat(fname, &info);
  209. if (srv == 0) {
  210. finfo->pool = pool;
  211. finfo->fname = fname;
  212. fill_out_finfo(finfo, &info, wanted);
  213. if (wanted & APR_FINFO_LINK)
  214. wanted &= ~APR_FINFO_LINK;
  215. return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
  216. }
  217. else {
  218. #if !defined(ENOENT) || !defined(ENOTDIR)
  219. #error ENOENT || ENOTDIR not defined; please see the
  220. #error comments at this line in the source for a workaround.
  221. /*
  222. * If ENOENT || ENOTDIR is not defined in one of the your OS's
  223. * include files, APR cannot report a good reason why the stat()
  224. * of the file failed; there are cases where it can fail even though
  225. * the file exists. This opens holes in Apache, for example, because
  226. * it becomes possible for someone to get a directory listing of a
  227. * directory even though there is an index (eg. index.html) file in
  228. * it. If you do not have a problem with this, delete the above
  229. * #error lines and start the compile again. If you need to do this,
  230. * please submit a bug report to http://www.apache.org/bug_report.html
  231. * letting us know that you needed to do this. Please be sure to
  232. * include the operating system you are using.
  233. */
  234. /* WARNING: All errors will be handled as not found
  235. */
  236. #if !defined(ENOENT)
  237. return APR_ENOENT;
  238. #else
  239. /* WARNING: All errors but not found will be handled as not directory
  240. */
  241. if (errno != ENOENT)
  242. return APR_ENOENT;
  243. else
  244. return errno;
  245. #endif
  246. #else /* All was defined well, report the usual: */
  247. return errno;
  248. #endif
  249. }
  250. }