linux/tools/testing/selftests/openat2/helpers.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Author: Aleksa Sarai <cyphar@cyphar.com>
   4 * Copyright (C) 2018-2019 SUSE LLC.
   5 */
   6
   7#define _GNU_SOURCE
   8#include <errno.h>
   9#include <fcntl.h>
  10#include <stdbool.h>
  11#include <string.h>
  12#include <syscall.h>
  13#include <limits.h>
  14
  15#include "helpers.h"
  16
  17bool needs_openat2(const struct open_how *how)
  18{
  19        return how->resolve != 0;
  20}
  21
  22int raw_openat2(int dfd, const char *path, void *how, size_t size)
  23{
  24        int ret = syscall(__NR_openat2, dfd, path, how, size);
  25        return ret >= 0 ? ret : -errno;
  26}
  27
  28int sys_openat2(int dfd, const char *path, struct open_how *how)
  29{
  30        return raw_openat2(dfd, path, how, sizeof(*how));
  31}
  32
  33int sys_openat(int dfd, const char *path, struct open_how *how)
  34{
  35        int ret = openat(dfd, path, how->flags, how->mode);
  36        return ret >= 0 ? ret : -errno;
  37}
  38
  39int sys_renameat2(int olddirfd, const char *oldpath,
  40                  int newdirfd, const char *newpath, unsigned int flags)
  41{
  42        int ret = syscall(__NR_renameat2, olddirfd, oldpath,
  43                                          newdirfd, newpath, flags);
  44        return ret >= 0 ? ret : -errno;
  45}
  46
  47int touchat(int dfd, const char *path)
  48{
  49        int fd = openat(dfd, path, O_CREAT, 0700);
  50        if (fd >= 0)
  51                close(fd);
  52        return fd;
  53}
  54
  55char *fdreadlink(int fd)
  56{
  57        char *target, *tmp;
  58
  59        E_asprintf(&tmp, "/proc/self/fd/%d", fd);
  60
  61        target = malloc(PATH_MAX);
  62        if (!target)
  63                ksft_exit_fail_msg("fdreadlink: malloc failed\n");
  64        memset(target, 0, PATH_MAX);
  65
  66        E_readlink(tmp, target, PATH_MAX);
  67        free(tmp);
  68        return target;
  69}
  70
  71bool fdequal(int fd, int dfd, const char *path)
  72{
  73        char *fdpath, *dfdpath, *other;
  74        bool cmp;
  75
  76        fdpath = fdreadlink(fd);
  77        dfdpath = fdreadlink(dfd);
  78
  79        if (!path)
  80                E_asprintf(&other, "%s", dfdpath);
  81        else if (*path == '/')
  82                E_asprintf(&other, "%s", path);
  83        else
  84                E_asprintf(&other, "%s/%s", dfdpath, path);
  85
  86        cmp = !strcmp(fdpath, other);
  87
  88        free(fdpath);
  89        free(dfdpath);
  90        free(other);
  91        return cmp;
  92}
  93
  94bool openat2_supported = false;
  95
  96void __attribute__((constructor)) init(void)
  97{
  98        struct open_how how = {};
  99        int fd;
 100
 101        BUILD_BUG_ON(sizeof(struct open_how) != OPEN_HOW_SIZE_VER0);
 102
 103        /* Check openat2(2) support. */
 104        fd = sys_openat2(AT_FDCWD, ".", &how);
 105        openat2_supported = (fd >= 0);
 106
 107        if (fd >= 0)
 108                close(fd);
 109}
 110