分享

Linux/Unix 编程中 POSIX 函数的线程安全问题

 lycbje 2014-01-27
				
 /* thread-safe version of basename() */ 
 char* basename_ta(char *path, char *buf, int buflen) { 

    #define DEFAULT_RESULT_DOT     "."
    #define DEFAULT_RESULT_SLASH   "/"

    /* 如果输入的路径长度小于 PATH_MAX,
     * 则使用自动变量 i_fixed_bufer 作为内部缓冲区 , 
     * 否则申请堆内存做为字符串存放缓冲区。
     */ 

    char i_fixed_buf[PATH_MAX+1]; 
    const int i_fixed_buf_len = sizeof(i_fixed_buf)/sizeof(char); 

    char *result = buf; 
    char *i_buf = NULL; 
    int i_buf_len = 0; 

    int adjusted_path_len = 0; 
    int path_len = 0; 

    int i, j; 
    char tmp = 0; 

    if (path == NULL) { 
        /* 如果输入为空指针,则直接返回当前目录 */ 
        path = DEFAULT_RESULT_DOT; 
    } 

    /* 分配内部缓冲区用来存放输入字符串 */ 
    path_len = strlen(path); 
    if ((path_len + 1) > i_fixed_buf_len) { 
        i_buf_len = (path_len + 1); 
        i_buf = (char*) malloc(i_buf_len * sizeof(char)); 
    } else { 
        i_buf_len = i_fixed_buf_len; 
        i_buf = i_fixed_buf; 
    } 

    /* 拷贝字符串到缓冲区,以便接下来对字符串做预处理 */ 
    strcpy(i_buf, path); 
    adjusted_path_len = path_len; 

    /* 预处理:删除路径未的路径符号 '/'; */ 
    if (adjusted_path_len > 1) { 
        while (i_buf[adjusted_path_len-1] == '/') { 
            if (adjusted_path_len != 1) { 
                adjusted_path_len--; 
            } else { 
                break; 
            } 
        } 
        i_buf[adjusted_path_len] = '\0'; 
    } 

    /* 预处理:折叠最后出现的连续 '/'; */ 
    if (adjusted_path_len > 1) { 

        for (i = (adjusted_path_len -1), j = 0; i >= 0; i--) { 
            if (j == 0) { 
                if (i_buf[i] == '/') 
                    j = i; 
            } else { 
                if (i_buf[i] != '/') { 
                    i++; 
                    break; 
                } 
            } 
        } 

        if (j != 0 && i < j) { 
            /* 折叠多余的路径符号 '/'; 
             */ 
            strcpy(i_buf+i, i_buf+j); 
        } 

        adjusted_path_len -= (j - i); 
    } 

    /* 预处理:寻找最后一个路径符号 '/' */ 
    for (i = 0, j = -1; i < adjusted_path_len; i++) { 
        if (i_buf[i] == '/') 
            j = i; 
    } 

    /* 查找 basename */ 
    if (j >= 0) { 

        /* found one '/' */ 
        if (adjusted_path_len == 1) {  /* 输入的是跟路径 ("/"),则返回根路径 */ 
            if (2 > buflen) { 
                return NULL; 
            } else { 
                strcpy(result, DEFAULT_RESULT_SLASH); 
            } 
        } else { 
            if ((adjusted_path_len - j) > buflen) {  /* 缓冲区不够,返回空指针 */ 
                result = NULL; 
            } else { 
                strcpy(result, (i_buf+j+1)); 
            } 
        } 

    } else { 

        /* no '/' found  */ 
        if (adjusted_path_len == 0) { 
            if (2 > buflen) {              /* 如果传入的参数为空字符串 ("") */ 
                return NULL;                /* 直接返回当前目录 (".")  */ 
            } else { 
                strcpy(result, DEFAULT_RESULT_DOT); 
            } 
        } else { 
            if ((adjusted_path_len+1) > buflen) {      
                result = NULL;             /* 缓冲区不够,返回空指针    */ 
            } else { 
                strcpy(result, i_buf);   /* 拷贝整个字符串做为返回值   */ 
            } 
        } 
    } 

    if (i_buf_len != i_fixed_buf_len) {   /* 释放缓冲区         */ 
        free(i_buf); 
        i_buf = NULL; 
    } 

    return result; 
 } 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多