/* * Applies the localisation algorithm of 'filename' * within 'wgt'. Use the scratch buffer given by 'path'. * * Returns the filepath of the located file or NULL * if not found. If not NULL, the returned value is either * 'path' or the normalized version of 'filename'. */ static const char *localize(struct wgt *wgt, const char *filename, char path[PATH_MAX]) { unsigned int i; /* get the normalized name */ filename = normalsubpath(filename); if (!filename) { errno = EINVAL; return NULL; } /* search in locales */ for (i = 0 ; i < wgt->nrlocales ; i++) { if (snprintf(path, PATH_MAX, "locales/%s/%s", wgt->locales[i], filename) >= PATH_MAX) { errno = EINVAL; return NULL; } if (0 == faccessat(wgt->rootfd, path, F_OK, 0)) return path; } if (0 == faccessat(wgt->rootfd, filename, F_OK, 0)) return filename; errno = ENOENT; return NULL; }
static int test_file_access(const char *path, int mode) { if (faccessat_confused_about_superuser() && mode == X_OK && geteuid() == 0 && !has_exec_bit_set(path)) return 0; return !faccessat(AT_FDCWD, path, mode, AT_EACCESS); }
static int pkg_load_message_from_file(int fd, struct pkg *pkg, const char *path) { char *buf = NULL; off_t size = 0; int ret; ucl_object_t *obj; assert(pkg != NULL); assert(path != NULL); if (faccessat(fd, path, F_OK, 0) == 0) { pkg_debug(1, "Reading message: '%s'", path); if ((ret = file_to_bufferat(fd, path, &buf, &size)) != EPKG_OK) { return (ret); } if (*buf == '[') { ret = pkg_message_from_str(pkg, buf, size); free(buf); return (ret); } else { obj = ucl_object_fromstring_common(buf, size, UCL_STRING_RAW|UCL_STRING_TRIM); ret = pkg_message_from_ucl(pkg, obj); ucl_object_unref(obj); free(buf); return (ret); } } return (EPKG_FATAL); }
void test_create_file_at() { char *file = alloc_filename("file"); char *hardlink = alloc_filename("hardlink"); char *hardlink2 = alloc_filename("hardlink2"); int dir_fd = get_dir_fd("."); struct stat st; int fd = openat(dir_fd, file, O_CREAT | O_WRONLY | O_EXCL, 0777); t_check(fd >= 0); t_check_zero(fstat(fd, &st)); t_check_zero(close(fd)); t_check_zero(fstatat(dir_fd, file, &st, 0)); t_check_zero(faccessat(dir_fd, file, R_OK | W_OK, 0)); t_check_zero(fchmodat(dir_fd, file, 0777, 0)); t_check_zero(fchownat(dir_fd, file, -1, -1, 0)); struct timeval times[2] = { { 123, 321 }, { 456, 654 } }; t_check_zero(futimesat(dir_fd, file, times)); t_check_zero(linkat(dir_fd, file, dir_fd, hardlink, 0)); t_check_zero(renameat(dir_fd, hardlink, dir_fd, hardlink2)); t_check_zero(unlinkat(dir_fd, hardlink2, 0)); t_check_zero(unlinkat(dir_fd, file, 0)); close(dir_fd); free(file); free(hardlink); free(hardlink2); }
static void test_faccessat(void) { //#define FACCESSAT #if defined(FACCESSAT) if (access("./name", W_OK) == 0) { printf("access check uid and gid\n"); } else { printf("access not file\n"); } if (faccessat(AT_FDCWD, "./name", W_OK, 0) == 0) { printf("faccessat check uid and gid\n"); } else { printf("faccessat not file\n"); } printf("AT_EACCESS = %d\n", AT_EACCESS); #endif //FACCESSAT }
static int ensure_etc_hosts_exists(const char *root, int rootfd) { char name[MACHINE_NAME_LEN + 1]; char hosts[128]; int fd, len; if(faccessat(rootfd, "etc/hosts", F_OK, AT_EACCESS) == 0) return 1; goto_if(!get_machine_name(name, sizeof(name)), _fail, "Failed to get machine name"); goto_if((len = snprintf(hosts, sizeof(hosts), "%s\t%s\t%s\t%s\n", "127.0.0.1", name, "localhost", "localhost.localdomain")) >= sizeof(hosts), _fail, "/etc/hosts line too long: \"%s\"", hosts); pgoto_if((fd = openat(rootfd, "etc/hosts", O_WRONLY|O_CREAT, 0644)) == -1, _fail, "Failed to create \"%s/etc/hosts\"", root); pgoto_if(write(fd, hosts, len) != len, _fail_fd, "Failed to write \"%s/etc/hosts\"", root); pgoto_if(close(fd) != 0, _fail, "Failed to close \"%s/etc/hosts\"", root); return 1; _fail_fd: close(fd); _fail: return 0; }
static int process_hostname(void) { const char *etc_hostname; int r; etc_hostname = prefix_roota("/etc/hostname"); if (faccessat(AT_FDCWD, etc_hostname, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) return 0; r = prompt_hostname(); if (r < 0) return r; if (isempty(arg_hostname)) return 0; mkdir_parents(etc_hostname, 0755); r = write_string_file(etc_hostname, arg_hostname); if (r < 0) { log_error("Failed to write %s: %s", etc_hostname, strerror(-r)); return r; } log_info("%s written.", etc_hostname); return 0; }
static int process_machine_id(void) { const char *etc_machine_id; char id[SD_ID128_STRING_MAX]; int r; etc_machine_id = prefix_roota("/etc/machine-id"); if (faccessat(AT_FDCWD, etc_machine_id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) return 0; if (!arg_root) return 0; if (sd_id128_equal(arg_machine_id, SD_ID128_NULL)) return 0; mkdir_parents(etc_machine_id, 0755); r = write_string_file(etc_machine_id, sd_id128_to_string(arg_machine_id, id)); if (r < 0) { log_error("Failed to write machine id: %s", strerror(-r)); return r; } log_info("%s written.", etc_machine_id); return 0; }
int sysfs_is_partition_dirent(DIR *dir, struct dirent *d, const char *parent_name) { char path[256]; #ifdef _DIRENT_HAVE_D_TYPE if (d->d_type != DT_DIR && d->d_type != DT_LNK) return 0; #endif if (parent_name) { const char *p = parent_name; size_t len; /* /dev/sda --> "sda" */ if (*parent_name == '/') { p = strrchr(parent_name, '/'); if (!p) return 0; p++; } len = strlen(p); if (strlen(d->d_name) <= len) return 0; /* partitions subdir name is "<parent>[:digit:]" */ return strncmp(p, d->d_name, len) == 0 && isdigit(*(d->d_name + len)); } /* Cannot use /partition file, not supported on old sysfs */ snprintf(path, sizeof(path), "%s/start", d->d_name); return faccessat(dirfd(dir), path, R_OK, 0) == 0; }
static void pkg_load_from_file(int fd, struct pkg *pkg, pkg_attr attr, const char *path) { if (faccessat(fd, path, F_OK, 0) == 0) { pkg_debug(1, "Reading: '%s'", path); pkg_set_from_fileat(fd, pkg, attr, path, false); } }
ATF_TC_BODY(faccessat_fderr1, tc) { int dfd; ATF_REQUIRE(mkdir(DIR, 0755) == 0); ATF_REQUIRE((dfd = open(DIR, O_RDONLY, 0)) != -1); ATF_REQUIRE(faccessat(dfd, FILEERR, F_OK, 0) == -1); ATF_REQUIRE(close(dfd) == 0); }
static int prompt_root_password(void) { const char *msg1, *msg2, *etc_shadow; int r; if (arg_root_password) return 0; if (!arg_prompt_root_password) return 0; etc_shadow = prefix_roota("/etc/shadow"); if (faccessat(AT_FDCWD, etc_shadow, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) return 0; print_welcome(); putchar('\n'); msg1 = strappenda(draw_special_char(DRAW_TRIANGULAR_BULLET), " Please enter a new root password (empty to skip): "); msg2 = strappenda(draw_special_char(DRAW_TRIANGULAR_BULLET), " Please enter new root password again: "); for (;;) { _cleanup_free_ char *a = NULL, *b = NULL; r = ask_password_tty(msg1, 0, false, NULL, &a); if (r < 0) { log_error("Failed to query root password: %s", strerror(-r)); return r; } if (isempty(a)) { log_warning("No password entered, skipping."); break; } r = ask_password_tty(msg2, 0, false, NULL, &b); if (r < 0) { log_error("Failed to query root password: %s", strerror(-r)); clear_string(a); return r; } if (!streq(a, b)) { log_error("Entered passwords did not match, please try again."); clear_string(a); clear_string(b); continue; } clear_string(b); arg_root_password = a; a = NULL; break; } return 0; }
ATF_TC_BODY(faccessat_fdlink, tc) { int dfd; ATF_REQUIRE(mkdir(DIR, 0755) == 0); ATF_REQUIRE(symlink(FILE, LINK) == 0); /* NB: FILE does not exists */ ATF_REQUIRE((dfd = open(DIR, O_RDONLY, 0)) != -1); ATF_REQUIRE(faccessat(dfd, BASELINK, F_OK, 0) == -1); ATF_REQUIRE(errno == ENOENT); #ifdef __FreeBSD__ atf_tc_expect_fail("Depends on non-standard behavior not mentioned in POSIX.1-2008"); #endif ATF_REQUIRE(faccessat(dfd, BASELINK, F_OK, AT_SYMLINK_NOFOLLOW) == 0); ATF_REQUIRE(close(dfd) == 0); }
ATF_TC_BODY(faccessat_fderr3, tc) { int fd; ATF_REQUIRE(mkdir(DIR, 0755) == 0); ATF_REQUIRE((fd = open(FILE, O_CREAT|O_RDWR, 0644)) != -1); ATF_REQUIRE(close(fd) == 0); ATF_REQUIRE(faccessat(-1, FILE, F_OK, 0) == -1); }
ATF_TC_BODY(faccessat_fdcwd, tc) { int fd; ATF_REQUIRE(mkdir(DIR, 0755) == 0); ATF_REQUIRE((fd = open(FILE, O_CREAT|O_RDWR, 0644)) != -1); ATF_REQUIRE(close(fd) == 0); ATF_REQUIRE(chdir(DIR) == 0); ATF_REQUIRE(faccessat(AT_FDCWD, BASEFILE, F_OK, 0) == 0); }
/* * Tests wether the connected 'wgt' has the 'filename'. * * It is an error (with errno = EINVAL) to test an * invalid filename. * * Returns 0 if it hasn't it, 1 if it has it or * -1 if an error occured. */ int wgt_has(struct wgt *wgt, const char *filename) { assert(wgt); assert(wgt_is_connected(wgt)); filename = normalsubpath(filename); if (!filename) { errno = EINVAL; return -1; } return 0 == faccessat(wgt->rootfd, filename, F_OK, 0); }
/* Search for a compose file. According to Compose(5) man page the compose file searched in the following locations: - XCOMPOSEFILE variable. - .XCompose at $HOME. - System wide compose file for the current locale. */ static char * get_compose_file_for_locale() { struct matcher_context context = { NULL }; char *xcomposefile; char *to_be_freed; char *home; int err; xcomposefile = getenv ("XCOMPOSEFILE"); if (xcomposefile != NULL) return strdup (xcomposefile); home = getenv ("HOME"); if (home != NULL) { err = asprintf (&xcomposefile, "%s/.XCompose", home); if (err != -1) { if (faccessat(AT_FDCWD, xcomposefile, R_OK, AT_EACCESS) == 0) return xcomposefile; else { free (xcomposefile); /* TODO: check and report whether the compose file doesn't exist or read permission was not granted to us. */ } } } context.value = setlocale (LC_ALL, NULL); map_iterate (X11_PREFIX "/share/X11/locale/locale.alias", match_left_set_right, &context); to_be_freed = context.result; if (context.result != NULL) { /* Current locale is an alias. Use the real name to index the database. */ context.value = context.result; } context.result = NULL; map_iterate (X11_PREFIX "/share/X11/locale/compose.dir", match_right_set_left, &context); free (to_be_freed); /* compose.dir contains relative paths to compose files. */ to_be_freed = context.result; err = asprintf (&context.result, X11_PREFIX "/share/X11/locale/%s", context.result); if (err == -1) context.result = NULL; free (to_be_freed); return context.result; }
ATF_TC_BODY(faccessat_fd, tc) { int dfd; int fd; ATF_REQUIRE(mkdir(DIR, 0755) == 0); ATF_REQUIRE((fd = open(FILE, O_CREAT|O_RDWR, 0644)) != -1); ATF_REQUIRE(close(fd) == 0); ATF_REQUIRE((dfd = open(DIR, O_RDONLY, 0)) != -1); ATF_REQUIRE(faccessat(dfd, BASEFILE, F_OK, 0) == 0); ATF_REQUIRE(close(dfd) == 0); }
static int callback_access (const char *path, int mode) { path = ENSURE_RELPATH (path); /* Apparently at least GNU coreutils rm calls `faccessat(W_OK)` * before trying to do an unlink. So...we'll just lie about * writable access here. */ if (faccessat (basefd, path, mode, 0) == -1) return -errno; return 0; }
ATF_TC_BODY(faccessat_fderr2, tc) { int dfd; int fd; char cwd[MAXPATHLEN]; ATF_REQUIRE(mkdir(DIR, 0755) == 0); ATF_REQUIRE((fd = open(FILE, O_CREAT|O_RDWR, 0644)) != -1); ATF_REQUIRE(close(fd) == 0); ATF_REQUIRE((dfd = open(getcwd(cwd, MAXPATHLEN), O_RDONLY, 0)) != -1); ATF_REQUIRE(faccessat(dfd, BASEFILE, F_OK, 0) == -1); ATF_REQUIRE(close(dfd) == 0); }
int ftestexecutableat(int dirfd, const char* path) { struct stat st; if ( fstatat(dirfd, path, &st, AT_SYMLINK_NOFOLLOW) != 0 ) return -1; if ( !S_ISREG(st.st_mode) ) return errno = EISDIR, -1; if ( faccessat(dirfd, path, X_OK, AT_EACCESS | AT_SYMLINK_NOFOLLOW) == 0 ) return 1; else if ( errno == EACCES ) return 0; else return -1; }
/* * We cannot use POSIX access() for two reasons: * 1. It uses real uid, rather than effective or filesystem uid. * 2. It dereferences symlinks. * Instead, we're using faccessat(). * TODO: To simplify things, we're mandating absolute paths. We should * probably properly handle relative paths for this later and remove this * restriction. Given this, the first argument to faccessat() is ignored. * TODO: POSIX faccessat() doesn't support AT_SYMLINK_NOFOLLOW, and neither * does musl. See if we can upstream support into musl. Utilizing * AT_SYMLINK_NOFOLLOW is disabled for now so it will compile against musl. */ static int bru_access(const char *path, int mask) { SET_CALLER_UID(); REDIR_PATH(path, new_path); /* * Disabling AT_SYMLINK_NOFOLLOW since musl does not (yet?) support it. * int ret = faccessat(0, new_path, mask, AT_EACCESS | AT_SYMLINK_NOFOLLOW); */ int ret = faccessat(0, new_path, mask, AT_EACCESS); SET_RET_ERRNO(); return ret; }
int main() { struct stat st; struct stat st2; openat(AT_FDCWD, PWD "openat.txt", O_CREAT | O_WRONLY, 0644); assert(stat("openat.txt", &st) == 0); // relative path assert(faccessat(AT_FDCWD, PWD "openat.txt", F_OK, 0) == 0); assert(fstatat(AT_FDCWD, PWD "openat.txt", &st2, 0) == 0); assert(fchmodat(AT_FDCWD, PWD "openat.txt", 0777, 0) == 0); struct timeval my_times[2]; my_times[0].tv_sec = 0; my_times[0].tv_usec = 0; my_times[1].tv_sec = 0; my_times[1].tv_usec = 0; assert(futimesat(AT_FDCWD, PWD "openat.txt", my_times, 0) == 0); // see /etc/passwd, user 'pgbovine' is 508:100 assert(fchownat(AT_FDCWD, PWD "openat.txt", 508, 100, 0) == 0); assert(linkat(AT_FDCWD, PWD "openat.txt", AT_FDCWD, PWD "openat_hardlink.txt", 0) == 0); assert(stat("openat_hardlink.txt", &st) == 0); // relative path assert(symlinkat(PWD "openat.txt", AT_FDCWD, PWD "openat_symlink.txt") == 0); assert(lstat("openat_symlink.txt", &st) == 0); // relative path char res[300]; assert(readlinkat(AT_FDCWD, PWD "openat_symlink.txt", res, sizeof(res)) > 0); assert(renameat(AT_FDCWD, PWD "openat.txt", AT_FDCWD, PWD "openat_newname.txt", 0) == 0); assert(stat("openat.txt", &st) != 0); // should not exist anymore assert(stat("openat_newname.txt", &st) == 0); // relative path unlinkat(AT_FDCWD, PWD "openat_newname.txt", 0); unlinkat(AT_FDCWD, PWD "openat_hardlink.txt", 0); unlinkat(AT_FDCWD, PWD "openat_symlink.txt", 0); mknodat(AT_FDCWD, PWD "mknodat.fifo", S_IFIFO); assert(stat("mknodat.fifo", &st) == 0); // relative path unlinkat(AT_FDCWD, PWD "mknodat.fifo", 0); mkdirat(AT_FDCWD, PWD "mkdirat_dir", 0); assert(stat("mkdirat_dir", &st) == 0); // relative path unlinkat(AT_FDCWD, PWD "mkdirat_dir", AT_REMOVEDIR); // like 'rmdir' return 0; }
static int process_locale(void) { const char *etc_localeconf; char* locales[3]; unsigned i = 0; int r; etc_localeconf = prefix_roota("/etc/locale.conf"); if (faccessat(AT_FDCWD, etc_localeconf, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) return 0; if (arg_copy_locale && arg_root) { mkdir_parents(etc_localeconf, 0755); r = copy_file("/etc/locale.conf", etc_localeconf, 0, 0644); if (r != -ENOENT) { if (r < 0) { log_error("Failed to copy %s: %s", etc_localeconf, strerror(-r)); return r; } log_info("%s copied.", etc_localeconf); return 0; } } r = prompt_locale(); if (r < 0) return r; if (!isempty(arg_locale)) locales[i++] = strappenda("LANG=", arg_locale); if (!isempty(arg_locale_messages) && !streq(arg_locale_messages, arg_locale)) locales[i++] = strappenda("LC_MESSAGES=", arg_locale_messages); if (i == 0) return 0; locales[i] = NULL; mkdir_parents(etc_localeconf, 0755); r = write_env_file(etc_localeconf, locales); if (r < 0) { log_error("Failed to write %s: %s", etc_localeconf, strerror(-r)); return r; } log_info("%s written.", etc_localeconf); return 0; }
CAMLprim value netsys_faccessat(value dirfd, value path, value perms, value flags) { #ifdef HAVE_AT int ret, cv_perms, cv_flags; cv_perms = convert_flag_list(perms, access_permission_table); cv_flags = convert_flag_list(flags, at_flags_table); cv_flags &= (AT_EACCESS | AT_SYMLINK_NOFOLLOW); ret = faccessat(Int_val(dirfd), String_val(path), cv_perms, cv_flags); if (ret == -1) uerror("faccessat", path); return Val_unit; #else invalid_argument("Netsys_posix.faccessat not available"); #endif }
int sysfs_is_partition_dirent(DIR *dir, struct dirent *d, const char *parent_name) { char path[256]; #ifdef _DIRENT_HAVE_D_TYPE if (d->d_type != DT_DIR) return 0; #endif if (strncmp(parent_name, d->d_name, strlen(parent_name))) return 0; /* Cannot use /partition file, not supported on old sysfs */ snprintf(path, sizeof(path), "%s/start", d->d_name); return faccessat(dirfd(dir), path, R_OK, 0) == 0; }
static int process_timezone(void) { const char *etc_localtime, *e; int r; etc_localtime = prefix_roota("/etc/localtime"); if (faccessat(AT_FDCWD, etc_localtime, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) return 0; if (arg_copy_timezone && arg_root) { _cleanup_free_ char *p = NULL; r = readlink_malloc("/etc/localtime", &p); if (r != -ENOENT) { if (r < 0) { log_error("Failed to read host timezone: %s", strerror(-r)); return r; } mkdir_parents(etc_localtime, 0755); if (symlink(p, etc_localtime) < 0) { log_error("Failed to create %s symlink: %m", etc_localtime); return -errno; } log_info("%s copied.", etc_localtime); return 0; } } r = prompt_timezone(); if (r < 0) return r; if (isempty(arg_timezone)) return 0; e = strappenda("../usr/share/zoneinfo/", arg_timezone); mkdir_parents(etc_localtime, 0755); if (symlink(e, etc_localtime) < 0) { log_error("Failed to create %s symlink: %m", etc_localtime); return -errno; } log_info("%s written", etc_localtime); return 0; }
int ast_faccessat(int cwd, const char* path, mode_t mode, int flags) { int r = -1; PATHIFY(cwd, path, 1, 0); if (path == dot && cwd >= 0) { int f; RESTART(f, fcntl(cwd, F_GETFL)); if (f < 0) r = -1; else if (mode & R_OK) { if ((f & (O_WRONLY|O_RDWR)) == O_WRONLY) { errno = EACCES; r = -1; } } else if (mode & W_OK) { if (!(f & (O_WRONLY|O_RDWR))) { errno = EACCES; r = -1; } } else if (mode & X_OK) { struct stat st; RESTART(r, fstat(cwd, &st)); if (r >= 0 && !(st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) { errno = EACCES; r = -1; } } } else RESTART(r, faccessat(cwd, path, mode, flags)); PATHEND(); return r; }
bool VolumeManager::isAsecInDirectory(const char *dir, const char *asecName) const { int dirfd = open(dir, O_DIRECTORY); if (dirfd < 0) { SLOGE("Couldn't open internal ASEC dir (%s)", strerror(errno)); return -1; } bool ret = false; if (!faccessat(dirfd, asecName, F_OK, AT_SYMLINK_NOFOLLOW)) { ret = true; } close(dirfd); return ret; }
static void _make_tmpdir(stepd_step_rec_t *job) { char *tmpdir; if (!(tmpdir = getenvp(job->env, "TMPDIR"))) setenvf(&job->env, "TMPDIR", "/tmp"); /* task may want it set */ else if (mkdir(tmpdir, 0700) < 0) { struct stat st; int mkdir_errno = errno; if (stat(tmpdir, &st)) { /* does the file exist ? */ /* show why we were not able to create it */ error("Unable to create TMPDIR [%s]: %s", tmpdir, strerror(mkdir_errno)); } else if (!S_ISDIR(st.st_mode)) { /* is it a directory? */ error("TMPDIR [%s] is not a directory", tmpdir); } /* Eaccess wasn't introduced until glibc 2.4 but euidaccess * has been around for a while. So to make sure we * still work with older systems we include this check. */ #if defined(HAVE_FACCESSAT) else if (faccessat(AT_FDCWD, tmpdir, X_OK|W_OK, AT_EACCESS)) #elif defined(HAVE_EACCESS) else if (eaccess(tmpdir, X_OK|W_OK)) /* check permissions */ #else else if (euidaccess(tmpdir, X_OK|W_OK)) #endif error("TMPDIR [%s] is not writeable", tmpdir); else return; error("Setting TMPDIR to /tmp"); setenvf(&job->env, "TMPDIR", "/tmp"); } return; }