/* Copyright (C) 2015-2020, Dirk Krause SPDX-License-Identifier: BSD-3-Clause */ /* WARNING: This file was generated by the dkct program (see http://dktools.sourceforge.net/ for details). Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk4fopc8.ctr */ /** @file dk4fopc8.c The dk4fopc8 module. */ #line 131 "dk4fopc8.ctr" #include "dk4conf.h" #if DK4_ON_WINDOWS #ifndef WINDOWS_H_INCLUDED #include #define WINDOWS_H_INCLUDED 1 #endif #endif #include "dk4fopc8.h" #ifndef DK4STAT8_H_INCLUDED #include "dk4stat8.h" #endif #ifndef DK4STAT_H_INCLUDED #include "dk4stat.h" #endif #ifndef DK4MPL_H_INCLUDED #include "dk4mpl.h" #endif #ifndef DK4STR8_H_INCLUDED #include "dk4str8.h" #endif #ifndef DK4UNUSED_H_INCLUDED #include "dk4unused.h" #endif #if DK4_HAVE_SYS_TYPES_H #ifndef SYS_TYPES_H_INCLUDED #include #define SYS_TYPES_H_INCLUDED 1 #endif #endif #if DK4_HAVE_UNISTD_H #ifndef UNISTD_H_INCLUDED #include #define UNISTD_H_INCLUDED 1 #endif #endif #if DK4_HAVE_ERRNO_H #ifndef ERRNO_H_INCLUDED #include #define ERRNO_H_INCLUDED 1 #endif #endif #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif #line 193 "dk4fopc8.ctr" #if !DK4_ON_WINDOWS #if DK4_HAVE_BACKSLASH_AS_SEP /** Path component separator. */ static const unsigned char sep = '\\'; #else /** Path component separator. */ static const unsigned char sep = '/'; #endif /** Check whether one of the components in the path is a symbolic link. @param name Path name to check. @return 1 if there is no symlink in the path, 0 otherwise. */ static int dk4fopen_check_no_symlink_in_path(const char *name) { char buf[DK4_MAX_PATH]; dk4_stat_t lstb; char *p1; int back = 0; #if DK4_USE_ASSERT assert(NULL != name); #endif if (sizeof(buf) > dk4str8_len(name)) { back = 1; dk4str8_cpy_s(buf, sizeof(buf), name, NULL); p1 = dk4str8_chr(buf, sep); while ((NULL != p1) && (1 == back)) { *p1 = '\0'; if (0 < dk4str8_len(buf)) { if (0 != dk4stat_l_c8(&lstb, buf, NULL)) { if (0 != dk4stat_is_symlink(&lstb, NULL)) { back = 0; } } } *(p1++) = sep; p1 = dk4str8_chr(p1, sep); } } return back; } #endif int dk4fopen_check_c8( const char *name, #if DK4_ON_WINDOWS int DK4_ARG_UNUSED(ww), int DK4_ARG_UNUSED(tests), #else int ww, int tests, #endif dk4_er_t *erp ) { #if DK4_ON_WINDOWS WIN32_FIND_DATAA ffdata; HANDLE ha; DWORD dwattr; int back = 1; DK4_UNUSED_ARG(ww) DK4_UNUSED_ARG(tests) #line 265 "dk4fopc8.ctr" /* Check name */ #if DK4_USE_ASSERT assert(NULL != name); #endif if (NULL == name) { #line 271 "dk4fopc8.ctr" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); back = 0; goto finished; } /* Retrieve attributes. */ dwattr = GetFileAttributesA(name); if (INVALID_FILE_ATTRIBUTES == dwattr) { ha = FindFirstFileA(name, &ffdata); if (INVALID_HANDLE_VALUE != ha) { dwattr = ffdata.dwFileAttributes; FindClose(ha); } } if (INVALID_FILE_ATTRIBUTES == dwattr) { #line 286 "dk4fopc8.ctr" goto finished; } /* Check directory */ if ((DWORD)0UL != (FILE_ATTRIBUTE_DIRECTORY & dwattr)) { #line 291 "dk4fopc8.ctr" back = 0; dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); goto finished; } /* Check device */ if ((DWORD)0UL != (FILE_ATTRIBUTE_DEVICE & dwattr)) { #line 298 "dk4fopc8.ctr" back = 0; dk4error_set_idetails(erp, DK4_E_SEC_CHECK, DK4_FOPEN_SC_IS_REGULAR); } finished: #line 303 "dk4fopc8.ctr" return back; #else dk4_stat_t stb; dk4_stat_t lstb; int back = 1; #line 309 "dk4fopc8.ctr" /* Check name argument. */ if (NULL == name) { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); back = 0; goto finished; } /* Check existing path. */ if (0 == dk4stat_c8(&stb, name, NULL)) { #line 321 "dk4fopc8.ctr" goto finished; } /* Check directory. */ if (0 != dk4stat_is_directory(&stb, NULL)) { #line 327 "dk4fopc8.ctr" dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); back = 0; goto finished; } /* Write regular files only. */ if ((0 != ww) && (0 != (tests & DK4_FOPEN_SC_IS_REGULAR))) { if (0 == dk4stat_is_regular(&stb, NULL)) { #line 336 "dk4fopc8.ctr" dk4error_set_idetails(erp, DK4_E_SEC_CHECK, DK4_FOPEN_SC_IS_REGULAR); back = 0; goto finished; } } /* Do not write if any path element is a symbolic link. */ if ((0 != ww) && (0 != (tests & DK4_FOPEN_SC_WR_SYMLINK_IN_PATH))) { if (0 == dk4fopen_check_no_symlink_in_path(name)) { #line 346 "dk4fopc8.ctr" dk4error_set_idetails(erp, DK4_E_SEC_CHECK, DK4_FOPEN_SC_WR_SYMLINK_IN_PATH); back = 0; goto finished; } } /* Obtain symbolic link information. */ if (0 == dk4stat_l_c8(&lstb, name, NULL)) { #line 355 "dk4fopc8.ctr" goto finished; } /* Do not write to file via link. */ if ((0 != ww) && (0 != (tests & DK4_FOPEN_SC_WR_PATH_IS_SYMLINK))) { if (0 != dk4stat_is_symlink(&lstb, NULL)) { #line 362 "dk4fopc8.ctr" dk4error_set_idetails(erp, DK4_E_SEC_CHECK, DK4_FOPEN_SC_WR_PATH_IS_SYMLINK); back = 0; goto finished; } } /* Do not write file via link if file owner differs from link owner. */ #if DK4_HAVE_FILE_UIDGID if ((0 != ww) && (0 != (tests & DK4_FOPEN_SC_WR_SYMLINK_OWNER))) { if (lstb.st_uid != stb.st_uid) { #line 373 "dk4fopc8.ctr" dk4error_set_idetails(erp, DK4_E_SEC_CHECK, DK4_FOPEN_SC_WR_SYMLINK_OWNER); back = 0; goto finished; } } #endif finished: #line 381 "dk4fopc8.ctr" return back; #endif } FILE * dk4fopen_c8(const char *name, const char *mode, int tests, dk4_er_t *erp) { FILE *back = NULL; /* Result */ const char *cptr; /* Traverse mode */ int ww = 0; /* Flag: Want to write */ #if DK4_HAVE_FOPEN_S errno_t errn; #endif #if DK4_USE_ASSERT assert(NULL != name); assert(NULL != mode); #endif if ((NULL != name) && (NULL != mode)) { cptr = mode; while (*cptr) { switch (*cptr) { case 'w': case 'a': case '+': { ww = 1; } break; } cptr++; } if (0 != dk4fopen_check_c8(name, ww, tests, erp)) { #if DK4_HAVE_FOPEN_S errn = fopen_s(&back, name, mode); if (0 != errn) { back = NULL; dk4error_set_idetails( erp, ((ww) ? DK4_E_OPEN_WRITE_FAILED : DK4_E_OPEN_READ_FAILED), errn ); } #else #if DK4_HAVE_LARGEFILE64_SOURCE && DK4_HAVE_FOPEN64 errno = 0; back = fopen64(name, mode); if (NULL == back) { dk4error_set_idetails( erp, ((ww) ? DK4_E_OPEN_WRITE_FAILED : DK4_E_OPEN_READ_FAILED), errno ); } #else errno = 0; back = fopen(name, mode); if (NULL == back) { dk4error_set_idetails( erp, ((ww) ? DK4_E_OPEN_WRITE_FAILED : DK4_E_OPEN_READ_FAILED), errno ); } #endif #endif } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; }