file.c revision 285612
1193323Sed
2193323Sed/**
3193323Sed * \file file.c
4193323Sed *
5193323Sed * Handle options that have file names for arguments.
6193323Sed *
7193323Sed * @addtogroup autoopts
8193323Sed * @{
9193323Sed */
10193323Sed/*
11193323Sed *  This file is part of AutoOpts, a companion to AutoGen.
12193323Sed *  AutoOpts is free software.
13193323Sed *  AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved
14193323Sed *
15193323Sed *  AutoOpts is available under any one of two licenses.  The license
16193323Sed *  in use must be one of these two and the choice is under the control
17193323Sed *  of the user of the license.
18193323Sed *
19193323Sed *   The GNU Lesser General Public License, version 3 or later
20193323Sed *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
21193323Sed *
22193323Sed *   The Modified Berkeley Software Distribution License
23193323Sed *      See the file "COPYING.mbsd"
24193323Sed *
25193323Sed *  These files have the following sha256 sums:
26193323Sed *
27193323Sed *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
28193323Sed *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
29193323Sed *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
30195340Sed */
31193323Sed
32193323Sed/**
33193323Sed *  Make sure the directory containing the subject file exists and that
34193323Sed *  the file exists or does not exist, per the option requirements.
35193323Sed *
36193323Sed * @param ftype file existence type flags
37198090Srdivacky * @param pOpts program option descriptor
38193323Sed * @param pOD   the option descriptor
39193323Sed */
40193323Sedstatic void
41198090Srdivackycheck_existence(teOptFileType ftype, tOptions * pOpts, tOptDesc * pOD)
42193323Sed{
43193323Sed    char const * fname = pOD->optArg.argString;
44193323Sed    struct stat sb;
45193323Sed
46193323Sed    errno = 0;
47193323Sed
48193323Sed    switch (ftype & FTYPE_MODE_EXIST_MASK) {
49193323Sed    case FTYPE_MODE_MUST_NOT_EXIST:
50193323Sed        if ((stat(fname, &sb) == 0) || (errno != ENOENT)) {
51193323Sed            if (errno == 0)
52198090Srdivacky                errno = EINVAL;
53193323Sed            fserr_exit(pOpts->pzProgName, "stat", fname);
54193323Sed            /* NOTREACHED */
55193323Sed        }
56193323Sed        /* FALLTHROUGH */
57193323Sed
58193323Sed    default:
59193323Sed    case FTYPE_MODE_MAY_EXIST:
60193323Sed    {
61193323Sed        char * p = strrchr(fname, DIRCH);
62193323Sed        size_t l;
63193323Sed
64193323Sed        if (p == NULL)
65193323Sed            /*
66193323Sed             *  The file may or may not exist and its directory is ".".
67193323Sed             *  Assume that "." exists.
68193323Sed             */
69193323Sed            break;
70193323Sed
71193323Sed        l = (size_t)(p - fname);
72193323Sed        p = AGALOC(l + 1, "fname");
73193323Sed        memcpy(p, fname, l);
74193323Sed        p[l] = NUL;
75193323Sed
76193323Sed        if ((stat(p, &sb) != 0) || (errno = EINVAL, ! S_ISDIR(sb.st_mode)))
77201360Srdivacky            fserr_exit(pOpts->pzProgName, "stat", p);
78201360Srdivacky            /* NOTREACHED */
79201360Srdivacky
80201360Srdivacky        AGFREE(p);
81193323Sed        break;
82193323Sed    }
83193323Sed
84193323Sed    case FTYPE_MODE_MUST_EXIST:
85193323Sed        if (  (stat(fname, &sb) != 0)
86193323Sed           || (errno = EINVAL, ! S_ISREG(sb.st_mode))  )
87193323Sed            fserr_exit(pOpts->pzProgName, "stat", fname);
88193323Sed            /* NOTREACHED */
89193323Sed
90193323Sed        break;
91193323Sed    }
92193323Sed}
93193323Sed
94193323Sed/**
95193323Sed *  Open the specified file with open(2) and save the FD.
96193323Sed *
97193323Sed * @param pOpts program option descriptor
98193323Sed * @param pOD   the option descriptor
99193323Sed * @param mode  the open mode (uses int flags value)
100193323Sed */
101193323Sedstatic void
102193323Sedopen_file_fd(tOptions * pOpts, tOptDesc * pOD, tuFileMode mode)
103193323Sed{
104193323Sed    int fd = open(pOD->optArg.argString, mode.file_flags);
105193323Sed    if (fd < 0)
106193323Sed        fserr_exit(pOpts->pzProgName, "open", pOD->optArg.argString);
107198892Srdivacky        /* NOTREACHED */
108193323Sed
109201360Srdivacky    if ((pOD->fOptState & OPTST_ALLOC_ARG) != 0)
110201360Srdivacky        pOD->optCookie = VOIDP(pOD->optArg.argString);
111201360Srdivacky    else
112201360Srdivacky        AGDUPSTR(pOD->optCookie, pOD->optArg.argString, "file name");
113201360Srdivacky
114201360Srdivacky    pOD->optArg.argFd = fd;
115201360Srdivacky    pOD->fOptState &= ~OPTST_ALLOC_ARG;
116201360Srdivacky}
117201360Srdivacky
118193323Sed/**
119198892Srdivacky *  Open the specified file with open(2) and save the FD.
120198892Srdivacky *
121201360Srdivacky * @param pOpts program option descriptor
122201360Srdivacky * @param pOD   the option descriptor
123198892Srdivacky * @param mode  the open mode (uses "char *" mode value)
124193323Sed */
125201360Srdivackystatic void
126201360Srdivackyfopen_file_fp(tOptions * pOpts, tOptDesc * pOD, tuFileMode mode)
127201360Srdivacky{
128201360Srdivacky    FILE * fp = fopen(pOD->optArg.argString, mode.file_mode);
129201360Srdivacky    if (fp == NULL)
130201360Srdivacky        fserr_exit(pOpts->pzProgName, "fopen", pOD->optArg.argString);
131201360Srdivacky        /* NOTREACHED */
132198892Srdivacky
133193323Sed    if ((pOD->fOptState & OPTST_ALLOC_ARG) != 0)
134198892Srdivacky        pOD->optCookie = VOIDP(pOD->optArg.argString);
135193323Sed    else
136198892Srdivacky        AGDUPSTR(pOD->optCookie, pOD->optArg.argString, "file name");
137193323Sed
138193323Sed    pOD->optArg.argFp = fp;
139193323Sed    pOD->fOptState &= ~OPTST_ALLOC_ARG;
140193323Sed}
141193323Sed
142193323Sed/*=export_func  optionFileCheck
143193323Sed * private:
144193323Sed *
145193323Sed * what:  Decipher a boolean value
146198892Srdivacky * arg:   + tOptions *    + pOpts    + program options descriptor  +
147193323Sed * arg:   + tOptDesc *    + pOptDesc + the descriptor for this arg +
148193323Sed * arg:   + teOptFileType + ftype    + File handling type          +
149193323Sed * arg:   + tuFileMode    + mode     + file open mode (if needed)  +
150193323Sed *
151193323Sed * doc:
152193323Sed *   Make sure the named file conforms with the file type mode.
153193323Sed *   The mode specifies if the file must exist, must not exist or may
154193323Sed *   (or may not) exist.  The mode may also specify opening the
155193323Sed *   file: don't, open just the descriptor (fd), or open as a stream
156193323Sed *   (FILE * pointer).
157193323Sed=*/
158193323Sedvoid
159193323SedoptionFileCheck(tOptions * pOpts, tOptDesc * pOD,
160198090Srdivacky                teOptFileType ftype, tuFileMode mode)
161198090Srdivacky{
162193323Sed    if (pOpts <= OPTPROC_EMIT_LIMIT) {
163198090Srdivacky        if (pOpts != OPTPROC_EMIT_USAGE)
164198090Srdivacky            return;
165198090Srdivacky
166198090Srdivacky        switch (ftype & FTYPE_MODE_EXIST_MASK) {
167198090Srdivacky        case FTYPE_MODE_MUST_NOT_EXIST:
168198090Srdivacky            fputs(zFileCannotExist + tab_skip_ct, option_usage_fp);
169198090Srdivacky            break;
170193323Sed
171193323Sed        case FTYPE_MODE_MUST_EXIST:
172193323Sed            fputs(zFileMustExist + tab_skip_ct, option_usage_fp);
173193323Sed            break;
174193323Sed        }
175193323Sed        return;
176193323Sed    }
177193323Sed
178193323Sed    if ((pOD->fOptState & OPTST_RESET) != 0) {
179193323Sed        if (pOD->optCookie != NULL)
180193323Sed            AGFREE(pOD->optCookie);
181193323Sed        return;
182193323Sed    }
183193323Sed
184193323Sed    check_existence(ftype, pOpts, pOD);
185193323Sed
186193323Sed    switch (ftype & FTYPE_MODE_OPEN_MASK) {
187193323Sed    default:
188193323Sed    case FTYPE_MODE_NO_OPEN:  break;
189193323Sed    case FTYPE_MODE_OPEN_FD:  open_file_fd( pOpts, pOD, mode); break;
190193323Sed    case FTYPE_MODE_FOPEN_FP: fopen_file_fp(pOpts, pOD, mode); break;
191193323Sed    }
192193323Sed}
193193323Sed
194193323Sed/** @}
195193323Sed *
196193323Sed * Local Variables:
197193323Sed * mode: C
198193323Sed * c-file-style: "stroustrup"
199193323Sed * indent-tabs-mode: nil
200193323Sed * End:
201193323Sed * end of autoopts/file.c */
202193323Sed