Merge "Kill IPv6 sockets as well as IPv4 sockets." into honeycomb-LTE
diff --git a/init/property_service.c b/init/property_service.c
index be56a19..7fc4f65 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -189,15 +189,6 @@
     __futex_wake(&pi->serial, INT32_MAX);
 }
 
-static int property_write(prop_info *pi, const char *value)
-{
-    int valuelen = strlen(value);
-    if(valuelen >= PROP_VALUE_MAX) return -1;
-    update_prop_info(pi, value, valuelen);
-    return 0;
-}
-
-
 /*
  * Checks permissions for starting/stoping system services.
  * AID_SYSTEM and AID_ROOT are always allowed.
@@ -384,8 +375,8 @@
     }
 
     r = recv(s, &msg, sizeof(msg), 0);
-    close(s);
     if(r != sizeof(prop_msg)) {
+        close(s);
         ERROR("sys_prop: mis-match msg size recieved: %d expected: %d\n",
               r, sizeof(prop_msg));
         return;
@@ -416,6 +407,11 @@
     default:
         break;
     }
+
+    // Note: bionic's property client code assumes that the property
+    // server will not close the socket until *AFTER* the property is
+    // written to memory.
+    close(s);
 }
 
 void get_property_workspace(int *fd, int *sz)
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 8e08ef3..657797e 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -401,7 +401,7 @@
 service drm /system/bin/drmserver
     class main
     user drm
-    group inet system
+    group system inet
 
 service media /system/bin/mediaserver
     class main
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 0b8f656..7112ebf 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -581,17 +581,50 @@
         struct fuse_attr_out out;
         char *path, buffer[PATH_BUFFER_SIZE];
         int res = 0;
+        struct timespec times[2];
 
         TRACE("SETATTR fh=%llx id=%llx valid=%x\n",
               req->fh, hdr->nodeid, req->valid);
 
-        /* XXX: incomplete implementation -- truncate only.  chmod/chown
-         * should NEVER be implemented. */
+        /* XXX: incomplete implementation on purpose.   chmod/chown
+         * should NEVER be implemented.*/
 
         path = node_get_path(node, buffer, 0);
         if (req->valid & FATTR_SIZE)
             res = truncate(path, req->size);
+        if (res)
+            goto getout;
 
+        /* Handle changing atime and mtime.  If FATTR_ATIME_and FATTR_ATIME_NOW
+         * are both set, then set it to the current time.  Else, set it to the
+         * time specified in the request.  Same goes for mtime.  Use utimensat(2)
+         * as it allows ATIME and MTIME to be changed independently, and has
+         * nanosecond resolution which fuse also has.
+         */
+        if (req->valid & (FATTR_ATIME | FATTR_MTIME)) {
+            times[0].tv_nsec = UTIME_OMIT;
+            times[1].tv_nsec = UTIME_OMIT;
+            if (req->valid & FATTR_ATIME) {
+                if (req->valid & FATTR_ATIME_NOW) {
+                  times[0].tv_nsec = UTIME_NOW;
+                } else {
+                  times[0].tv_sec = req->atime;
+                  times[0].tv_nsec = req->atimensec;
+                }
+            }
+            if (req->valid & FATTR_MTIME) {
+                if (req->valid & FATTR_MTIME_NOW) {
+                  times[1].tv_nsec = UTIME_NOW;
+                } else {
+                  times[1].tv_sec = req->mtime;
+                  times[1].tv_nsec = req->mtimensec;
+                }
+            }
+            TRACE("Calling utimensat on %s with atime %ld, mtime=%ld\n", path, times[0].tv_sec, times[1].tv_sec);
+            res = utimensat(-1, path, times, 0);
+        }
+
+        getout:
         memset(&out, 0, sizeof(out));
         node_get_attr(node, &out.attr);
         out.attr_valid = 10;