13cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich/* 23cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * Copyright (C) 2015 The Android Open Source Project 33cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * All rights reserved. 43cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * 53cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * Redistribution and use in source and binary forms, with or without 63cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * modification, are permitted provided that the following conditions 73cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * are met: 83cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * * Redistributions of source code must retain the above copyright 93cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * notice, this list of conditions and the following disclaimer. 103cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * * Redistributions in binary form must reproduce the above copyright 113cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * notice, this list of conditions and the following disclaimer in 123cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * the documentation and/or other materials provided with the 133cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * distribution. 143cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * 153cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 163cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 173cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 183cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 193cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 203cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 213cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 223cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 233cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 243cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 253cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 263cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich * SUCH DAMAGE. 273cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich */ 283cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 293cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#include <fcntl.h> 303cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#include <sys/stat.h> 313cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#include <sys/types.h> 323cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#include <errno.h> 333cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#include <unistd.h> 343cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 353cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich#include "private/ErrnoRestorer.h" 363cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 3700490ae3f351e07ed4cc2a94b11cba6a22f37311Nick Kralevichextern "C" int ___fchmodat(int, const char*, mode_t); 383cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 393cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevichint fchmodat(int dirfd, const char* pathname, mode_t mode, int flags) { 403cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich if ((flags & ~AT_SYMLINK_NOFOLLOW) != 0) { 413cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich errno = EINVAL; 423cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich return -1; 433cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich } 443cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 453cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich if (flags & AT_SYMLINK_NOFOLLOW) { 463cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // Emulate AT_SYMLINK_NOFOLLOW using the mechanism described 473cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // at https://sourceware.org/bugzilla/show_bug.cgi?id=14578 483cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // comment #10 493cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 503cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich int fd = openat(dirfd, pathname, O_PATH | O_NOFOLLOW | O_CLOEXEC); 513cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich if (fd == -1) { 523cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich return -1; // returns errno from openat 533cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich } 543cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 553cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // POSIX requires that ENOTSUP be returned when the system 563cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // doesn't support setting the mode of a symbolic link. 573cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // This is true for all Linux kernels. 583cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // We rely on the O_PATH compatibility layer added in the 593cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich // fchmod() function to get errno correct. 603cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich int result = fchmod(fd, mode); 613cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich ErrnoRestorer errno_restorer; // don't let close() clobber errno 623cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich close(fd); 633cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich return result; 643cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich } 653cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich 6600490ae3f351e07ed4cc2a94b11cba6a22f37311Nick Kralevich return ___fchmodat(dirfd, pathname, mode); 673cbc6c627fe57c9a9783c52d148078f8d52f7b96Nick Kralevich} 68