file.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /**
  2. * \file file.c
  3. *
  4. * Handle options that have file names for arguments.
  5. *
  6. * @addtogroup autoopts
  7. * @{
  8. */
  9. /*
  10. * This file is part of AutoOpts, a companion to AutoGen.
  11. * AutoOpts is free software.
  12. * AutoOpts is Copyright (C) 1992-2016 by Bruce Korb - all rights reserved
  13. *
  14. * AutoOpts is available under any one of two licenses. The license
  15. * in use must be one of these two and the choice is under the control
  16. * of the user of the license.
  17. *
  18. * The GNU Lesser General Public License, version 3 or later
  19. * See the files "COPYING.lgplv3" and "COPYING.gplv3"
  20. *
  21. * The Modified Berkeley Software Distribution License
  22. * See the file "COPYING.mbsd"
  23. *
  24. * These files have the following sha256 sums:
  25. *
  26. * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3
  27. * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3
  28. * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd
  29. */
  30. /**
  31. * Make sure the directory containing the subject file exists and that
  32. * the file exists or does not exist, per the option requirements.
  33. *
  34. * @param ftype file existence type flags
  35. * @param pOpts program option descriptor
  36. * @param pOD the option descriptor
  37. */
  38. static void
  39. check_existence(teOptFileType ftype, tOptions * pOpts, tOptDesc * pOD)
  40. {
  41. char const * fname = pOD->optArg.argString;
  42. struct stat sb;
  43. errno = 0;
  44. switch (ftype & FTYPE_MODE_EXIST_MASK) {
  45. case FTYPE_MODE_MUST_NOT_EXIST:
  46. if ((stat(fname, &sb) == 0) || (errno != ENOENT)) {
  47. if (errno == 0)
  48. errno = EINVAL;
  49. fserr_exit(pOpts->pzProgName, "stat", fname);
  50. /* NOTREACHED */
  51. }
  52. /* FALLTHROUGH */
  53. default:
  54. case FTYPE_MODE_MAY_EXIST:
  55. {
  56. char * p = strrchr(fname, DIRCH);
  57. size_t l;
  58. if (p == NULL)
  59. /*
  60. * The file may or may not exist and its directory is ".".
  61. * Assume that "." exists.
  62. */
  63. break;
  64. l = (size_t)(p - fname);
  65. p = AGALOC(l + 1, "fname");
  66. memcpy(p, fname, l);
  67. p[l] = NUL;
  68. if ((stat(p, &sb) != 0) || (errno = EINVAL, ! S_ISDIR(sb.st_mode)))
  69. fserr_exit(pOpts->pzProgName, "stat", p);
  70. /* NOTREACHED */
  71. AGFREE(p);
  72. break;
  73. }
  74. case FTYPE_MODE_MUST_EXIST:
  75. if ( (stat(fname, &sb) != 0)
  76. || (errno = EINVAL, ! S_ISREG(sb.st_mode)) )
  77. fserr_exit(pOpts->pzProgName, "stat", fname);
  78. /* NOTREACHED */
  79. break;
  80. }
  81. }
  82. /**
  83. * Open the specified file with open(2) and save the FD.
  84. *
  85. * @param pOpts program option descriptor
  86. * @param pOD the option descriptor
  87. * @param mode the open mode (uses int flags value)
  88. */
  89. static void
  90. open_file_fd(tOptions * pOpts, tOptDesc * pOD, tuFileMode mode)
  91. {
  92. int fd = open(pOD->optArg.argString, mode.file_flags);
  93. if (fd < 0)
  94. fserr_exit(pOpts->pzProgName, "open", pOD->optArg.argString);
  95. /* NOTREACHED */
  96. if ((pOD->fOptState & OPTST_ALLOC_ARG) != 0)
  97. pOD->optCookie = VOIDP(pOD->optArg.argString);
  98. else
  99. AGDUPSTR(pOD->optCookie, pOD->optArg.argString, "file name");
  100. pOD->optArg.argFd = fd;
  101. pOD->fOptState &= ~OPTST_ALLOC_ARG;
  102. }
  103. /**
  104. * Open the specified file with open(2) and save the FD.
  105. *
  106. * @param pOpts program option descriptor
  107. * @param pOD the option descriptor
  108. * @param mode the open mode (uses "char *" mode value)
  109. */
  110. static void
  111. fopen_file_fp(tOptions * pOpts, tOptDesc * pOD, tuFileMode mode)
  112. {
  113. FILE * fp = fopen(pOD->optArg.argString, mode.file_mode);
  114. if (fp == NULL)
  115. fserr_exit(pOpts->pzProgName, "fopen", pOD->optArg.argString);
  116. /* NOTREACHED */
  117. if ((pOD->fOptState & OPTST_ALLOC_ARG) != 0)
  118. pOD->optCookie = VOIDP(pOD->optArg.argString);
  119. else
  120. AGDUPSTR(pOD->optCookie, pOD->optArg.argString, "file name");
  121. pOD->optArg.argFp = fp;
  122. pOD->fOptState &= ~OPTST_ALLOC_ARG;
  123. }
  124. /*=export_func optionFileCheck
  125. * private:
  126. *
  127. * what: Decipher a boolean value
  128. * arg: + tOptions * + pOpts + program options descriptor +
  129. * arg: + tOptDesc * + pOptDesc + the descriptor for this arg +
  130. * arg: + teOptFileType + ftype + File handling type +
  131. * arg: + tuFileMode + mode + file open mode (if needed) +
  132. *
  133. * doc:
  134. * Make sure the named file conforms with the file type mode.
  135. * The mode specifies if the file must exist, must not exist or may
  136. * (or may not) exist. The mode may also specify opening the
  137. * file: don't, open just the descriptor (fd), or open as a stream
  138. * (FILE * pointer).
  139. =*/
  140. void
  141. optionFileCheck(tOptions * pOpts, tOptDesc * pOD,
  142. teOptFileType ftype, tuFileMode mode)
  143. {
  144. if (pOpts <= OPTPROC_EMIT_LIMIT) {
  145. if (pOpts != OPTPROC_EMIT_USAGE)
  146. return;
  147. switch (ftype & FTYPE_MODE_EXIST_MASK) {
  148. case FTYPE_MODE_MUST_NOT_EXIST:
  149. fputs(zFileCannotExist + tab_skip_ct, option_usage_fp);
  150. break;
  151. case FTYPE_MODE_MUST_EXIST:
  152. fputs(zFileMustExist + tab_skip_ct, option_usage_fp);
  153. break;
  154. }
  155. return;
  156. }
  157. if ((pOD->fOptState & OPTST_RESET) != 0) {
  158. if (pOD->optCookie != NULL)
  159. AGFREE(pOD->optCookie);
  160. return;
  161. }
  162. check_existence(ftype, pOpts, pOD);
  163. switch (ftype & FTYPE_MODE_OPEN_MASK) {
  164. default:
  165. case FTYPE_MODE_NO_OPEN: break;
  166. case FTYPE_MODE_OPEN_FD: open_file_fd( pOpts, pOD, mode); break;
  167. case FTYPE_MODE_FOPEN_FP: fopen_file_fp(pOpts, pOD, mode); break;
  168. }
  169. }
  170. /** @}
  171. *
  172. * Local Variables:
  173. * mode: C
  174. * c-file-style: "stroustrup"
  175. * indent-tabs-mode: nil
  176. * End:
  177. * end of autoopts/file.c */