diff options
40 files changed, 772 insertions, 131 deletions
@@ -302,8 +302,10 @@ void handle_packet(apacket *p, atransport *t) { 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 @@ jdwp_process_event( int socket, unsigned events, void* _proc ) 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 @@ jdwp_process_event( int socket, unsigned events, void* _proc ) 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 @@ jdwp_process_event( int socket, unsigned events, void* _proc ) 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 *find_local_socket(unsigned id) 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 @@ static void local_socket_event_func(int fd, unsigned ev, void *_s) 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 *create_remote_socket(unsigned id, atransport *t) 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 @@ asocket *create_smart_socket(void (*action_cb)(asocket *s, const char *act)) { 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 @@ int builtInVendorIds[] = { 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 @@ void usb_vendors_init(void) /* 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 @@ ifeq ($(TARGET_ARCH),arm) 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 @@ static int logsocket = -1; /* 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 @@ mapinfo *parse_maps_line(char *line) 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 @@ void dump_crash_banner(int tfd, unsigned pid, unsigned tid, int sig) 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 @@ static void parse_exidx_info(mapinfo *milist, pid_t pid) break; } } + + /* Try to load symbols from this file */ + mi->symbols = symbol_table_create(mi->name); } } } @@ -420,7 +424,7 @@ void dump_crash_report(int tfd, unsigned pid, unsigned tid, bool at_fault) 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 @@ void dump_crash_report(int tfd, unsigned pid, unsigned tid, bool at_fault) 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 @@ static _Unwind_Reason_Code log_function(_Unwind_Context *context, pid_t pid, 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 @@ static _Unwind_Reason_Code log_function(_Unwind_Context *context, pid_t pid, 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 @@ typedef struct mapinfo { 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 @@ static Action *queue_action(unsigned op, const char *fmt, ...) { 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 @@ extern "C" { */ #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 @@ extern "C" { #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 @@ extern "C" { * 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 @@ typedef enum { #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 @@ typedef enum { __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 @@ extern "C" { 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 @@ static struct fs_path_config android_files[] = { { 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 index 377754b..d8ec88e 100644..100755 --- a/init/util.c +++ b/init/util.c @@ -439,8 +439,9 @@ void get_hardware_name(char *hardware, unsigned int *revision) 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 @@ include $(CLEAR_VARS) 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 @@ static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1 }; * 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_buf_write(int bufID, int prio, const char *tag, const char *ms 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 @@ int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fm 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 @@ LOCAL_PATH:= $(call my-dir) 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 @@ ifneq ($(BUILD_TINY_ANDROID),true) 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 @@ include $(CLEAR_VARS) 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 @@ void ARMAssembler::UXTB16(int cc, int Rd, int Rm, int rotate) { *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 @@ public: 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 @@ public: // 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 @@ void ARMAssemblerProxy::UXTB16(int cc, int Rd, int Rm, int rotate) { 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 @@ public: 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 @@ static const struct arm32_insn arm32_i[] = { { 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 @@ disasm(const disasm_interface_t *di, u_int loc, int altfmt) 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 @@ void GGLAssembler::extract(integer_t& d, int s, int h, int l, int bits) 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 @@ void GGLAssembler::extract(integer_t& d, int s, int h, int l, int bits) 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 @@ void ggl_copyPixels(void* con, GGLint xs, GGLint ys, 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 @@ void rect_memcpy(context_t* c, size_t yc) // ---------------------------------------------------------------------------- }; // 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 @@ LOCAL_PATH:= $(call my-dir) 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 @@ bool NetlinkEvent::decode(char *buffer, int size) { } 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 @@ copy_from := \ 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 @@ esac # 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 @@ TOOLS := \ 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 @@ int chmod_main(int argc, char **argv) } 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 @@ int insmod_main(int argc, char **argv) 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 @@ static int listdir(const char *name, int flags) 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 @@ static int listdir(const char *name, int flags) 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 @@ static int listdir(const char *name, int flags) } 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 @@ int ls_main(int argc, char **argv) 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 mkdir_main(int argc, char *argv[]) { 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 @@ int route_main(int argc, char *argv[]) /* 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; } } |
