Android development tools line_endings hacking

/********************************************************************
 *       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
"
            "
"
            "Convert FILES to either unix or dos line endings.
");
    return 1;
}

// 定义Node数据结构
typedef struct Node {
    struct Node *next;
    char buf[BUFSIZE*2+3];
} Node;

int
main(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
", 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,后面有'',那只需要+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
", argv[i]);
                    return 1;
                }
                buf[amt2] = '';   // 字符串结尾
                // 先转成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
", argv[i]);
                        return 1;
                    }
                }
                node = root;
                root = root->next;
                free(node);
            }
        }
        close(fd);
    }
    return 0;
}

// 这里相当于是字符的的不断的拷贝
void
to_unix(char* buf)
{
    char* p = buf;
    char* q = buf;
    while (*p) {
        if (p[0] == '
' && p[1] == '
') {
            // dos
            *q = '
';
            p += 2;
            q += 1;
        }
        else if (p[0] == '
') {
            // old mac
            *q = '
';
            p += 1;
            q += 1;
        }
        else {
            *q = *p;
            p += 1;
            q += 1;
        }
    }
    *q = '';
}

// 这里和to_unix的动作正好相反
void
unix_to_dos(char* buf2, const char* buf)
{
    const char* p = buf;
    char* q = buf2;
    while (*p) {
        if (*p == '
') {
            q[0] = '
';
            q[1] = '
';
            q += 2;
            p += 1;
        } else {
            *q = *p;
            p += 1;
            q += 1;
        }
    }
    *q = '';
}
原文地址:https://www.cnblogs.com/zengjfgit/p/5453959.html