12825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich/*
22825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * Copyright (C) 2015 The Android Open Source Project
32825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * All rights reserved.
42825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich *
52825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * Redistribution and use in source and binary forms, with or without
62825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * modification, are permitted provided that the following conditions
72825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * are met:
82825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich *  * Redistributions of source code must retain the above copyright
92825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich *    notice, this list of conditions and the following disclaimer.
102825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich *  * Redistributions in binary form must reproduce the above copyright
112825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich *    notice, this list of conditions and the following disclaimer in
122825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich *    the documentation and/or other materials provided with the
132825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich *    distribution.
142825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich *
152825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
172825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
182825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
192825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
202825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
212825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
222825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
232825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
242825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
252825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
262825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich * SUCH DAMAGE.
272825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich */
282825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich
292825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich#include <sys/stat.h>
302825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich#include <sys/types.h>
312825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich#include <sys/xattr.h>
322825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich#include <errno.h>
332825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich#include <fcntl.h>
342825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich#include <stdio.h>
352825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich
362825f10b7f61558c264231a536cf3affc0d84204Nick Kralevichextern "C" int ___fsetxattr(int, const char*, const void*, size_t, int);
372825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich
382825f10b7f61558c264231a536cf3affc0d84204Nick Kralevichint fsetxattr(int fd, const char* name, const void* value, size_t size, int flags) {
392825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  int saved_errno = errno;
402825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  int result = ___fsetxattr(fd, name, value, size, flags);
412825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich
422825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  if ((result == 0) || (errno != EBADF)) {
432825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich    return result;
442825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  }
452825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich
462825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  // fd could be an O_PATH file descriptor, and the kernel
472825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  // may not directly support fsetxattr() on such a file descriptor.
482825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  // Use /proc/self/fd instead to emulate this support.
492825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  int fd_flag = fcntl(fd, F_GETFL);
502825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
512825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich    errno = EBADF;
522825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich    return -1;
532825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  }
542825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich
552825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  char buf[40];
562825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
572825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  errno = saved_errno;
582825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich  return setxattr(buf, name, value, size, flags);
592825f10b7f61558c264231a536cf3affc0d84204Nick Kralevich}
60