am 520ca3e1: Merge "builtins.c: Don\'t require file open() for chmod/chown"

* commit '520ca3e13a134386762c3fc754a8bc2e51af3c2f':
  builtins.c: Don't require file open() for chmod/chown
diff --git a/init/builtins.c b/init/builtins.c
index d42ec81..76c0a18 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -49,6 +49,8 @@
 
 #include <private/android_filesystem_config.h>
 
+#define chmod DO_NOT_USE_CHMOD_USE_FCHMODAT_SYMLINK_NOFOLLOW
+
 int add_environment(const char *name, const char *value);
 
 extern int init_module(void *, unsigned long, const char *);
@@ -76,63 +78,6 @@
     }
 }
 
-static int _open(const char *path)
-{
-    int fd;
-
-    fd = open(path, O_RDONLY | O_NOFOLLOW);
-    if (fd < 0)
-        fd = open(path, O_WRONLY | O_NOFOLLOW);
-
-    return fd;
-}
-
-static int _chown(const char *path, unsigned int uid, unsigned int gid)
-{
-    int fd;
-    int ret;
-
-    fd = _open(path);
-    if (fd < 0) {
-        return -1;
-    }
-
-    ret = fchown(fd, uid, gid);
-    if (ret < 0) {
-        int errno_copy = errno;
-        close(fd);
-        errno = errno_copy;
-        return -1;
-    }
-
-    close(fd);
-
-    return 0;
-}
-
-static int _chmod(const char *path, mode_t mode)
-{
-    int fd;
-    int ret;
-
-    fd = _open(path);
-    if (fd < 0) {
-        return -1;
-    }
-
-    ret = fchmod(fd, mode);
-    if (ret < 0) {
-        int errno_copy = errno;
-        close(fd);
-        errno = errno_copy;
-        return -1;
-    }
-
-    close(fd);
-
-    return 0;
-}
-
 static int insmod(const char *filename, char *options)
 {
     void *module;
@@ -320,7 +265,7 @@
     ret = make_dir(args[1], mode);
     /* chmod in case the directory already exists */
     if (ret == -1 && errno == EEXIST) {
-        ret = _chmod(args[1], mode);
+        ret = fchmodat(AT_FDCWD, args[1], mode, AT_SYMLINK_NOFOLLOW);
     }
     if (ret == -1) {
         return -errno;
@@ -334,13 +279,13 @@
             gid = decode_uid(args[4]);
         }
 
-        if (_chown(args[1], uid, gid) < 0) {
+        if (lchown(args[1], uid, gid) == -1) {
             return -errno;
         }
 
         /* chown may have cleared S_ISUID and S_ISGID, chmod again */
         if (mode & (S_ISUID | S_ISGID)) {
-            ret = _chmod(args[1], mode);
+            ret = fchmodat(AT_FDCWD, args[1], mode, AT_SYMLINK_NOFOLLOW);
             if (ret == -1) {
                 return -errno;
             }
@@ -814,10 +759,10 @@
 int do_chown(int nargs, char **args) {
     /* GID is optional. */
     if (nargs == 3) {
-        if (_chown(args[2], decode_uid(args[1]), -1) < 0)
+        if (lchown(args[2], decode_uid(args[1]), -1) == -1)
             return -errno;
     } else if (nargs == 4) {
-        if (_chown(args[3], decode_uid(args[1]), decode_uid(args[2])) < 0)
+        if (lchown(args[3], decode_uid(args[1]), decode_uid(args[2])) == -1)
             return -errno;
     } else {
         return -1;
@@ -840,7 +785,7 @@
 
 int do_chmod(int nargs, char **args) {
     mode_t mode = get_mode(args[1]);
-    if (_chmod(args[2], mode) < 0) {
+    if (fchmodat(AT_FDCWD, args[2], mode, AT_SYMLINK_NOFOLLOW) < 0) {
         return -errno;
     }
     return 0;