1e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich/*
2e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * Copyright (C) 2015 The Android Open Source Project
3e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * All rights reserved.
4e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich *
5e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * Redistribution and use in source and binary forms, with or without
6e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * modification, are permitted provided that the following conditions
7e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * are met:
8e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich *  * Redistributions of source code must retain the above copyright
9e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich *    notice, this list of conditions and the following disclaimer.
10e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich *  * Redistributions in binary form must reproduce the above copyright
11e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich *    notice, this list of conditions and the following disclaimer in
12e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich *    the documentation and/or other materials provided with the
13e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich *    distribution.
14e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich *
15e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich * SUCH DAMAGE.
27e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich */
28e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich
29e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich#include <sys/stat.h>
30e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich#include <sys/types.h>
31e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich#include <sys/xattr.h>
32e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich#include <errno.h>
33e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich#include <fcntl.h>
34e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich#include <stdio.h>
35e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich
36e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevichextern "C" ssize_t ___flistxattr(int, char*, size_t);
37e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich
38e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevichssize_t flistxattr(int fd, char *list, size_t size) {
39e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  int saved_errno = errno;
40e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  ssize_t result = ___flistxattr(fd, list, size);
41e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich
42e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  if ((result != -1) || (errno != EBADF)) {
43e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich    return result;
44e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  }
45e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich
46e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  // fd could be an O_PATH file descriptor, and the kernel
47e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  // may not directly support fgetxattr() on such a file descriptor.
48e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  // Use /proc/self/fd instead to emulate this support.
49e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  int fd_flag = fcntl(fd, F_GETFL);
50e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
51e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich    errno = EBADF;
52e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich    return -1;
53e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  }
54e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich
55e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  char buf[40];
56e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
57e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  errno = saved_errno;
58e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich  return listxattr(buf, list, size);
59e1d0810cd7e2aa045d5cc1e7d2b8697acd8467beNick Kralevich}
60