標籤:
/******************************************************************** * Android development tools line_endings hacking * 說明: * 本文主要是對android原始碼中的line_endings開發工具進行瞭解讀, * 目的是為了知道傳說中的額dos,unix檔案之間轉換的工作機制。 * * 2016-5-3 深圳 南山平山村 曾劍鋒 *******************************************************************/#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/stat.h>#define BUFSIZE (1024*8)static void to_unix(char* buf);static void unix_to_dos(char* buf2, const char* buf);// 使用方法int usage(){ fprintf(stderr, "usage: line_endings unix|dos FILES\n" "\n" "Convert FILES to either unix or dos line endings.\n"); return 1;}// 定義Node資料結構typedef struct Node { struct Node *next; char buf[BUFSIZE*2+3];} Node;intmain(int argc, char** argv){ // 枚舉UNIX,DOS兩種資料 enum { UNIX, DOS } ending; int i; // 參數個數判斷 if (argc < 2) { return usage(); } // 參數比較 if (0 == strcmp("unix", argv[1])) { ending = UNIX; } else if (0 == strcmp("dos", argv[1])) { ending = DOS; } else { return usage(); } // 命令列傳入的參數可能有多個,利用for迴圈進行輪流轉換。 for (i=2; i<argc; i++) { int fd; int len; // force implied chmod(argv[i], S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); // 開啟檔案 fd = open(argv[i], O_RDWR); if (fd < 0) { fprintf(stderr, "unable to open file for read/write: %s\n", argv[i]); return 1; } // 擷取檔案大小 len = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); // 檔案長度正常才有必要進行轉換 if (len > 0) { // 建立根節點 Node* root = malloc(sizeof(Node)); Node* node = root; node->buf[0] = 0; // root節點的buf資料位元0 while (len > 0) { // 建立節點,並出示節點 node->next = malloc(sizeof(Node)); node = node->next; node->next = NULL; // 這裡還是沒搞太懂為什麼要+2,後面有‘\0‘,那隻需要+1就行了,為什麼 // 還要+2,沒搞懂。 char buf[BUFSIZE+2]; ssize_t amt; ssize_t amt2 = len < BUFSIZE ? len : BUFSIZE; amt = read(fd, buf, amt2); if (amt != amt2) { fprintf(stderr, "unable to read file: %s\n", argv[i]); return 1; } buf[amt2] = ‘\0‘; // 字串結尾 // 先轉成unix文檔 to_unix(buf); if (ending == UNIX) { strcpy(node->buf, buf); } else { // 這裡BUFSIZE*2的主要原因應該是怕所有的都是分行符號,這樣轉換出來 // 就是*2了,但是沒搞懂為什麼要+3,個人感覺最多有個+1就行了。 char buf2[(BUFSIZE*2)+3]; unix_to_dos(buf2, buf); strcpy(node->buf, buf2); } len -= amt2; } // 將檔案長度修改為0,並重新從檔案頭開始 ftruncate(fd, 0); lseek(fd, 0, SEEK_SET); // 迴圈將鏈表中的內容寫入檔案,並釋放鏈表中的內容 while (root) { ssize_t amt2 = strlen(root->buf); if (amt2 > 0) { ssize_t amt = write(fd, root->buf, amt2); if (amt != amt2) { fprintf(stderr, "unable to write file: %s\n", argv[i]); return 1; } } node = root; root = root->next; free(node); } } close(fd); } return 0;}// 這裡相當於是字元的的不斷的拷貝voidto_unix(char* buf){ char* p = buf; char* q = buf; while (*p) { if (p[0] == ‘\r‘ && p[1] == ‘\n‘) { // dos *q = ‘\n‘; p += 2; q += 1; } else if (p[0] == ‘\r‘) { // old mac *q = ‘\n‘; p += 1; q += 1; } else { *q = *p; p += 1; q += 1; } } *q = ‘\0‘;}// 這裡和to_unix的動作正好相反voidunix_to_dos(char* buf2, const char* buf){ const char* p = buf; char* q = buf2; while (*p) { if (*p == ‘\n‘) { q[0] = ‘\r‘; q[1] = ‘\n‘; q += 2; p += 1; } else { *q = *p; p += 1; q += 1; } } *q = ‘\0‘;}
Android development tools line_endings hacking