使用反射完成android的getprop操作无须root..

public static String getProp(Context context, String property)

{

try{

ClassLoader cl = context.getClassLoader();

@SuppressWarnings(“rawtypes”)

Class SystemProperties = cl.loadClass(“android.os.SystemProperties”)

Method get = SystemProperties.getMethod(“get”,String.class)

Object[] params = new Object[1];

params[0] = new String(property);

return (String) get.invoke(SystemProperties, params);

 

}catch(Exception e)

{
return null;

}

}

Hex-Rays ARM Decompiler v1.0 Comparison Page

嗯!

人的闺女儿有花戴~你爹我钱少不能买~扯下了二尺红头绳~替我鸡宝扎起来~扎呀扎起来~~~

没钱买ARM Decompiler,希望能多看下面的转换对比,了解ARM汇编代码与C代码之间的常见专版类型,

俗话说的好啊 : 没有伞的孩子只能努力奔跑..

 

原始链接来自哪里你懂的.

https://www.hex-rays.com/products/decompiler/compare_arm0.shtml

 

Simple case
; struct_result *__fastcall sub_210DC(struct_result *result) var_10 = -0x10 var_4 = -4 MOV R12, SP STMFD SP!, {R0} STMFD SP!, {R12,LR} SUB SP, SP, #4 LDR R2, [SP,#0x10+var_4] MOV R3, #0 STR R3, [R2] LDR R3, [SP,#0x10+var_4] ADD R2, R3, #4 MOV R3, #0 STR R3, [R2] LDR R3, [SP,#0x10+var_4] ADD R2, R3, #8 MOV R3, #0 STR R3, [R2] LDR R3, [SP,#0x10+var_4] STR R3, [SP,#0x10+var_10] LDR R0, [SP,#0x10+var_10] ADD SP, SP, #4 LDMFD SP, {SP,LR} BX LR ; End of function sub_210DC struct_result *__fastcall sub_210DC(struct_result *result) { result->dword0 = 0; result->dword4 = 0; result->dword8 = 0; return result; }
Let’s start with a very simple function. It accepts a pointer to a structure and zeroes out its first three fields. While the function logic is obvious by just looking at the decompiler output, the assembly listing has too much noise and requires studying it. 

The decompiler saves your time and allows you to concentrate on more exciting aspects of reverse engineering.

64-bit arithmetics
; bool __cdecl uh_gt_uc() EXPORT _uh_gt_uc__YA_NXZ _uh_gt_uc__YA_NXZ ; DATA XREF: .pdata:$T7452o var_2C = -0x2C var_28 = -0x28 var_24 = -0x24 var_20 = -0x20 var_1C = -0x1C var_18 = -0x18 var_14 = -0x14 var_10 = -0x10 var_C = -0xC var_8 = -8 var_4 = -4 STR LR, [SP,#var_4]! ; $M7441 ; $LN8@uh_gt_uc SUB SP, SP, #0x28 $M7449 BL uh STR R1, [SP,#0x2C+var_24] STR R0, [SP,#0x2C+var_28] BL uc STRB R0, [SP,#0x2C+var_20] LDRB R3, [SP,#0x2C+var_20] STR R3, [SP,#0x2C+var_1C] LDR R1, [SP,#0x2C+var_1C] LDR R3, [SP,#0x2C+var_1C] MOV R2, R3,ASR#31 LDR R3, [SP,#0x2C+var_28] STR R3, [SP,#0x2C+var_18] LDR R3, [SP,#0x2C+var_24] STR R3, [SP,#0x2C+var_14] LDR R3, [SP,#0x2C+var_18] STR R3, [SP,#0x2C+var_10] STR R1, [SP,#0x2C+var_C] LDR R3, [SP,#0x2C+var_14] CMP R3, R2 BCC $LN3_8 loc_6AC BHI $LN5_0 loc_6B0 LDR R2, [SP,#0x2C+var_10] LDR R3, [SP,#0x2C+var_C] CMP R2, R3 BLS $LN3_8 $LN5_0 MOV R3, #1 STR R3, [SP,#0x2C+var_8] B $LN4_8 ; ————————————————————————— $LN3_8 ; uh_gt_uc(void)+68j MOV R3, #0 STR R3, [SP,#0x2C+var_8] $LN4_8 LDR R3, [SP,#0x2C+var_8] AND R3, R3, #0xFF STRB R3, [SP,#0x2C+var_2C] LDRB R0, [SP,#0x2C+var_2C] ADD SP, SP, #0x28 LDR PC, [SP+4+var_4],#4 ; End of function uh_gt_uc(void) bool __fastcall uh_gt_uc() { unsigned __int64 v0; // ST04_8@1 v0 = uh(); return v0 > uc(); }
Sorry for a long code snippet, ARM code tends to be longer compared to x86 code. This makes our comparison even more impressive: look at how concise is the decompiler output!

Conditional instructions
; int __cdecl ReadShort(void *, unsigned __int32 offset, int whence) ReadShort whence = -0x18 var_A = -0xA var_8 = -8 STMFD SP!, {R4,LR} SUB SP, SP, #0x10 ; whence MOV R4, #0 ADD R3, SP, #0x18+var_8 STRH R4, [R3,#-2]! STR R2, [SP,#0x18+whence] ; whence MOV R2, R3 ; buffer MOV R3, #2 ; len BL ReadData CMP R0, R4 MOVNE R0, R4 LDREQSH R0, [SP,#0x18+var_A] ADD SP, SP, #0x10 LDMFD SP!, {R4,PC} ; End of function ReadShort int __cdecl ReadShort(void *a1, unsigned __int32 offset, int whence) { int result; // r0@2 __int16 v4; // [sp+Eh] [bp-Ah]@1 v4 = 0; if ( ReadData(a1, offset, &v4, 2u, whence) ) result = 0; else result = v4; return result; }
The ARM processor has conditional instructions that can shorten the code but require high attention from the reader. The case above is very simple, just note that there is a pair of instructions: MOVNE andLDREQSH. Only one of them will be executed at once. This is how simple if-then-else looks in ARM. 

The pseudocode shows it much better and does not require any explanations. 

A quiz question: did you notice that MOVNE loads zero to R0? (because I didn’t:)
Also note that in the disassembly listing we see var_8 but the location really used is var_A, which corresponds to v4.

Conditional instructions – 2
; signed int __fastcall get_next_byte(entry_t *entry) get_next_byte ; DATA XREF: sub_3BC+30o ; LDR R2, [R0,#4] CMP R2, #0 LDRNE R3, [R0] LDRNEB R1, [R3],#1 CMPNE R1, #0 MOVEQ R1, #1 STREQ R1, [R0,#0xC] MOVEQ R0, 0xFFFFFFFF MOVEQ PC, LR SUB R2, R2, #1 STR R2, [R0,#4] STR R3, [R0] MOV R0, R1 RET ; End of function get_next_byte signed int __fastcall get_next_byte(entry_t *entry) { signed int chr; // r1@0 unsigned __int8 *ptr; // r3@0 int count; // r2@1 char done; // zf@1 signed int result; // r0@4 count = entry->count; done = count == 0; if ( count ) { ptr = entry->ptr + 1; chr = *entry->ptr; done = chr == 0; } if ( done ) { entry->done = 1; result = -1; } else { entry->count = count – 1; entry->ptr = ptr; result = chr; } return result; }
Look, the decompiler output is longer! This is a rare case when the pseudocode is longer than the disassembly listing, but it is a for a good cause: to keep it readable. There are so many conditional instructions here, it is very easy to misunderstand the dependencies. For example, did you notice that the first MOVEQ may use the condition codes set by CMP? The subtle detail is that CMPNE may be skipped and the condition codes set by CMP may reach MOVEQs. 

The decompiler represented it perfectly well. I renamed some variables and set their types, but this was an easy task.

Complex instructions
; void __fastcall sub_2A38(list_t *ptr, unsigned int a2) sub_2A38 ; CODE XREF: sub_5C8+48p ; sub_648+5Cp … MOV R2, #0 STMFD SP!, {LR} MOV R3, R2 MOV R12, R2 MOV LR, R2 SUBS R1, R1, #0x20 loc_2A50 ; CODE XREF: sub_2A38+24j STMCSIA R0!, {R2,R3,R12,LR} STMCSIA R0!, {R2,R3,R12,LR} SUBCSS R1, R1, #0x20 BCS loc_2A50 MOVS R1, R1,LSL#28 STMCSIA R0!, {R2,R3,R12,LR} STMMIIA R0!, {R2,R3} LDMFD SP!, {LR} MOVS R1, R1,LSL#2 STRCS R2, [R0],#4 MOVEQ PC, LR STRMIH R2, [R0],#2 TST R1, #0x40000000 STRNEB R2, [R0],#1 RET ; End of function sub_2A38 void __fastcall sub_2A38(list_t *ptr, unsigned int a2) { char copybig; // cf@1 unsigned int size; // r1@1 list_t *v4; // r0@3 int remains; // r1@4 int final; // r1@8 copybig = a2 >= 0x20; size = a2 – 32; do { if ( !copybig ) break; ptr->dword0 = 0; ptr->dword4 = 0; ptr->dword8 = 0; ptr->dwordC = 0; v4 = ptr + 1; v4->dword0 = 0; v4->dword4 = 0; v4->dword8 = 0; v4->dwordC = 0; ptr = v4 + 1; copybig = size >= 0x20; size -= 32; } while ( copybig ); remains = size << 28; if ( copybig ) { ptr->dword0 = 0; ptr->dword4 = 0; ptr->dword8 = 0; ptr->dwordC = 0; ++ptr; } if ( remains < 0 ) { ptr->dword0 = 0; ptr->dword4 = 0; ptr = (list_t *)((char *)ptr + 8); } final = 4 * remains; if ( copybig ) { ptr->dword0 = 0; ptr = (list_t *)((char *)ptr + 4); } if ( final ) { if ( final < 0 ) { LOWORD(ptr->dword0) = 0; ptr = (list_t *)((char *)ptr + 2); } if ( final & 0x40000000 ) LOBYTE(ptr->dword0) = 0; } }
Conditional instructions are just part of the story. ARM is also famous for having a plethora of data movement instructions. They come with a set of possible suffixes that subtly change the meaning of the instruction. Take STMCSIA, for example. It is a STM instruction, but then you have to remember thatCS means “carry set” and IA means “increment after”. 

In short, the disassembly listing is like Chinese. The pseudocode is longer but requires much less time to understand.

Compiler helper functions
EXPORT op_two64 op_two64 ; CODE XREF: refer_all+31Cp ; main+78p anonymous_1 = -0x28 var_20 = -0x20 anonymous_0 = -0x18 var_10 = -0x10 arg_0 = 4 000 MOV R12, SP 000 STMFD SP!, {R4,R11,R12,LR,PC} 014 SUB R11, R12, #4 014 SUB SP, SP, #0x18 02C SUB R4, R11, #-var_10 02C STMDB R4, {R0,R1} 02C MOV R1, 0xFFFFFFF0 02C SUB R12, R11, #-var_10 02C ADD R1, R12, R1 02C STMIA R1, {R2,R3} 02C LDR R3, [R11,#arg_0] 02C CMP R3, #1 02C BNE loc_9C44 02C MOV R3, 0xFFFFFFF0 02C SUB R0, R11, #-var_10 02C ADD R3, R0, R3 02C SUB R4, R11, #-var_10 02C LDMDB R4, {R1,R2} 02C LDMIA R3, {R3,R4} 02C ADDS R3, R3, R1 02C ADC R4, R4, R2 02C SUB R12, R11, #-var_20 02C STMDB R12, {R3,R4} 02C B loc_9D04 ; ————————————————————————— loc_9C44 ; CODE XREF: op_two64+30j 02C LDR R3, [R11,#arg_0] 02C CMP R3, #2 02C BNE loc_9C7C 02C MOV R3, 0xFFFFFFF0 02C SUB R0, R11, #-var_10 02C ADD R3, R0, R3 02C SUB R4, R11, #-var_10 02C LDMDB R4, {R1,R2} 02C LDMIA R3, {R3,R4} 02C SUBS R3, R1, R3 02C SBC R4, R2, R4 02C SUB R12, R11, #-var_20 02C STMDB R12, {R3,R4} 02C B loc_9D04 ; ————————————————————————— loc_9C7C ; CODE XREF: op_two64+68j 02C LDR R3, [R11,#arg_0] 02C CMP R3, #3 02C BNE loc_9CB8 02C MOV R3, 0xFFFFFFF0 02C SUB R0, R11, #-var_10 02C ADD R3, R0, R3 02C SUB R2, R11, #-var_10 02C LDMDB R2, {R0,R1} 02C LDMIA R3, {R2,R3} 02C BL __muldi3 02C MOV R4, R1 02C MOV R3, R0 02C SUB R12, R11, #-var_20 02C STMDB R12, {R3,R4} 02C B loc_9D04 ; ————————————————————————— loc_9CB8 ; CODE XREF: op_two64+A0j 02C LDR R3, [R11,#arg_0] 02C CMP R3, #4 02C BNE loc_9CF4 02C MOV R3, 0xFFFFFFF0 02C SUB R0, R11, #-var_10 02C ADD R3, R0, R3 02C SUB R2, R11, #-var_10 02C LDMDB R2, {R0,R1} 02C LDMIA R3, {R2,R3} 02C BL __divdi3 02C MOV R4, R1 02C MOV R3, R0 02C SUB R12, R11, #-var_20 02C STMDB R12, {R3,R4} 02C B loc_9D04 ; ————————————————————————— loc_9CF4 ; CODE XREF: op_two64+DCj 02C MOV R3, 0xFFFFFFFF 02C MOV R2, 0xFFFFFFFF 02C SUB R4, R11, #-var_20 02C STMDB R4, {R2,R3} loc_9D04 ; CODE XREF: op_two64+5Cj ; op_two64+94j … 02C SUB R12, R11, #-var_20 02C LDMDB R12, {R0,R1} 02C SUB SP, R11, #0x10 014 LDMFD SP, {R4,R11,SP,PC} ; End of function op_two64 signed __int64 __fastcall op_two64(signed __int64 a1, signed __int64 a2, int a3) { signed __int64 v4; // [sp+0h] [bp-28h]@2 switch ( a3 ) { case 1: v4 = a2 + a1; break; case 2: v4 = a1 – a2; break; case 3: v4 = a1 * a2; break; case 4: v4 = a1 / a2; break; default: v4 = -1LL; break; } return v4; }
Sorry for another long code snippet. Just wanted to show you that the decompiler can handle compiler helper functions (like __divdi3) and handles 64-bit arithmetic quite well.

Immediate constants
loc_110D6 ; CODE XREF: sub_10E38+43Cj ; sub_10E38+442j … LDR R1, =(tmin_ptr – 0x1CDB8) LDR R2, =(tmax_ptr – 0x1CDB8) LDR R0, =(aRttMinAvgMaxMd – 0x1CDB8) LDR R6, [R7,R1] LDR R5, [R7,R2] MOVS R3, #0xFA LDR R4, [R6] LSLS R1, R3, #2 LDR R6, [R5] ADDS R5, R7, R0 ; “rtt min/avg/max/mdev = %ld.%03ld/%lu.%0″… MOVS R0, R4 BLX __aeabi_idiv MOV R8, R0 MOVS R0, R4 MOVS R4, #0xFA LSLS R1, R4, #2 BLX __aeabi_idivmod LDR R3, =0 LDR R2, =0x3E8 MOVS R4, R1 LDR R0, [SP,#0x78+var_40] LDR R1, [SP,#0x78+var_40+4] BLX __aeabi_ldivmod LDR R3, =0 LDR R2, =0x3E8 STR R0, [SP,#0x78+var_50] STR R1, [SP,#0x78+var_4C] LDR R0, [SP,#0x78+var_40] LDR R1, [SP,#0x78+var_40+4] BLX __aeabi_ldivmod MOVS R1, #0xFA MOVS R0, R6 LSLS R1, R1, #2 STR R2, [SP,#0x78+var_78] BLX __aeabi_idiv STR R0, [SP,#0x78+var_74] MOVS R0, R6 MOVS R6, #0xFA LSLS R1, R6, #2 BLX __aeabi_idivmod MOVS R2, #0xFA STR R1, [SP,#0x78+var_70] LDR R0, [SP,#0x78+var_38] LSLS R1, R2, #2 BLX __aeabi_idiv MOVS R3, #0xFA STR R0, [SP,#0x78+var_6C] LSLS R1, R3, #2 LDR R0, [SP,#0x78+var_38] BLX __aeabi_idivmod MOVS R0, R5 ; format STR R1, [SP,#0x78+var_68] MOVS R2, R4 MOV R1, R8 LDR R3, [SP,#0x78+var_50] BLX printf printf( “rtt min/avg/max/mdev = %ld.%03ld/%lu.%03ld/%ld.%03ld/%ld.%03ld ms”, tmin / 1000, tmin % 1000, v27 / 1000, v27 % 1000, tmax / 1000, tmax % 1000, v28 / 1000, v28 % 1000);
Since ARM instructions can not have big immediate constants, sometimes they are loaded with two isntructions. There are many 0xFA (250 decimal) constants in the disassembly listing, but all of them are shifted to the left by 2 before use. The decompiler saves you from these petty details. 

Also a side: the decompiler can handle ARM mode as well as Thumb mode instructions. It just does not care about the instruction encoding because it is already handled by IDA.

Position independent code
sub_65768 ; DATA XREF: .data:007E37A4o var_18 = -0x18 var_14 = -0x14 var_10 = -0x10 arg_0 = 0 PUSH {LR} LDR.W R12, =aResponsetype ; “responseType” SUB SP, SP, #0x14 ADR.W LR, loc_65774 loc_65774 ; DATA XREF: sub_65768+8o ADD R12, LR LDR.W LR, [SP,#0x18+arg_0] STR.W LR, [SP,#0x18+var_18] MOV.W LR, #0x10 STR.W LR, [SP,#0x18+var_14] LDR.W LR, =0xFFF0883C ADD R12, LR STR.W R12, [SP,#0x18+var_10] BL sub_65378 ADD SP, SP, #0x14 POP {PC} ; End of function sub_65768 int __fastcall sub_65768(int a1, int a2, int a3, int a4, int a5) { return sub_65378(a1, a2, a3, a4, a5, 16, (int)myarray); }
In some case the disassembly listing can be misleading, especially with PIC (position independent code). While the address of a constant string is loaded into R12, the code does not care about it. It is just how variable addresses are calculated in PIC-code (it is .got-someoffset). Such calculations are very frequent in shared objects and unfortunately IDA can not handle all of them. 

But the decompiler did a great job of tracing R12.

NOTE: these are just some selected examples that can be illustrated as side-by-side differences. There are lots of features that are not mentioned on this page – simply because there was nothing to compare them with. The ARM decompiler can handle variadic functions (and we added a special command to specify the number of call arguments if it is miscalculated), indirect calls (the user can control the call arguments), structures passed by value, user defined calling conventions, etc. As this is the first version, floating point calculations and fancy SIMD instructions are not supported but we will eventually added them.

Hex-Rays ARM Decompiler v1.0 is capable of handling real world compiler generated code.

mmap()—建立内存映射

相关函数:munmap, open

头文件:#include <unistd.h>      #include <sys/mman.h>

定义函数:void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offsize);

函数说明:
mmap()用来将某个文件内容映射到内存中, 对该内存区域的存取即是直接对该文件内容的读写.

1、参数start 指向欲对应的内存起始地址, 通常设为NULL, 代表让系统自动选定地址, 对应成功后该地址会返回.

2、参数length 代表将文件中多大的部分对应到内存.

3、参数 prot 代表映射区域的保护方式有下列组合
PROT_EXEC 映射区域可被执行
PROT_READ 映射区域可被读取
PROT_WRITE 映射区域可被写入
PROT_NONE 映射区域不能存取

4、参数 flags 会影响映射区域的各种特性
MAP_FIXED 如果参数 start 所指的地址无法成功建立映射时, 则放弃映射, 不对地址做修正.通常不鼓励用此旗标.
MAP_SHARED 对应射区域的写入数据会复制回文件内, 而且允许其他映射该文件的进程共享.
MAP_PRIVATE 对应射区域的写入操作会产生一个映射文件的复制, 即私人的”写入时复制” (copy
on write)对此区域作的任何修改都不会写回原来的文件内容.
MAP_ANONYMOUS 建立匿名映射. 此时会忽略参数fd, 不涉及文件, 而且映射区域无法和其他进程共享.
MAP_DENYWRITE 只允许对应射区域的写入操作, 其他对文件直接写入的操作将会被拒绝.
MAP_LOCKED 将映射区域锁定住, 这表示该区域不会被置换(swap).

在调用mmap()时必须要指定MAP_SHARED 或MAP_PRIVATE.

5、参数fd 为open()返回的文件描述词,代表欲映射到内存的文件.

6、参数offset为文件映射的偏移量, 通常设置为0, 代表从文件最前方开始对应, offset必须是分页大小的整数倍.

返回值:若映射成功则返回映射区的内存起始地址, 否则返回MAP_FAILED(-1), 错误原因存于errno 中.

错误代码:
EBADF 参数fd 不是有效的文件描述词
EACCES 存取权限有误. 如果是MAP_PRIVATE 情况下文件必须可读, 使用MAP_SHARED 则要有
PROT_WRITE 以及该文件要能写入.
EINVAL 参数start、length 或offset 有一个不合法.
EAGAIN 文件被锁住, 或是有太多内存被锁住.
ENOMEM 内存不足.

范例
/* 利用mmap()来读取/etc/passwd 文件内容 */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
main()
{
int fd;
void *start;
struct stat sb;
fd = open(“/etc/passwd”, O_RDONLY); //打开/etc/passwd
fstat(fd, &sb); //取得文件大小
start = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if(start == MAP_FAILED) //判断是否映射成功
return;
printf(“%s”, start); munma(start, sb.st_size); //解除映射
closed(fd);
}

执行结果:
root : x : 0 : root : /root : /bin/bash
bin : x : 1 : 1 : bin : /bin :
daemon : x : 2 : 2 :daemon : /sbin
adm : x : 3 : 4 : adm : /var/adm :
lp : x :4 :7 : lp : /var/spool/lpd :
sync : x : 5 : 0 : sync : /sbin : bin/sync :
shutdown : x : 6 : 0 : shutdown : /sbin : /sbin/shutdown
halt : x : 7 : 0 : halt : /sbin : /sbin/halt
mail : x : 8 : 12 : mail : /var/spool/mail :
news : x :9 :13 : news : /var/spool/news :
uucp : x :10 :14 : uucp : /var/spool/uucp :
operator : x : 11 : 0 :operator : /root:
games : x : 12 :100 : games :/usr/games:
gopher : x : 13 : 30 : gopher : /usr/lib/gopher-data:
ftp : x : 14 : 50 : FTP User : /home/ftp:
nobody : x :99: 99: Nobody : /:
xfs 😡 :100 :101 : X Font Server : /etc/xll/fs : /bin/false
gdm : x : 42 :42 : : /home/gdm: /bin/bash
kids : x : 500 :500 :/home/kids : /bin/bash

stat()—获取文件状态

相关函数:fstat, lstat, chmod, chown, readlink, utime

头文件:#include <sys/stat.h>   #include <unistd.h>

定义函数:int stat(const char * file_name, struct stat *buf);

函数说明:stat()用来将参数file_name 所指的文件状态, 复制到参数buf 所指的结构中。

下面是struct stat 内各参数的说明:
struct stat
{
dev_t st_dev; //device 文件的设备编号
ino_t st_ino; //inode 文件的i-node
mode_t st_mode; //protection 文件的类型和存取的权限
nlink_t st_nlink; //number of hard links 连到该文件的硬连接数目, 刚建立的文件值为1.
uid_t st_uid; //user ID of owner 文件所有者的用户识别码
gid_t st_gid; //group ID of owner 文件所有者的组识别码
dev_t st_rdev; //device type 若此文件为装置设备文件, 则为其设备编号
off_t st_size; //total size, in bytes 文件大小, 以字节计算
unsigned long st_blksize; //blocksize for filesystem I/O 文件系统的I/O 缓冲区大小.
unsigned long st_blocks; //number of blocks allocated 占用文件区块的个数, 每一区块大小为512 个字节.
time_t st_atime; //time of lastaccess 文件最近一次被存取或被执行的时间, 一般只有在用mknod、utime、read、write 与tructate 时改变.
time_t st_mtime; //time of last modification 文件最后一次被修改的时间, 一般只有在用mknod、utime 和write 时才会改变
time_t st_ctime; //time of last change i-node 最近一次被更改的时间, 此参数会在文件所有者、组、权限被更改时更新
};

先前所描述的st_mode 则定义了下列数种情况:
1、S_IFMT 0170000 文件类型的位遮罩
2、S_IFSOCK 0140000 scoket
3、S_IFLNK 0120000 符号连接
4、S_IFREG 0100000 一般文件
5、S_IFBLK 0060000 区块装置
6、S_IFDIR 0040000 目录
7、S_IFCHR 0020000 字符装置
8、S_IFIFO 0010000 先进先出
9、S_ISUID 04000 文件的 (set user-id on execution)位
10、S_ISGID 02000 文件的 (set group-id on execution)位
11、S_ISVTX 01000 文件的sticky 位
12、S_IRUSR (S_IREAD) 00400 文件所有者具可读取权限
13、S_IWUSR (S_IWRITE)00200 文件所有者具可写入权限
14、S_IXUSR (S_IEXEC) 00100 文件所有者具可执行权限
15、S_IRGRP 00040 用户组具可读取权限
16、S_IWGRP 00020 用户组具可写入权限
17、S_IXGRP 00010 用户组具可执行权限
18、S_IROTH 00004 其他用户具可读取权限
19、S_IWOTH 00002 其他用户具可写入权限
20、S_IXOTH 00001 其他用户具可执行权限上述的文件类型在 POSIX 中定义了检查这些类型的宏定义
21、S_ISLNK (st_mode) 判断是否为符号连接
22、S_ISREG (st_mode) 是否为一般文件
23、S_ISDIR (st_mode) 是否为目录
24、S_ISCHR (st_mode) 是否为字符装置文件
25、S_ISBLK (s3e) 是否为先进先出
26、S_ISSOCK (st_mode) 是否为socket 若一目录具有sticky 位 (S_ISVTX), 则表示在此目录下的文件只能被该文件所有者、此目录所有者或root 来删除或改名.

返回值:执行成功则返回0,失败返回-1,错误代码存于errno。

错误代码:
1、ENOENT 参数file_name 指定的文件不存在
2、ENOTDIR 路径中的目录存在但却非真正的目录
3、ELOOP 欲打开的文件有过多符号连接问题, 上限为16 符号连接
4、EFAULT 参数buf 为无效指针, 指向无法存在的内存空间
5、EACCESS 存取文件时被拒绝
6、ENOMEM 核心内存不足
7、ENAMETOOLONG 参数file_name 的路径名称太长

范例
#include <sys/stat.h>
#include <unistd.h>
main()
{
struct stat buf;
stat(“/etc/passwd”, &buf);
printf(“/etc/passwd file size = %d \n”, buf.st_size);
}

执行:
/etc/passwd file size = 705

[Google Android] GCM: Getting Started

GCM:

重要: 会存在一个叫做

GCMIntentService的类. 在该类中的onRegistered, onUnRegistered, onMessage, onError 以及 onRecoverableError 都是回调入口函数. 

[ 并且在MainActivity中,存在注册GCM的代码. 在Manifest文件中会注册一些Service以及一些权限 ] 

GCM相关的android病毒行为描述看这里: http://www.securelist.com/en/blog/8113/GCM_in_malicious_attachments

 

GCM简介文章链接看下面:

原始文章:http://www.cnblogs.com/tamer/archive/2012/06/28/2568739.html

 

GCM:入门

此文描述了如何使用GCM提供的辅助库(客户端服务器)来编写一个Android应用程序和服务器端的逻辑。

创建一个谷歌API项目


要创建一个谷歌API项目:

  1. 打开谷歌API的控制台页面
  2. 如果你还没有创建一个API项目,这个页面会提示你这样做:

    注:如果您已经有项目,你看到的第一页将是仪表板页面。从那里你可以通过打开项目的下拉菜单(左上角),并选择Other>Create一个新的项目。

  3. 点击创建项目。你的浏览器URL将会改成这样的:
    https://code.google.com/apis/console/#project:4815162342
  4. 注意#project:后面的值:(示例中的4815162342)。这是你的项目ID,并且后面会用作GCM发件人的ID。

启用GCM服务


为了启用GCM服务:

  1. 在谷歌API的控制页面的主页中,选择服务
  2. 切换Google Cloud Messaging按钮的状态为ON。
  3. 在服务条款页面中接受这些条款。

获取一个API密钥


为了获取一个API密钥:

  1. 在谷歌API控制台主页面中,选择API Access。你将会看到一个类似于以下内容的页面:
  

2.  点击Create new Server key。会出现以下页面:

  

3.  点击 Create:

  

请注意在这个示例中API key 的值(YourKeyWillBeShownHere),它稍后会被用到。

注:如果你想换掉这个密钥,请点击Generate new key。一个新的密钥就会创建,而之前的密钥在未来24内仍然有效。如果你想让之前的密钥立即失效(例如:你认为它已经被破解了),请点击Delete key

安装辅助库


在执行下面章节描述的步骤之前,请确保已经安装好辅助库(参考:客户端服务器)。打开Android SDK Manager,安装Extras > Google Cloud Messaging for Android Library。这会在YOUR_SDK_ROOT/extras/google/目录下创建一个gcm文件夹,gcm文件夹下包含:gcm-client,gcm-demo-appenginegcm-demo-clientgcm-demo-server, and gcm-server子目录。

注:SDK Manager版本要求r20以上,之前的版本发现不了GCM库。所以先打开eclipse升级ADT。

开始编写Android程序


此章节描述了用GCM编写Android程序的步骤。

步骤 1:拷贝gcm.jar到程序的classpath目录下

在编写程序之前,请先拷贝SDK目录下gcm-client/dist目录下的gcm.jar文件到程序的classpath。

步骤 2:按照以下步骤更改项目的AndroidManifest.xml文件

1.  GCM需要Android2.2或更高版本,所以如果你的程序不依赖GCM就无法正常工作,那么请在AndroidManifest文件中添加以下内容,“xx”处替换为最新的目标SDK版本号:

<uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="xx"/>

2.  声明并使用一个自定义的权限以此来确保只有这个程序可以接收你的GCM消息:

<permissionandroid:name="my_app_package.permission.C2D_MESSAGE"android:protectionLevel="signature"/><uses-permissionandroid:name="my_app_package.permission.C2D_MESSAGE"/>

这个权限必须称作:my_app_package.permission.C2D_MESSAG(程序包名.permission.C2D_MESSAG,程序包名就是在manifest文件中定义包名),不然将不能正常运行。

注:如果你的程序针对的是4.1或更高版本的系统(即,minSdkVersion 16),那么就不需要这个权限。

3.  添加权限接收GCM消息:

<uses-permissionandroid:name="com.google.android.c2dm.permission.RECEIVE"/>

4.  添加以下广播接收器:

复制代码
<receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
        <action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
        <category android:name="my_app_package"/>
    </intent-filter>
</receiver>
复制代码

这个Broadcast receiver负责处理2个从GCM发来的Intent(com.google.android.c2dm.intent.RECEIVE和com.google.android.c2dm.intent.REGISTRATION),并且要在manifest文件中定义(而非通过编码实现)。因此,这些Intent甚至可以在程序未运行的情况下被接收到。通过设置com.google.android.c2dm.permission.SEND权限,可以确保这些Intent只能通过GCM系统框架发送到这个receiver(普通程序是没有权限发出这些Intent的)。

注意在category标签里的android:name必须替换成你程序的包名(如果程序是针对16或更高的minSdkVersion的平台那么就不需要有category这个标签了)。

5.  添加以下Intent服务:

<service android:name=".GCMIntentService"/>

在下一步中,这个Intent服务会被GCMBroadcastReceiver(由GCM库提供)调用。它必须称作my_app_package.GCMIntentService,除非你用重写了GCMBroadcastRecevier方法的子类来作为此服务的名字。

步骤 3:实现my_app_package.GCMIntentService类

下面来实现my_app_package.GCMIntentService类,重写下面的几个回调方法(这些方法会被GCMBroadcastReceiver调用):

  • onRegistered(Context context, String regId): 收到注册Intent后此方法会被调用,GCM分配的注册ID会做为参数传递到设备/应用程序对。通常,你应该发送regid到你的服务器,这样服务器就可以根据这个regid发消息到设备上。
  • onUnregistered(Context context, String regId): 当设备从GCM注销时会被调用。通常你应该发送regid到服务器,这样就可以注销这个设备了。
  • onMessage(Context context, Intent intent): 当你的服务器发送了一个消息到GCM后会被调用,并且GCM会把这个消息传送到相应的设备。如果这个消息包含有效负载数据,它们的内容会作为Intent的extras被传送。
  • onError(Context context, String errorId): 当设备试图注册或注销时,但是GCM返回错误时此方法会被调用。通常此方法就是分析错误并修复问题而不会做别的事情。
  • onRecoverableError(Context context, String errorId): 当设备试图注册或注销时,但是GCM服务器无效时。GCM库会使用应急方案重试操作,除非这个方式被重写并返回false。这个方法是可选的并且只有当你想显示信息给用户或想取消重试操作的时候才会被重写。

注: 上面的方法运行在Intent服务的线程里,因此可以自由访问网络而不会阻塞UI线程。

步骤 4:实现你程序的主Activity

在你程序的主activity里添加下面的导入语句:

import com.google.android.gcm.GCMRegistrar;

在onCreate()方法里添加下面的代码:

GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
final String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals("")) {
  GCMRegistrar.register(this, SENDER_ID);
} else {
  Log.v(TAG, "Already registered");
}

checkDevice()方法用来验证设备是否支持GCM,如果不支持会抛出异常(例如,模拟器就不包含Google APIs)。相似地,checkManifest()方法来验证程序的manifest包含了在开始编写Android程序中所有符合要求的描述(这个方法只有你在开发程序的时候需要;一旦这个程序准备发布的时候,你就可以把它移除掉)。

一旦这些健康检查做完了,就可以调用GCMRegsistrar.register()通过传送注册GCM时得到的SENDER_ID来注册设备了。但是由于GCMRegistrar单例保持跟踪所有收到的注册Intent的注册ID,所以可以先调用GCMRegistrar.getRegistrationId()方法检查此设备是否已经注册。

注:可能设备已经成功注册到GCM,但是没有成功发送注册ID到你的服务器,这种情况你应当重试。请查看高级主题来了解处理这种情况的更多详情。

编写服务端程序


编写服务器程序请做如下准备:

  1. 拷贝SDK的gcm-server/dist目录下的gcm-server.jar到你服务器的classpath。
  2. 创建一个servlet(或其它服务器端机制),被Android程序用来发送从GCM收到的注册ID。Android程序可能也要发送一些其它的信息,例如用户的email地址或用户名,这样服务器就可以对注册ID和用户设备进行关联。
  3. 相似地,创建一个servlet用来注销注册ID。
  4. 当服务器需要发送一条消息到设备时,可以使用GCM库中的com.google.android.gcm.server.Sender辅助类。例如:
import com.google.android.gcm.server.*;
Sender sender = new Sender(myApiKey);
Message message = new Message.Builder().build();
MulticastResult result = sender.send(message, devices, 5);

上面的代码段实现了如下工作:

  • 用你项目的API key创建一个Sender对象。
  • 用获得的注册ID来创建一个消息(消息的构建者也要有方法来设置全部的消息参数,例如collapse key和有效负载数据)。
  • 发送这个消息(如果GCM服务器无效的话,有5次重发机会),并保存响应给result。

现在就需要解析响应结果并对如下情况采取适当的措施:

  • 如果消息被创建了,但是结果返回了一个被认可的注册ID,那么需要用这个认可的ID替换当前的注册ID。
  • 如果返回的错误是NotRegistered,那么需要移除这个注册ID,因为那个设备没有安装此程序。

这有一个代码段来处理这两种情况:

if (result.getMessageId() != null) {
 String canonicalRegId = result.getCanonicalRegistrationId();
 if (canonicalRegId != null) {
   // same device has more than on registration ID: update database
 }
} else {
 String error = result.getErrorCodeName();
 if (error.equals(Constants.ERROR_NOT_REGISTERED)) {
   // application has been removed from device - unregister database
 }
}

Android Notification flags

 

public static final int FLAG_SHOW_LIGHTS = 1;               置位第1位
public static final int FLAG_ONGOING_EVENT = 2;             置位第2位 (正在下载中,等等)
public static final int FLAG_INSISTENT = 4;                            置位第3位
public static final int FLAG_ONLY_ALERT_ONCE = 8;              置位第4位
public static final int FLAG_AUTO_CANCEL = 16;                   置位第5位
public static final int FLAG_NO_CLEAR = 32;                       置位第6位 (不可清除广告,不可清除通知等等)
public static final int FLAG_FOREGROUND_SERVICE = 64;     置位第7位

@Deprecated
public static final int FLAG_HIGH_PRIORITY = 128;                置位第8位