am 0c0f68e8: Fix a long standing bug in the output buffer size computation.
Merge commit '0c0f68e8ff9fb88eaae614d1da316f0037484886' into gingerbread-plus-aosp
* commit '0c0f68e8ff9fb88eaae614d1da316f0037484886':
Fix a long standing bug in the output buffer size computation.
diff --git a/adb/adb.c b/adb/adb.c
index 95dc001..ee78688 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -302,8 +302,10 @@
{
asocket *s;
- D("handle_packet() %d\n", p->msg.command);
-
+ D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
+ ((char*) (&(p->msg.command)))[1],
+ ((char*) (&(p->msg.command)))[2],
+ ((char*) (&(p->msg.command)))[3]);
print_packet("recv", p);
switch(p->msg.command){
diff --git a/adb/jdwp_service.c b/adb/jdwp_service.c
index 0c26f7b..296f718 100644
--- a/adb/jdwp_service.c
+++ b/adb/jdwp_service.c
@@ -5,6 +5,7 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
/* here's how these things work.
@@ -320,6 +321,7 @@
struct iovec iov;
char dummy = '!';
char buffer[sizeof(struct cmsghdr) + sizeof(int)];
+ int flags;
iov.iov_base = &dummy;
iov.iov_len = 1;
@@ -337,10 +339,27 @@
cmsg->cmsg_type = SCM_RIGHTS;
((int*)CMSG_DATA(cmsg))[0] = fd;
+ flags = fcntl(proc->socket,F_GETFL,0);
+
+ if (flags == -1) {
+ D("failed to get cntl flags for socket %d: %s\n",
+ proc->pid, strerror(errno));
+ goto CloseProcess;
+
+ }
+
+ if (fcntl(proc->socket, F_SETFL, flags & ~O_NONBLOCK) == -1) {
+ D("failed to remove O_NONBLOCK flag for socket %d: %s\n",
+ proc->pid, strerror(errno));
+ goto CloseProcess;
+ }
+
for (;;) {
ret = sendmsg(proc->socket, &msg, 0);
- if (ret >= 0)
+ if (ret >= 0) {
+ adb_close(fd);
break;
+ }
if (errno == EINTR)
continue;
D("sending new file descriptor to JDWP %d failed: %s\n",
@@ -354,6 +373,12 @@
for (n = 1; n < proc->out_count; n++)
proc->out_fds[n-1] = proc->out_fds[n];
+ if (fcntl(proc->socket, F_SETFL, flags) == -1) {
+ D("failed to set O_NONBLOCK flag for socket %d: %s\n",
+ proc->pid, strerror(errno));
+ goto CloseProcess;
+ }
+
if (--proc->out_count == 0)
fdevent_del( proc->fde, FDE_WRITE );
}
diff --git a/adb/sockets.c b/adb/sockets.c
index 9f1b598..43925e4 100644
--- a/adb/sockets.c
+++ b/adb/sockets.c
@@ -65,8 +65,11 @@
asocket *result = NULL;
adb_mutex_lock(&socket_list_lock);
- for(s = local_socket_list.next; s != &local_socket_list && !result; s = s->next) {
- if(s->id == id) result = s;
+ for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
+ if (s->id == id) {
+ result = s;
+ break;
+ }
}
adb_mutex_unlock(&socket_list_lock);
@@ -366,7 +369,7 @@
asocket *create_local_socket(int fd)
{
asocket *s = calloc(1, sizeof(asocket));
- if(s == 0) fatal("cannot allocate socket");
+ if (s == NULL) fatal("cannot allocate socket");
install_local_socket(s);
s->fd = fd;
s->enqueue = local_socket_enqueue;
@@ -482,7 +485,7 @@
asocket *s = calloc(1, sizeof(aremotesocket));
adisconnect* dis = &((aremotesocket*)s)->disconnect;
- if(s == 0) fatal("cannot allocate socket");
+ if (s == NULL) fatal("cannot allocate socket");
s->id = id;
s->enqueue = remote_socket_enqueue;
s->ready = remote_socket_ready;
@@ -761,8 +764,7 @@
{
D("Creating smart socket \n");
asocket *s = calloc(1, sizeof(asocket));
- if(s == 0) fatal("cannot allocate socket");
- s->id = 0;
+ if (s == NULL) fatal("cannot allocate socket");
s->enqueue = smart_socket_enqueue;
s->ready = smart_socket_ready;
s->close = smart_socket_close;
diff --git a/adb/usb_vendors.c b/adb/usb_vendors.c
index 7cbd741..efeb2a0 100644
--- a/adb/usb_vendors.c
+++ b/adb/usb_vendors.c
@@ -69,6 +69,8 @@
#define VENDOR_ID_PANTECH 0x10A9
// Qualcomm's USB Vendor ID
#define VENDOR_ID_QUALCOMM 0x05c6
+// On-The-Go-Video's USB Vendor ID
+#define VENDOR_ID_OTGV 0x2257
// NEC's USB Vendor ID
#define VENDOR_ID_NEC 0x0409
// Panasonic Mobile Communication's USB Vendor ID
@@ -96,6 +98,7 @@
VENDOR_ID_KYOCERA,
VENDOR_ID_PANTECH,
VENDOR_ID_QUALCOMM,
+ VENDOR_ID_OTGV,
VENDOR_ID_NEC,
VENDOR_ID_PMC,
VENDOR_ID_TOSHIBA,
@@ -160,7 +163,7 @@
/* builds the path to the adb vendor id file. returns 0 if success */
int build_path(char* buff, size_t len, const char* format, const char* home)
{
- if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_ADB_INI) >= len) {
+ if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_ADB_INI) >= (signed)len) {
return 1;
}
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 3c1cf02..ccc001b 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -5,7 +5,7 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= debuggerd.c getevent.c unwind-arm.c pr-support.c utility.c
+LOCAL_SRC_FILES:= debuggerd.c getevent.c unwind-arm.c pr-support.c utility.c symbol_table.c
LOCAL_CFLAGS := -Wall
LOCAL_MODULE := debuggerd
diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c
index 7c36367..24b7e72 100644
--- a/debuggerd/debuggerd.c
+++ b/debuggerd/debuggerd.c
@@ -63,7 +63,7 @@
/* Log information onto the tombstone */
void _LOG(int tfd, bool in_tombstone_only, const char *fmt, ...)
{
- char buf[128];
+ char buf[512];
va_list ap;
va_start(ap, fmt);
@@ -106,10 +106,11 @@
mi->start = strtoul(line, 0, 16);
mi->end = strtoul(line + 9, 0, 16);
- /* To be filled in parse_exidx_info if the mapped section starts with
+ /* To be filled in parse_elf_info if the mapped section starts with
* elf_header
*/
mi->exidx_start = mi->exidx_end = 0;
+ mi->symbols = 0;
mi->next = 0;
strcpy(mi->name, line + 49);
@@ -353,7 +354,7 @@
if(sig) dump_fault_addr(tfd, tid, sig);
}
-static void parse_exidx_info(mapinfo *milist, pid_t pid)
+static void parse_elf_info(mapinfo *milist, pid_t pid)
{
mapinfo *mi;
for (mi = milist; mi != NULL; mi = mi->next) {
@@ -383,6 +384,9 @@
break;
}
}
+
+ /* Try to load symbols from this file */
+ mi->symbols = symbol_table_create(mi->name);
}
}
}
@@ -420,7 +424,7 @@
fclose(fp);
}
- parse_exidx_info(milist, tid);
+ parse_elf_info(milist, tid);
/* If stack unwinder fails, use the default solution to dump the stack
* content.
@@ -439,6 +443,7 @@
while(milist) {
mapinfo *next = milist->next;
+ symbol_table_free(milist->symbols);
free(milist);
milist = next;
}
diff --git a/debuggerd/symbol_table.c b/debuggerd/symbol_table.c
new file mode 100644
index 0000000..150c058
--- /dev/null
+++ b/debuggerd/symbol_table.c
@@ -0,0 +1,178 @@
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "symbol_table.h"
+
+#include <linux/elf.h>
+
+// Compare func for qsort
+static int qcompar(const void *a, const void *b)
+{
+ return ((struct symbol*)a)->addr - ((struct symbol*)b)->addr;
+}
+
+// Compare func for bsearch
+static int bcompar(const void *addr, const void *element)
+{
+ struct symbol *symbol = (struct symbol*)element;
+
+ if((unsigned int)addr < symbol->addr) {
+ return -1;
+ }
+
+ if((unsigned int)addr - symbol->addr >= symbol->size) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Create a symbol table from a given file
+ *
+ * Parameters:
+ * filename - Filename to process
+ *
+ * Returns:
+ * A newly-allocated SymbolTable structure, or NULL if error.
+ * Free symbol table with symbol_table_free()
+ */
+struct symbol_table *symbol_table_create(const char *filename)
+{
+ struct symbol_table *table = NULL;
+
+ // Open the file, and map it into memory
+ struct stat sb;
+ int length;
+ char *base;
+
+ int fd = open(filename, O_RDONLY);
+
+ if(fd < 0) {
+ goto out;
+ }
+
+ fstat(fd, &sb);
+ length = sb.st_size;
+
+ base = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0);
+
+ if(!base) {
+ goto out_close;
+ }
+
+ // Parse the file header
+ Elf32_Ehdr *hdr = (Elf32_Ehdr*)base;
+ Elf32_Shdr *shdr = (Elf32_Shdr*)(base + hdr->e_shoff);
+
+ // Search for the dynamic symbols section
+ int dynsym_idx = -1;
+ int i;
+
+ for(i = 0; i < hdr->e_shnum; i++) {
+ if(shdr[i].sh_type == SHT_DYNSYM ) {
+ dynsym_idx = i;
+ }
+ }
+
+ if(dynsym_idx == -1) {
+ goto out_unmap;
+ }
+
+ Elf32_Sym *dynsyms = (Elf32_Sym*)(base + shdr[dynsym_idx].sh_offset);
+ int numsyms = shdr[dynsym_idx].sh_size / shdr[dynsym_idx].sh_entsize;
+
+ table = malloc(sizeof(struct symbol_table));
+ if(!table) {
+ goto out_unmap;
+ }
+ table->num_symbols = 0;
+
+ // Iterate through the dynamic symbol table, and count how many symbols
+ // are actually defined
+ for(i = 0; i < numsyms; i++) {
+ if(dynsyms[i].st_shndx != SHN_UNDEF) {
+ table->num_symbols++;
+ }
+ }
+
+ int dynstr_idx = shdr[dynsym_idx].sh_link;
+ char *dynstr = base + shdr[dynstr_idx].sh_offset;
+
+ // Now, create an entry in our symbol table structure for each symbol...
+ table->symbols = malloc(table->num_symbols * sizeof(struct symbol));
+ if(!table->symbols) {
+ free(table);
+ table = NULL;
+ goto out_unmap;
+ }
+
+ // ...and populate them
+ int j = 0;
+ for(i = 0; i < numsyms; i++) {
+ if(dynsyms[i].st_shndx != SHN_UNDEF) {
+ table->symbols[j].name = strdup(dynstr + dynsyms[i].st_name);
+ table->symbols[j].addr = dynsyms[i].st_value;
+ table->symbols[j].size = dynsyms[i].st_size;
+ j++;
+ }
+ }
+
+ // Sort the symbol table entries, so they can be bsearched later
+ qsort(table->symbols, table->num_symbols, sizeof(struct symbol), qcompar);
+
+out_unmap:
+ munmap(base, length);
+
+out_close:
+ close(fd);
+
+out:
+ return table;
+}
+
+/*
+ * Free a symbol table
+ *
+ * Parameters:
+ * table - Table to free
+ */
+void symbol_table_free(struct symbol_table *table)
+{
+ int i;
+
+ if(!table) {
+ return;
+ }
+
+ for(i=0; i<table->num_symbols; i++) {
+ free(table->symbols[i].name);
+ }
+
+ free(table->symbols);
+ free(table);
+}
+
+/*
+ * Search for an address in the symbol table
+ *
+ * Parameters:
+ * table - Table to search in
+ * addr - Address to search for.
+ *
+ * Returns:
+ * A pointer to the Symbol structure corresponding to the
+ * symbol which contains this address, or NULL if no symbol
+ * contains it.
+ */
+const struct symbol *symbol_table_lookup(struct symbol_table *table, unsigned int addr)
+{
+ if(!table) {
+ return NULL;
+ }
+
+ return bsearch((void*)addr, table->symbols, table->num_symbols, sizeof(struct symbol), bcompar);
+}
diff --git a/debuggerd/symbol_table.h b/debuggerd/symbol_table.h
new file mode 100644
index 0000000..d9d2520
--- /dev/null
+++ b/debuggerd/symbol_table.h
@@ -0,0 +1,19 @@
+#ifndef SYMBOL_TABLE_H
+#define SYMBOL_TABLE_H
+
+struct symbol {
+ unsigned int addr;
+ unsigned int size;
+ char *name;
+};
+
+struct symbol_table {
+ struct symbol *symbols;
+ int num_symbols;
+};
+
+struct symbol_table *symbol_table_create(const char *filename);
+void symbol_table_free(struct symbol_table *table);
+const struct symbol *symbol_table_lookup(struct symbol_table *table, unsigned int addr);
+
+#endif
diff --git a/debuggerd/unwind-arm.c b/debuggerd/unwind-arm.c
index 9642d2e..b081161 100644
--- a/debuggerd/unwind-arm.c
+++ b/debuggerd/unwind-arm.c
@@ -37,6 +37,8 @@
#include <unwind.h>
#include "utility.h"
+#include "symbol_table.h"
+
typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
@@ -393,6 +395,7 @@
phase2_vrs *vrs = (phase2_vrs*) context;
const mapinfo *mi;
bool only_in_tombstone = !at_fault;
+ const struct symbol* sym = 0;
if (stack_level < STACK_CONTENT_DEPTH) {
sp_list[stack_level] = vrs->core.r[R_SP];
@@ -451,9 +454,20 @@
rel_pc = pc;
mi = pc_to_mapinfo(map, pc, &rel_pc);
- _LOG(tfd, only_in_tombstone,
- " #%02d pc %08x %s\n", stack_level, rel_pc,
- mi ? mi->name : "");
+ /* See if we can determine what symbol this stack frame resides in */
+ if (mi != 0 && mi->symbols != 0) {
+ sym = symbol_table_lookup(mi->symbols, rel_pc);
+ }
+
+ if (sym) {
+ _LOG(tfd, only_in_tombstone,
+ " #%02d pc %08x %s (%s)\n", stack_level, rel_pc,
+ mi ? mi->name : "", sym->name);
+ } else {
+ _LOG(tfd, only_in_tombstone,
+ " #%02d pc %08x %s\n", stack_level, rel_pc,
+ mi ? mi->name : "");
+ }
return _URC_NO_REASON;
}
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index 49f5951..2ffdf56 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -21,6 +21,8 @@
#include <stddef.h>
#include <stdbool.h>
+#include "symbol_table.h"
+
#ifndef PT_ARM_EXIDX
#define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */
#endif
@@ -33,6 +35,7 @@
unsigned end;
unsigned exidx_start;
unsigned exidx_end;
+ struct symbol_table *symbols;
char name[];
} mapinfo;
diff --git a/fastboot/engine.c b/fastboot/engine.c
index 8ba202c..48073ee 100644
--- a/fastboot/engine.c
+++ b/fastboot/engine.c
@@ -97,14 +97,20 @@
{
Action *a;
va_list ap;
+ size_t cmdsize;
a = calloc(1, sizeof(Action));
if (a == 0) die("out of memory");
va_start(ap, fmt);
- vsprintf(a->cmd, fmt, ap);
+ cmdsize = vsnprintf(a->cmd, sizeof(a->cmd), fmt, ap);
va_end(ap);
+ if (cmdsize >= sizeof(a->cmd)) {
+ free(a);
+ die("Command length (%d) exceeds maximum size (%d)", cmdsize, sizeof(a->cmd));
+ }
+
if (action_last) {
action_last->next = a;
} else {
diff --git a/include/arch/target_linux-x86/AndroidConfig.h b/include/arch/target_linux-x86/AndroidConfig.h
index b9800dd..2152d6a 100644
--- a/include/arch/target_linux-x86/AndroidConfig.h
+++ b/include/arch/target_linux-x86/AndroidConfig.h
@@ -227,7 +227,7 @@
/*
* Define if we have Linux's dbus
*/
-#define HAVE_DBUS 1
+/* #define HAVE_DBUS 1 */
/*
* Define if tm struct has tm_gmtoff field
diff --git a/include/cutils/log.h b/include/cutils/log.h
index dd47c35..f602017 100644
--- a/include/cutils/log.h
+++ b/include/cutils/log.h
@@ -291,11 +291,11 @@
*/
#define LOG_ALWAYS_FATAL_IF(cond, ...) \
( (CONDITION(cond)) \
- ? ((void)android_printAssert(#cond, LOG_TAG, __VA_ARGS__)) \
+ ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \
: (void)0 )
#define LOG_ALWAYS_FATAL(...) \
- ( ((void)android_printAssert(NULL, LOG_TAG, __VA_ARGS__)) )
+ ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) )
/*
* Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that
@@ -308,7 +308,7 @@
#else
-#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, __VA_ARGS__)
+#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__)
#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__)
#endif
@@ -317,7 +317,7 @@
* Assertion that generates a log message when the assertion fails.
* Stripped out of release builds. Uses the current LOG_TAG.
*/
-#define LOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), __VA_ARGS__)
+#define LOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__)
//#define LOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond)
// ---------------------------------------------------------------------
@@ -403,8 +403,24 @@
#define android_vprintLog(prio, cond, tag, fmt...) \
__android_log_vprint(prio, tag, fmt)
+/* XXX Macros to work around syntax errors in places where format string
+ * arg is not passed to LOG_ASSERT, LOG_ALWAYS_FATAL or LOG_ALWAYS_FATAL_IF
+ * (happens only in debug builds).
+ */
+
+/* Returns 2nd arg. Used to substitute default value if caller's vararg list
+ * is empty.
+ */
+#define __android_second(dummy, second, ...) second
+
+/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise
+ * returns nothing.
+ */
+#define __android_rest(first, ...) , ## __VA_ARGS__
+
#define android_printAssert(cond, tag, fmt...) \
- __android_log_assert(cond, tag, fmt)
+ __android_log_assert(cond, tag, \
+ __android_second(0, ## fmt, NULL) __android_rest(fmt))
#define android_writeLog(prio, tag, text) \
__android_log_write(prio, tag, text)
@@ -413,7 +429,7 @@
__android_log_bwrite(tag, payload, len)
#define android_btWriteLog(tag, type, payload, len) \
__android_log_btwrite(tag, type, payload, len)
-
+
// TODO: remove these prototypes and their users
#define android_testLog(prio, tag) (1)
#define android_writevLog(vec,num) do{}while(0)
diff --git a/include/pixelflinger/pixelflinger.h b/include/pixelflinger/pixelflinger.h
index dca0b90..8a2b442 100644
--- a/include/pixelflinger/pixelflinger.h
+++ b/include/pixelflinger/pixelflinger.h
@@ -315,7 +315,7 @@
ssize_t gglInit(GGLContext** context);
ssize_t gglUninit(GGLContext* context);
-GGLint gglBitBlti(
+GGLint gglBitBlit(
GGLContext* c,
int tmu,
GGLint crop[4],
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 1dbe171..903f99f 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -165,6 +165,7 @@
{ 00640, AID_SYSTEM, AID_SYSTEM, "system/etc/bluetooth/auto_pairing.conf" },
{ 00444, AID_RADIO, AID_AUDIO, "system/etc/AudioPara4.csv" },
{ 00555, AID_ROOT, AID_ROOT, "system/etc/ppp/*" },
+ { 00555, AID_ROOT, AID_ROOT, "system/etc/rc.*" },
{ 00644, AID_SYSTEM, AID_SYSTEM, "data/app/*" },
{ 00644, AID_SYSTEM, AID_SYSTEM, "data/app-private/*" },
{ 00644, AID_APP, AID_APP, "data/data/*" },
diff --git a/init/util.c b/init/util.c
old mode 100644
new mode 100755
index 377754b..d8ec88e
--- a/init/util.c
+++ b/init/util.c
@@ -439,8 +439,9 @@
if (x) {
x += 2;
n = 0;
- while (*x && !isspace(*x)) {
- hardware[n++] = tolower(*x);
+ while (*x && *x != '\n') {
+ if (!isspace(*x))
+ hardware[n++] = tolower(*x);
x++;
if (n == 31) break;
}
diff --git a/libdiskconfig/Android.mk b/libdiskconfig/Android.mk
index 1d0ecb4..c887955 100644
--- a/libdiskconfig/Android.mk
+++ b/libdiskconfig/Android.mk
@@ -3,17 +3,25 @@
ifneq ($(TARGET_SIMULATOR),true)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
+commonSources := \
diskconfig.c \
diskutils.c \
write_lst.c \
config_mbr.c
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(commonSources)
LOCAL_MODULE := libdiskconfig
LOCAL_SYSTEM_SHARED_LIBRARIES := libcutils liblog libc
-
include $(BUILD_SHARED_LIBRARY)
+ifeq ($(HOST_OS),linux)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(commonSources)
+LOCAL_MODULE := libdiskconfig_host
+LOCAL_SYSTEM_SHARED_LIBRARIES := libcutils
+LOCAL_CFLAGS := -O2 -g -W -Wall -Werror -D_LARGEFILE64_SOURCE
+include $(BUILD_HOST_STATIC_LIBRARY)
+endif # HOST_OS == linux
+
endif # ! TARGET_SIMULATOR
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index 9923bba..a0a753b 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -56,7 +56,7 @@
* the simulator rather than a desktop tool and want to use the device.
*/
static enum {
- kLogUninitialized, kLogNotAvailable, kLogAvailable
+ kLogUninitialized, kLogNotAvailable, kLogAvailable
} g_log_status = kLogUninitialized;
int __android_log_dev_available(void)
{
@@ -189,7 +189,7 @@
int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap)
{
- char buf[LOG_BUF_SIZE];
+ char buf[LOG_BUF_SIZE];
vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
@@ -223,12 +223,23 @@
void __android_log_assert(const char *cond, const char *tag,
const char *fmt, ...)
{
- va_list ap;
- char buf[LOG_BUF_SIZE];
+ char buf[LOG_BUF_SIZE];
- va_start(ap, fmt);
- vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
- va_end(ap);
+ if (fmt) {
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
+ va_end(ap);
+ } else {
+ /* Msg not provided, log condition. N.B. Do not use cond directly as
+ * format string as it could contain spurious '%' syntax (e.g.
+ * "%d" in "blocks%devs == 0").
+ */
+ if (cond)
+ snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
+ else
+ strcpy(buf, "Unspecified assertion failed");
+ }
__android_log_write(ANDROID_LOG_FATAL, tag, buf);
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index 6491d24..ed2ab5e 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -2,17 +2,6 @@
include $(CLEAR_VARS)
#
-# ARMv6 specific objects
-#
-
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_ASFLAGS := -march=armv6
-LOCAL_SRC_FILES := rotate90CW_4x4_16v6.S
-LOCAL_MODULE := libpixelflinger_armv6
-include $(BUILD_STATIC_LIBRARY)
-endif
-
-#
# C/C++ and ARMv5 objects
#
@@ -77,10 +66,6 @@
LOCAL_SHARED_LIBRARIES += libhardware_legacy
LOCAL_CFLAGS += -DWITH_LIB_HARDWARE
endif
-
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_WHOLE_STATIC_LIBRARIES := libpixelflinger_armv6
-endif
include $(BUILD_SHARED_LIBRARY)
#
@@ -91,9 +76,6 @@
LOCAL_MODULE:= libpixelflinger_static
LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES)
LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS)
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_WHOLE_STATIC_LIBRARIES := libpixelflinger_armv6
-endif
include $(BUILD_STATIC_LIBRARY)
diff --git a/libpixelflinger/codeflinger/ARMAssembler.cpp b/libpixelflinger/codeflinger/ARMAssembler.cpp
index d3720c3..fa9f1ad 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.cpp
+++ b/libpixelflinger/codeflinger/ARMAssembler.cpp
@@ -433,6 +433,16 @@
{
*mPC++ = (cc<<28) | 0x6CF0070 | (Rd<<12) | ((rotate >> 3) << 10) | Rm;
}
+#if 0
+#pragma mark -
+#pragma mark Bit manipulation (ARMv7+ only)...
+#endif
+
+// Bit manipulation (ARMv7+ only)...
+void ARMAssembler::UBFX(int cc, int Rd, int Rn, int lsb, int width)
+{
+ *mPC++ = (cc<<28) | 0x7E00000 | ((width-1)<<16) | (Rd<<12) | (lsb<<7) | 0x50 | Rn;
+}
}; // namespace android
diff --git a/libpixelflinger/codeflinger/ARMAssembler.h b/libpixelflinger/codeflinger/ARMAssembler.h
index a667cb5..e7f038a 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.h
+++ b/libpixelflinger/codeflinger/ARMAssembler.h
@@ -124,6 +124,7 @@
virtual void SMLAW(int cc, int y,
int Rd, int Rm, int Rs, int Rn);
virtual void UXTB16(int cc, int Rd, int Rm, int rotate);
+ virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width);
private:
ARMAssembler(const ARMAssembler& rhs);
diff --git a/libpixelflinger/codeflinger/ARMAssemblerInterface.h b/libpixelflinger/codeflinger/ARMAssemblerInterface.h
index ff6af2a..796342a 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerInterface.h
+++ b/libpixelflinger/codeflinger/ARMAssemblerInterface.h
@@ -206,6 +206,9 @@
// byte/half word extract...
virtual void UXTB16(int cc, int Rd, int Rm, int rotate) = 0;
+ // bit manipulation...
+ virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width) = 0;
+
// -----------------------------------------------------------------------
// convenience...
// -----------------------------------------------------------------------
diff --git a/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp b/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp
index 7c422db..c57d7da 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp
+++ b/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp
@@ -199,5 +199,9 @@
mTarget->UXTB16(cc, Rd, Rm, rotate);
}
+void ARMAssemblerProxy::UBFX(int cc, int Rd, int Rn, int lsb, int width) {
+ mTarget->UBFX(cc, Rd, Rn, lsb, width);
+}
+
}; // namespace android
diff --git a/libpixelflinger/codeflinger/ARMAssemblerProxy.h b/libpixelflinger/codeflinger/ARMAssemblerProxy.h
index 9134cce..8c7f270 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerProxy.h
+++ b/libpixelflinger/codeflinger/ARMAssemblerProxy.h
@@ -115,6 +115,7 @@
int Rd, int Rm, int Rs, int Rn);
virtual void UXTB16(int cc, int Rd, int Rm, int rotate);
+ virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width);
private:
ARMAssemblerInterface* mTarget;
diff --git a/libpixelflinger/codeflinger/disassem.c b/libpixelflinger/codeflinger/disassem.c
index c17f3ec..aeb8034 100644
--- a/libpixelflinger/codeflinger/disassem.c
+++ b/libpixelflinger/codeflinger/disassem.c
@@ -81,6 +81,8 @@
* g - 2nd fp operand (register) (bits 16-18)
* h - 3rd fp operand (register/immediate) (bits 0-4)
* j - xtb rotate literal (bits 10-11)
+ * i - bfx lsb literal (bits 7-11)
+ * w - bfx width literal (bits 16-20)
* b - branch address
* t - thumb branch address (bits 24, 0-23)
* k - breakpoint comment (bits 0-3, 8-19)
@@ -124,6 +126,7 @@
{ 0x0fe000f0, 0x00a00090, "umlal", "Sdnms" },
{ 0x0fe000f0, 0x00e00090, "smlal", "Sdnms" },
{ 0x0fff03f0, 0x06cf0070, "uxtb16", "dmj" },
+ { 0x0fe00070, 0x07e00050, "ubfx", "dmiw" },
{ 0x0d700000, 0x04200000, "strt", "daW" },
{ 0x0d700000, 0x04300000, "ldrt", "daW" },
{ 0x0d700000, 0x04600000, "strbt", "daW" },
@@ -412,6 +415,14 @@
case 'j':
di->di_printf("ror #%d", ((insn >> 10) & 3) << 3);
break;
+ /* i - bfx lsb literal (bits 7-11) */
+ case 'i':
+ di->di_printf("#%d", (insn >> 7) & 31);
+ break;
+ /* w - bfx width literal (bits 16-20) */
+ case 'w':
+ di->di_printf("#%d", 1 + ((insn >> 16) & 31));
+ break;
/* b - branch address */
case 'b':
branch = ((insn << 2) & 0x03ffffff);
diff --git a/libpixelflinger/codeflinger/load_store.cpp b/libpixelflinger/codeflinger/load_store.cpp
index 93c5825..ed20a00 100644
--- a/libpixelflinger/codeflinger/load_store.cpp
+++ b/libpixelflinger/codeflinger/load_store.cpp
@@ -18,9 +18,12 @@
#include <assert.h>
#include <stdio.h>
#include <cutils/log.h>
-
#include "codeflinger/GGLAssembler.h"
+#ifdef __ARM_ARCH__
+#include <machine/cpu-features.h>
+#endif
+
namespace android {
// ----------------------------------------------------------------------------
@@ -110,6 +113,20 @@
assert(maskLen<=8);
assert(h);
+#if __ARM_ARCH__ >= 7
+ const int mask = (1<<maskLen)-1;
+ if ((h == bits) && !l && (s != d.reg)) {
+ MOV(AL, 0, d.reg, s); // component = packed;
+ } else if ((h == bits) && l) {
+ MOV(AL, 0, d.reg, reg_imm(s, LSR, l)); // component = packed >> l;
+ } else if (!l && isValidImmediate(mask)) {
+ AND(AL, 0, d.reg, s, imm(mask)); // component = packed & mask;
+ } else if (!l && isValidImmediate(~mask)) {
+ BIC(AL, 0, d.reg, s, imm(~mask)); // component = packed & mask;
+ } else {
+ UBFX(AL, d.reg, s, l, maskLen); // component = (packed & mask) >> l;
+ }
+#else
if (h != bits) {
const int mask = ((1<<maskLen)-1) << l;
if (isValidImmediate(mask)) {
@@ -132,6 +149,7 @@
if (s != d.reg) {
MOV(AL, 0, d.reg, s);
}
+#endif
d.s = maskLen;
}
diff --git a/libpixelflinger/raster.cpp b/libpixelflinger/raster.cpp
index d751202..32b2a97 100644
--- a/libpixelflinger/raster.cpp
+++ b/libpixelflinger/raster.cpp
@@ -143,7 +143,7 @@
using namespace android;
-GGLint gglBitBlti(GGLContext* con, int tmu, GGLint crop[4], GGLint where[4])
+GGLint gglBitBlit(GGLContext* con, int tmu, GGLint crop[4], GGLint where[4])
{
GGL_CONTEXT(c, (void*)con);
diff --git a/libpixelflinger/scanline.cpp b/libpixelflinger/scanline.cpp
index a2f43eb..931d648 100644
--- a/libpixelflinger/scanline.cpp
+++ b/libpixelflinger/scanline.cpp
@@ -1518,26 +1518,3 @@
// ----------------------------------------------------------------------------
}; // namespace android
-using namespace android;
-extern "C" void ggl_test_codegen(uint32_t n, uint32_t p, uint32_t t0, uint32_t t1)
-{
-#if ANDROID_ARM_CODEGEN
- GGLContext* c;
- gglInit(&c);
- needs_t needs;
- needs.n = n;
- needs.p = p;
- needs.t[0] = t0;
- needs.t[1] = t1;
- sp<ScanlineAssembly> a(new ScanlineAssembly(needs, ASSEMBLY_SCRATCH_SIZE));
- GGLAssembler assembler( new ARMAssembler(a) );
- int err = assembler.scanline(needs, (context_t*)c);
- if (err != 0) {
- printf("error %08x (%s)\n", err, strerror(-err));
- }
- gglUninit(c);
-#else
- printf("This test runs only on ARM\n");
-#endif
-}
-
diff --git a/libpixelflinger/tests/codegen/Android.mk b/libpixelflinger/tests/codegen/Android.mk
index 1bc4214..aa320fc 100644
--- a/libpixelflinger/tests/codegen/Android.mk
+++ b/libpixelflinger/tests/codegen/Android.mk
@@ -2,12 +2,15 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- codegen.cpp
+ codegen.cpp.arm
LOCAL_SHARED_LIBRARIES := \
libcutils \
libpixelflinger
+LOCAL_C_INCLUDES := \
+ system/core/libpixelflinger
+
LOCAL_MODULE:= test-opengl-codegen
LOCAL_MODULE_TAGS := tests
diff --git a/libpixelflinger/tests/codegen/codegen.cpp b/libpixelflinger/tests/codegen/codegen.cpp
index 1865888..94e2481 100644
--- a/libpixelflinger/tests/codegen/codegen.cpp
+++ b/libpixelflinger/tests/codegen/codegen.cpp
@@ -1,9 +1,54 @@
#include <stdio.h>
#include <stdint.h>
-extern "C" void ggl_test_codegen(
- uint32_t n, uint32_t p, uint32_t t0, uint32_t t1);
+#include "private/pixelflinger/ggl_context.h"
+#include "buffer.h"
+#include "scanline.h"
+
+#include "codeflinger/CodeCache.h"
+#include "codeflinger/GGLAssembler.h"
+#include "codeflinger/ARMAssembler.h"
+
+#if defined(__arm__)
+# define ANDROID_ARM_CODEGEN 1
+#else
+# define ANDROID_ARM_CODEGEN 0
+#endif
+
+#define ASSEMBLY_SCRATCH_SIZE 2048
+
+using namespace android;
+
+class ScanlineAssembly : public Assembly {
+ AssemblyKey<needs_t> mKey;
+public:
+ ScanlineAssembly(needs_t needs, size_t size)
+ : Assembly(size), mKey(needs) { }
+ const AssemblyKey<needs_t>& key() const { return mKey; }
+};
+
+static void ggl_test_codegen(uint32_t n, uint32_t p, uint32_t t0, uint32_t t1)
+{
+#if ANDROID_ARM_CODEGEN
+ GGLContext* c;
+ gglInit(&c);
+ needs_t needs;
+ needs.n = n;
+ needs.p = p;
+ needs.t[0] = t0;
+ needs.t[1] = t1;
+ sp<ScanlineAssembly> a(new ScanlineAssembly(needs, ASSEMBLY_SCRATCH_SIZE));
+ GGLAssembler assembler( new ARMAssembler(a) );
+ int err = assembler.scanline(needs, (context_t*)c);
+ if (err != 0) {
+ printf("error %08x (%s)\n", err, strerror(-err));
+ }
+ gglUninit(c);
+#else
+ printf("This test runs only on ARM\n");
+#endif
+}
int main(int argc, char** argv)
{
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index c2ba647..86c1f42 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -93,13 +93,11 @@
}
const char *NetlinkEvent::findParam(const char *paramName) {
- int i;
-
- for (i = 0; i < NL_PARAMS_MAX; i++) {
- if (!mParams[i])
- break;
- if (!strncmp(mParams[i], paramName, strlen(paramName)))
- return &mParams[i][strlen(paramName) + 1];
+ size_t len = strlen(paramName);
+ for (int i = 0; mParams[i] && i < NL_PARAMS_MAX; ++i) {
+ const char *ptr = mParams[i] + len;
+ if (!strncmp(mParams[i], paramName, len) && *ptr == '=')
+ return ++ptr;
}
SLOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName);
diff --git a/patch.txt b/patch.txt
new file mode 100644
index 0000000..258965d
--- /dev/null
+++ b/patch.txt
@@ -0,0 +1,16 @@
+diff --git a/init/util.c b/init/util.c
+index 4d98cc2..0667593 100755
+--- a/init/util.c
++++ b/init/util.c
+@@ -657,8 +657,9 @@ static void get_hardware_name(void)
+ if (x) {
+ x += 2;
+ n = 0;
+- while (*x && !isspace(*x)) {
+- hardware[n++] = tolower(*x);
++ while (*x && *x != '\n') {
++ if (!isspace(*x))
++ hardware[n++] = tolower(*x);
+ x++;
+ if (n == 31) break;
+ }
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 329be7f..380bb60 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -7,7 +7,7 @@
etc/dbus.conf \
etc/hosts
-ifeq ($(TARGET_PRODUCT),generic)
+ifeq ($(TARGET_PRODUCT),full)
copy_from += etc/vold.fstab
endif
diff --git a/rootdir/etc/init.goldfish.sh b/rootdir/etc/init.goldfish.sh
index 5ff0a3a..cfa2c82 100755
--- a/rootdir/etc/init.goldfish.sh
+++ b/rootdir/etc/init.goldfish.sh
@@ -45,3 +45,13 @@
# this line doesn't really do anything useful. however without it the
# previous setprop doesn't seem to apply for some really odd reason
setprop ro.qemu.init.completed 1
+
+# set up the second interface (for inter-emulator connections)
+# if required
+my_ip=`getprop net.shared_net_ip`
+case "$my_ip" in
+ "")
+ ;;
+ *) ifconfig eth1 "$my_ip" netmask 255.255.255.0 up
+ ;;
+esac
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 588dac0..ef3980a 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -41,7 +41,7 @@
printenv \
smd \
chmod \
- chown \
+ chown \
newfs_msdos \
netstat \
ioctl \
diff --git a/toolbox/chmod.c b/toolbox/chmod.c
index 31a53bf..2a524e9 100644
--- a/toolbox/chmod.c
+++ b/toolbox/chmod.c
@@ -4,17 +4,74 @@
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
+#include <sys/limits.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
+void recurse_chmod(char* path, int mode)
+{
+ struct dirent *dp;
+ DIR *dir = opendir(path);
+ if (dir == NULL) {
+ // not a directory, carry on
+ return;
+ }
+ char *subpath = malloc(sizeof(char)*PATH_MAX);
+ int pathlen = strlen(path);
+
+ while ((dp = readdir(dir)) != NULL) {
+ if (strcmp(dp->d_name, ".") == 0 ||
+ strcmp(dp->d_name, "..") == 0) continue;
+
+ if (strlen(dp->d_name) + pathlen + 2/*NUL and slash*/ > PATH_MAX) {
+ fprintf(stderr, "Invalid path specified: too long\n");
+ exit(1);
+ }
+
+ strcpy(subpath, path);
+ strcat(subpath, "/");
+ strcat(subpath, dp->d_name);
+
+ if (chmod(subpath, mode) < 0) {
+ fprintf(stderr, "Unable to chmod %s: %s\n", subpath, strerror(errno));
+ exit(1);
+ }
+
+ recurse_chmod(subpath, mode);
+ }
+ free(subpath);
+ closedir(dir);
+}
+
+static int usage()
+{
+ fprintf(stderr, "Usage: chmod [OPTION] <MODE> <FILE>\n");
+ fprintf(stderr, " -R, --recursive change files and directories recursively\n");
+ fprintf(stderr, " --help display this help and exit\n");
+
+ return 10;
+}
+
int chmod_main(int argc, char **argv)
{
int i;
- if (argc < 3) {
- fprintf(stderr, "Usage: chmod <MODE> <FILE>\n");
- return 10;
+ if (argc < 3 || strcmp(argv[1], "--help") == 0) {
+ return usage();
+ }
+
+ int recursive = (strcmp(argv[1], "-R") == 0 ||
+ strcmp(argv[1], "--recursive") == 0) ? 1 : 0;
+
+ if (recursive && argc < 4) {
+ return usage();
+ }
+
+ if (recursive) {
+ argc--;
+ argv++;
}
int mode = 0;
@@ -29,11 +86,15 @@
}
s++;
}
+
for (i = 2; i < argc; i++) {
if (chmod(argv[i], mode) < 0) {
fprintf(stderr, "Unable to chmod %s: %s\n", argv[i], strerror(errno));
return 10;
}
+ if (recursive) {
+ recurse_chmod(argv[i], mode);
+ }
}
return 0;
}
diff --git a/toolbox/insmod.c b/toolbox/insmod.c
index 44b9847..756a64b 100644
--- a/toolbox/insmod.c
+++ b/toolbox/insmod.c
@@ -77,7 +77,6 @@
memcpy(ptr, argv[i], len);
ptr += len;
*ptr++ = ' ';
- *ptr++ = '\0';
}
*(ptr - 1) = '\0';
}
diff --git a/toolbox/ls.c b/toolbox/ls.c
index 8799514..962bf47 100644
--- a/toolbox/ls.c
+++ b/toolbox/ls.c
@@ -13,6 +13,130 @@
#include <grp.h>
#include <linux/kdev_t.h>
+#include <limits.h>
+
+// dynamic arrays
+typedef struct {
+ int count;
+ int capacity;
+ void** items;
+} dynarray_t;
+
+#define DYNARRAY_INITIALIZER { 0, 0, NULL }
+
+static void dynarray_init( dynarray_t *a )
+{
+ a->count = a->capacity = 0;
+ a->items = NULL;
+}
+
+static void dynarray_reserve_more( dynarray_t *a, int count )
+{
+ int old_cap = a->capacity;
+ int new_cap = old_cap;
+ const int max_cap = INT_MAX/sizeof(void*);
+ void** new_items;
+ int new_count = a->count + count;
+
+ if (count <= 0)
+ return;
+
+ if (count > max_cap - a->count)
+ abort();
+
+ new_count = a->count + count;
+
+ while (new_cap < new_count) {
+ old_cap = new_cap;
+ new_cap += (new_cap >> 2) + 4;
+ if (new_cap < old_cap || new_cap > max_cap) {
+ new_cap = max_cap;
+ }
+ }
+ new_items = realloc(a->items, new_cap*sizeof(void*));
+ if (new_items == NULL)
+ abort();
+
+ a->items = new_items;
+ a->capacity = new_cap;
+}
+
+static void dynarray_append( dynarray_t *a, void* item )
+{
+ if (a->count >= a->capacity)
+ dynarray_reserve_more(a, 1);
+
+ a->items[a->count++] = item;
+}
+
+static void dynarray_done( dynarray_t *a )
+{
+ free(a->items);
+ a->items = NULL;
+ a->count = a->capacity = 0;
+}
+
+#define DYNARRAY_FOREACH_TYPE(_array,_item_type,_item,_stmnt) \
+ do { \
+ int _nn_##__LINE__ = 0; \
+ for (;_nn_##__LINE__ < (_array)->count; ++ _nn_##__LINE__) { \
+ _item_type _item = (_item_type)(_array)->items[_nn_##__LINE__]; \
+ _stmnt; \
+ } \
+ } while (0)
+
+#define DYNARRAY_FOREACH(_array,_item,_stmnt) \
+ DYNARRAY_FOREACH_TYPE(_array,void *,_item,_stmnt)
+
+// string arrays
+
+typedef dynarray_t strlist_t;
+
+#define STRLIST_INITIALIZER DYNARRAY_INITIALIZER
+
+#define STRLIST_FOREACH(_list,_string,_stmnt) \
+ DYNARRAY_FOREACH_TYPE(_list,char *,_string,_stmnt)
+
+static void strlist_init( strlist_t *list )
+{
+ dynarray_init(list);
+}
+
+static void strlist_append_b( strlist_t *list, const void* str, size_t slen )
+{
+ char *copy = malloc(slen+1);
+ memcpy(copy, str, slen);
+ copy[slen] = '\0';
+ dynarray_append(list, copy);
+}
+
+static void strlist_append_dup( strlist_t *list, const char *str)
+{
+ strlist_append_b(list, str, strlen(str));
+}
+
+static void strlist_done( strlist_t *list )
+{
+ STRLIST_FOREACH(list, string, free(string));
+ dynarray_done(list);
+}
+
+static int strlist_compare_strings(const void* a, const void* b)
+{
+ const char *sa = *(const char **)a;
+ const char *sb = *(const char **)b;
+ return strcmp(sa, sb);
+}
+
+static void strlist_sort( strlist_t *list )
+{
+ if (list->count > 0) {
+ qsort(list->items,
+ (size_t)list->count,
+ sizeof(void*),
+ strlist_compare_strings);
+ }
+}
// bits for flags argument
#define LIST_LONG (1 << 0)
@@ -233,7 +357,8 @@
char tmp[4096];
DIR *d;
struct dirent *de;
-
+ strlist_t files = STRLIST_INITIALIZER;
+
d = opendir(name);
if(d == 0) {
fprintf(stderr, "opendir failed, %s\n", strerror(errno));
@@ -248,10 +373,16 @@
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue;
if(de->d_name[0] == '.' && (flags & LIST_ALL) == 0) continue;
- listfile(name, de->d_name, flags);
+ strlist_append_dup(&files, de->d_name);
}
+ strlist_sort(&files);
+ STRLIST_FOREACH(&files, filename, listfile(name, filename, flags));
+ strlist_done(&files);
+
if (flags & LIST_RECURSIVE) {
+ strlist_t subdirs = STRLIST_INITIALIZER;
+
rewinddir(d);
while ((de = readdir(d)) != 0) {
@@ -284,10 +415,15 @@
}
if (S_ISDIR(s.st_mode)) {
- printf("\n%s:\n", tmp);
- listdir(tmp, flags);
+ strlist_append_dup(&subdirs, tmp);
}
}
+ strlist_sort(&subdirs);
+ STRLIST_FOREACH(&subdirs, path, {
+ printf("\n%s:\n", path);
+ listdir(path, flags);
+ });
+ strlist_done(&subdirs);
}
closedir(d);
@@ -331,27 +467,40 @@
if(argc > 1) {
int i;
int err = 0;
+ strlist_t files = STRLIST_INITIALIZER;
for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-l")) {
- flags |= LIST_LONG;
- } else if (!strcmp(argv[i], "-s")) {
- flags |= LIST_SIZE;
- } else if (!strcmp(argv[i], "-a")) {
- flags |= LIST_ALL;
- } else if (!strcmp(argv[i], "-R")) {
- flags |= LIST_RECURSIVE;
- } else if (!strcmp(argv[i], "-d")) {
- flags |= LIST_DIRECTORIES;
- } else {
- listed++;
- if(listpath(argv[i], flags) != 0) {
- err = EXIT_FAILURE;
+ if (argv[i][0] == '-') {
+ /* an option ? */
+ const char *arg = argv[i]+1;
+ while (arg[0]) {
+ switch (arg[0]) {
+ case 'l': flags |= LIST_LONG; break;
+ case 's': flags |= LIST_SIZE; break;
+ case 'R': flags |= LIST_RECURSIVE; break;
+ case 'd': flags |= LIST_DIRECTORIES; break;
+ case 'a': flags |= LIST_ALL; break;
+ default:
+ fprintf(stderr, "%s: Unknown option '-%c'. Aborting.\n", "ls", arg[0]);
+ exit(1);
+ }
+ arg++;
}
+ } else {
+ /* not an option ? */
+ strlist_append_dup(&files, argv[i]);
}
}
- if (listed > 0) return err;
+ if (files.count > 0) {
+ STRLIST_FOREACH(&files, path, {
+ if (listpath(path, flags) != 0) {
+ err = EXIT_FAILURE;
+ }
+ });
+ strlist_done(&files);
+ return err;
+ }
}
// list working directory if no files or directories were specified
diff --git a/toolbox/mkdir.c b/toolbox/mkdir.c
index 121adab..656970a 100644
--- a/toolbox/mkdir.c
+++ b/toolbox/mkdir.c
@@ -2,10 +2,14 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
+#include <sys/limits.h>
+#include <sys/stat.h>
static int usage()
{
- fprintf(stderr,"mkdir <target>\n");
+ fprintf(stderr,"mkdir [OPTION] <target>\n");
+ fprintf(stderr," --help display usage and exit\n");
+ fprintf(stderr," -p, --parents create parent directories as needed\n");
return -1;
}
@@ -13,15 +17,60 @@
{
int symbolic = 0;
int ret;
- if(argc < 2) return usage();
+ if(argc < 2 || strcmp(argv[1], "--help") == 0) {
+ return usage();
+ }
+
+ int recursive = (strcmp(argv[1], "-p") == 0 ||
+ strcmp(argv[1], "--parents") == 0) ? 1 : 0;
+
+ if(recursive && argc < 3) {
+ // -p specified without a path
+ return usage();
+ }
+
+ if(recursive) {
+ argc--;
+ argv++;
+ }
+
+ char currpath[PATH_MAX], *pathpiece;
+ struct stat st;
while(argc > 1) {
argc--;
argv++;
- ret = mkdir(argv[0], 0777);
- if(ret < 0) {
- fprintf(stderr, "mkdir failed for %s, %s\n", argv[0], strerror(errno));
- return ret;
+ if(recursive) {
+ // reset path
+ strcpy(currpath, "");
+ // create the pieces of the path along the way
+ pathpiece = strtok(argv[0], "/");
+ if(argv[0][0] == '/') {
+ // prepend / if needed
+ strcat(currpath, "/");
+ }
+ while(pathpiece != NULL) {
+ if(strlen(currpath) + strlen(pathpiece) + 2/*NUL and slash*/ > PATH_MAX) {
+ fprintf(stderr, "Invalid path specified: too long\n");
+ return 1;
+ }
+ strcat(currpath, pathpiece);
+ strcat(currpath, "/");
+ if(stat(currpath, &st) != 0) {
+ ret = mkdir(currpath, 0777);
+ if(ret < 0) {
+ fprintf(stderr, "mkdir failed for %s, %s\n", currpath, strerror(errno));
+ return ret;
+ }
+ }
+ pathpiece = strtok(NULL, "/");
+ }
+ } else {
+ ret = mkdir(argv[0], 0777);
+ if(ret < 0) {
+ fprintf(stderr, "mkdir failed for %s, %s\n", argv[0], strerror(errno));
+ return ret;
+ }
}
}
diff --git a/toolbox/route.c b/toolbox/route.c
index 107e48a..3e10014 100644
--- a/toolbox/route.c
+++ b/toolbox/route.c
@@ -80,14 +80,24 @@
/* route add -net 192.168.1.2 netmask 255.255.255.0 gw 192.168.1.1 */
if (argc > 7 && !strcmp(argv[2], "-net") &&
- !strcmp(argv[4], "netmask") && !strcmp(argv[6], "gw")) {
- rt.rt_flags = RTF_UP | RTF_GATEWAY;
- if (set_address(argv[3], &rt.rt_dst) &&
- set_address(argv[5], &rt.rt_genmask) &&
- set_address(argv[7], &rt.rt_gateway)) {
- errno = 0;
+ !strcmp(argv[4], "netmask")) {
+ if (!strcmp(argv[6], "gw")) {
+ rt.rt_flags = RTF_UP | RTF_GATEWAY;
+ if (set_address(argv[3], &rt.rt_dst) &&
+ set_address(argv[5], &rt.rt_genmask) &&
+ set_address(argv[7], &rt.rt_gateway)) {
+ errno = 0;
+ }
+ goto apply;
+ } else if (!strcmp(argv[6], "dev")) {
+ rt.rt_flags = RTF_UP;
+ rt.rt_dev = argv[7];
+ if (set_address(argv[3], &rt.rt_dst) &&
+ set_address(argv[5], &rt.rt_genmask)) {
+ errno = 0;
+ }
+ goto apply;
}
- goto apply;
}
}