/* 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; } |
|