1*c243e490SMarcel Moolenaar /* 2*c243e490SMarcel Moolenaar * Automated Testing Framework (atf) 3*c243e490SMarcel Moolenaar * 4*c243e490SMarcel Moolenaar * Copyright (c) 2007 The NetBSD Foundation, Inc. 5*c243e490SMarcel Moolenaar * All rights reserved. 6*c243e490SMarcel Moolenaar * 7*c243e490SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 8*c243e490SMarcel Moolenaar * modification, are permitted provided that the following conditions 9*c243e490SMarcel Moolenaar * are met: 10*c243e490SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 11*c243e490SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 12*c243e490SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 13*c243e490SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 14*c243e490SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 15*c243e490SMarcel Moolenaar * 16*c243e490SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17*c243e490SMarcel Moolenaar * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18*c243e490SMarcel Moolenaar * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19*c243e490SMarcel Moolenaar * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20*c243e490SMarcel Moolenaar * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21*c243e490SMarcel Moolenaar * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*c243e490SMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23*c243e490SMarcel Moolenaar * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24*c243e490SMarcel Moolenaar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25*c243e490SMarcel Moolenaar * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26*c243e490SMarcel Moolenaar * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27*c243e490SMarcel Moolenaar * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*c243e490SMarcel Moolenaar */ 29*c243e490SMarcel Moolenaar 30*c243e490SMarcel Moolenaar #if defined(HAVE_CONFIG_H) 31*c243e490SMarcel Moolenaar #include "bconfig.h" 32*c243e490SMarcel Moolenaar #endif 33*c243e490SMarcel Moolenaar 34*c243e490SMarcel Moolenaar #include <sys/types.h> 35*c243e490SMarcel Moolenaar #include <sys/param.h> 36*c243e490SMarcel Moolenaar #include <sys/mount.h> 37*c243e490SMarcel Moolenaar #include <sys/stat.h> 38*c243e490SMarcel Moolenaar #include <sys/wait.h> 39*c243e490SMarcel Moolenaar 40*c243e490SMarcel Moolenaar #include <dirent.h> 41*c243e490SMarcel Moolenaar #include <errno.h> 42*c243e490SMarcel Moolenaar #include <libgen.h> 43*c243e490SMarcel Moolenaar #include <stdarg.h> 44*c243e490SMarcel Moolenaar #include <stdio.h> 45*c243e490SMarcel Moolenaar #include <stdlib.h> 46*c243e490SMarcel Moolenaar #include <string.h> 47*c243e490SMarcel Moolenaar #include <unistd.h> 48*c243e490SMarcel Moolenaar 49*c243e490SMarcel Moolenaar #include "atf-c/defs.h" 50*c243e490SMarcel Moolenaar #include "atf-c/error.h" 51*c243e490SMarcel Moolenaar 52*c243e490SMarcel Moolenaar #include "fs.h" 53*c243e490SMarcel Moolenaar #include "sanity.h" 54*c243e490SMarcel Moolenaar #include "text.h" 55*c243e490SMarcel Moolenaar #include "user.h" 56*c243e490SMarcel Moolenaar 57*c243e490SMarcel Moolenaar /* --------------------------------------------------------------------- 58*c243e490SMarcel Moolenaar * Prototypes for auxiliary functions. 59*c243e490SMarcel Moolenaar * --------------------------------------------------------------------- */ 60*c243e490SMarcel Moolenaar 61*c243e490SMarcel Moolenaar static bool check_umask(const mode_t, const mode_t); 62*c243e490SMarcel Moolenaar static atf_error_t copy_contents(const atf_fs_path_t *, char **); 63*c243e490SMarcel Moolenaar static mode_t current_umask(void); 64*c243e490SMarcel Moolenaar static atf_error_t do_mkdtemp(char *); 65*c243e490SMarcel Moolenaar static atf_error_t normalize(atf_dynstr_t *, char *); 66*c243e490SMarcel Moolenaar static atf_error_t normalize_ap(atf_dynstr_t *, const char *, va_list); 67*c243e490SMarcel Moolenaar static void replace_contents(atf_fs_path_t *, const char *); 68*c243e490SMarcel Moolenaar static const char *stat_type_to_string(const int); 69*c243e490SMarcel Moolenaar 70*c243e490SMarcel Moolenaar /* --------------------------------------------------------------------- 71*c243e490SMarcel Moolenaar * The "invalid_umask" error type. 72*c243e490SMarcel Moolenaar * --------------------------------------------------------------------- */ 73*c243e490SMarcel Moolenaar 74*c243e490SMarcel Moolenaar struct invalid_umask_error_data { 75*c243e490SMarcel Moolenaar /* One of atf_fs_stat_*_type. */ 76*c243e490SMarcel Moolenaar int m_type; 77*c243e490SMarcel Moolenaar 78*c243e490SMarcel Moolenaar /* The original path causing the error. */ 79*c243e490SMarcel Moolenaar /* XXX: Ideally this would be an atf_fs_path_t, but if we create it 80*c243e490SMarcel Moolenaar * from the error constructor, we cannot delete the path later on. 81*c243e490SMarcel Moolenaar * Can't remember why atf_error_new does not take a hook for 82*c243e490SMarcel Moolenaar * deletion. */ 83*c243e490SMarcel Moolenaar char m_path[1024]; 84*c243e490SMarcel Moolenaar 85*c243e490SMarcel Moolenaar /* The umask that caused the error. */ 86*c243e490SMarcel Moolenaar mode_t m_umask; 87*c243e490SMarcel Moolenaar }; 88*c243e490SMarcel Moolenaar typedef struct invalid_umask_error_data invalid_umask_error_data_t; 89*c243e490SMarcel Moolenaar 90*c243e490SMarcel Moolenaar static 91*c243e490SMarcel Moolenaar void 92*c243e490SMarcel Moolenaar invalid_umask_format(const atf_error_t err, char *buf, size_t buflen) 93*c243e490SMarcel Moolenaar { 94*c243e490SMarcel Moolenaar const invalid_umask_error_data_t *data; 95*c243e490SMarcel Moolenaar 96*c243e490SMarcel Moolenaar PRE(atf_error_is(err, "invalid_umask")); 97*c243e490SMarcel Moolenaar 98*c243e490SMarcel Moolenaar data = atf_error_data(err); 99*c243e490SMarcel Moolenaar snprintf(buf, buflen, "Could not create the temporary %s %s because " 100*c243e490SMarcel Moolenaar "it will not have enough access rights due to the current " 101*c243e490SMarcel Moolenaar "umask %05o", stat_type_to_string(data->m_type), 102*c243e490SMarcel Moolenaar data->m_path, (unsigned int)data->m_umask); 103*c243e490SMarcel Moolenaar } 104*c243e490SMarcel Moolenaar 105*c243e490SMarcel Moolenaar static 106*c243e490SMarcel Moolenaar atf_error_t 107*c243e490SMarcel Moolenaar invalid_umask_error(const atf_fs_path_t *path, const int type, 108*c243e490SMarcel Moolenaar const mode_t failing_mask) 109*c243e490SMarcel Moolenaar { 110*c243e490SMarcel Moolenaar atf_error_t err; 111*c243e490SMarcel Moolenaar invalid_umask_error_data_t data; 112*c243e490SMarcel Moolenaar 113*c243e490SMarcel Moolenaar data.m_type = type; 114*c243e490SMarcel Moolenaar 115*c243e490SMarcel Moolenaar strncpy(data.m_path, atf_fs_path_cstring(path), sizeof(data.m_path)); 116*c243e490SMarcel Moolenaar data.m_path[sizeof(data.m_path) - 1] = '\0'; 117*c243e490SMarcel Moolenaar 118*c243e490SMarcel Moolenaar data.m_umask = failing_mask; 119*c243e490SMarcel Moolenaar 120*c243e490SMarcel Moolenaar err = atf_error_new("invalid_umask", &data, sizeof(data), 121*c243e490SMarcel Moolenaar invalid_umask_format); 122*c243e490SMarcel Moolenaar 123*c243e490SMarcel Moolenaar return err; 124*c243e490SMarcel Moolenaar } 125*c243e490SMarcel Moolenaar 126*c243e490SMarcel Moolenaar /* --------------------------------------------------------------------- 127*c243e490SMarcel Moolenaar * The "unknown_file_type" error type. 128*c243e490SMarcel Moolenaar * --------------------------------------------------------------------- */ 129*c243e490SMarcel Moolenaar 130*c243e490SMarcel Moolenaar struct unknown_type_error_data { 131*c243e490SMarcel Moolenaar const char *m_path; 132*c243e490SMarcel Moolenaar int m_type; 133*c243e490SMarcel Moolenaar }; 134*c243e490SMarcel Moolenaar typedef struct unknown_type_error_data unknown_type_error_data_t; 135*c243e490SMarcel Moolenaar 136*c243e490SMarcel Moolenaar static 137*c243e490SMarcel Moolenaar void 138*c243e490SMarcel Moolenaar unknown_type_format(const atf_error_t err, char *buf, size_t buflen) 139*c243e490SMarcel Moolenaar { 140*c243e490SMarcel Moolenaar const unknown_type_error_data_t *data; 141*c243e490SMarcel Moolenaar 142*c243e490SMarcel Moolenaar PRE(atf_error_is(err, "unknown_type")); 143*c243e490SMarcel Moolenaar 144*c243e490SMarcel Moolenaar data = atf_error_data(err); 145*c243e490SMarcel Moolenaar snprintf(buf, buflen, "Unknown file type %d of %s", data->m_type, 146*c243e490SMarcel Moolenaar data->m_path); 147*c243e490SMarcel Moolenaar } 148*c243e490SMarcel Moolenaar 149*c243e490SMarcel Moolenaar static 150*c243e490SMarcel Moolenaar atf_error_t 151*c243e490SMarcel Moolenaar unknown_type_error(const char *path, int type) 152*c243e490SMarcel Moolenaar { 153*c243e490SMarcel Moolenaar atf_error_t err; 154*c243e490SMarcel Moolenaar unknown_type_error_data_t data; 155*c243e490SMarcel Moolenaar 156*c243e490SMarcel Moolenaar data.m_path = path; 157*c243e490SMarcel Moolenaar data.m_type = type; 158*c243e490SMarcel Moolenaar 159*c243e490SMarcel Moolenaar err = atf_error_new("unknown_type", &data, sizeof(data), 160*c243e490SMarcel Moolenaar unknown_type_format); 161*c243e490SMarcel Moolenaar 162*c243e490SMarcel Moolenaar return err; 163*c243e490SMarcel Moolenaar } 164*c243e490SMarcel Moolenaar 165*c243e490SMarcel Moolenaar /* --------------------------------------------------------------------- 166*c243e490SMarcel Moolenaar * Auxiliary functions. 167*c243e490SMarcel Moolenaar * --------------------------------------------------------------------- */ 168*c243e490SMarcel Moolenaar 169*c243e490SMarcel Moolenaar static 170*c243e490SMarcel Moolenaar bool 171*c243e490SMarcel Moolenaar check_umask(const mode_t exp_mode, const mode_t min_mode) 172*c243e490SMarcel Moolenaar { 173*c243e490SMarcel Moolenaar const mode_t actual_mode = (~current_umask() & exp_mode); 174*c243e490SMarcel Moolenaar return (actual_mode & min_mode) == min_mode; 175*c243e490SMarcel Moolenaar } 176*c243e490SMarcel Moolenaar 177*c243e490SMarcel Moolenaar static 178*c243e490SMarcel Moolenaar atf_error_t 179*c243e490SMarcel Moolenaar copy_contents(const atf_fs_path_t *p, char **buf) 180*c243e490SMarcel Moolenaar { 181*c243e490SMarcel Moolenaar atf_error_t err; 182*c243e490SMarcel Moolenaar char *str; 183*c243e490SMarcel Moolenaar 184*c243e490SMarcel Moolenaar str = (char *)malloc(atf_dynstr_length(&p->m_data) + 1); 185*c243e490SMarcel Moolenaar if (str == NULL) 186*c243e490SMarcel Moolenaar err = atf_no_memory_error(); 187*c243e490SMarcel Moolenaar else { 188*c243e490SMarcel Moolenaar strcpy(str, atf_dynstr_cstring(&p->m_data)); 189*c243e490SMarcel Moolenaar *buf = str; 190*c243e490SMarcel Moolenaar err = atf_no_error(); 191*c243e490SMarcel Moolenaar } 192*c243e490SMarcel Moolenaar 193*c243e490SMarcel Moolenaar return err; 194*c243e490SMarcel Moolenaar } 195*c243e490SMarcel Moolenaar 196*c243e490SMarcel Moolenaar static 197*c243e490SMarcel Moolenaar mode_t 198*c243e490SMarcel Moolenaar current_umask(void) 199*c243e490SMarcel Moolenaar { 200*c243e490SMarcel Moolenaar const mode_t current = umask(0); 201*c243e490SMarcel Moolenaar (void)umask(current); 202*c243e490SMarcel Moolenaar return current; 203*c243e490SMarcel Moolenaar } 204*c243e490SMarcel Moolenaar 205*c243e490SMarcel Moolenaar static 206*c243e490SMarcel Moolenaar atf_error_t 207*c243e490SMarcel Moolenaar do_mkdtemp(char *tmpl) 208*c243e490SMarcel Moolenaar { 209*c243e490SMarcel Moolenaar atf_error_t err; 210*c243e490SMarcel Moolenaar 211*c243e490SMarcel Moolenaar PRE(strstr(tmpl, "XXXXXX") != NULL); 212*c243e490SMarcel Moolenaar 213*c243e490SMarcel Moolenaar if (mkdtemp(tmpl) == NULL) 214*c243e490SMarcel Moolenaar err = atf_libc_error(errno, "Cannot create temporary directory " 215*c243e490SMarcel Moolenaar "with template '%s'", tmpl); 216*c243e490SMarcel Moolenaar else 217*c243e490SMarcel Moolenaar err = atf_no_error(); 218*c243e490SMarcel Moolenaar 219*c243e490SMarcel Moolenaar return err; 220*c243e490SMarcel Moolenaar } 221*c243e490SMarcel Moolenaar 222*c243e490SMarcel Moolenaar static 223*c243e490SMarcel Moolenaar atf_error_t 224*c243e490SMarcel Moolenaar do_mkstemp(char *tmpl, int *fdout) 225*c243e490SMarcel Moolenaar { 226*c243e490SMarcel Moolenaar atf_error_t err; 227*c243e490SMarcel Moolenaar 228*c243e490SMarcel Moolenaar PRE(strstr(tmpl, "XXXXXX") != NULL); 229*c243e490SMarcel Moolenaar 230*c243e490SMarcel Moolenaar *fdout = mkstemp(tmpl); 231*c243e490SMarcel Moolenaar if (*fdout == -1) 232*c243e490SMarcel Moolenaar err = atf_libc_error(errno, "Cannot create temporary file " 233*c243e490SMarcel Moolenaar "with template '%s'", tmpl); 234*c243e490SMarcel Moolenaar 235*c243e490SMarcel Moolenaar else 236*c243e490SMarcel Moolenaar err = atf_no_error(); 237*c243e490SMarcel Moolenaar 238*c243e490SMarcel Moolenaar return err; 239*c243e490SMarcel Moolenaar } 240*c243e490SMarcel Moolenaar 241*c243e490SMarcel Moolenaar static 242*c243e490SMarcel Moolenaar atf_error_t 243*c243e490SMarcel Moolenaar normalize(atf_dynstr_t *d, char *p) 244*c243e490SMarcel Moolenaar { 245*c243e490SMarcel Moolenaar const char *ptr; 246*c243e490SMarcel Moolenaar char *last; 247*c243e490SMarcel Moolenaar atf_error_t err; 248*c243e490SMarcel Moolenaar bool first; 249*c243e490SMarcel Moolenaar 250*c243e490SMarcel Moolenaar PRE(strlen(p) > 0); 251*c243e490SMarcel Moolenaar PRE(atf_dynstr_length(d) == 0); 252*c243e490SMarcel Moolenaar 253*c243e490SMarcel Moolenaar if (p[0] == '/') 254*c243e490SMarcel Moolenaar err = atf_dynstr_append_fmt(d, "/"); 255*c243e490SMarcel Moolenaar else 256*c243e490SMarcel Moolenaar err = atf_no_error(); 257*c243e490SMarcel Moolenaar 258*c243e490SMarcel Moolenaar first = true; 259*c243e490SMarcel Moolenaar last = NULL; /* Silence GCC warning. */ 260*c243e490SMarcel Moolenaar ptr = strtok_r(p, "/", &last); 261*c243e490SMarcel Moolenaar while (!atf_is_error(err) && ptr != NULL) { 262*c243e490SMarcel Moolenaar if (strlen(ptr) > 0) { 263*c243e490SMarcel Moolenaar err = atf_dynstr_append_fmt(d, "%s%s", first ? "" : "/", ptr); 264*c243e490SMarcel Moolenaar first = false; 265*c243e490SMarcel Moolenaar } 266*c243e490SMarcel Moolenaar 267*c243e490SMarcel Moolenaar ptr = strtok_r(NULL, "/", &last); 268*c243e490SMarcel Moolenaar } 269*c243e490SMarcel Moolenaar 270*c243e490SMarcel Moolenaar return err; 271*c243e490SMarcel Moolenaar } 272*c243e490SMarcel Moolenaar 273*c243e490SMarcel Moolenaar static 274*c243e490SMarcel Moolenaar atf_error_t 275*c243e490SMarcel Moolenaar normalize_ap(atf_dynstr_t *d, const char *p, va_list ap) 276*c243e490SMarcel Moolenaar { 277*c243e490SMarcel Moolenaar char *str; 278*c243e490SMarcel Moolenaar atf_error_t err; 279*c243e490SMarcel Moolenaar va_list ap2; 280*c243e490SMarcel Moolenaar 281*c243e490SMarcel Moolenaar err = atf_dynstr_init(d); 282*c243e490SMarcel Moolenaar if (atf_is_error(err)) 283*c243e490SMarcel Moolenaar goto out; 284*c243e490SMarcel Moolenaar 285*c243e490SMarcel Moolenaar va_copy(ap2, ap); 286*c243e490SMarcel Moolenaar err = atf_text_format_ap(&str, p, ap2); 287*c243e490SMarcel Moolenaar va_end(ap2); 288*c243e490SMarcel Moolenaar if (atf_is_error(err)) 289*c243e490SMarcel Moolenaar atf_dynstr_fini(d); 290*c243e490SMarcel Moolenaar else { 291*c243e490SMarcel Moolenaar err = normalize(d, str); 292*c243e490SMarcel Moolenaar free(str); 293*c243e490SMarcel Moolenaar } 294*c243e490SMarcel Moolenaar 295*c243e490SMarcel Moolenaar out: 296*c243e490SMarcel Moolenaar return err; 297*c243e490SMarcel Moolenaar } 298*c243e490SMarcel Moolenaar 299*c243e490SMarcel Moolenaar static 300*c243e490SMarcel Moolenaar void 301*c243e490SMarcel Moolenaar replace_contents(atf_fs_path_t *p, const char *buf) 302*c243e490SMarcel Moolenaar { 303*c243e490SMarcel Moolenaar atf_error_t err; 304*c243e490SMarcel Moolenaar 305*c243e490SMarcel Moolenaar PRE(atf_dynstr_length(&p->m_data) == strlen(buf)); 306*c243e490SMarcel Moolenaar 307*c243e490SMarcel Moolenaar atf_dynstr_clear(&p->m_data); 308*c243e490SMarcel Moolenaar err = atf_dynstr_append_fmt(&p->m_data, "%s", buf); 309*c243e490SMarcel Moolenaar 310*c243e490SMarcel Moolenaar INV(!atf_is_error(err)); 311*c243e490SMarcel Moolenaar } 312*c243e490SMarcel Moolenaar 313*c243e490SMarcel Moolenaar static 314*c243e490SMarcel Moolenaar const char * 315*c243e490SMarcel Moolenaar stat_type_to_string(const int type) 316*c243e490SMarcel Moolenaar { 317*c243e490SMarcel Moolenaar const char *str; 318*c243e490SMarcel Moolenaar 319*c243e490SMarcel Moolenaar if (type == atf_fs_stat_blk_type) 320*c243e490SMarcel Moolenaar str = "block device"; 321*c243e490SMarcel Moolenaar else if (type == atf_fs_stat_chr_type) 322*c243e490SMarcel Moolenaar str = "character device"; 323*c243e490SMarcel Moolenaar else if (type == atf_fs_stat_dir_type) 324*c243e490SMarcel Moolenaar str = "directory"; 325*c243e490SMarcel Moolenaar else if (type == atf_fs_stat_fifo_type) 326*c243e490SMarcel Moolenaar str = "named pipe"; 327*c243e490SMarcel Moolenaar else if (type == atf_fs_stat_lnk_type) 328*c243e490SMarcel Moolenaar str = "symbolic link"; 329*c243e490SMarcel Moolenaar else if (type == atf_fs_stat_reg_type) 330*c243e490SMarcel Moolenaar str = "regular file"; 331*c243e490SMarcel Moolenaar else if (type == atf_fs_stat_sock_type) 332*c243e490SMarcel Moolenaar str = "socket"; 333*c243e490SMarcel Moolenaar else if (type == atf_fs_stat_wht_type) 334*c243e490SMarcel Moolenaar str = "whiteout"; 335*c243e490SMarcel Moolenaar else { 336*c243e490SMarcel Moolenaar UNREACHABLE; 337*c243e490SMarcel Moolenaar str = NULL; 338*c243e490SMarcel Moolenaar } 339*c243e490SMarcel Moolenaar 340*c243e490SMarcel Moolenaar return str; 341*c243e490SMarcel Moolenaar } 342*c243e490SMarcel Moolenaar 343*c243e490SMarcel Moolenaar /* --------------------------------------------------------------------- 344*c243e490SMarcel Moolenaar * The "atf_fs_path" type. 345*c243e490SMarcel Moolenaar * --------------------------------------------------------------------- */ 346*c243e490SMarcel Moolenaar 347*c243e490SMarcel Moolenaar /* 348*c243e490SMarcel Moolenaar * Constructors/destructors. 349*c243e490SMarcel Moolenaar */ 350*c243e490SMarcel Moolenaar 351*c243e490SMarcel Moolenaar atf_error_t 352*c243e490SMarcel Moolenaar atf_fs_path_init_ap(atf_fs_path_t *p, const char *fmt, va_list ap) 353*c243e490SMarcel Moolenaar { 354*c243e490SMarcel Moolenaar atf_error_t err; 355*c243e490SMarcel Moolenaar va_list ap2; 356*c243e490SMarcel Moolenaar 357*c243e490SMarcel Moolenaar va_copy(ap2, ap); 358*c243e490SMarcel Moolenaar err = normalize_ap(&p->m_data, fmt, ap2); 359*c243e490SMarcel Moolenaar va_end(ap2); 360*c243e490SMarcel Moolenaar 361*c243e490SMarcel Moolenaar return err; 362*c243e490SMarcel Moolenaar } 363*c243e490SMarcel Moolenaar 364*c243e490SMarcel Moolenaar atf_error_t 365*c243e490SMarcel Moolenaar atf_fs_path_init_fmt(atf_fs_path_t *p, const char *fmt, ...) 366*c243e490SMarcel Moolenaar { 367*c243e490SMarcel Moolenaar va_list ap; 368*c243e490SMarcel Moolenaar atf_error_t err; 369*c243e490SMarcel Moolenaar 370*c243e490SMarcel Moolenaar va_start(ap, fmt); 371*c243e490SMarcel Moolenaar err = atf_fs_path_init_ap(p, fmt, ap); 372*c243e490SMarcel Moolenaar va_end(ap); 373*c243e490SMarcel Moolenaar 374*c243e490SMarcel Moolenaar return err; 375*c243e490SMarcel Moolenaar } 376*c243e490SMarcel Moolenaar 377*c243e490SMarcel Moolenaar atf_error_t 378*c243e490SMarcel Moolenaar atf_fs_path_copy(atf_fs_path_t *dest, const atf_fs_path_t *src) 379*c243e490SMarcel Moolenaar { 380*c243e490SMarcel Moolenaar return atf_dynstr_copy(&dest->m_data, &src->m_data); 381*c243e490SMarcel Moolenaar } 382*c243e490SMarcel Moolenaar 383*c243e490SMarcel Moolenaar void 384*c243e490SMarcel Moolenaar atf_fs_path_fini(atf_fs_path_t *p) 385*c243e490SMarcel Moolenaar { 386*c243e490SMarcel Moolenaar atf_dynstr_fini(&p->m_data); 387*c243e490SMarcel Moolenaar } 388*c243e490SMarcel Moolenaar 389*c243e490SMarcel Moolenaar /* 390*c243e490SMarcel Moolenaar * Getters. 391*c243e490SMarcel Moolenaar */ 392*c243e490SMarcel Moolenaar 393*c243e490SMarcel Moolenaar atf_error_t 394*c243e490SMarcel Moolenaar atf_fs_path_branch_path(const atf_fs_path_t *p, atf_fs_path_t *bp) 395*c243e490SMarcel Moolenaar { 396*c243e490SMarcel Moolenaar const size_t endpos = atf_dynstr_rfind_ch(&p->m_data, '/'); 397*c243e490SMarcel Moolenaar atf_error_t err; 398*c243e490SMarcel Moolenaar 399*c243e490SMarcel Moolenaar if (endpos == atf_dynstr_npos) 400*c243e490SMarcel Moolenaar err = atf_fs_path_init_fmt(bp, "."); 401*c243e490SMarcel Moolenaar else if (endpos == 0) 402*c243e490SMarcel Moolenaar err = atf_fs_path_init_fmt(bp, "/"); 403*c243e490SMarcel Moolenaar else 404*c243e490SMarcel Moolenaar err = atf_dynstr_init_substr(&bp->m_data, &p->m_data, 0, endpos); 405*c243e490SMarcel Moolenaar 406*c243e490SMarcel Moolenaar #if defined(HAVE_CONST_DIRNAME) 407*c243e490SMarcel Moolenaar INV(atf_equal_dynstr_cstring(&bp->m_data, 408*c243e490SMarcel Moolenaar dirname(atf_dynstr_cstring(&p->m_data)))); 409*c243e490SMarcel Moolenaar #endif /* defined(HAVE_CONST_DIRNAME) */ 410*c243e490SMarcel Moolenaar 411*c243e490SMarcel Moolenaar return err; 412*c243e490SMarcel Moolenaar } 413*c243e490SMarcel Moolenaar 414*c243e490SMarcel Moolenaar const char * 415*c243e490SMarcel Moolenaar atf_fs_path_cstring(const atf_fs_path_t *p) 416*c243e490SMarcel Moolenaar { 417*c243e490SMarcel Moolenaar return atf_dynstr_cstring(&p->m_data); 418*c243e490SMarcel Moolenaar } 419*c243e490SMarcel Moolenaar 420*c243e490SMarcel Moolenaar atf_error_t 421*c243e490SMarcel Moolenaar atf_fs_path_leaf_name(const atf_fs_path_t *p, atf_dynstr_t *ln) 422*c243e490SMarcel Moolenaar { 423*c243e490SMarcel Moolenaar size_t begpos = atf_dynstr_rfind_ch(&p->m_data, '/'); 424*c243e490SMarcel Moolenaar atf_error_t err; 425*c243e490SMarcel Moolenaar 426*c243e490SMarcel Moolenaar if (begpos == atf_dynstr_npos) 427*c243e490SMarcel Moolenaar begpos = 0; 428*c243e490SMarcel Moolenaar else 429*c243e490SMarcel Moolenaar begpos++; 430*c243e490SMarcel Moolenaar 431*c243e490SMarcel Moolenaar err = atf_dynstr_init_substr(ln, &p->m_data, begpos, atf_dynstr_npos); 432*c243e490SMarcel Moolenaar 433*c243e490SMarcel Moolenaar #if defined(HAVE_CONST_BASENAME) 434*c243e490SMarcel Moolenaar INV(atf_equal_dynstr_cstring(ln, 435*c243e490SMarcel Moolenaar basename(atf_dynstr_cstring(&p->m_data)))); 436*c243e490SMarcel Moolenaar #endif /* defined(HAVE_CONST_BASENAME) */ 437*c243e490SMarcel Moolenaar 438*c243e490SMarcel Moolenaar return err; 439*c243e490SMarcel Moolenaar } 440*c243e490SMarcel Moolenaar 441*c243e490SMarcel Moolenaar bool 442*c243e490SMarcel Moolenaar atf_fs_path_is_absolute(const atf_fs_path_t *p) 443*c243e490SMarcel Moolenaar { 444*c243e490SMarcel Moolenaar return atf_dynstr_cstring(&p->m_data)[0] == '/'; 445*c243e490SMarcel Moolenaar } 446*c243e490SMarcel Moolenaar 447*c243e490SMarcel Moolenaar bool 448*c243e490SMarcel Moolenaar atf_fs_path_is_root(const atf_fs_path_t *p) 449*c243e490SMarcel Moolenaar { 450*c243e490SMarcel Moolenaar return atf_equal_dynstr_cstring(&p->m_data, "/"); 451*c243e490SMarcel Moolenaar } 452*c243e490SMarcel Moolenaar 453*c243e490SMarcel Moolenaar /* 454*c243e490SMarcel Moolenaar * Modifiers. 455*c243e490SMarcel Moolenaar */ 456*c243e490SMarcel Moolenaar 457*c243e490SMarcel Moolenaar atf_error_t 458*c243e490SMarcel Moolenaar atf_fs_path_append_ap(atf_fs_path_t *p, const char *fmt, va_list ap) 459*c243e490SMarcel Moolenaar { 460*c243e490SMarcel Moolenaar atf_dynstr_t aux; 461*c243e490SMarcel Moolenaar atf_error_t err; 462*c243e490SMarcel Moolenaar va_list ap2; 463*c243e490SMarcel Moolenaar 464*c243e490SMarcel Moolenaar va_copy(ap2, ap); 465*c243e490SMarcel Moolenaar err = normalize_ap(&aux, fmt, ap2); 466*c243e490SMarcel Moolenaar va_end(ap2); 467*c243e490SMarcel Moolenaar if (!atf_is_error(err)) { 468*c243e490SMarcel Moolenaar const char *auxstr = atf_dynstr_cstring(&aux); 469*c243e490SMarcel Moolenaar const bool needslash = auxstr[0] != '/'; 470*c243e490SMarcel Moolenaar 471*c243e490SMarcel Moolenaar err = atf_dynstr_append_fmt(&p->m_data, "%s%s", 472*c243e490SMarcel Moolenaar needslash ? "/" : "", auxstr); 473*c243e490SMarcel Moolenaar 474*c243e490SMarcel Moolenaar atf_dynstr_fini(&aux); 475*c243e490SMarcel Moolenaar } 476*c243e490SMarcel Moolenaar 477*c243e490SMarcel Moolenaar return err; 478*c243e490SMarcel Moolenaar } 479*c243e490SMarcel Moolenaar 480*c243e490SMarcel Moolenaar atf_error_t 481*c243e490SMarcel Moolenaar atf_fs_path_append_fmt(atf_fs_path_t *p, const char *fmt, ...) 482*c243e490SMarcel Moolenaar { 483*c243e490SMarcel Moolenaar va_list ap; 484*c243e490SMarcel Moolenaar atf_error_t err; 485*c243e490SMarcel Moolenaar 486*c243e490SMarcel Moolenaar va_start(ap, fmt); 487*c243e490SMarcel Moolenaar err = atf_fs_path_append_ap(p, fmt, ap); 488*c243e490SMarcel Moolenaar va_end(ap); 489*c243e490SMarcel Moolenaar 490*c243e490SMarcel Moolenaar return err; 491*c243e490SMarcel Moolenaar } 492*c243e490SMarcel Moolenaar 493*c243e490SMarcel Moolenaar atf_error_t 494*c243e490SMarcel Moolenaar atf_fs_path_append_path(atf_fs_path_t *p, const atf_fs_path_t *p2) 495*c243e490SMarcel Moolenaar { 496*c243e490SMarcel Moolenaar return atf_fs_path_append_fmt(p, "%s", atf_dynstr_cstring(&p2->m_data)); 497*c243e490SMarcel Moolenaar } 498*c243e490SMarcel Moolenaar 499*c243e490SMarcel Moolenaar atf_error_t 500*c243e490SMarcel Moolenaar atf_fs_path_to_absolute(const atf_fs_path_t *p, atf_fs_path_t *pa) 501*c243e490SMarcel Moolenaar { 502*c243e490SMarcel Moolenaar atf_error_t err; 503*c243e490SMarcel Moolenaar 504*c243e490SMarcel Moolenaar PRE(!atf_fs_path_is_absolute(p)); 505*c243e490SMarcel Moolenaar 506*c243e490SMarcel Moolenaar err = atf_fs_getcwd(pa); 507*c243e490SMarcel Moolenaar if (atf_is_error(err)) 508*c243e490SMarcel Moolenaar goto out; 509*c243e490SMarcel Moolenaar 510*c243e490SMarcel Moolenaar err = atf_fs_path_append_path(pa, p); 511*c243e490SMarcel Moolenaar if (atf_is_error(err)) 512*c243e490SMarcel Moolenaar atf_fs_path_fini(pa); 513*c243e490SMarcel Moolenaar 514*c243e490SMarcel Moolenaar out: 515*c243e490SMarcel Moolenaar return err; 516*c243e490SMarcel Moolenaar } 517*c243e490SMarcel Moolenaar 518*c243e490SMarcel Moolenaar /* 519*c243e490SMarcel Moolenaar * Operators. 520*c243e490SMarcel Moolenaar */ 521*c243e490SMarcel Moolenaar 522*c243e490SMarcel Moolenaar bool atf_equal_fs_path_fs_path(const atf_fs_path_t *p1, 523*c243e490SMarcel Moolenaar const atf_fs_path_t *p2) 524*c243e490SMarcel Moolenaar { 525*c243e490SMarcel Moolenaar return atf_equal_dynstr_dynstr(&p1->m_data, &p2->m_data); 526*c243e490SMarcel Moolenaar } 527*c243e490SMarcel Moolenaar 528*c243e490SMarcel Moolenaar /* --------------------------------------------------------------------- 529*c243e490SMarcel Moolenaar * The "atf_fs_path" type. 530*c243e490SMarcel Moolenaar * --------------------------------------------------------------------- */ 531*c243e490SMarcel Moolenaar 532*c243e490SMarcel Moolenaar /* 533*c243e490SMarcel Moolenaar * Constants. 534*c243e490SMarcel Moolenaar */ 535*c243e490SMarcel Moolenaar 536*c243e490SMarcel Moolenaar const int atf_fs_stat_blk_type = 1; 537*c243e490SMarcel Moolenaar const int atf_fs_stat_chr_type = 2; 538*c243e490SMarcel Moolenaar const int atf_fs_stat_dir_type = 3; 539*c243e490SMarcel Moolenaar const int atf_fs_stat_fifo_type = 4; 540*c243e490SMarcel Moolenaar const int atf_fs_stat_lnk_type = 5; 541*c243e490SMarcel Moolenaar const int atf_fs_stat_reg_type = 6; 542*c243e490SMarcel Moolenaar const int atf_fs_stat_sock_type = 7; 543*c243e490SMarcel Moolenaar const int atf_fs_stat_wht_type = 8; 544*c243e490SMarcel Moolenaar 545*c243e490SMarcel Moolenaar /* 546*c243e490SMarcel Moolenaar * Constructors/destructors. 547*c243e490SMarcel Moolenaar */ 548*c243e490SMarcel Moolenaar 549*c243e490SMarcel Moolenaar atf_error_t 550*c243e490SMarcel Moolenaar atf_fs_stat_init(atf_fs_stat_t *st, const atf_fs_path_t *p) 551*c243e490SMarcel Moolenaar { 552*c243e490SMarcel Moolenaar atf_error_t err; 553*c243e490SMarcel Moolenaar const char *pstr = atf_fs_path_cstring(p); 554*c243e490SMarcel Moolenaar 555*c243e490SMarcel Moolenaar if (lstat(pstr, &st->m_sb) == -1) { 556*c243e490SMarcel Moolenaar err = atf_libc_error(errno, "Cannot get information of %s; " 557*c243e490SMarcel Moolenaar "lstat(2) failed", pstr); 558*c243e490SMarcel Moolenaar } else { 559*c243e490SMarcel Moolenaar int type = st->m_sb.st_mode & S_IFMT; 560*c243e490SMarcel Moolenaar err = atf_no_error(); 561*c243e490SMarcel Moolenaar switch (type) { 562*c243e490SMarcel Moolenaar case S_IFBLK: st->m_type = atf_fs_stat_blk_type; break; 563*c243e490SMarcel Moolenaar case S_IFCHR: st->m_type = atf_fs_stat_chr_type; break; 564*c243e490SMarcel Moolenaar case S_IFDIR: st->m_type = atf_fs_stat_dir_type; break; 565*c243e490SMarcel Moolenaar case S_IFIFO: st->m_type = atf_fs_stat_fifo_type; break; 566*c243e490SMarcel Moolenaar case S_IFLNK: st->m_type = atf_fs_stat_lnk_type; break; 567*c243e490SMarcel Moolenaar case S_IFREG: st->m_type = atf_fs_stat_reg_type; break; 568*c243e490SMarcel Moolenaar case S_IFSOCK: st->m_type = atf_fs_stat_sock_type; break; 569*c243e490SMarcel Moolenaar #if defined(S_IFWHT) 570*c243e490SMarcel Moolenaar case S_IFWHT: st->m_type = atf_fs_stat_wht_type; break; 571*c243e490SMarcel Moolenaar #endif 572*c243e490SMarcel Moolenaar default: 573*c243e490SMarcel Moolenaar err = unknown_type_error(pstr, type); 574*c243e490SMarcel Moolenaar } 575*c243e490SMarcel Moolenaar } 576*c243e490SMarcel Moolenaar 577*c243e490SMarcel Moolenaar return err; 578*c243e490SMarcel Moolenaar } 579*c243e490SMarcel Moolenaar 580*c243e490SMarcel Moolenaar void 581*c243e490SMarcel Moolenaar atf_fs_stat_copy(atf_fs_stat_t *dest, const atf_fs_stat_t *src) 582*c243e490SMarcel Moolenaar { 583*c243e490SMarcel Moolenaar dest->m_type = src->m_type; 584*c243e490SMarcel Moolenaar dest->m_sb = src->m_sb; 585*c243e490SMarcel Moolenaar } 586*c243e490SMarcel Moolenaar 587*c243e490SMarcel Moolenaar void 588*c243e490SMarcel Moolenaar atf_fs_stat_fini(atf_fs_stat_t *st ATF_DEFS_ATTRIBUTE_UNUSED) 589*c243e490SMarcel Moolenaar { 590*c243e490SMarcel Moolenaar } 591*c243e490SMarcel Moolenaar 592*c243e490SMarcel Moolenaar /* 593*c243e490SMarcel Moolenaar * Getters. 594*c243e490SMarcel Moolenaar */ 595*c243e490SMarcel Moolenaar 596*c243e490SMarcel Moolenaar dev_t 597*c243e490SMarcel Moolenaar atf_fs_stat_get_device(const atf_fs_stat_t *st) 598*c243e490SMarcel Moolenaar { 599*c243e490SMarcel Moolenaar return st->m_sb.st_dev; 600*c243e490SMarcel Moolenaar } 601*c243e490SMarcel Moolenaar 602*c243e490SMarcel Moolenaar ino_t 603*c243e490SMarcel Moolenaar atf_fs_stat_get_inode(const atf_fs_stat_t *st) 604*c243e490SMarcel Moolenaar { 605*c243e490SMarcel Moolenaar return st->m_sb.st_ino; 606*c243e490SMarcel Moolenaar } 607*c243e490SMarcel Moolenaar 608*c243e490SMarcel Moolenaar mode_t 609*c243e490SMarcel Moolenaar atf_fs_stat_get_mode(const atf_fs_stat_t *st) 610*c243e490SMarcel Moolenaar { 611*c243e490SMarcel Moolenaar return st->m_sb.st_mode & ~S_IFMT; 612*c243e490SMarcel Moolenaar } 613*c243e490SMarcel Moolenaar 614*c243e490SMarcel Moolenaar off_t 615*c243e490SMarcel Moolenaar atf_fs_stat_get_size(const atf_fs_stat_t *st) 616*c243e490SMarcel Moolenaar { 617*c243e490SMarcel Moolenaar return st->m_sb.st_size; 618*c243e490SMarcel Moolenaar } 619*c243e490SMarcel Moolenaar 620*c243e490SMarcel Moolenaar int 621*c243e490SMarcel Moolenaar atf_fs_stat_get_type(const atf_fs_stat_t *st) 622*c243e490SMarcel Moolenaar { 623*c243e490SMarcel Moolenaar return st->m_type; 624*c243e490SMarcel Moolenaar } 625*c243e490SMarcel Moolenaar 626*c243e490SMarcel Moolenaar bool 627*c243e490SMarcel Moolenaar atf_fs_stat_is_owner_readable(const atf_fs_stat_t *st) 628*c243e490SMarcel Moolenaar { 629*c243e490SMarcel Moolenaar return st->m_sb.st_mode & S_IRUSR; 630*c243e490SMarcel Moolenaar } 631*c243e490SMarcel Moolenaar 632*c243e490SMarcel Moolenaar bool 633*c243e490SMarcel Moolenaar atf_fs_stat_is_owner_writable(const atf_fs_stat_t *st) 634*c243e490SMarcel Moolenaar { 635*c243e490SMarcel Moolenaar return st->m_sb.st_mode & S_IWUSR; 636*c243e490SMarcel Moolenaar } 637*c243e490SMarcel Moolenaar 638*c243e490SMarcel Moolenaar bool 639*c243e490SMarcel Moolenaar atf_fs_stat_is_owner_executable(const atf_fs_stat_t *st) 640*c243e490SMarcel Moolenaar { 641*c243e490SMarcel Moolenaar return st->m_sb.st_mode & S_IXUSR; 642*c243e490SMarcel Moolenaar } 643*c243e490SMarcel Moolenaar 644*c243e490SMarcel Moolenaar bool 645*c243e490SMarcel Moolenaar atf_fs_stat_is_group_readable(const atf_fs_stat_t *st) 646*c243e490SMarcel Moolenaar { 647*c243e490SMarcel Moolenaar return st->m_sb.st_mode & S_IRGRP; 648*c243e490SMarcel Moolenaar } 649*c243e490SMarcel Moolenaar 650*c243e490SMarcel Moolenaar bool 651*c243e490SMarcel Moolenaar atf_fs_stat_is_group_writable(const atf_fs_stat_t *st) 652*c243e490SMarcel Moolenaar { 653*c243e490SMarcel Moolenaar return st->m_sb.st_mode & S_IWGRP; 654*c243e490SMarcel Moolenaar } 655*c243e490SMarcel Moolenaar 656*c243e490SMarcel Moolenaar bool 657*c243e490SMarcel Moolenaar atf_fs_stat_is_group_executable(const atf_fs_stat_t *st) 658*c243e490SMarcel Moolenaar { 659*c243e490SMarcel Moolenaar return st->m_sb.st_mode & S_IXGRP; 660*c243e490SMarcel Moolenaar } 661*c243e490SMarcel Moolenaar 662*c243e490SMarcel Moolenaar bool 663*c243e490SMarcel Moolenaar atf_fs_stat_is_other_readable(const atf_fs_stat_t *st) 664*c243e490SMarcel Moolenaar { 665*c243e490SMarcel Moolenaar return st->m_sb.st_mode & S_IROTH; 666*c243e490SMarcel Moolenaar } 667*c243e490SMarcel Moolenaar 668*c243e490SMarcel Moolenaar bool 669*c243e490SMarcel Moolenaar atf_fs_stat_is_other_writable(const atf_fs_stat_t *st) 670*c243e490SMarcel Moolenaar { 671*c243e490SMarcel Moolenaar return st->m_sb.st_mode & S_IWOTH; 672*c243e490SMarcel Moolenaar } 673*c243e490SMarcel Moolenaar 674*c243e490SMarcel Moolenaar bool 675*c243e490SMarcel Moolenaar atf_fs_stat_is_other_executable(const atf_fs_stat_t *st) 676*c243e490SMarcel Moolenaar { 677*c243e490SMarcel Moolenaar return st->m_sb.st_mode & S_IXOTH; 678*c243e490SMarcel Moolenaar } 679*c243e490SMarcel Moolenaar 680*c243e490SMarcel Moolenaar /* --------------------------------------------------------------------- 681*c243e490SMarcel Moolenaar * Free functions. 682*c243e490SMarcel Moolenaar * --------------------------------------------------------------------- */ 683*c243e490SMarcel Moolenaar 684*c243e490SMarcel Moolenaar const int atf_fs_access_f = 1 << 0; 685*c243e490SMarcel Moolenaar const int atf_fs_access_r = 1 << 1; 686*c243e490SMarcel Moolenaar const int atf_fs_access_w = 1 << 2; 687*c243e490SMarcel Moolenaar const int atf_fs_access_x = 1 << 3; 688*c243e490SMarcel Moolenaar 689*c243e490SMarcel Moolenaar /* 690*c243e490SMarcel Moolenaar * An implementation of access(2) but using the effective user value 691*c243e490SMarcel Moolenaar * instead of the real one. Also avoids false positives for root when 692*c243e490SMarcel Moolenaar * asking for execute permissions, which appear in SunOS. 693*c243e490SMarcel Moolenaar */ 694*c243e490SMarcel Moolenaar atf_error_t 695*c243e490SMarcel Moolenaar atf_fs_eaccess(const atf_fs_path_t *p, int mode) 696*c243e490SMarcel Moolenaar { 697*c243e490SMarcel Moolenaar atf_error_t err; 698*c243e490SMarcel Moolenaar struct stat st; 699*c243e490SMarcel Moolenaar bool ok; 700*c243e490SMarcel Moolenaar 701*c243e490SMarcel Moolenaar PRE(mode & atf_fs_access_f || mode & atf_fs_access_r || 702*c243e490SMarcel Moolenaar mode & atf_fs_access_w || mode & atf_fs_access_x); 703*c243e490SMarcel Moolenaar 704*c243e490SMarcel Moolenaar if (lstat(atf_fs_path_cstring(p), &st) == -1) { 705*c243e490SMarcel Moolenaar err = atf_libc_error(errno, "Cannot get information from file %s", 706*c243e490SMarcel Moolenaar atf_fs_path_cstring(p)); 707*c243e490SMarcel Moolenaar goto out; 708*c243e490SMarcel Moolenaar } 709*c243e490SMarcel Moolenaar 710*c243e490SMarcel Moolenaar err = atf_no_error(); 711*c243e490SMarcel Moolenaar 712*c243e490SMarcel Moolenaar /* Early return if we are only checking for existence and the file 713*c243e490SMarcel Moolenaar * exists (stat call returned). */ 714*c243e490SMarcel Moolenaar if (mode & atf_fs_access_f) 715*c243e490SMarcel Moolenaar goto out; 716*c243e490SMarcel Moolenaar 717*c243e490SMarcel Moolenaar ok = false; 718*c243e490SMarcel Moolenaar if (atf_user_is_root()) { 719*c243e490SMarcel Moolenaar if (!ok && !(mode & atf_fs_access_x)) { 720*c243e490SMarcel Moolenaar /* Allow root to read/write any file. */ 721*c243e490SMarcel Moolenaar ok = true; 722*c243e490SMarcel Moolenaar } 723*c243e490SMarcel Moolenaar 724*c243e490SMarcel Moolenaar if (!ok && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { 725*c243e490SMarcel Moolenaar /* Allow root to execute the file if any of its execution bits 726*c243e490SMarcel Moolenaar * are set. */ 727*c243e490SMarcel Moolenaar ok = true; 728*c243e490SMarcel Moolenaar } 729*c243e490SMarcel Moolenaar } else { 730*c243e490SMarcel Moolenaar if (!ok && (atf_user_euid() == st.st_uid)) { 731*c243e490SMarcel Moolenaar ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRUSR)) || 732*c243e490SMarcel Moolenaar ((mode & atf_fs_access_w) && (st.st_mode & S_IWUSR)) || 733*c243e490SMarcel Moolenaar ((mode & atf_fs_access_x) && (st.st_mode & S_IXUSR)); 734*c243e490SMarcel Moolenaar } 735*c243e490SMarcel Moolenaar if (!ok && atf_user_is_member_of_group(st.st_gid)) { 736*c243e490SMarcel Moolenaar ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRGRP)) || 737*c243e490SMarcel Moolenaar ((mode & atf_fs_access_w) && (st.st_mode & S_IWGRP)) || 738*c243e490SMarcel Moolenaar ((mode & atf_fs_access_x) && (st.st_mode & S_IXGRP)); 739*c243e490SMarcel Moolenaar } 740*c243e490SMarcel Moolenaar if (!ok && ((atf_user_euid() != st.st_uid) && 741*c243e490SMarcel Moolenaar !atf_user_is_member_of_group(st.st_gid))) { 742*c243e490SMarcel Moolenaar ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IROTH)) || 743*c243e490SMarcel Moolenaar ((mode & atf_fs_access_w) && (st.st_mode & S_IWOTH)) || 744*c243e490SMarcel Moolenaar ((mode & atf_fs_access_x) && (st.st_mode & S_IXOTH)); 745*c243e490SMarcel Moolenaar } 746*c243e490SMarcel Moolenaar } 747*c243e490SMarcel Moolenaar 748*c243e490SMarcel Moolenaar if (!ok) 749*c243e490SMarcel Moolenaar err = atf_libc_error(EACCES, "Access check failed"); 750*c243e490SMarcel Moolenaar 751*c243e490SMarcel Moolenaar out: 752*c243e490SMarcel Moolenaar return err; 753*c243e490SMarcel Moolenaar } 754*c243e490SMarcel Moolenaar 755*c243e490SMarcel Moolenaar atf_error_t 756*c243e490SMarcel Moolenaar atf_fs_exists(const atf_fs_path_t *p, bool *b) 757*c243e490SMarcel Moolenaar { 758*c243e490SMarcel Moolenaar atf_error_t err; 759*c243e490SMarcel Moolenaar 760*c243e490SMarcel Moolenaar err = atf_fs_eaccess(p, atf_fs_access_f); 761*c243e490SMarcel Moolenaar if (atf_is_error(err)) { 762*c243e490SMarcel Moolenaar if (atf_error_is(err, "libc") && atf_libc_error_code(err) == ENOENT) { 763*c243e490SMarcel Moolenaar atf_error_free(err); 764*c243e490SMarcel Moolenaar err = atf_no_error(); 765*c243e490SMarcel Moolenaar *b = false; 766*c243e490SMarcel Moolenaar } 767*c243e490SMarcel Moolenaar } else 768*c243e490SMarcel Moolenaar *b = true; 769*c243e490SMarcel Moolenaar 770*c243e490SMarcel Moolenaar return err; 771*c243e490SMarcel Moolenaar } 772*c243e490SMarcel Moolenaar 773*c243e490SMarcel Moolenaar atf_error_t 774*c243e490SMarcel Moolenaar atf_fs_getcwd(atf_fs_path_t *p) 775*c243e490SMarcel Moolenaar { 776*c243e490SMarcel Moolenaar atf_error_t err; 777*c243e490SMarcel Moolenaar char *cwd; 778*c243e490SMarcel Moolenaar 779*c243e490SMarcel Moolenaar #if defined(HAVE_GETCWD_DYN) 780*c243e490SMarcel Moolenaar cwd = getcwd(NULL, 0); 781*c243e490SMarcel Moolenaar #else 782*c243e490SMarcel Moolenaar cwd = getcwd(NULL, MAXPATHLEN); 783*c243e490SMarcel Moolenaar #endif 784*c243e490SMarcel Moolenaar if (cwd == NULL) { 785*c243e490SMarcel Moolenaar err = atf_libc_error(errno, "Cannot determine current directory"); 786*c243e490SMarcel Moolenaar goto out; 787*c243e490SMarcel Moolenaar } 788*c243e490SMarcel Moolenaar 789*c243e490SMarcel Moolenaar err = atf_fs_path_init_fmt(p, "%s", cwd); 790*c243e490SMarcel Moolenaar free(cwd); 791*c243e490SMarcel Moolenaar 792*c243e490SMarcel Moolenaar out: 793*c243e490SMarcel Moolenaar return err; 794*c243e490SMarcel Moolenaar } 795*c243e490SMarcel Moolenaar 796*c243e490SMarcel Moolenaar atf_error_t 797*c243e490SMarcel Moolenaar atf_fs_mkdtemp(atf_fs_path_t *p) 798*c243e490SMarcel Moolenaar { 799*c243e490SMarcel Moolenaar atf_error_t err; 800*c243e490SMarcel Moolenaar char *buf; 801*c243e490SMarcel Moolenaar 802*c243e490SMarcel Moolenaar if (!check_umask(S_IRWXU, S_IRWXU)) { 803*c243e490SMarcel Moolenaar err = invalid_umask_error(p, atf_fs_stat_dir_type, current_umask()); 804*c243e490SMarcel Moolenaar goto out; 805*c243e490SMarcel Moolenaar } 806*c243e490SMarcel Moolenaar 807*c243e490SMarcel Moolenaar err = copy_contents(p, &buf); 808*c243e490SMarcel Moolenaar if (atf_is_error(err)) 809*c243e490SMarcel Moolenaar goto out; 810*c243e490SMarcel Moolenaar 811*c243e490SMarcel Moolenaar err = do_mkdtemp(buf); 812*c243e490SMarcel Moolenaar if (atf_is_error(err)) 813*c243e490SMarcel Moolenaar goto out_buf; 814*c243e490SMarcel Moolenaar 815*c243e490SMarcel Moolenaar replace_contents(p, buf); 816*c243e490SMarcel Moolenaar 817*c243e490SMarcel Moolenaar INV(!atf_is_error(err)); 818*c243e490SMarcel Moolenaar out_buf: 819*c243e490SMarcel Moolenaar free(buf); 820*c243e490SMarcel Moolenaar out: 821*c243e490SMarcel Moolenaar return err; 822*c243e490SMarcel Moolenaar } 823*c243e490SMarcel Moolenaar 824*c243e490SMarcel Moolenaar atf_error_t 825*c243e490SMarcel Moolenaar atf_fs_mkstemp(atf_fs_path_t *p, int *fdout) 826*c243e490SMarcel Moolenaar { 827*c243e490SMarcel Moolenaar atf_error_t err; 828*c243e490SMarcel Moolenaar char *buf; 829*c243e490SMarcel Moolenaar int fd; 830*c243e490SMarcel Moolenaar 831*c243e490SMarcel Moolenaar if (!check_umask(S_IRWXU, S_IRWXU)) { 832*c243e490SMarcel Moolenaar err = invalid_umask_error(p, atf_fs_stat_reg_type, current_umask()); 833*c243e490SMarcel Moolenaar goto out; 834*c243e490SMarcel Moolenaar } 835*c243e490SMarcel Moolenaar 836*c243e490SMarcel Moolenaar err = copy_contents(p, &buf); 837*c243e490SMarcel Moolenaar if (atf_is_error(err)) 838*c243e490SMarcel Moolenaar goto out; 839*c243e490SMarcel Moolenaar 840*c243e490SMarcel Moolenaar err = do_mkstemp(buf, &fd); 841*c243e490SMarcel Moolenaar if (atf_is_error(err)) 842*c243e490SMarcel Moolenaar goto out_buf; 843*c243e490SMarcel Moolenaar 844*c243e490SMarcel Moolenaar replace_contents(p, buf); 845*c243e490SMarcel Moolenaar *fdout = fd; 846*c243e490SMarcel Moolenaar 847*c243e490SMarcel Moolenaar INV(!atf_is_error(err)); 848*c243e490SMarcel Moolenaar out_buf: 849*c243e490SMarcel Moolenaar free(buf); 850*c243e490SMarcel Moolenaar out: 851*c243e490SMarcel Moolenaar return err; 852*c243e490SMarcel Moolenaar } 853*c243e490SMarcel Moolenaar 854*c243e490SMarcel Moolenaar atf_error_t 855*c243e490SMarcel Moolenaar atf_fs_rmdir(const atf_fs_path_t *p) 856*c243e490SMarcel Moolenaar { 857*c243e490SMarcel Moolenaar atf_error_t err; 858*c243e490SMarcel Moolenaar 859*c243e490SMarcel Moolenaar if (rmdir(atf_fs_path_cstring(p))) { 860*c243e490SMarcel Moolenaar if (errno == EEXIST) { 861*c243e490SMarcel Moolenaar /* Some operating systems (e.g. OpenSolaris 200906) return 862*c243e490SMarcel Moolenaar * EEXIST instead of ENOTEMPTY for non-empty directories. 863*c243e490SMarcel Moolenaar * Homogenize the return value so that callers don't need 864*c243e490SMarcel Moolenaar * to bother about differences in operating systems. */ 865*c243e490SMarcel Moolenaar errno = ENOTEMPTY; 866*c243e490SMarcel Moolenaar } 867*c243e490SMarcel Moolenaar err = atf_libc_error(errno, "Cannot remove directory"); 868*c243e490SMarcel Moolenaar } else 869*c243e490SMarcel Moolenaar err = atf_no_error(); 870*c243e490SMarcel Moolenaar 871*c243e490SMarcel Moolenaar return err; 872*c243e490SMarcel Moolenaar } 873*c243e490SMarcel Moolenaar 874*c243e490SMarcel Moolenaar atf_error_t 875*c243e490SMarcel Moolenaar atf_fs_unlink(const atf_fs_path_t *p) 876*c243e490SMarcel Moolenaar { 877*c243e490SMarcel Moolenaar atf_error_t err; 878*c243e490SMarcel Moolenaar const char *path; 879*c243e490SMarcel Moolenaar 880*c243e490SMarcel Moolenaar path = atf_fs_path_cstring(p); 881*c243e490SMarcel Moolenaar 882*c243e490SMarcel Moolenaar if (unlink(path) != 0) 883*c243e490SMarcel Moolenaar err = atf_libc_error(errno, "Cannot unlink file: '%s'", path); 884*c243e490SMarcel Moolenaar else 885*c243e490SMarcel Moolenaar err = atf_no_error(); 886*c243e490SMarcel Moolenaar 887*c243e490SMarcel Moolenaar return err; 888*c243e490SMarcel Moolenaar } 889