1258945Sroberto
2258945Sroberto/**
3258945Sroberto * \file file.c
4258945Sroberto *
5280849Scy * Handle options that have file names for arguments.
6258945Sroberto *
7280849Scy * @addtogroup autoopts
8280849Scy * @{
9280849Scy */
10280849Scy/*
11258945Sroberto *  This file is part of AutoOpts, a companion to AutoGen.
12258945Sroberto *  AutoOpts is free software.
13285169Scy *  AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved
14258945Sroberto *
15258945Sroberto *  AutoOpts is available under any one of two licenses.  The license
16258945Sroberto *  in use must be one of these two and the choice is under the control
17258945Sroberto *  of the user of the license.
18258945Sroberto *
19258945Sroberto *   The GNU Lesser General Public License, version 3 or later
20258945Sroberto *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
21258945Sroberto *
22258945Sroberto *   The Modified Berkeley Software Distribution License
23258945Sroberto *      See the file "COPYING.mbsd"
24258945Sroberto *
25280849Scy *  These files have the following sha256 sums:
26258945Sroberto *
27280849Scy *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
28280849Scy *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
29280849Scy *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
30258945Sroberto */
31258945Sroberto
32280849Scy/**
33280849Scy *  Make sure the directory containing the subject file exists and that
34280849Scy *  the file exists or does not exist, per the option requirements.
35280849Scy *
36280849Scy * @param ftype file existence type flags
37280849Scy * @param pOpts program option descriptor
38280849Scy * @param pOD   the option descriptor
39280849Scy */
40280849Scystatic void
41280849Scycheck_existence(teOptFileType ftype, tOptions * pOpts, tOptDesc * pOD)
42280849Scy{
43280849Scy    char const * fname = pOD->optArg.argString;
44280849Scy    struct stat sb;
45280849Scy
46280849Scy    errno = 0;
47280849Scy
48280849Scy    switch (ftype & FTYPE_MODE_EXIST_MASK) {
49280849Scy    case FTYPE_MODE_MUST_NOT_EXIST:
50280849Scy        if ((stat(fname, &sb) == 0) || (errno != ENOENT)) {
51280849Scy            if (errno == 0)
52280849Scy                errno = EINVAL;
53280849Scy            fserr_exit(pOpts->pzProgName, "stat", fname);
54280849Scy            /* NOTREACHED */
55280849Scy        }
56280849Scy        /* FALLTHROUGH */
57280849Scy
58280849Scy    default:
59280849Scy    case FTYPE_MODE_MAY_EXIST:
60280849Scy    {
61280849Scy        char * p = strrchr(fname, DIRCH);
62280849Scy        size_t l;
63280849Scy
64280849Scy        if (p == NULL)
65280849Scy            /*
66280849Scy             *  The file may or may not exist and its directory is ".".
67280849Scy             *  Assume that "." exists.
68280849Scy             */
69280849Scy            break;
70280849Scy
71280849Scy        l = (size_t)(p - fname);
72280849Scy        p = AGALOC(l + 1, "fname");
73280849Scy        memcpy(p, fname, l);
74280849Scy        p[l] = NUL;
75280849Scy
76280849Scy        if ((stat(p, &sb) != 0) || (errno = EINVAL, ! S_ISDIR(sb.st_mode)))
77280849Scy            fserr_exit(pOpts->pzProgName, "stat", p);
78280849Scy            /* NOTREACHED */
79280849Scy
80280849Scy        AGFREE(p);
81280849Scy        break;
82280849Scy    }
83280849Scy
84280849Scy    case FTYPE_MODE_MUST_EXIST:
85280849Scy        if (  (stat(fname, &sb) != 0)
86280849Scy           || (errno = EINVAL, ! S_ISREG(sb.st_mode))  )
87280849Scy            fserr_exit(pOpts->pzProgName, "stat", fname);
88280849Scy            /* NOTREACHED */
89280849Scy
90280849Scy        break;
91280849Scy    }
92280849Scy}
93280849Scy
94280849Scy/**
95280849Scy *  Open the specified file with open(2) and save the FD.
96280849Scy *
97280849Scy * @param pOpts program option descriptor
98280849Scy * @param pOD   the option descriptor
99280849Scy * @param mode  the open mode (uses int flags value)
100280849Scy */
101280849Scystatic void
102280849Scyopen_file_fd(tOptions * pOpts, tOptDesc * pOD, tuFileMode mode)
103280849Scy{
104280849Scy    int fd = open(pOD->optArg.argString, mode.file_flags);
105280849Scy    if (fd < 0)
106280849Scy        fserr_exit(pOpts->pzProgName, "open", pOD->optArg.argString);
107280849Scy        /* NOTREACHED */
108280849Scy
109280849Scy    if ((pOD->fOptState & OPTST_ALLOC_ARG) != 0)
110285169Scy        pOD->optCookie = VOIDP(pOD->optArg.argString);
111280849Scy    else
112280849Scy        AGDUPSTR(pOD->optCookie, pOD->optArg.argString, "file name");
113280849Scy
114280849Scy    pOD->optArg.argFd = fd;
115280849Scy    pOD->fOptState &= ~OPTST_ALLOC_ARG;
116280849Scy}
117280849Scy
118280849Scy/**
119280849Scy *  Open the specified file with open(2) and save the FD.
120280849Scy *
121280849Scy * @param pOpts program option descriptor
122280849Scy * @param pOD   the option descriptor
123280849Scy * @param mode  the open mode (uses "char *" mode value)
124280849Scy */
125280849Scystatic void
126280849Scyfopen_file_fp(tOptions * pOpts, tOptDesc * pOD, tuFileMode mode)
127280849Scy{
128280849Scy    FILE * fp = fopen(pOD->optArg.argString, mode.file_mode);
129280849Scy    if (fp == NULL)
130280849Scy        fserr_exit(pOpts->pzProgName, "fopen", pOD->optArg.argString);
131280849Scy        /* NOTREACHED */
132280849Scy
133280849Scy    if ((pOD->fOptState & OPTST_ALLOC_ARG) != 0)
134285169Scy        pOD->optCookie = VOIDP(pOD->optArg.argString);
135280849Scy    else
136280849Scy        AGDUPSTR(pOD->optCookie, pOD->optArg.argString, "file name");
137280849Scy
138280849Scy    pOD->optArg.argFp = fp;
139280849Scy    pOD->fOptState &= ~OPTST_ALLOC_ARG;
140280849Scy}
141280849Scy
142258945Sroberto/*=export_func  optionFileCheck
143258945Sroberto * private:
144258945Sroberto *
145258945Sroberto * what:  Decipher a boolean value
146285169Scy * arg:   + tOptions *    + pOpts    + program options descriptor  +
147285169Scy * arg:   + tOptDesc *    + pOptDesc + the descriptor for this arg +
148258945Sroberto * arg:   + teOptFileType + ftype    + File handling type          +
149258945Sroberto * arg:   + tuFileMode    + mode     + file open mode (if needed)  +
150258945Sroberto *
151258945Sroberto * doc:
152258945Sroberto *   Make sure the named file conforms with the file type mode.
153258945Sroberto *   The mode specifies if the file must exist, must not exist or may
154258945Sroberto *   (or may not) exist.  The mode may also specify opening the
155258945Sroberto *   file: don't, open just the descriptor (fd), or open as a stream
156285169Scy *   (FILE * pointer).
157258945Sroberto=*/
158258945Srobertovoid
159280849ScyoptionFileCheck(tOptions * pOpts, tOptDesc * pOD,
160258945Sroberto                teOptFileType ftype, tuFileMode mode)
161258945Sroberto{
162258945Sroberto    if (pOpts <= OPTPROC_EMIT_LIMIT) {
163258945Sroberto        if (pOpts != OPTPROC_EMIT_USAGE)
164258945Sroberto            return;
165258945Sroberto
166258945Sroberto        switch (ftype & FTYPE_MODE_EXIST_MASK) {
167258945Sroberto        case FTYPE_MODE_MUST_NOT_EXIST:
168280849Scy            fputs(zFileCannotExist + tab_skip_ct, option_usage_fp);
169258945Sroberto            break;
170258945Sroberto
171258945Sroberto        case FTYPE_MODE_MUST_EXIST:
172280849Scy            fputs(zFileMustExist + tab_skip_ct, option_usage_fp);
173258945Sroberto            break;
174258945Sroberto        }
175258945Sroberto        return;
176258945Sroberto    }
177258945Sroberto
178258945Sroberto    if ((pOD->fOptState & OPTST_RESET) != 0) {
179258945Sroberto        if (pOD->optCookie != NULL)
180258945Sroberto            AGFREE(pOD->optCookie);
181258945Sroberto        return;
182258945Sroberto    }
183258945Sroberto
184280849Scy    check_existence(ftype, pOpts, pOD);
185258945Sroberto
186258945Sroberto    switch (ftype & FTYPE_MODE_OPEN_MASK) {
187258945Sroberto    default:
188280849Scy    case FTYPE_MODE_NO_OPEN:  break;
189280849Scy    case FTYPE_MODE_OPEN_FD:  open_file_fd( pOpts, pOD, mode); break;
190280849Scy    case FTYPE_MODE_FOPEN_FP: fopen_file_fp(pOpts, pOD, mode); break;
191258945Sroberto    }
192280849Scy}
193258945Sroberto
194280849Scy/** @}
195280849Scy *
196258945Sroberto * Local Variables:
197258945Sroberto * mode: C
198258945Sroberto * c-file-style: "stroustrup"
199258945Sroberto * indent-tabs-mode: nil
200258945Sroberto * End:
201258945Sroberto * end of autoopts/file.c */
202