Merge "Bug 3381298 Remove old /data/drm/plugins/native"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index b84e1b65..8611d3b 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -47,3 +47,6 @@
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/init.rc)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/init.rc)
diff --git a/adb/commandline.c b/adb/commandline.c
index 3600e5a..5ed1b52 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -683,6 +683,7 @@
char buf[4096];
int no_daemon = 0;
int is_daemon = 0;
+ int is_server = 0;
int persist = 0;
int r;
int quote;
@@ -719,7 +720,9 @@
/* modifiers and flags */
while(argc > 0) {
- if(!strcmp(argv[0],"nodaemon")) {
+ if(!strcmp(argv[0],"server")) {
+ is_server = 1;
+ } else if(!strcmp(argv[0],"nodaemon")) {
no_daemon = 1;
} else if (!strcmp(argv[0], "fork-server")) {
/* this is a special flag used only when the ADB client launches the ADB Server */
@@ -766,7 +769,7 @@
adb_set_transport(ttype, serial);
adb_set_tcp_specifics(server_port);
- if ((argc > 0) && (!strcmp(argv[0],"server"))) {
+ if (is_server) {
if (no_daemon || is_daemon) {
r = adb_main(is_daemon, server_port);
} else {
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 752c953..6cfe79b 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -29,7 +29,7 @@
LOCAL_SRC_FILES += $(TARGET_ARCH)/crashglue.S
LOCAL_MODULE := crasher
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_TAGS := optional
#LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_SHARED_LIBRARIES := libcutils libc
include $(BUILD_EXECUTABLE)
@@ -45,7 +45,7 @@
LOCAL_SRC_FILES := vfp-crasher.c vfp.S
LOCAL_MODULE := vfp-crasher
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := libcutils libc
include $(BUILD_EXECUTABLE)
endif # ARCH_ARM_HAVE_VFP == true
diff --git a/gpttool/Android.mk b/gpttool/Android.mk
new file mode 100644
index 0000000..a9fffe9
--- /dev/null
+++ b/gpttool/Android.mk
@@ -0,0 +1,14 @@
+ifeq ($(HOST_OS),linux)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := gpttool.c
+LOCAL_STATIC_LIBRARIES := libz
+
+LOCAL_MODULE := gpttool
+LOCAL_MODULE_TAGS := eng
+
+include $(BUILD_HOST_EXECUTABLE)
+
+endif
diff --git a/gpttool/gpttool.c b/gpttool/gpttool.c
new file mode 100644
index 0000000..05d5177
--- /dev/null
+++ b/gpttool/gpttool.c
@@ -0,0 +1,376 @@
+/* system/core/gpttool/gpttool.c
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include <zlib.h>
+
+#include <linux/fs.h>
+
+#include <sys/stat.h>
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+typedef unsigned long long u64;
+
+const u8 partition_type_uuid[16] = {
+ 0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44,
+ 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7,
+};
+
+
+#define EFI_VERSION 0x00010000
+#define EFI_MAGIC "EFI PART"
+#define EFI_ENTRIES 128
+#define EFI_NAMELEN 36
+
+struct efi_header {
+ u8 magic[8];
+
+ u32 version;
+ u32 header_sz;
+
+ u32 crc32;
+ u32 reserved;
+
+ u64 header_lba;
+ u64 backup_lba;
+ u64 first_lba;
+ u64 last_lba;
+
+ u8 volume_uuid[16];
+
+ u64 entries_lba;
+
+ u32 entries_count;
+ u32 entries_size;
+ u32 entries_crc32;
+} __attribute__((packed));
+
+struct efi_entry {
+ u8 type_uuid[16];
+ u8 uniq_uuid[16];
+ u64 first_lba;
+ u64 last_lba;
+ u64 attr;
+ u16 name[EFI_NAMELEN];
+};
+
+struct ptable {
+ u8 mbr[512];
+ union {
+ struct efi_header header;
+ u8 block[512];
+ };
+ struct efi_entry entry[EFI_ENTRIES];
+};
+
+void get_uuid(u8 *uuid)
+{
+ int fd;
+ fd = open("/dev/urandom", O_RDONLY);
+ read(fd, uuid, 16);
+ close(fd);
+}
+
+void init_mbr(u8 *mbr, u32 blocks)
+{
+ mbr[0x1be] = 0x00; // nonbootable
+ mbr[0x1bf] = 0xFF; // bogus CHS
+ mbr[0x1c0] = 0xFF;
+ mbr[0x1c1] = 0xFF;
+
+ mbr[0x1c2] = 0xEE; // GPT partition
+ mbr[0x1c3] = 0xFF; // bogus CHS
+ mbr[0x1c4] = 0xFF;
+ mbr[0x1c5] = 0xFF;
+
+ mbr[0x1c6] = 0x01; // start
+ mbr[0x1c7] = 0x00;
+ mbr[0x1c8] = 0x00;
+ mbr[0x1c9] = 0x00;
+
+ memcpy(mbr + 0x1ca, &blocks, sizeof(u32));
+
+ mbr[0x1fe] = 0x55;
+ mbr[0x1ff] = 0xaa;
+}
+
+int add_ptn(struct ptable *ptbl, u64 first, u64 last, const char *name)
+{
+ struct efi_header *hdr = &ptbl->header;
+ struct efi_entry *entry = ptbl->entry;
+ unsigned n;
+
+ if (first < 34) {
+ fprintf(stderr,"partition '%s' overlaps partition table\n", name);
+ return -1;
+ }
+
+ if (last > hdr->last_lba) {
+ fprintf(stderr,"partition '%s' does not fit on disk\n", name);
+ return -1;
+ }
+ for (n = 0; n < EFI_ENTRIES; n++, entry++) {
+ if (entry->type_uuid[0])
+ continue;
+ memcpy(entry->type_uuid, partition_type_uuid, 16);
+ get_uuid(entry->uniq_uuid);
+ entry->first_lba = first;
+ entry->last_lba = last;
+ for (n = 0; (n < EFI_NAMELEN) && *name; n++)
+ entry->name[n] = *name++;
+ return 0;
+ }
+ fprintf(stderr,"out of partition table entries\n");
+ return -1;
+}
+
+int usage(void)
+{
+ fprintf(stderr,
+ "usage: gpttool write <disk> [ <partition> ]*\n"
+ " gpttool read <disk>\n"
+ " gpttool test [ <partition> ]*\n"
+ "\n"
+ "partition: [<name>]:<size>[kmg] | @<file-of-partitions>\n"
+ );
+ return 0;
+}
+
+void show(struct ptable *ptbl)
+{
+ struct efi_entry *entry = ptbl->entry;
+ unsigned n, m;
+ char name[EFI_NAMELEN];
+
+ fprintf(stderr,"ptn start block end block name\n");
+ fprintf(stderr,"---- ------------- ------------- --------------------\n");
+
+ for (n = 0; n < EFI_ENTRIES; n++, entry++) {
+ if (entry->type_uuid[0] == 0)
+ break;
+ for (m = 0; m < EFI_NAMELEN; m++) {
+ name[m] = entry->name[m] & 127;
+ }
+ name[m] = 0;
+ fprintf(stderr,"#%03d %13lld %13lld %s\n",
+ n + 1, entry->first_lba, entry->last_lba, name);
+ }
+}
+
+u64 find_next_lba(struct ptable *ptbl)
+{
+ struct efi_entry *entry = ptbl->entry;
+ unsigned n;
+ u64 a = 0;
+ for (n = 0; n < EFI_ENTRIES; n++, entry++) {
+ if ((entry->last_lba + 1) > a)
+ a = entry->last_lba + 1;
+ }
+ return a;
+}
+
+u64 next_lba = 0;
+
+u64 parse_size(char *sz)
+{
+ int l = strlen(sz);
+ u64 n = strtoull(sz, 0, 10);
+ if (l) {
+ switch(sz[l-1]){
+ case 'k':
+ case 'K':
+ n *= 1024;
+ break;
+ case 'm':
+ case 'M':
+ n *= (1024 * 1024);
+ break;
+ case 'g':
+ case 'G':
+ n *= (1024 * 1024 * 1024);
+ break;
+ }
+ }
+ return n;
+}
+
+int parse_ptn(struct ptable *ptbl, char *x)
+{
+ char *y = strchr(x, ':');
+ u64 sz;
+
+ if (!y) {
+ fprintf(stderr,"invalid partition entry: %s\n", x);
+ return -1;
+ }
+ *y++ = 0;
+
+ if (*y == 0) {
+ sz = ptbl->header.last_lba - next_lba;
+ } else {
+ sz = parse_size(y);
+ if (sz & 511) {
+ fprintf(stderr,"partition size must be multiple of 512\n");
+ return -1;
+ }
+ sz /= 512;
+ }
+
+ if (sz == 0) {
+ fprintf(stderr,"zero size partitions not allowed\n");
+ return -1;
+ }
+
+ if (x[0] && add_ptn(ptbl, next_lba, next_lba + sz - 1, x))
+ return -1;
+
+ next_lba = next_lba + sz;
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ struct ptable ptbl;
+ struct efi_entry *entry;
+ struct efi_header *hdr = &ptbl.header;
+ struct stat s;
+ u32 n;
+ u64 sz, blk;
+ int fd;
+ const char *device;
+ int real_disk = 0;
+
+ if (argc < 2)
+ return usage();
+
+ if (!strcmp(argv[1], "write")) {
+ if (argc < 3)
+ return usage();
+ device = argv[2];
+ argc -= 2;
+ argv += 2;
+ real_disk = 1;
+ } else if (!strcmp(argv[1], "test")) {
+ argc -= 1;
+ argv += 1;
+ real_disk = 0;
+ sz = 2097152 * 16;
+ fprintf(stderr,"< simulating 16GB disk >\n\n");
+ } else {
+ return usage();
+ }
+
+ if (real_disk) {
+ if (!strcmp(device, "/dev/sda") ||
+ !strcmp(device, "/dev/sdb")) {
+ fprintf(stderr,"error: refusing to partition sda or sdb\n");
+ return -1;
+ }
+
+ fd = open(device, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr,"error: cannot open '%s'\n", device);
+ return -1;
+ }
+ if (ioctl(fd, BLKGETSIZE64, &sz)) {
+ fprintf(stderr,"error: cannot query block device size\n");
+ return -1;
+ }
+ sz /= 512;
+ fprintf(stderr,"blocks %lld\n", sz);
+ }
+
+ memset(&ptbl, 0, sizeof(ptbl));
+
+ init_mbr(ptbl.mbr, sz - 1);
+
+ memcpy(hdr->magic, EFI_MAGIC, sizeof(hdr->magic));
+ hdr->version = EFI_VERSION;
+ hdr->header_sz = sizeof(struct efi_header);
+ hdr->header_lba = 1;
+ hdr->backup_lba = sz - 1;
+ hdr->first_lba = 34;
+ hdr->last_lba = sz - 1;
+ get_uuid(hdr->volume_uuid);
+ hdr->entries_lba = 2;
+ hdr->entries_count = 128;
+ hdr->entries_size = sizeof(struct efi_entry);
+
+ while (argc > 1) {
+ if (argv[1][0] == '@') {
+ char line[256], *p;
+ FILE *f;
+ f = fopen(argv[1] + 1, "r");
+ if (!f) {
+ fprintf(stderr,"cannot read partitions from '%s\n", argv[1]);
+ return -1;
+ }
+ while (fgets(line, sizeof(line), f)) {
+ p = line + strlen(line);
+ while (p > line) {
+ p--;
+ if (*p > ' ')
+ break;
+ *p = 0;
+ }
+ p = line;
+ while (*p && (*p <= ' '))
+ p++;
+ if (*p == '#')
+ continue;
+ if (*p == 0)
+ continue;
+ if (parse_ptn(&ptbl, p))
+ return -1;
+ }
+ fclose(f);
+ } else {
+ if (parse_ptn(&ptbl, argv[1]))
+ return -1;
+ }
+ argc--;
+ argv++;
+ }
+
+ n = crc32(0, Z_NULL, 0);
+ n = crc32(n, (void*) ptbl.entry, sizeof(ptbl.entry));
+ hdr->entries_crc32 = n;
+
+ n = crc32(0, Z_NULL, 0);
+ n = crc32(n, (void*) &ptbl.header, sizeof(ptbl.header));
+ hdr->crc32 = n;
+
+ show(&ptbl);
+
+ if (real_disk) {
+ write(fd, &ptbl, sizeof(ptbl));
+ fsync(fd);
+
+ if (ioctl(fd, BLKRRPART, 0)) {
+ fprintf(stderr,"could not re-read partition table\n");
+ }
+ close(fd);
+ }
+ return 0;
+}
diff --git a/include/cutils/atomic-arm.h b/include/cutils/atomic-arm.h
index 004cc0c..16fe512 100644
--- a/include/cutils/atomic-arm.h
+++ b/include/cutils/atomic-arm.h
@@ -146,38 +146,6 @@
#if defined(__thumb__)
-extern int32_t android_atomic_swap(int32_t new_value,
- volatile int32_t *ptr);
-#elif defined(__ARM_HAVE_LDREX_STREX)
-extern inline int32_t android_atomic_swap(int32_t new_value,
- volatile int32_t *ptr)
-{
- int32_t prev, status;
- do {
- __asm__ __volatile__ ("ldrex %0, [%3]\n"
- "strex %1, %4, [%3]"
- : "=&r" (prev), "=&r" (status), "+m" (*ptr)
- : "r" (ptr), "r" (new_value)
- : "cc");
- } while (__builtin_expect(status != 0, 0));
- android_memory_barrier();
- return prev;
-}
-#else
-extern inline int32_t android_atomic_swap(int32_t new_value,
- volatile int32_t *ptr)
-{
- int32_t prev;
- __asm__ __volatile__ ("swp %0, %2, [%3]"
- : "=&r" (prev), "+m" (*ptr)
- : "r" (new_value), "r" (ptr)
- : "cc");
- android_memory_barrier();
- return prev;
-}
-#endif
-
-#if defined(__thumb__)
extern int32_t android_atomic_add(int32_t increment,
volatile int32_t *ptr);
#elif defined(__ARM_HAVE_LDREX_STREX)
diff --git a/include/cutils/atomic-x86.h b/include/cutils/atomic-x86.h
index bce23ad..438012e 100644
--- a/include/cutils/atomic-x86.h
+++ b/include/cutils/atomic-x86.h
@@ -98,17 +98,6 @@
return android_atomic_cas(old_value, new_value, ptr);
}
-extern inline int32_t android_atomic_swap(int32_t new_value,
- volatile int32_t *ptr)
-{
- __asm__ __volatile__ ("xchgl %1, %0"
- : "=r" (new_value)
- : "m" (*ptr), "0" (new_value)
- : "memory");
- /* new_value now holds the old value of *ptr */
- return new_value;
-}
-
extern inline int32_t android_atomic_add(int32_t increment,
volatile int32_t *ptr)
{
diff --git a/include/cutils/atomic.h b/include/cutils/atomic.h
index a50bf0f..ae42eb8 100644
--- a/include/cutils/atomic.h
+++ b/include/cutils/atomic.h
@@ -90,13 +90,6 @@
void android_atomic_release_store(int32_t value, volatile int32_t* addr);
/*
- * Unconditional swap operation with release ordering.
- *
- * Stores the new value at *addr, and returns the previous value.
- */
-int32_t android_atomic_swap(int32_t value, volatile int32_t* addr);
-
-/*
* Compare-and-set operation with "acquire" or "release" ordering.
*
* This returns zero if the new value was successfully stored, which will
diff --git a/include/netutils/dhcp.h b/include/netutils/dhcp.h
index 96798c5..bd16240 100644
--- a/include/netutils/dhcp.h
+++ b/include/netutils/dhcp.h
@@ -24,12 +24,12 @@
extern int do_dhcp(char *iname);
extern int dhcp_do_request(const char *ifname,
- in_addr_t *ipaddr,
- in_addr_t *gateway,
- in_addr_t *mask,
- in_addr_t *dns1,
- in_addr_t *dns2,
- in_addr_t *server,
+ char *ipaddr,
+ char *gateway,
+ uint32_t *prefixLength,
+ char *dns1,
+ char *dns2,
+ char *server,
uint32_t *lease);
extern int dhcp_stop(const char *ifname);
extern int dhcp_release_lease(const char *ifname);
diff --git a/include/netutils/ifc.h b/include/netutils/ifc.h
index e245262..650d89d 100644
--- a/include/netutils/ifc.h
+++ b/include/netutils/ifc.h
@@ -36,6 +36,7 @@
extern int ifc_reset_connections(const char *ifname);
+extern int ifc_get_addr(const char *name, in_addr_t *addr);
extern int ifc_set_addr(const char *name, in_addr_t addr);
extern int ifc_set_mask(const char *name, in_addr_t mask);
extern int ifc_set_hwaddr(const char *name, const void *ptr);
diff --git a/include/usbhost/usbhost.h b/include/usbhost/usbhost.h
index 41e2ddc..c330cab 100644
--- a/include/usbhost/usbhost.h
+++ b/include/usbhost/usbhost.h
@@ -125,15 +125,6 @@
const struct usb_device_descriptor* usb_device_get_device_descriptor(struct usb_device *device);
-/* Sends a control message to the specified device on endpoint zero */
-int usb_device_send_control(struct usb_device *device,
- int requestType,
- int request,
- int value,
- int index,
- int length,
- void* buffer);
-
/* Returns a USB descriptor string for the given string ID.
* Used to implement usb_device_get_manufacturer_name,
* usb_device_get_product_name and usb_device_get_serial.
@@ -184,6 +175,23 @@
int usb_device_connect_kernel_driver(struct usb_device *device,
unsigned int interface, int connect);
+/* Sends a control message to the specified device on endpoint zero */
+int usb_device_control_transfer(struct usb_device *device,
+ int requestType,
+ int request,
+ int value,
+ int index,
+ void* buffer,
+ int length,
+ unsigned int timeout);
+
+/* Reads or writes on a bulk endpoint */
+int usb_device_bulk_transfer(struct usb_device *device,
+ int endpoint,
+ void* buffer,
+ int length,
+ unsigned int timeout);
+
/* Creates a new usb_request. */
struct usb_request *usb_request_new(struct usb_device *dev,
const struct usb_endpoint_descriptor *ep_desc);
diff --git a/libcutils/atomic-android-sh.c b/libcutils/atomic-android-sh.c
index f8f1f57..8bac68a 100644
--- a/libcutils/atomic-android-sh.c
+++ b/libcutils/atomic-android-sh.c
@@ -113,18 +113,6 @@
return oldValue;
}
-int32_t android_atomic_acquire_swap(int32_t value, volatile int32_t* addr) {
- return android_atomic_release_swap(value, addr);
-}
-
-int32_t android_atomic_release_swap(int32_t value, volatile int32_t* addr) {
- int32_t oldValue;
- do {
- oldValue = *addr;
- } while (android_atomic_cmpxchg(oldValue, value, addr));
- return oldValue;
-}
-
int android_atomic_acquire_cmpxchg(int32_t oldvalue, int32_t newvalue,
volatile int32_t* addr) {
return android_atomic_release_cmpxchg(oldValue, newValue, addr);
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c
index 1802688..030e677 100644
--- a/libnetutils/dhcp_utils.c
+++ b/libnetutils/dhcp_utils.c
@@ -60,60 +60,60 @@
return -1; /* failure */
}
-static void fill_ip_info(const char *interface,
- in_addr_t *ipaddr,
- in_addr_t *gateway,
- in_addr_t *mask,
- in_addr_t *dns1,
- in_addr_t *dns2,
- in_addr_t *server,
+static int fill_ip_info(const char *interface,
+ char *ipaddr,
+ char *gateway,
+ uint32_t *prefixLength,
+ char *dns1,
+ char *dns2,
+ char *server,
uint32_t *lease)
{
char prop_name[PROPERTY_KEY_MAX];
char prop_value[PROPERTY_VALUE_MAX];
- struct in_addr addr;
- in_addr_t iaddr;
snprintf(prop_name, sizeof(prop_name), "%s.%s.ipaddress", DHCP_PROP_NAME_PREFIX, interface);
- if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) {
- *ipaddr = addr.s_addr;
- } else {
- *ipaddr = 0;
- }
+ property_get(prop_name, ipaddr, NULL);
+
snprintf(prop_name, sizeof(prop_name), "%s.%s.gateway", DHCP_PROP_NAME_PREFIX, interface);
- if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) {
- *gateway = addr.s_addr;
- } else {
- *gateway = 0;
- }
+ property_get(prop_name, gateway, NULL);
+
snprintf(prop_name, sizeof(prop_name), "%s.%s.mask", DHCP_PROP_NAME_PREFIX, interface);
- if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) {
- *mask = addr.s_addr;
- } else {
- *mask = 0;
+ if (property_get(prop_name, prop_value, NULL)) {
+ int p;
+ // this conversion is v4 only, but this dhcp client is v4 only anyway
+ in_addr_t mask = ntohl(inet_addr(prop_value));
+ // Check netmask is a valid IP address. ntohl gives NONE response (all 1's) for
+ // non 255.255.255.255 inputs. if we get that value check if it is legit..
+ if (mask == INADDR_NONE && strcmp(prop_value, "255.255.255.255") != 0) {
+ snprintf(errmsg, sizeof(errmsg), "DHCP gave invalid net mask %s", prop_value);
+ return -1;
+ }
+ for (p = 0; p < 32; p++) {
+ if (mask == 0) break;
+ // check for non-contiguous netmask, e.g., 255.254.255.0
+ if ((mask & 0x80000000) == 0) {
+ snprintf(errmsg, sizeof(errmsg), "DHCP gave invalid net mask %s", prop_value);
+ return -1;
+ }
+ mask = mask << 1;
+ }
+ *prefixLength = p;
}
snprintf(prop_name, sizeof(prop_name), "%s.%s.dns1", DHCP_PROP_NAME_PREFIX, interface);
- if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) {
- *dns1 = addr.s_addr;
- } else {
- *dns1 = 0;
- }
+ property_get(prop_name, dns1, NULL);
+
snprintf(prop_name, sizeof(prop_name), "%s.%s.dns2", DHCP_PROP_NAME_PREFIX, interface);
- if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) {
- *dns2 = addr.s_addr;
- } else {
- *dns2 = 0;
- }
+ property_get(prop_name, dns2, NULL);
+
snprintf(prop_name, sizeof(prop_name), "%s.%s.server", DHCP_PROP_NAME_PREFIX, interface);
- if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) {
- *server = addr.s_addr;
- } else {
- *server = 0;
- }
+ property_get(prop_name, server, NULL);
+
snprintf(prop_name, sizeof(prop_name), "%s.%s.leasetime", DHCP_PROP_NAME_PREFIX, interface);
if (property_get(prop_name, prop_value, NULL)) {
*lease = atol(prop_value);
}
+ return 0;
}
static const char *ipaddr_to_string(in_addr_t addr)
@@ -129,12 +129,12 @@
* configuring the interface.
*/
int dhcp_do_request(const char *interface,
- in_addr_t *ipaddr,
- in_addr_t *gateway,
- in_addr_t *mask,
- in_addr_t *dns1,
- in_addr_t *dns2,
- in_addr_t *server,
+ char *ipaddr,
+ char *gateway,
+ uint32_t *prefixLength,
+ char *dns1,
+ char *dns2,
+ char *server,
uint32_t *lease)
{
char result_prop_name[PROPERTY_KEY_MAX];
@@ -175,8 +175,13 @@
}
if (strcmp(prop_value, "ok") == 0) {
char dns_prop_name[PROPERTY_KEY_MAX];
- fill_ip_info(interface, ipaddr, gateway, mask, dns1, dns2, server, lease);
- /* copy the dhcp.XXX.dns properties to net.XXX.dns */
+ if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns1, dns2, server, lease)
+ == -1) {
+ return -1;
+ }
+
+ /* copy dns data to system properties - TODO - remove this after we have async
+ * notification of renewal's */
snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", interface);
property_set(dns_prop_name, *dns1 ? ipaddr_to_string(*dns1) : "");
snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", interface);
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index 95a144c..6788391 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -25,6 +25,7 @@
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <net/if.h>
#include <linux/if.h>
#include <linux/if_ether.h>
@@ -126,7 +127,7 @@
if(r < 0) return -1;
*if_indexp = ifr.ifr_ifindex;
- return 0;
+ return 0;
}
static int ifc_set_flags(const char *name, unsigned set, unsigned clr)
@@ -163,7 +164,7 @@
ifc_init_ifr(name, &ifr);
init_sockaddr_in(&ifr.ifr_addr, addr);
-
+
return ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr);
}
@@ -184,10 +185,27 @@
ifc_init_ifr(name, &ifr);
init_sockaddr_in(&ifr.ifr_addr, mask);
-
+
return ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr);
}
+int ifc_get_addr(const char *name, in_addr_t *addr)
+{
+ struct ifreq ifr;
+ int ret = 0;
+
+ ifc_init_ifr(name, &ifr);
+ if (addr != NULL) {
+ ret = ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr);
+ if (ret < 0) {
+ *addr = 0;
+ } else {
+ *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr;
+ }
+ }
+ return ret;
+}
+
int ifc_get_info(const char *name, in_addr_t *addr, in_addr_t *mask, unsigned *flags)
{
struct ifreq ifr;
@@ -200,7 +218,7 @@
*addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr;
}
}
-
+
if (mask != NULL) {
if(ioctl(ifc_ctl_sock, SIOCGIFNETMASK, &ifr) < 0) {
*mask = 0;
@@ -311,11 +329,20 @@
int ifc_disable(const char *ifname)
{
+ unsigned addr, count;
int result;
ifc_init();
result = ifc_down(ifname);
+
ifc_set_addr(ifname, 0);
+ for (count=0, addr=1;((addr != 0) && (count < 255)); count++) {
+ if (ifc_get_addr(ifname, &addr) < 0)
+ break;
+ if (addr)
+ ifc_set_addr(ifname, 0);
+ }
+
ifc_close();
return result;
}
@@ -333,7 +360,7 @@
init_sockaddr_in(&ifr.ifr_addr, myaddr);
result = ioctl(ifc_ctl_sock, SIOCKILLADDR, &ifr);
ifc_close();
-
+
return result;
#else
return 0;
diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk
index dd2b32d..3b1f618 100644
--- a/libsysutils/Android.mk
+++ b/libsysutils/Android.mk
@@ -1,3 +1,4 @@
+ifneq ($(BUILD_TINY_ANDROID),true)
BUILD_LIBSYSUTILS := false
ifneq ($(TARGET_SIMULATOR),true)
BUILD_LIBSYSUTILS := true
@@ -33,3 +34,4 @@
include $(BUILD_SHARED_LIBRARY)
endif
+endif
diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c
index 89a7f0a..576ee00 100644
--- a/libusbhost/usbhost.c
+++ b/libusbhost/usbhost.c
@@ -332,30 +332,6 @@
return (struct usb_device_descriptor*)device->desc;
}
-int usb_device_send_control(struct usb_device *device,
- int requestType,
- int request,
- int value,
- int index,
- int length,
- void* buffer)
-{
- struct usbdevfs_ctrltransfer ctrl;
-
- // this usually requires read/write permission
- if (!usb_device_reopen_writeable(device))
- return -1;
-
- memset(&ctrl, 0, sizeof(ctrl));
- ctrl.bRequestType = requestType;
- ctrl.bRequest = request;
- ctrl.wValue = value;
- ctrl.wIndex = index;
- ctrl.wLength = length;
- ctrl.data = buffer;
- return ioctl(device->fd, USBDEVFS_CONTROL, &ctrl);
-}
-
char* usb_device_get_string(struct usb_device *device, int id)
{
char string[256];
@@ -368,18 +344,18 @@
memset(languages, 0, sizeof(languages));
// read list of supported languages
- result = usb_device_send_control(device,
+ result = usb_device_control_transfer(device,
USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR,
- (USB_DT_STRING << 8) | 0, 0, sizeof(languages), languages);
+ (USB_DT_STRING << 8) | 0, 0, languages, sizeof(languages), 0);
if (result > 0)
languageCount = (result - 2) / 2;
for (i = 1; i <= languageCount; i++) {
memset(buffer, 0, sizeof(buffer));
- result = usb_device_send_control(device,
+ result = usb_device_control_transfer(device,
USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR,
- (USB_DT_STRING << 8) | id, languages[i], sizeof(buffer), buffer);
+ (USB_DT_STRING << 8) | id, languages[i], buffer, sizeof(buffer), 0);
if (result > 0) {
int i;
// skip first word, and copy the rest to the string, changing shorts to bytes.
@@ -467,6 +443,48 @@
return ioctl(device->fd, USBDEVFS_IOCTL, &ctl);
}
+int usb_device_control_transfer(struct usb_device *device,
+ int requestType,
+ int request,
+ int value,
+ int index,
+ void* buffer,
+ int length,
+ unsigned int timeout)
+{
+ struct usbdevfs_ctrltransfer ctrl;
+
+ // this usually requires read/write permission
+ if (!usb_device_reopen_writeable(device))
+ return -1;
+
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.bRequestType = requestType;
+ ctrl.bRequest = request;
+ ctrl.wValue = value;
+ ctrl.wIndex = index;
+ ctrl.wLength = length;
+ ctrl.data = buffer;
+ ctrl.timeout = timeout;
+ return ioctl(device->fd, USBDEVFS_CONTROL, &ctrl);
+}
+
+int usb_device_bulk_transfer(struct usb_device *device,
+ int endpoint,
+ void* buffer,
+ int length,
+ unsigned int timeout)
+{
+ struct usbdevfs_bulktransfer ctrl;
+
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.ep = endpoint;
+ ctrl.len = length;
+ ctrl.data = buffer;
+ ctrl.timeout = timeout;
+ return ioctl(device->fd, USBDEVFS_BULK, &ctrl);
+}
+
struct usb_request *usb_request_new(struct usb_device *dev,
const struct usb_endpoint_descriptor *ep_desc)
{
diff --git a/netcfg/netcfg.c b/netcfg/netcfg.c
index 9cd883a..aae1228 100644
--- a/netcfg/netcfg.c
+++ b/netcfg/netcfg.c
@@ -20,6 +20,7 @@
#include <errno.h>
#include <dirent.h>
#include <netinet/ether.h>
+#include <netinet/if_ether.h>
#include <netutils/ifc.h>
#include <netutils/dhcp.h>
@@ -44,13 +45,14 @@
void usage(void)
{
fprintf(stderr,"usage: netcfg [<interface> {dhcp|up|down}]\n");
- exit(1);
+ exit(1);
}
int dump_interface(const char *name)
{
unsigned addr, mask, flags;
-
+ unsigned char hwbuf[ETH_ALEN];
+
if(ifc_get_info(name, &addr, &mask, &flags)) {
return 0;
}
@@ -58,7 +60,15 @@
printf("%-8s %s ", name, flags & 1 ? "UP " : "DOWN");
printf("%-16s", ipaddr(addr));
printf("%-16s", ipaddr(mask));
- printf("0x%08x\n", flags);
+ printf("0x%08x ", flags);
+ if (!ifc_get_hwaddr(name, hwbuf)) {
+ int i;
+ for(i=0; i < (ETH_ALEN-1); i++)
+ printf("%02x:", hwbuf[i]);
+ printf("%02x\n", hwbuf[i]);
+ } else {
+ printf("\n");
+ }
return 0;
}
@@ -66,10 +76,10 @@
{
DIR *d;
struct dirent *de;
-
+
d = opendir("/sys/class/net");
if(d == 0) return -1;
-
+
while((de = readdir(d))) {
if(de->d_name[0] == '.') continue;
dump_interface(de->d_name);
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 6e7a1f1..7f99ce7 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -208,15 +208,28 @@
# Define the memory thresholds at which the above process classes will
# be killed. These numbers are in pages (4k).
- setprop ro.FOREGROUND_APP_MEM 2048
- setprop ro.VISIBLE_APP_MEM 3072
- setprop ro.PERCEPTIBLE_APP_MEM 4096
- setprop ro.HEAVY_WEIGHT_APP_MEM 4096
- setprop ro.SECONDARY_SERVER_MEM 6144
- setprop ro.BACKUP_APP_MEM 6144
- setprop ro.HOME_APP_MEM 6144
- setprop ro.HIDDEN_APP_MEM 7168
- setprop ro.EMPTY_APP_MEM 8192
+ # These are currently tuned for tablets with approx 1GB RAM.
+ setprop ro.FOREGROUND_APP_MEM 8192
+ setprop ro.VISIBLE_APP_MEM 10240
+ setprop ro.PERCEPTIBLE_APP_MEM 12288
+ setprop ro.HEAVY_WEIGHT_APP_MEM 12288
+ setprop ro.SECONDARY_SERVER_MEM 14336
+ setprop ro.BACKUP_APP_MEM 14336
+ setprop ro.HOME_APP_MEM 14336
+ setprop ro.HIDDEN_APP_MEM 16384
+ setprop ro.EMPTY_APP_MEM 20480
+
+ # Old values for phones. Should probably be adjusted up for the next
+ # phone version.
+ #setprop ro.FOREGROUND_APP_MEM 2048
+ #setprop ro.VISIBLE_APP_MEM 3072
+ #setprop ro.PERCEPTIBLE_APP_MEM 4096
+ #setprop ro.HEAVY_WEIGHT_APP_MEM 4096
+ #setprop ro.SECONDARY_SERVER_MEM 6144
+ #setprop ro.BACKUP_APP_MEM 6144
+ #setprop ro.HOME_APP_MEM 6144
+ #setprop ro.HIDDEN_APP_MEM 7168
+ #setprop ro.EMPTY_APP_MEM 8192
# Write value must be consistent with the above properties.
# Note that the driver only supports 6 slots, so we have combined some of
@@ -226,7 +239,7 @@
write /proc/sys/vm/overcommit_memory 1
write /proc/sys/vm/min_free_order_shift 4
- write /sys/module/lowmemorykiller/parameters/minfree 2048,3072,4096,6144,7168,8192
+ write /sys/module/lowmemorykiller/parameters/minfree 8192,10240,12288,14336,16384,20480
# Set init its forked children's oom_adj.
write /proc/1/oom_adj -16
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index cc2cce7..0b8f656 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -95,6 +95,12 @@
__u32 namelen;
char *name;
+ /* If non-null, this is the real name of the file in the underlying storage.
+ * This may differ from the field "name" only by case.
+ * strlen(actual_name) will always equal strlen(name), so it is safe to use
+ * namelen for both fields.
+ */
+ char *actual_name;
};
struct fuse {
@@ -109,21 +115,13 @@
char rootpath[1024];
};
-/* true if file names should be squashed to lower case */
-static int force_lower_case = 0;
static unsigned uid = -1;
static unsigned gid = -1;
#define PATH_BUFFER_SIZE 1024
-static void normalize_name(char *name)
-{
- if (force_lower_case) {
- char ch;
- while ((ch = *name) != 0)
- *name++ = tolower(ch);
- }
-}
+#define NO_CASE_SENSITIVE_MATCH 0
+#define CASE_SENSITIVE_MATCH 1
/*
* Get the real-life absolute path to a node.
@@ -131,8 +129,10 @@
* buf: storage for returned string
* name: append this string to path if set
*/
-char *node_get_path(struct node *node, char *buf, const char *name)
+char *do_node_get_path(struct node *node, char *buf, const char *name, int match_case_insensitive)
{
+ struct node *in_node = node;
+ const char *in_name = name;
char *out = buf + PATH_BUFFER_SIZE - 1;
int len;
out[0] = 0;
@@ -143,7 +143,7 @@
}
while (node) {
- name = node->name;
+ name = (node->actual_name ? node->actual_name : node->name);
len = node->namelen;
node = node->parent;
start:
@@ -151,12 +151,45 @@
return 0;
out -= len;
memcpy(out, name, len);
- out --;
- out[0] = '/';
+ /* avoid double slash at beginning of path */
+ if (out[0] != '/') {
+ out --;
+ out[0] = '/';
+ }
}
- normalize_name(out);
- return out;
+ /* If we are searching for a file within node (rather than computing node's path)
+ * and fail, then we need to look for a case insensitive match.
+ */
+ if (in_name && match_case_insensitive && access(out, F_OK) != 0) {
+ char *path, buffer[PATH_BUFFER_SIZE];
+ DIR* dir;
+ struct dirent* entry;
+ path = do_node_get_path(in_node, buffer, NULL, NO_CASE_SENSITIVE_MATCH);
+ dir = opendir(path);
+ if (!dir) {
+ ERROR("opendir %s failed: %s", path, strerror(errno));
+ return out;
+ }
+
+ while ((entry = readdir(dir))) {
+ if (!strcasecmp(entry->d_name, in_name)) {
+ /* we have a match - replace the name */
+ len = strlen(in_name);
+ memcpy(buf + PATH_BUFFER_SIZE - len - 1, entry->d_name, len);
+ break;
+ }
+ }
+ closedir(dir);
+ }
+
+ return out;
+}
+
+char *node_get_path(struct node *node, char *buf, const char *name)
+{
+ /* We look for case insensitive matches by default */
+ return do_node_get_path(node, buf, name, CASE_SENSITIVE_MATCH);
}
void attr_from_stat(struct fuse_attr *attr, struct stat *s)
@@ -214,6 +247,41 @@
parent->refcount++;
}
+/* Check to see if our parent directory already has a file with a name
+ * that differs only by case. If we find one, store it in the actual_name
+ * field so node_get_path will map it to this file in the underlying storage.
+ */
+static void node_find_actual_name(struct node *node)
+{
+ char *path, buffer[PATH_BUFFER_SIZE];
+ const char *node_name = node->name;
+ DIR* dir;
+ struct dirent* entry;
+
+ if (!node->parent) return;
+
+ path = node_get_path(node->parent, buffer, 0);
+ dir = opendir(path);
+ if (!dir) {
+ ERROR("opendir %s failed: %s", path, strerror(errno));
+ return;
+ }
+
+ while ((entry = readdir(dir))) {
+ const char *test_name = entry->d_name;
+ if (strcmp(test_name, node_name) && !strcasecmp(test_name, node_name)) {
+ /* we have a match - differs but only by case */
+ node->actual_name = strdup(test_name);
+ if (!node->actual_name) {
+ ERROR("strdup failed - out of memory\n");
+ exit(1);
+ }
+ break;
+ }
+ }
+ closedir(dir);
+}
+
struct node *node_create(struct node *parent, const char *name, __u64 nid, __u64 gen)
{
struct node *node;
@@ -234,7 +302,7 @@
add_node_to_parent(node, parent);
memcpy(node->name, name, namelen + 1);
node->namelen = namelen;
-
+ node_find_actual_name(node);
return node;
}
@@ -246,6 +314,7 @@
return 0;
node->name = newname;
memcpy(node->name, name, node->namelen + 1);
+ node_find_actual_name(node);
return node->name;
}
@@ -397,6 +466,7 @@
/* TODO: remove debugging - poison memory */
memset(node->name, 0xef, node->namelen);
free(node->name);
+ free(node->actual_name);
memset(node, 0xfc, sizeof(*node));
free(node);
}
@@ -458,75 +528,6 @@
fuse_reply(fuse, unique, &out, sizeof(out));
}
-static int name_needs_normalizing(const char* name) {
- char ch;
- while ((ch = *name++) != 0) {
- if (ch != tolower(ch))
- return 1;
- }
- return 0;
-}
-
-static void recursive_fix_files(const char* path) {
- DIR* dir;
- struct dirent* entry;
- char pathbuf[PATH_MAX];
- char oldpath[PATH_MAX];
- int pathLength = strlen(path);
- int pathRemaining;
- char* fileSpot;
-
- if (pathLength >= sizeof(pathbuf) - 1) {
- ERROR("path too long: %s\n", path);
- return;
- }
- strcpy(pathbuf, path);
- if (pathbuf[pathLength - 1] != '/') {
- pathbuf[pathLength++] = '/';
- }
- fileSpot = pathbuf + pathLength;
- pathRemaining = sizeof(pathbuf) - pathLength - 1;
-
- dir = opendir(path);
- if (!dir) {
- ERROR("opendir %s failed: %s", path, strerror(errno));
- return;
- }
-
- while ((entry = readdir(dir))) {
- const char* name = entry->d_name;
- int nameLength;
-
- // ignore "." and ".."
- if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
- continue;
- }
-
- nameLength = strlen(name);
- if (nameLength > pathRemaining) {
- ERROR("path %s/%s too long\n", path, name);
- continue;
- }
- strcpy(fileSpot, name);
-
- // make sure owner and group are correct
- chown(pathbuf, uid, gid);
-
- if (name_needs_normalizing(name)) {
- /* rename file to lower case file name */
- strlcpy(oldpath, pathbuf, sizeof(oldpath));
- normalize_name(pathbuf);
- rename(oldpath, pathbuf);
- }
-
- if (entry->d_type == DT_DIR) {
- /* recurse to subdirectories */
- recursive_fix_files(pathbuf);
- }
- }
- closedir(dir);
-}
-
void handle_fuse_request(struct fuse *fuse, struct fuse_in_header *hdr, void *data, unsigned len)
{
struct node *node;
@@ -682,7 +683,16 @@
fuse_status(fuse, hdr->unique, -ENOENT);
return;
}
- newpath = node_get_path(newparent, newbuffer, newname);
+ if (newparent == node) {
+ /* Special case for renaming a file where destination
+ * is same path differing only by case.
+ * In this case we don't want to look for a case insensitive match.
+ * This allows commands like "mv foo FOO" to work as expected.
+ */
+ newpath = do_node_get_path(newparent, newbuffer, newname, NO_CASE_SENSITIVE_MATCH);
+ } else {
+ newpath = node_get_path(newparent, newbuffer, newname);
+ }
if (!remove_child(node, target->nid)) {
ERROR("RENAME remove_child not found");
@@ -835,13 +845,19 @@
struct dirent *de;
struct dirhandle *h = id_to_ptr(req->fh);
TRACE("READDIR %p\n", h);
+ if (req->offset == 0) {
+ /* rewinddir() might have been called above us, so rewind here too */
+ TRACE("calling rewinddir()\n");
+ rewinddir(h->d);
+ }
de = readdir(h->d);
if (!de) {
fuse_status(fuse, hdr->unique, 0);
return;
}
fde->ino = FUSE_UNKNOWN_INO;
- fde->off = 0;
+ /* increment the offset so we can detect when rewinddir() seeks back to the beginning */
+ fde->off = req->offset + 1;
fde->type = de->d_type;
fde->namelen = strlen(de->d_name);
memcpy(fde->name, de->d_name, fde->namelen + 1);
@@ -922,30 +938,19 @@
int fd;
int res;
const char *path = NULL;
- int fix_files = 0;
int i;
for (i = 1; i < argc; i++) {
char* arg = argv[i];
- if (arg[0] == '-') {
- if (!strcmp(arg, "-l")) {
- force_lower_case = 1;
- } else if (!strcmp(arg, "-f")) {
- fix_files = 1;
- } else {
- return usage();
- }
- } else {
- if (!path)
- path = arg;
- else if (uid == -1)
- uid = strtoul(arg, 0, 10);
- else if (gid == -1)
- gid = strtoul(arg, 0, 10);
- else {
- ERROR("too many arguments\n");
- return usage();
- }
+ if (!path)
+ path = arg;
+ else if (uid == -1)
+ uid = strtoul(arg, 0, 10);
+ else if (gid == -1)
+ gid = strtoul(arg, 0, 10);
+ else {
+ ERROR("too many arguments\n");
+ return usage();
}
}
@@ -976,9 +981,6 @@
return -1;
}
- if (fix_files)
- recursive_fix_files(path);
-
if (setgid(gid) < 0) {
ERROR("cannot setgid!\n");
return -1;