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