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