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