Ignore error for fchown if sgid bit is set for parent directory

When a file is transferred to device, fchown will be called to set
gid/uid. If sgid permission is set, then gid will be set automatically,
in this case ignore return code from fchown.

Bug: 192445890
Test: Manual, confirm permissions:
adb shell ls -la /storage/emulated/0/Android/data/com.android.vending/
drwxrws---  3 u0_a207  ext_data_rw 3452 2021-06-29 14:49 .
push file to filesystem
adb push foo /storage/emulated/0/Android/data/com.android.vending/files

Change-Id: I9719bf7d2bb6dc473c826114067288ceecb52755
(cherry picked from commit e79769d3b6e535b6774528438d8c5514320b0279)
diff --git a/daemon/file_sync_service.cpp b/daemon/file_sync_service.cpp
index 513b8dd..b59da97 100644
--- a/daemon/file_sync_service.cpp
+++ b/daemon/file_sync_service.cpp
@@ -65,6 +65,7 @@
 
 using android::base::borrowed_fd;
 using android::base::Dirname;
+using android::base::Realpath;
 using android::base::StringPrintf;
 
 static bool should_use_fs_config(const std::string& path) {
@@ -369,8 +370,16 @@
             goto fail;
         } else {
             if (fchown(fd.get(), uid, gid) == -1) {
-                SendSyncFailErrno(s, "fchown failed");
-                goto fail;
+                struct stat st;
+                std::string real_path;
+
+                // Only return failure if parent directory does not have S_ISGID bit set,
+                // if S_ISGID is set then file will inherit groupid from directory
+                if (!Realpath(path, &real_path) || lstat(Dirname(real_path).c_str(), &st) == -1 ||
+                    (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) == 0)) {
+                    SendSyncFailErrno(s, "fchown failed");
+                    goto fail;
+                }
             }
 
 #if defined(__ANDROID__)