am eaa8432d: am 1b217b0c: system: vold: Conditionalize build (default on)
Merge commit 'eaa8432d3f5495f19a06836501d7538211529d98'
* commit 'eaa8432d3f5495f19a06836501d7538211529d98':
system: vold: Conditionalize build (default on)
diff --git a/adb/commandline.c b/adb/commandline.c
index 3711a62..3b3e6df 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -97,7 +97,7 @@
" returns an error if more than one emulator is running.\n"
" -s <serial number> - directs command to the USB device or emulator with\n"
" the given serial number. Overrides ANDROID_SERIAL\n"
- " envivornment variable.\n"
+ " environment variable.\n"
" -p <product name or path> - simple product name like 'sooner', or\n"
" a relative/absolute path to a product\n"
" out directory like 'out/target/product/sooner'.\n"
diff --git a/debuggerd/crashglue.S b/debuggerd/crashglue.S
index 888951b..0c1fd9b 100644
--- a/debuggerd/crashglue.S
+++ b/debuggerd/crashglue.S
@@ -1,5 +1,7 @@
.globl crash1
+.type crash1, %function
.globl crashnostack
+.type crashnostack, %function
crash1:
ldr r0, =0xa5a50000
@@ -25,4 +27,4 @@
mov sp, #0
mov r0, #0
ldr r0, [r0]
- b .
\ No newline at end of file
+ b .
diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c
index 996e6c2..145135f 100644
--- a/debuggerd/debuggerd.c
+++ b/debuggerd/debuggerd.c
@@ -606,15 +606,16 @@
(void)tid;
/* First log a helpful message */
LOG( "********************************************************\n"
- "* process %d crashed. debuggerd waiting for gdbserver \n"
- "* \n"
- "* adb shell gdbserver :port --attach %d & \n"
- "* \n"
- "* and press the HOME key. \n"
+ "* Process %d has been suspended while crashing. To\n"
+ "* attach gdbserver for a gdb connection on port 5039:\n"
+ "*\n"
+ "* adb shell gdbserver :5039 --attach %d &\n"
+ "*\n"
+ "* Press HOME key to let the process continue crashing.\n"
"********************************************************\n",
cr->pid, cr->pid);
- /* wait for HOME key */
+ /* wait for HOME key (TODO: something useful for devices w/o HOME key) */
if (init_getevent() == 0) {
int ms = 1200 / 10;
int dit = 1;
@@ -698,7 +699,7 @@
sprintf(buf,"/proc/%d/task/%d", cr.pid, tid);
if(stat(buf, &s)) {
- LOG("tid %d does not exist in pid %d. ignorning debug request\n",
+ LOG("tid %d does not exist in pid %d. ignoring debug request\n",
tid, cr.pid);
close(fd);
return;
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index 050f406..ca0c9ce 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -166,6 +166,9 @@
{
if (match_fastboot(info) == 0) {
char* serial = info->serial_number;
+ if (!info->writable) {
+ serial = "no permissions"; // like "adb devices"
+ }
if (!serial[0]) {
serial = "????????????";
}
@@ -555,6 +558,8 @@
return 0;
}
+ serial = getenv("ANDROID_SERIAL");
+
while (argc > 0) {
if(!strcmp(*argv, "-w")) {
wants_wipe = 1;
diff --git a/fastboot/usb.h b/fastboot/usb.h
index f3ec5bf..cc157d5 100644
--- a/fastboot/usb.h
+++ b/fastboot/usb.h
@@ -50,6 +50,8 @@
unsigned char has_bulk_in;
unsigned char has_bulk_out;
+ unsigned char writable;
+
char serial_number[256];
};
diff --git a/fastboot/usb_linux.c b/fastboot/usb_linux.c
index 3b40ba7..2ce53eb 100644
--- a/fastboot/usb_linux.c
+++ b/fastboot/usb_linux.c
@@ -89,7 +89,8 @@
return 0;
}
-static int filter_usb_device(int fd, char *ptr, int len, ifc_match_func callback,
+static int filter_usb_device(int fd, char *ptr, int len, int writable,
+ ifc_match_func callback,
int *ept_in_id, int *ept_out_id, int *ifc_id)
{
struct usb_device_descriptor *dev;
@@ -119,7 +120,8 @@
info.dev_class = dev->bDeviceClass;
info.dev_subclass = dev->bDeviceSubClass;
info.dev_protocol = dev->bDeviceProtocol;
-
+ info.writable = writable;
+
// read device serial number (if there is one)
info.serial_number[0] = 0;
if (dev->iSerialNumber) {
@@ -201,6 +203,7 @@
DIR *busdir, *devdir;
struct dirent *de;
int fd;
+ int writable;
busdir = opendir(base);
if(busdir == 0) return 0;
@@ -219,13 +222,20 @@
sprintf(devname, "%s/%s", busname, de->d_name);
// DBG("[ scanning %s ]\n", devname);
+ writable = 1;
if((fd = open(devname, O_RDWR)) < 0) {
- continue;
+ // Check if we have read-only access, so we can give a helpful
+ // diagnostic like "adb devices" does.
+ writable = 0;
+ if((fd = open(devname, O_RDONLY)) < 0) {
+ continue;
+ }
}
n = read(fd, desc, sizeof(desc));
- if(filter_usb_device(fd, desc, n, callback, &in, &out, &ifc) == 0){
+ if(filter_usb_device(fd, desc, n, writable, callback,
+ &in, &out, &ifc) == 0) {
usb = calloc(1, sizeof(usb_handle));
strcpy(usb->fname, devname);
usb->ep_in = in;
@@ -375,5 +385,3 @@
{
return find_usb_device("/dev/bus/usb", callback);
}
-
-
diff --git a/fastboot/usb_osx.c b/fastboot/usb_osx.c
index d6a8260..0b0512d 100644
--- a/fastboot/usb_osx.c
+++ b/fastboot/usb_osx.c
@@ -351,6 +351,7 @@
// device has no serial number
handle->info.serial_number[0] = 0;
}
+ handle->info.writable = 1;
if (try_interfaces(dev, handle)) {
goto error;
@@ -416,8 +417,6 @@
break;
}
- usb_ifc_info info;
-
if (try_device(device, &h) != 0) {
IOObjectRelease(device);
ret = -1;
diff --git a/fastboot/usb_windows.c b/fastboot/usb_windows.c
index 9c0a9cb..54008a4 100644
--- a/fastboot/usb_windows.c
+++ b/fastboot/usb_windows.c
@@ -301,6 +301,7 @@
info.ifc_class = interf_desc.bInterfaceClass;
info.ifc_subclass = interf_desc.bInterfaceSubClass;
info.ifc_protocol = interf_desc.bInterfaceProtocol;
+ info.writable = 1;
// read serial number (if there is one)
unsigned long serial_number_len = sizeof(info.serial_number);
diff --git a/include/cutils/adb_networking.h b/include/cutils/adb_networking.h
deleted file mode 100755
index 409d577..0000000
--- a/include/cutils/adb_networking.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2006 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.
- */
-
-#ifndef _ADB_NETWORKING_H
-#define _ADB_NETWORKING_H 1
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern int adb_networking_connect_fd(int fd, struct sockaddr_in *p_address);
-extern int adb_networking_gethostbyname(const char *name, struct in_addr *p_out_addr);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /*_ADB_NETWORKING_H*/
-
diff --git a/init/property_service.c b/init/property_service.c
index 7db7c2c..d2505dd 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -77,6 +77,7 @@
{ "service.adb.root", AID_SHELL, 0 },
{ "persist.sys.", AID_SYSTEM, 0 },
{ "persist.service.", AID_SYSTEM, 0 },
+ { "persist.security.", AID_SYSTEM, 0 },
{ NULL, 0, 0 }
};
diff --git a/libacc/Android.mk b/libacc/Android.mk
index 2b4998e..5101e16 100644
--- a/libacc/Android.mk
+++ b/libacc/Android.mk
@@ -11,7 +11,7 @@
include $(BUILD_SHARED_LIBRARY)
-# Shared library for host
+# Static library for host
# ========================================================
include $(CLEAR_VARS)
@@ -23,7 +23,7 @@
LOCAL_STATIC_LIBRARIES := libcutils
LOCAL_LDLIBS := -ldl
-include $(BUILD_HOST_SHARED_LIBRARY)
+include $(BUILD_HOST_STATIC_LIBRARY)
# Build children
# ========================================================
diff --git a/libacc/FEATURES b/libacc/FEATURES
index 97a876d..20f9d98 100644
--- a/libacc/FEATURES
+++ b/libacc/FEATURES
@@ -21,7 +21,7 @@
* Pointer indirection ('*') is supported.
- * Square brackets can be used for pointer arithmetic.
+ * Square brackets are supported.
* '=' and <op>= are supported.
@@ -37,11 +37,14 @@
+ variables can be initialized in declarations.
+ Only ANSI-style function declarations are supported.
- "..." is not supported.
- - short is not supported
+ - short is supported
- const is not supported
- - arrays are not supported
+ - signed and unsigned are not supported.
+ - arrays are supported
- long doubles are not supported
- - structs are not supported
+ - structs and unions are supported
+ - typedef is supported
+ - explicit storage class specifiers are not supported: register, auto, static, extern
- Unknown functions and variables are bound at compile time by calling
back to the caller. For the 'acc' command-line tool unknown functions
@@ -66,9 +69,12 @@
- Float and double constants are supported.
- - '#define' is supported without function like arguments. No macro
- recursion is tolerated. Other preprocessor directives are
- ignored.
+ - '#define' is supported without function like arguments.
+ - Macro recursion is allowed.
+ - Self-referential macros are handled as in gcc.
+ - '#pragma' is supported. The pragma text is passed to a callback function,
+ and is used to implement meta-information.
+ - Other preprocessor directives are ignored.
- C Strings and C character constants are supported. All ANSI C
character escapes are supported.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 808752e..8f33b0b 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -82,9 +82,7 @@
~Vector() {
if (mpBase) {
- for(size_t i = 0; i < mUsed; i++) {
- mpBase[mUsed].~E();
- }
+ clear();
free(mpBase);
}
}
@@ -110,10 +108,20 @@
* ensure(1) = item;
}
- size_t size() {
+ inline size_t size() {
return mUsed;
}
+ void clear() {
+ if (mpBase) {
+ size_t used = mUsed;
+ for(size_t i = 0; i < used; i++) {
+ mpBase[i].~E();
+ }
+ }
+ mUsed = 0;
+ }
+
private:
E* ensure(int n) {
size_t newUsed = mUsed + n;
@@ -151,6 +159,7 @@
class Compiler : public ErrorSink {
typedef int tokenid_t;
enum TypeTag {
+ TY_UNKNOWN = -1,
TY_INT, // 0
TY_CHAR, // 1
TY_SHORT, // 2
@@ -164,8 +173,18 @@
TY_PARAM // 10
};
+ enum StorageClass {
+ SC_DEFAULT, // 0
+ SC_AUTO, // 1
+ SC_REGISTER, // 2
+ SC_STATIC, // 3
+ SC_EXTERN, // 4
+ SC_TYPEDEF // 5
+ };
+
struct Type {
TypeTag tag;
+ StorageClass storageClass;
tokenid_t id; // For function arguments, global vars, local vars, struct elements
tokenid_t structTag; // For structs the name of the struct
int length; // length of array, offset of struct element. -1 means struct is forward defined
@@ -3898,6 +3917,16 @@
Vector<Mark> mLevelStack;
};
+ struct MacroState {
+ tokenid_t name; // Name of the current macro we are expanding
+ char* dptr; // point to macro text during macro playback
+ int dch; // Saves old value of ch during a macro playback
+ };
+
+#define MACRO_NESTING_MAX 32
+ MacroState macroState[MACRO_NESTING_MAX];
+ int macroLevel; // -1 means not playing any macro.
+
int ch; // Current input character, or EOF
tokenid_t tok; // token
intptr_t tokc; // token extra info
@@ -3909,8 +3938,6 @@
char* glo; // global variable index
String mTokenString;
bool mbSuppressMacroExpansion;
- char* dptr; // Macro state: Points to macro text during macro playback.
- int dch; // Macro state: Saves old value of ch during a macro playback.
char* pGlobalBase;
ACCSymbolLookupFn mpSymbolLookupFn;
void* mpSymbolLookupContext;
@@ -4018,9 +4045,6 @@
static const int LOCAL = 0x200;
- static const int SYM_FORWARD = 0;
- static const int SYM_DEFINE = 1;
-
/* tokens in string heap */
static const int TAG_TOK = ' ';
@@ -4102,11 +4126,17 @@
}
void inp() {
- if (dptr) {
- ch = *dptr++;
+ // Close any totally empty macros. We leave them on the stack until now
+ // so that we know which macros are being expanded when checking if the
+ // last token in the macro is a macro that's already being expanded.
+ while (macroLevel >= 0 && macroState[macroLevel].dptr == NULL) {
+ macroLevel--;
+ }
+ if (macroLevel >= 0) {
+ ch = *macroState[macroLevel].dptr++;
if (ch == 0) {
- dptr = 0;
- ch = dch;
+ ch = macroState[macroLevel].dch;
+ macroState[macroLevel].dptr = NULL; // This macro's done
}
} else {
if (mbBumpLine) {
@@ -4271,6 +4301,15 @@
// fprintf(stderr, "float constant: %s (%d) %g\n", pText, tok, tokd);
}
+ bool currentlyBeingExpanded(tokenid_t id) {
+ for (int i = 0; i <= macroLevel; i++) {
+ if (macroState[macroLevel].name == id) {
+ return true;
+ }
+ }
+ return false;
+ }
+
void next() {
int l, a;
@@ -4352,12 +4391,22 @@
if (! mbSuppressMacroExpansion) {
// Is this a macro?
char* pMacroDefinition = mTokenTable[tok].mpMacroDefinition;
- if (pMacroDefinition) {
+ if (pMacroDefinition && !currentlyBeingExpanded(tok)) {
// Yes, it is a macro
- dptr = pMacroDefinition;
- dch = ch;
- inp();
- next();
+#if 0
+ printf("Expanding macro %s -> %s",
+ mTokenString.getUnwrapped(), pMacroDefinition);
+#endif
+ if (macroLevel >= MACRO_NESTING_MAX-1) {
+ error("Too many levels of macro recursion.");
+ } else {
+ macroLevel++;
+ macroState[macroLevel].name = tok;
+ macroState[macroLevel].dptr = pMacroDefinition;
+ macroState[macroLevel].dch = ch;
+ inp();
+ next();
+ }
}
}
} else {
@@ -4443,9 +4492,7 @@
next();
mbSuppressMacroExpansion = false;
tokenid_t name = tok;
- String* pName = new String();
if (ch == '(') {
- delete pName;
error("Defines with arguments not supported");
return;
}
@@ -4473,6 +4520,13 @@
memcpy(pDefn, value.getUnwrapped(), value.len());
pDefn[value.len()] = 0;
mTokenTable[name].mpMacroDefinition = pDefn;
+#if 0
+ {
+ String buf;
+ decodeToken(buf, name, true);
+ fprintf(stderr, "define %s = \"%s\"\n", buf.getUnwrapped(), pDefn);
+ }
+#endif
}
void doPragma() {
@@ -4771,57 +4825,59 @@
Type* pDecl = NULL;
VariableInfo* pVI = NULL;
Type* pFn = pGen->getR0Type();
- assert(pFn->tag == TY_POINTER);
- assert(pFn->pHead->tag == TY_FUNC);
- pDecl = pFn->pHead;
- pGen->pushR0();
- Type* pArgList = pDecl->pTail;
- bool varArgs = pArgList == NULL;
- /* push args and invert order */
- a = pGen->beginFunctionCallArguments();
- int l = 0;
- int argCount = 0;
- while (tok != ')' && tok != EOF) {
- if (! varArgs && !pArgList) {
- error("Unexpected argument.");
- }
- expr();
- pGen->forceR0RVal();
- Type* pTargetType;
- if (pArgList) {
- pTargetType = pArgList->pHead;
- pArgList = pArgList->pTail;
- } else {
- // This is a ... function, just pass arguments in their
- // natural type.
- pTargetType = pGen->getR0Type();
- if (pTargetType->tag == TY_FLOAT) {
- pTargetType = mkpDouble;
- } else if (pTargetType->tag == TY_ARRAY) {
- // Pass arrays by pointer.
- pTargetType = pTargetType->pTail;
+ if (pFn->tag == TY_POINTER && pFn->pHead->tag == TY_FUNC) {
+ pDecl = pFn->pHead;
+ pGen->pushR0();
+ Type* pArgList = pDecl->pTail;
+ bool varArgs = pArgList == NULL;
+ /* push args and invert order */
+ a = pGen->beginFunctionCallArguments();
+ int l = 0;
+ int argCount = 0;
+ while (tok != ')' && tok != EOF) {
+ if (! varArgs && !pArgList) {
+ error("Unexpected argument.");
}
+ expr();
+ pGen->forceR0RVal();
+ Type* pTargetType;
+ if (pArgList) {
+ pTargetType = pArgList->pHead;
+ pArgList = pArgList->pTail;
+ } else {
+ // This is a ... function, just pass arguments in their
+ // natural type.
+ pTargetType = pGen->getR0Type();
+ if (pTargetType->tag == TY_FLOAT) {
+ pTargetType = mkpDouble;
+ } else if (pTargetType->tag == TY_ARRAY) {
+ // Pass arrays by pointer.
+ pTargetType = pTargetType->pTail;
+ }
+ }
+ if (pTargetType->tag == TY_VOID) {
+ error("Can't pass void value for argument %d",
+ argCount + 1);
+ } else {
+ l += pGen->storeR0ToArg(l, pTargetType);
+ }
+ if (accept(',')) {
+ // fine
+ } else if ( tok != ')') {
+ error("Expected ',' or ')'");
+ }
+ argCount += 1;
}
- if (pTargetType->tag == TY_VOID) {
- error("Can't pass void value for argument %d",
- argCount + 1);
- } else {
- l += pGen->storeR0ToArg(l, pTargetType);
+ if (! varArgs && pArgList) {
+ error("Expected more argument(s). Saw %d", argCount);
}
- if (accept(',')) {
- // fine
- } else if ( tok != ')') {
- error("Expected ',' or ')'");
- }
- argCount += 1;
+ pGen->endFunctionCallArguments(pDecl, a, l);
+ skip(')');
+ pGen->callIndirect(l, pDecl);
+ pGen->adjustStackAfterCall(pDecl, l, true);
+ } else {
+ error("Expected a function value to left of '('.");
}
- if (! varArgs && pArgList) {
- error("Expected more argument(s). Saw %d", argCount);
- }
- pGen->endFunctionCallArguments(pDecl, a, l);
- skip(')');
- pGen->callIndirect(l, pDecl);
- pGen->adjustStackAfterCall(pDecl, l, true);
} else {
break;
}
@@ -4957,11 +5013,11 @@
return pGen->gtst(0, 0);
}
- void block(intptr_t l, bool outermostFunctionBlock) {
+ void block(intptr_t* breakLabel, intptr_t continueAddress, bool outermostFunctionBlock) {
intptr_t a, n, t;
Type* pBaseType;
- if ((pBaseType = acceptPrimitiveType())) {
+ if ((pBaseType = acceptPrimitiveType(true))) {
/* declarations */
localDeclarations(pBaseType);
} else if (tok == TOK_IF) {
@@ -4969,12 +5025,12 @@
skip('(');
a = test_expr();
skip(')');
- block(l, false);
+ block(breakLabel, continueAddress, false);
if (tok == TOK_ELSE) {
next();
n = pGen->gjmp(0); /* jmp */
pGen->gsym(a);
- block(l, false);
+ block(breakLabel, continueAddress, false);
pGen->gsym(n); /* patch else jmp */
} else {
pGen->gsym(a); /* patch if test */
@@ -5004,7 +5060,7 @@
}
}
skip(')');
- block((intptr_t) &a, false);
+ block(&a, n, false);
pGen->gjmp(n - pCodeBuf->getPC() - pGen->jumpOffset()); /* jmp */
pGen->gsym(a);
} else if (tok == '{') {
@@ -5013,7 +5069,7 @@
}
next();
while (tok != '}' && tok != EOF)
- block(l, false);
+ block(breakLabel, continueAddress, false);
skip('}');
if (! outermostFunctionBlock) {
mLocals.popLevel();
@@ -5035,7 +5091,17 @@
}
rsym = pGen->gjmp(rsym); /* jmp */
} else if (accept(TOK_BREAK)) {
- *(int *) l = pGen->gjmp(*(int *) l);
+ if (breakLabel) {
+ *breakLabel = pGen->gjmp(*breakLabel);
+ } else {
+ error("break statement must be within a for, do, while, or switch statement");
+ }
+ } else if (accept(TOK_CONTINUE)) {
+ if (continueAddress) {
+ pGen->gjmp(continueAddress - pCodeBuf->getPC() - pGen->jumpOffset());
+ } else {
+ error("continue statement must be within a for, do, or while statement");
+ }
} else if (tok != ';')
commaExpr();
skip(';');
@@ -5067,9 +5133,10 @@
}
Type* createType(TypeTag tag, Type* pHead, Type* pTail) {
- assert(tag >= TY_INT && tag <= TY_PARAM);
+ assert(tag >= TY_UNKNOWN && tag <= TY_PARAM);
Type* pType = (Type*) mpCurrentArena->alloc(sizeof(Type));
memset(pType, 0, sizeof(*pType));
+ pType->storageClass = SC_DEFAULT;
pType->tag = tag;
pType->pHead = pHead;
pType->pTail = pTail;
@@ -5232,38 +5299,124 @@
fprintf(stderr, "%s\n", buffer.getUnwrapped());
}
- Type* acceptPrimitiveType() {
- Type* pType;
- if (tok == TOK_INT) {
- pType = mkpInt;
- } else if (tok == TOK_SHORT) {
- pType = mkpShort;
- } else if (tok == TOK_CHAR) {
- pType = mkpChar;
- } else if (tok == TOK_VOID) {
- pType = mkpVoid;
- } else if (tok == TOK_FLOAT) {
- pType = mkpFloat;
- } else if (tok == TOK_DOUBLE) {
- pType = mkpDouble;
- } else if (tok == TOK_STRUCT || tok == TOK_UNION) {
- return acceptStruct();
+ void insertTypeSpecifier(Type** ppType, TypeTag tag) {
+ if (! *ppType) {
+ *ppType = createType(tag, NULL, NULL);
} else {
- return NULL;
+ if ((*ppType)->tag != TY_UNKNOWN) {
+ error("Only one type specifier allowed.");
+ } else {
+ (*ppType)->tag = tag;
+ }
}
- next();
+ }
+
+ void insertStorageClass(Type** ppType, StorageClass storageClass) {
+ if (! *ppType) {
+ *ppType = createType(TY_UNKNOWN, NULL, NULL);
+ }
+ if ((*ppType)->storageClass != SC_DEFAULT) {
+ error("Only one storage class allowed.");
+ } else {
+ (*ppType)->storageClass = storageClass;
+ }
+ }
+
+ Type* acceptPrimitiveType(bool allowStorageClass) {
+ Type* pType = NULL;
+ for (bool keepGoing = true; keepGoing;) {
+ switch(tok) {
+ case TOK_AUTO:
+ insertStorageClass(&pType, SC_AUTO);
+ break;
+ case TOK_REGISTER:
+ insertStorageClass(&pType, SC_REGISTER);
+ break;
+ case TOK_STATIC:
+ insertStorageClass(&pType, SC_STATIC);
+ break;
+ case TOK_EXTERN:
+ insertStorageClass(&pType, SC_EXTERN);
+ break;
+ case TOK_TYPEDEF:
+ insertStorageClass(&pType, SC_TYPEDEF);
+ break;
+ case TOK_INT:
+ insertTypeSpecifier(&pType, TY_INT);
+ break;
+ case TOK_SHORT:
+ insertTypeSpecifier(&pType, TY_SHORT);
+ break;
+ case TOK_CHAR:
+ insertTypeSpecifier(&pType, TY_CHAR);
+ break;
+ case TOK_VOID:
+ insertTypeSpecifier(&pType, TY_VOID);
+ break;
+ case TOK_FLOAT:
+ insertTypeSpecifier(&pType, TY_FLOAT);
+ break;
+ case TOK_DOUBLE:
+ insertTypeSpecifier(&pType, TY_DOUBLE);
+ break;
+ case TOK_STRUCT:
+ case TOK_UNION:
+ {
+ insertTypeSpecifier(&pType, TY_STRUCT);
+ bool isStruct = (tok == TOK_STRUCT);
+ next();
+ pType = acceptStruct(pType, isStruct);
+ keepGoing = false;
+ }
+ break;
+ default:
+ // Is it a typedef?
+ if (isSymbol(tok)) {
+ VariableInfo* pV = VI(tok);
+ if (pV && pV->pType->storageClass == SC_TYPEDEF) {
+ if (! pType) {
+ pType = createType(TY_UNKNOWN, NULL, NULL);
+ }
+ StorageClass storageClass = pType->storageClass;
+ *pType = *pV->pType;
+ pType->storageClass = storageClass;
+ } else {
+ keepGoing = false;
+ }
+ } else {
+ keepGoing = false;
+ }
+ }
+ if (keepGoing) {
+ next();
+ }
+ }
+ if (pType) {
+ if (pType->tag == TY_UNKNOWN) {
+ pType->tag = TY_INT;
+ }
+ if (allowStorageClass) {
+ switch(pType->storageClass) {
+ case SC_AUTO: error("auto not supported."); break;
+ case SC_REGISTER: error("register not supported."); break;
+ case SC_STATIC: error("static not supported."); break;
+ case SC_EXTERN: error("extern not supported."); break;
+ default: break;
+ }
+ } else {
+ if (pType->storageClass != SC_DEFAULT) {
+ error("An explicit storage class is not allowed in this type declaration");
+ }
+ }
+ }
return pType;
}
- Type* acceptStruct() {
- assert(tok == TOK_STRUCT || tok == TOK_UNION);
- bool isStruct = tok == TOK_STRUCT;
- next();
+ Type* acceptStruct(Type* pStructType, bool isStruct) {
tokenid_t structTag = acceptSymbol();
bool isDeclaration = accept('{');
bool fail = false;
- Type* pStructType = createType(TY_STRUCT, NULL, NULL);
if (structTag) {
Token* pToken = &mTokenTable[structTag];
VariableInfo* pStructInfo = pToken->mpStructInfo;
@@ -5292,9 +5445,11 @@
if (needToDeclare) {
// This is a new struct name
pToken->mpStructInfo = mpCurrentSymbolStack->addStructTag(structTag);
+ StorageClass storageClass = pStructType->storageClass;
pStructType = createType(TY_STRUCT, NULL, NULL);
pStructType->structTag = structTag;
pStructType->pHead = pStructType;
+ pStructType->storageClass = storageClass;
if (! isDeclaration) {
// A forward declaration
pStructType->length = -1;
@@ -5312,7 +5467,7 @@
size_t structAlignment = 0;
Type** pParamHolder = & pStructType->pHead->pTail;
while (tok != '}' && tok != EOF) {
- Type* pPrimitiveType = expectPrimitiveType();
+ Type* pPrimitiveType = expectPrimitiveType(false);
if (pPrimitiveType) {
while (tok != ';' && tok != EOF) {
Type* pItem = acceptDeclaration(pPrimitiveType, true, false);
@@ -5375,6 +5530,7 @@
Type* acceptDeclaration(Type* pType, bool nameAllowed, bool nameRequired) {
tokenid_t declName = 0;
bool reportFailure = false;
+ StorageClass storageClass = pType->storageClass;
pType = acceptDecl2(pType, declName, nameAllowed,
nameRequired, reportFailure);
if (declName) {
@@ -5383,6 +5539,7 @@
pType = createType(pType->tag, pType->pHead, pType->pTail);
*pType = *pOldType;
pType->id = declName;
+ pType->storageClass = storageClass;
} else if (nameRequired) {
error("Expected a variable name");
}
@@ -5407,7 +5564,7 @@
/* Used for accepting types that appear in casts */
Type* acceptCastTypeDeclaration() {
- Type* pType = acceptPrimitiveType();
+ Type* pType = acceptPrimitiveType(false);
if (pType) {
pType = acceptDeclaration(pType, false, false);
}
@@ -5495,7 +5652,7 @@
Type* pHead = NULL;
Type* pTail = NULL;
for(;;) {
- Type* pBaseArg = acceptPrimitiveType();
+ Type* pBaseArg = acceptPrimitiveType(false);
if (pBaseArg) {
Type* pArg = acceptDeclaration(pBaseArg, nameAllowed, false);
if (pArg) {
@@ -5516,8 +5673,8 @@
return pHead;
}
- Type* expectPrimitiveType() {
- Type* pType = acceptPrimitiveType();
+ Type* expectPrimitiveType(bool allowStorageClass) {
+ Type* pType = acceptPrimitiveType(allowStorageClass);
if (!pType) {
String buf;
decodeToken(buf, tok, true);
@@ -5585,7 +5742,7 @@
break;
}
// Else it's a forward declaration of a function.
- } else {
+ } else if (pDecl->storageClass != SC_TYPEDEF) {
int variableAddress = 0;
size_t alignment = pGen->alignmentOf(pDecl);
assert(alignment > 0);
@@ -5610,7 +5767,7 @@
next();
}
skip(';');
- pBaseType = acceptPrimitiveType();
+ pBaseType = acceptPrimitiveType(true);
}
}
@@ -5622,8 +5779,12 @@
if (token == EOF ) {
buffer.printf("EOF");
} else if (token == TOK_NUM) {
- buffer.printf("numeric constant");
- } else if (token >= 0 && token < 256) {
+ buffer.printf("numeric constant %d(0x%x)", tokc, tokc);
+ } else if (token == TOK_NUM_FLOAT) {
+ buffer.printf("numeric constant float %g", tokd);
+ } else if (token == TOK_NUM_DOUBLE) {
+ buffer.printf("numeric constant double %g", tokd);
+ } else if (token >= 0 && token < 256) {
if (token < 32) {
buffer.printf("'\\x%02x'", token);
} else {
@@ -5670,7 +5831,7 @@
void globalDeclarations() {
mpCurrentSymbolStack = &mGlobals;
while (tok != EOF) {
- Type* pBaseType = expectPrimitiveType();
+ Type* pBaseType = expectPrimitiveType(true);
if (!pBaseType) {
break;
}
@@ -5687,7 +5848,6 @@
skip(';');
continue;
}
-
if (! isDefined(pDecl->id)) {
addGlobalSymbol(pDecl);
}
@@ -5698,19 +5858,23 @@
if (pDecl->tag < TY_FUNC) {
// it's a variable declaration
for(;;) {
- if (name && !name->pAddress) {
- name->pAddress = (int*) allocGlobalSpace(
- pGen->alignmentOf(name->pType),
- pGen->sizeOf(name->pType));
- }
- if (accept('=')) {
- if (tok == TOK_NUM) {
- if (name) {
- * (int*) name->pAddress = tokc;
+ if (pDecl->storageClass == SC_TYPEDEF) {
+ // Do not allocate storage.
+ } else {
+ if (name && !name->pAddress) {
+ name->pAddress = (int*) allocGlobalSpace(
+ pGen->alignmentOf(name->pType),
+ pGen->sizeOf(name->pType));
+ }
+ if (accept('=')) {
+ if (tok == TOK_NUM) {
+ if (name) {
+ * (int*) name->pAddress = tokc;
+ }
+ next();
+ } else {
+ error("Expected an integer constant");
}
- next();
- } else {
- error("Expected an integer constant");
}
}
if (!accept(',')) {
@@ -5763,7 +5927,7 @@
rsym = loc = 0;
pReturnType = pDecl->pHead;
a = pGen->functionEntry(pDecl);
- block(0, true);
+ block(0, 0, true);
pGen->gsym(rsym);
pGen->functionExit(pDecl, a, loc);
mLocals.popLevel();
@@ -5830,8 +5994,7 @@
rsym = 0;
loc = 0;
glo = 0;
- dptr = 0;
- dch = 0;
+ macroLevel = -1;
file = 0;
pGlobalBase = 0;
pCodeBuf = 0;
diff --git a/libacc/tests/Android.mk b/libacc/tests/Android.mk
index e9fbe03..6ddfa74 100644
--- a/libacc/tests/Android.mk
+++ b/libacc/tests/Android.mk
@@ -8,9 +8,13 @@
LOCAL_SRC_FILES:= \
main.cpp
-LOCAL_SHARED_LIBRARIES := \
- libacc
+LOCAL_STATIC_LIBRARIES := \
+ libacc \
+ libcutils
+LOCAL_LDLIBS := -ldl
+
+
LOCAL_MODULE_TAGS := tests
include $(BUILD_HOST_EXECUTABLE)
@@ -25,7 +29,8 @@
disassem.cpp
LOCAL_SHARED_LIBRARIES := \
- libacc
+ libacc \
+ libdl
LOCAL_CFLAGS := -O0 -g
@@ -41,8 +46,11 @@
LOCAL_SRC_FILES:= \
runtimeTest.cpp
-LOCAL_SHARED_LIBRARIES := \
- libacc
+LOCAL_STATIC_LIBRARIES := \
+ libacc \
+ libcutils
+
+LOCAL_LDLIBS := -ldl
LOCAL_MODULE_TAGS := tests
@@ -57,7 +65,8 @@
runtimeTest.cpp
LOCAL_SHARED_LIBRARIES := \
- libacc
+ libacc \
+ libdl
LOCAL_CFLAGS := -O0 -g
diff --git a/libacc/tests/data/continue.c b/libacc/tests/data/continue.c
new file mode 100644
index 0000000..d8b8e36
--- /dev/null
+++ b/libacc/tests/data/continue.c
@@ -0,0 +1,13 @@
+int main() {
+ int i, j, sum;
+ sum = 0;
+ for (i = 0; i < 10; i++) {
+ if (i & 1) continue;
+ for (j = 0; j < 10; j++) {
+ if (j & 1) continue;
+ sum += i * j;
+ }
+ }
+ return sum;
+}
+
diff --git a/libacc/tests/data/macros.c b/libacc/tests/data/macros.c
new file mode 100644
index 0000000..50e54dc
--- /dev/null
+++ b/libacc/tests/data/macros.c
@@ -0,0 +1,10 @@
+#define A B + B
+#define B C
+
+int main() {
+ int C = 3;
+ printf("A = %d\n", A);
+#define C 5
+ printf("A = %d\n", A);
+ return 0;
+}
diff --git a/libacc/tests/data/typedef.c b/libacc/tests/data/typedef.c
new file mode 100644
index 0000000..c392f6a
--- /dev/null
+++ b/libacc/tests/data/typedef.c
@@ -0,0 +1,40 @@
+typedef short COORD;
+typedef struct Point {
+ COORD x;
+ COORD y;
+} Point;
+
+void add(Point* result, Point* a, Point* b) {
+ result->x = a->x + b->x;
+ result->y = a->y + b->y;
+}
+
+void print(Point* p) {
+ printf("(%d, %d)", p->x, p->y);
+}
+
+void set(Point* p, int x, int y) {
+ p->x = x;
+ p->y = y;
+}
+
+int main() {
+ typedef char* String;
+ String s = "x = %d\n";
+ {
+ typedef int item;
+ item x = 3;
+ printf(s, x);
+ }
+ Point a, b, c;
+ set(&a, 1,2);
+ set(&b, 3,4);
+ add(&c, &a, &b);
+ print(&c);
+ printf(" = ");
+ print(&a);
+ printf(" + ");
+ print(&b);
+ printf("\n");
+ return 0;
+}
diff --git a/libacc/tests/test.py b/libacc/tests/test.py
index d984301..1b444c7 100644
--- a/libacc/tests/test.py
+++ b/libacc/tests/test.py
@@ -10,6 +10,7 @@
gUseArm = True
gUseX86 = True
gRunOTCCOutput = True
+gCompileOTCCANSI = True
def parseArgv():
@@ -59,7 +60,12 @@
def checkEnvironment():
global gRunOTCCOutput
- gRunOTCCOutput = uname() == "Linux" and unameM() != "x86_64" and outputCanRun()
+ global gCompileOTCCANSI
+ osName = uname()
+ gRunOTCCOutput = osName == "Linux" and unameM() != "x86_64" and outputCanRun()
+ # OSX doesn't have stdin/stdout/stderr accessible through dll load symbols, so
+ # we can't compile the ANSI version of the OTCC compiler on OS X.
+ gCompileOTCCANSI = osName == "Linux"
def adb(args):
return runCmd(["adb"] + args)
@@ -180,13 +186,19 @@
def testCompileReturnVal(self):
self.compileCheck(["data/returnval-ansi.c"], "")
- def testCompileOTCCANSII(self):
- self.compileCheck(["data/otcc-ansi.c"], "", "", ['x86'])
+ def testCompileOTCCANSI(self):
+ global gCompileOTCCANSI
+ if gCompileOTCCANSI:
+ self.compileCheck(["data/otcc-ansi.c"], "", "", ['x86'])
def testRunReturnVal(self):
self.compileCheck(["-R", "data/returnval-ansi.c"],
"Executing compiled code:\nresult: 42\n")
+ def testContinue(self):
+ self.compileCheck(["-R", "data/continue.c"],
+ "Executing compiled code:\nresult: 400\n")
+
def testStringLiteralConcatenation(self):
self.compileCheck(["-R", "data/testStringConcat.c"],
"Executing compiled code:\nresult: 13\n", "Hello, world\n")
@@ -311,6 +323,12 @@
result: 0""", """a = 99, b = 41
ga = 100, gb = 44""")
+ def testTypedef(self):
+ self.compileCheck(["-R", "data/typedef.c"], """Executing compiled code:
+result: 0""", """x = 3
+(4, 6) = (1, 2) + (3, 4)
+""")
+
def testPointerArithmetic(self):
self.compileCheck(["-R", "data/pointers.c"], """Executing compiled code:
result: 0""", """Pointer difference: 1 4
@@ -373,6 +391,12 @@
Total bad: 0
""")
+ def testMacros(self):
+ self.compileCheck(["-R", "data/macros.c"], """Executing compiled code:
+result: 0""", """A = 6
+A = 10
+""")
+
def testpointers2(self):
self.compileCheck(["-R", "data/pointers2.c"], """Executing compiled code:
result: 0""", """a = 0, *pa = 0
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 6418590..b219473 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -65,7 +65,6 @@
mspace.c \
selector.c \
tztime.c \
- adb_networking.c \
zygote.c
commonHostSources += \
diff --git a/libcutils/adb_networking.c b/libcutils/adb_networking.c
deleted file mode 100644
index d819d44..0000000
--- a/libcutils/adb_networking.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* libs/utils/adb_networking.c
-**
-** Copyright 2006, 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.
-*/
-
-#define ADB_PORT 5037
-
-#define _GNU_SOURCE /* for asprintf */
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-
-#include <cutils/adb_networking.h>
-#include <cutils/sockets.h>
-#include <cutils/properties.h>
-
-#define ADB_RESPONSE_SIZE 4
-
-/**
- * Unfortunately, java.net.Socket wants to create it's filedescriptor early
- * So, this function takes an fd that must be an unconnected
- * PF_LOCAL SOCK_STREAM
- */
-int adb_networking_connect_fd(int fd, struct sockaddr_in *p_address)
-{
- struct sockaddr_in local_addr;
- socklen_t alen;
- char *cmd;
- char buf[ADB_RESPONSE_SIZE + 1];
- ssize_t count_read;
- int ret;
- int err;
- /* for impl of inet_ntoa below*/
- union {
- uint8_t b[4];
- uint32_t l;
- } a;
-
- /* First, connect to adb */
-
- memset(&local_addr, 0, sizeof(local_addr));
- local_addr.sin_family = AF_INET;
- local_addr.sin_port = htons(ADB_PORT);
- local_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
- do {
- err = connect(fd, (struct sockaddr *) &local_addr, sizeof(local_addr));
- } while (err < 0 && errno == EINTR);
-
- if (err < 0) {
- return -1;
- }
-
- a.l = p_address->sin_addr.s_addr;
-
- // compose the command
- asprintf(&cmd, "tcp:%u:%u.%u.%u.%u",
- (unsigned int)ntohs(p_address->sin_port),
- a.b[0],a.b[1],a.b[2],a.b[3]);
-
- // buf is now the ascii hex length of cmd
- snprintf(buf, sizeof(buf), "%04X", strlen(cmd));
-
- // write the 4-byte length
- do {
- err = write(fd, buf, 4);
- } while (err < 0 && errno == EINTR);
-
- // write the command
- do {
- err = write(fd, cmd, strlen(cmd));
- } while (err < 0 && errno == EINTR);
-
- // read the result
- do {
- count_read = read(fd, buf, sizeof(buf) - 1);
- } while (count_read < 0 && errno != EINTR);
-
- if (count_read == ADB_RESPONSE_SIZE
- && 0 == strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) {
- ret = 0;
- } else {
- /* what errno here? <shrug? */
- errno = ENETUNREACH;
- ret = -1;
- }
-
- free(cmd);
-
- return ret;
-}
-
-/**
- * Fills in *p_out_addr and returns 0 on success
- * Memset's *p_out_addr and returns -1 on fail
- */
-
-int adb_networking_gethostbyname(const char *name, struct in_addr *p_out_addr)
-{
- int fd;
- char *cmd = NULL;
- char buf[ADB_RESPONSE_SIZE + 1];
- int err;
- ssize_t count_read;
-
- fd = socket_loopback_client(ADB_PORT, SOCK_STREAM);
-
- if (fd < 0) {
- return -1;
- }
-
- // compose the command
- asprintf(&cmd, "dns:%s", name);
-
- // buf is now the ascii hex length of cmd
- snprintf(buf, sizeof(buf), "%04X", strlen(cmd));
-
- // write the 4-byte length
- do {
- err = write(fd, buf, 4);
- } while (err < 0 && errno == EINTR);
-
- // write the command
- do {
- err = write(fd, cmd, strlen(cmd));
- } while (err < 0 && errno == EINTR);
-
- // read the result
- do {
- count_read = read(fd, buf, ADB_RESPONSE_SIZE);
- } while (count_read < 0 && errno != EINTR);
-
- if (count_read != ADB_RESPONSE_SIZE
- || 0 != strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) {
- goto error;
- }
-
- // read the actual IP address
- do {
- count_read = read(fd, &(p_out_addr->s_addr), sizeof(p_out_addr->s_addr));
- } while (count_read < 0 && errno != EINTR);
-
- if (count_read != 4) {
- goto error;
- }
-
- free(cmd);
- close(fd);
- return 0;
-error:
- free(cmd);
- close(fd);
- memset(p_out_addr, 0, sizeof(struct in_addr));
- return -1;
-}
-
diff --git a/libcutils/atomic-android-arm.S b/libcutils/atomic-android-arm.S
index da5c26b..1dd2363 100644
--- a/libcutils/atomic-android-arm.S
+++ b/libcutils/atomic-android-arm.S
@@ -24,17 +24,25 @@
.align
.global android_atomic_write
+ .type android_atomic_write, %function
.global android_atomic_inc
+ .type android_atomic_inc, %function
.global android_atomic_dec
+ .type android_atomic_dec, %function
.global android_atomic_add
+ .type android_atomic_add, %function
.global android_atomic_and
+ .type android_atomic_and, %function
.global android_atomic_or
+ .type android_atomic_or, %function
.global android_atomic_swap
+ .type android_atomic_swap, %function
.global android_atomic_cmpxchg
+ .type android_atomic_cmpxchg, %function
/*
* ----------------------------------------------------------------------------
diff --git a/libcutils/atomic-android-armv6.S b/libcutils/atomic-android-armv6.S
index a713089..1574c9c 100644
--- a/libcutils/atomic-android-armv6.S
+++ b/libcutils/atomic-android-armv6.S
@@ -19,17 +19,25 @@
.align
.global android_atomic_write
+ .type android_atomic_write, %function
.global android_atomic_inc
+ .type android_atomic_inc, %function
.global android_atomic_dec
+ .type android_atomic_dec, %function
.global android_atomic_add
+ .type android_atomic_add, %function
.global android_atomic_and
+ .type android_atomic_and, %function
.global android_atomic_or
+ .type android_atomic_or, %function
.global android_atomic_swap
+ .type android_atomic_swap, %function
.global android_atomic_cmpxchg
+ .type android_atomic_cmpxchg, %function
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 808255e..71a9882 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -116,6 +116,12 @@
mkdir /data/app 0771 system system
mkdir /data/property 0700 root root
+ # STOPSHIP: Temporary Encrypted File Systems workaround
+ mkdir /data/secure 0771 system system
+ mkdir /data/secure/data 0771 system system
+ mkdir /data/secure/misc 01771 system misc
+ mkdir /data/securemisc/vpn 0770 system system
+ mkdir /data/secure/misc/vpn/profiles 0770 system system
# create dalvik-cache and double-check the perms
mkdir /data/dalvik-cache 0771 system system
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 70b13dc..122a544 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -50,7 +50,8 @@
top \
iftop \
id \
- vmstat
+ vmstat \
+ nandread
LOCAL_SRC_FILES:= \
toolbox.c \
diff --git a/toolbox/ls.c b/toolbox/ls.c
index b221074..f340a83 100644
--- a/toolbox/ls.c
+++ b/toolbox/ls.c
@@ -86,15 +86,50 @@
}
}
-static int listfile_size(const char *path, int flags)
+static int show_total_size(const char *dirname, DIR *d, int flags)
+{
+ struct dirent *de;
+ char tmp[1024];
+ struct stat s;
+ int sum = 0;
+
+ /* run through the directory and sum up the file block sizes */
+ while ((de = readdir(d)) != 0) {
+ if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
+ continue;
+ if (de->d_name[0] == '.' && (flags & LIST_ALL) == 0)
+ continue;
+
+ if (strcmp(dirname, "/") == 0)
+ snprintf(tmp, sizeof(tmp), "/%s", de->d_name);
+ else
+ snprintf(tmp, sizeof(tmp), "%s/%s", dirname, de->d_name);
+
+ if (lstat(tmp, &s) < 0) {
+ fprintf(stderr, "stat failed on %s: %s\n", tmp, strerror(errno));
+ rewinddir(d);
+ return -1;
+ }
+
+ sum += s.st_blocks / 2;
+ }
+
+ printf("total %d\n", sum);
+ rewinddir(d);
+ return 0;
+}
+
+static int listfile_size(const char *path, const char *filename, int flags)
{
struct stat s;
- if (lstat(path, &s) < 0)
+ if (lstat(path, &s) < 0) {
+ fprintf(stderr, "lstat '%s' failed: %s\n", path, strerror(errno));
return -1;
+ }
/* blocks are 512 bytes, we want output to be KB */
- printf("%lld %s\n", s.st_blocks / 2, path);
+ printf("%lld %s\n", s.st_blocks / 2, filename);
return 0;
}
@@ -189,7 +224,7 @@
if ((flags & LIST_LONG) != 0) {
return listfile_long(pathname, flags);
} else /*((flags & LIST_SIZE) != 0)*/ {
- return listfile_size(pathname, flags);
+ return listfile_size(pathname, filename, flags);
}
}
@@ -198,13 +233,17 @@
char tmp[4096];
DIR *d;
struct dirent *de;
-
+
d = opendir(name);
if(d == 0) {
fprintf(stderr, "opendir failed, %s\n", strerror(errno));
return -1;
}
+ if ((flags & LIST_SIZE) != 0) {
+ show_total_size(name, d, flags);
+ }
+
while((de = readdir(d)) != 0){
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue;
if(de->d_name[0] == '.' && (flags & LIST_ALL) == 0) continue;
diff --git a/toolbox/nandread.c b/toolbox/nandread.c
new file mode 100644
index 0000000..aacccdb
--- /dev/null
+++ b/toolbox/nandread.c
@@ -0,0 +1,256 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <mtd/mtd-user.h>
+#include <sys/ioctl.h>
+
+int test_empty(const char *buf, size_t size)
+{
+ while(size--) {
+ if (*buf++ != 0xff)
+ return 0;
+ }
+ return 1;
+}
+
+int nandread_main(int argc, char **argv)
+{
+ char *devname = NULL;
+ char *filename = NULL;
+ char *statusfilename = NULL;
+ char *statusext = ".stat";
+ int fd;
+ int outfd = -1;
+ FILE *statusfile = NULL;
+ int ret;
+ int verbose = 0;
+ void *buffer;
+ loff_t pos, opos;
+ int c;
+ int i;
+ int empty_pages = 0;
+ int page_count = 0;
+ int bad_block;
+ uint32_t *oob_data;
+ uint8_t *oob_fixed;
+ size_t spare_size = 64;
+ struct mtd_info_user mtdinfo;
+ struct mtd_ecc_stats initial_ecc, last_ecc, ecc;
+ struct mtd_oob_buf oobbuf;
+ struct nand_ecclayout ecclayout;
+
+ do {
+ c = getopt(argc, argv, "d:f:s:hv");
+ if (c == EOF)
+ break;
+ switch (c) {
+ case 'd':
+ devname = optarg;
+ break;
+ case 'f':
+ filename = optarg;
+ break;
+ case 's':
+ spare_size = atoi(optarg);
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'h':
+ fprintf(stderr, "%s [-d <dev>] [-f file] [-s sparesize] [-vh]\n"
+ " -d <dev> Read from <dev>\n"
+ " -f <file> Write to <file>\n"
+ " -s <size> Number of spare bytes in file (default 64)\n"
+ " -v Print info\n"
+ " -h Print help\n", argv[0]);
+ return -1;
+ case '?':
+ fprintf(stderr, "%s: invalid option -%c\n",
+ argv[0], optopt);
+ exit(1);
+ }
+ } while (1);
+
+ if (optind < argc) {
+ fprintf(stderr, "%s: extra arguments\n", argv[0]);
+ return 1;
+ }
+ if (!devname) {
+ fprintf(stderr, "%s: specify device name\n", argv[0]);
+ return 1;
+ }
+
+ fd = open(devname, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "cannot open %s, %s\n", devname, strerror(errno));
+ return 1;
+ }
+
+ if (filename) {
+ outfd = creat(filename, 0666);
+ if (outfd < 0) {
+ fprintf(stderr, "cannot open %s, %s\n", filename, strerror(errno));
+ return 1;
+ }
+ statusfilename = malloc(strlen(filename) + strlen(statusext) + 1);
+ strcpy(statusfilename, filename);
+ strcat(statusfilename, statusext);
+ statusfile = fopen(statusfilename, "w+");
+ if (!statusfile) {
+ fprintf(stderr, "cannot open %s, %s\n", statusfilename, strerror(errno));
+ return 1;
+ }
+ }
+
+ ret = ioctl(fd, MEMGETINFO, &mtdinfo);
+ if (ret) {
+ fprintf(stderr, "failed get mtd info for %s, %s\n",
+ devname, strerror(errno));
+ return 1;
+ }
+
+ if (verbose) {
+ printf("size: %u\n", mtdinfo.size);
+ printf("erase size: %u\n", mtdinfo.erasesize);
+ printf("write size: %u\n", mtdinfo.writesize);
+ printf("oob size: %u\n", mtdinfo.oobsize);
+ }
+
+ buffer = malloc(mtdinfo.writesize + mtdinfo.oobsize + spare_size);
+ if (!buffer) {
+ fprintf(stderr, "failed allocate readbuffer size %u\n",
+ mtdinfo.writesize + mtdinfo.oobsize);
+ return 1;
+ }
+
+ oobbuf.length = mtdinfo.oobsize;
+ oob_data = (uint32_t *)((uint8_t *)buffer + mtdinfo.writesize);
+ memset(oob_data, 0xff, spare_size);
+ oobbuf.ptr = (uint8_t *)oob_data + spare_size;
+
+ ret = ioctl(fd, ECCGETLAYOUT, &ecclayout);
+ if (ret) {
+ fprintf(stderr, "failed get ecc layout for %s, %s\n",
+ devname, strerror(errno));
+ return 1;
+ }
+ if (verbose) {
+ printf("ecc bytes: %u\n", ecclayout.eccbytes);
+ printf("oobavail: %u\n", ecclayout.oobavail);
+ }
+ if (ecclayout.oobavail > spare_size)
+ printf("oobavail, %d > image spare size, %d\n", ecclayout.oobavail, spare_size);
+
+ ret = ioctl(fd, ECCGETSTATS, &initial_ecc);
+ if (ret) {
+ fprintf(stderr, "failed get ecc stats for %s, %s\n",
+ devname, strerror(errno));
+ return 1;
+ }
+ last_ecc = initial_ecc;
+
+ if (verbose) {
+ printf("initial ecc corrected: %u\n", initial_ecc.corrected);
+ printf("initial ecc failed: %u\n", initial_ecc.failed);
+ printf("initial ecc badblocks: %u\n", initial_ecc.badblocks);
+ printf("initial ecc bbtblocks: %u\n", initial_ecc.bbtblocks);
+ }
+
+ for (pos = 0, opos = 0; pos < mtdinfo.size; pos += mtdinfo.writesize) {
+ bad_block = 0;
+ if (verbose > 3)
+ printf("reading at %llx\n", pos);
+ lseek64(fd, pos, SEEK_SET);
+ ret = read(fd, buffer, mtdinfo.writesize);
+ if (ret < (int)mtdinfo.writesize) {
+ fprintf(stderr, "short read at %llx, %d\n", pos, ret);
+ bad_block = 2;
+ }
+ oobbuf.start = pos;
+ ret = ioctl(fd, MEMREADOOB, &oobbuf);
+ if (ret) {
+ fprintf(stderr, "failed to read oob data at %llx, %d\n", pos, ret);
+ bad_block = 2;
+ }
+ ret = ioctl(fd, ECCGETSTATS, &ecc);
+ if (ret) {
+ fprintf(stderr, "failed get ecc stats for %s, %s\n",
+ devname, strerror(errno));
+ return 1;
+ }
+ ret = ioctl(fd, MEMGETBADBLOCK, &pos);
+ if (ret && errno != EOPNOTSUPP) {
+ printf("badblock at %llx\n", pos);
+ bad_block = 1;
+ }
+ if (ecc.corrected != last_ecc.corrected)
+ printf("ecc corrected, %u, at %llx\n", ecc.corrected - last_ecc.corrected, pos);
+ if (ecc.failed != last_ecc.failed)
+ printf("ecc failed, %u, at %llx\n", ecc.failed - last_ecc.failed, pos);
+ if (ecc.badblocks != last_ecc.badblocks)
+ printf("ecc badblocks, %u, at %llx\n", ecc.badblocks - last_ecc.badblocks, pos);
+ if (ecc.bbtblocks != last_ecc.bbtblocks)
+ printf("ecc bbtblocks, %u, at %llx\n", ecc.bbtblocks - last_ecc.bbtblocks, pos);
+
+ oob_fixed = (uint8_t *)oob_data;
+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) {
+ int len = ecclayout.oobfree[i].length;
+ if (oob_fixed + len > oobbuf.ptr)
+ len = oobbuf.ptr - oob_fixed;
+ if (len) {
+ memcpy(oob_fixed, oobbuf.ptr + ecclayout.oobfree[i].offset, len);
+ oob_fixed += len;
+ }
+ }
+
+ if (outfd >= 0) {
+ ret = write(outfd, buffer, mtdinfo.writesize + spare_size);
+ if (ret < (int)(mtdinfo.writesize + spare_size)) {
+ fprintf(stderr, "short write at %llx, %d\n", pos, ret);
+ close(outfd);
+ outfd = -1;
+ }
+ if (ecc.corrected != last_ecc.corrected)
+ fprintf(statusfile, "%08llx: ecc corrected\n", opos);
+ if (ecc.failed != last_ecc.failed)
+ fprintf(statusfile, "%08llx: ecc failed\n", opos);
+ if (bad_block == 1)
+ fprintf(statusfile, "%08llx: badblock\n", opos);
+ if (bad_block == 2)
+ fprintf(statusfile, "%08llx: read error\n", opos);
+ opos += mtdinfo.writesize + spare_size;
+ }
+
+ last_ecc = ecc;
+ page_count++;
+ if (test_empty(buffer, mtdinfo.writesize + mtdinfo.oobsize + spare_size))
+ empty_pages++;
+ else if (verbose > 2 || (verbose > 1 && !(pos & (mtdinfo.erasesize - 1))))
+ printf("page at %llx (%d oobbytes): %08x %08x %08x %08x "
+ "%08x %08x %08x %08x\n", pos, oobbuf.start,
+ oob_data[0], oob_data[1], oob_data[2], oob_data[3],
+ oob_data[4], oob_data[5], oob_data[6], oob_data[7]);
+ }
+
+ if (outfd >= 0) {
+ fprintf(statusfile, "read %d pages, %d empty\n", page_count, empty_pages);
+ fprintf(statusfile, "total ecc corrected, %u\n", ecc.corrected - initial_ecc.corrected);
+ fprintf(statusfile, "total ecc failed, %u\n", ecc.failed - initial_ecc.failed);
+ fprintf(statusfile, "total ecc badblocks, %u\n", ecc.badblocks - initial_ecc.badblocks);
+ fprintf(statusfile, "total ecc bbtblocks, %u\n", ecc.bbtblocks - initial_ecc.bbtblocks);
+ }
+ if (verbose) {
+ printf("total ecc corrected, %u\n", ecc.corrected - initial_ecc.corrected);
+ printf("total ecc failed, %u\n", ecc.failed - initial_ecc.failed);
+ printf("total ecc badblocks, %u\n", ecc.badblocks - initial_ecc.badblocks);
+ printf("total ecc bbtblocks, %u\n", ecc.bbtblocks - initial_ecc.bbtblocks);
+ }
+ printf("read %d pages, %d empty\n", page_count, empty_pages);
+
+ return 0;
+}
+