1/* $NetBSD: fsaccess.c,v 1.1 2024/02/18 20:57:57 christos Exp $ */ 2 3/* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16#include <errno.h> 17#include <stdbool.h> 18#include <sys/stat.h> 19#include <sys/types.h> 20 21#include "errno2result.h" 22 23/*! \file 24 * \brief 25 * The OS-independent part of the API is in lib/isc. 26 */ 27#include "../fsaccess.c" 28 29isc_result_t 30isc_fsaccess_set(const char *path, isc_fsaccess_t access) { 31 struct stat statb; 32 mode_t mode; 33 bool is_dir = false; 34 isc_fsaccess_t bits; 35 isc_result_t result; 36 37 if (stat(path, &statb) != 0) { 38 return (isc__errno2result(errno)); 39 } 40 41 if ((statb.st_mode & S_IFDIR) != 0) { 42 is_dir = true; 43 } else if ((statb.st_mode & S_IFREG) == 0) { 44 return (ISC_R_INVALIDFILE); 45 } 46 47 result = check_bad_bits(access, is_dir); 48 if (result != ISC_R_SUCCESS) { 49 return (result); 50 } 51 52 /* 53 * Done with checking bad bits. Set mode_t. 54 */ 55 mode = 0; 56 57#define SET_AND_CLEAR1(modebit) \ 58 if ((access & bits) != 0) { \ 59 mode |= modebit; \ 60 access &= ~bits; \ 61 } 62#define SET_AND_CLEAR(user, group, other) \ 63 SET_AND_CLEAR1(user); \ 64 bits <<= STEP; \ 65 SET_AND_CLEAR1(group); \ 66 bits <<= STEP; \ 67 SET_AND_CLEAR1(other); 68 69 bits = ISC_FSACCESS_READ | ISC_FSACCESS_LISTDIRECTORY; 70 71 SET_AND_CLEAR(S_IRUSR, S_IRGRP, S_IROTH); 72 73 bits = ISC_FSACCESS_WRITE | ISC_FSACCESS_CREATECHILD | 74 ISC_FSACCESS_DELETECHILD; 75 76 SET_AND_CLEAR(S_IWUSR, S_IWGRP, S_IWOTH); 77 78 bits = ISC_FSACCESS_EXECUTE | ISC_FSACCESS_ACCESSCHILD; 79 80 SET_AND_CLEAR(S_IXUSR, S_IXGRP, S_IXOTH); 81 82 INSIST(access == 0); 83 84 if (chmod(path, mode) < 0) { 85 return (isc__errno2result(errno)); 86 } 87 88 return (ISC_R_SUCCESS); 89} 90