bool w_is_path_absolute_cstr_len(const char *path, uint32_t len) { #ifdef _WIN32 char drive_letter; if (len <= 2) { return false; } // "\something" if (is_slash(path[0])) { // "\\something" is absolute, "\something" is relative to the current // dir of the current drive, whatever that may be, for a given process return is_slash(path[1]); } drive_letter = (char)tolower(path[0]); // "C:something" if (drive_letter >= 'a' && drive_letter <= 'z' && path[1] == ':') { // "C:\something" is absolute, but "C:something" is relative to // the current dir on the C drive(!) return is_slash(path[2]); } // we could check for things like NUL:, COM: and so on here. // While those are technically absolute names, we can't watch them, so // we don't consider them absolute for the purposes of checking whether // the path is a valid watchable root return false; #else return len > 0 && path[0] == '/'; #endif }
char * tr_sys_path_basename (const char * path, tr_error ** error) { if (path == NULL || path[0] == '\0') return tr_strdup ("."); if (!is_valid_path (path)) { set_system_error (error, ERROR_PATH_NOT_FOUND); return NULL; } const char * end = path + strlen (path); while (end > path && is_slash (*(end - 1))) --end; if (end == path) return tr_strdup ("/"); const char * name = end; while (name > path && *(name - 1) != ':' && !is_slash (*(name - 1))) --name; if (name == end) return tr_strdup ("/"); return tr_strndup (name, end - name); }
char* tr_sys_path_dirname(char const* path, tr_error** error) { if (path == NULL || path[0] == '\0') { return tr_strdup("."); } if (!is_valid_path(path)) { set_system_error(error, ERROR_PATH_NOT_FOUND); return NULL; } bool const is_unc = is_unc_path(path); if (is_unc && path[2] == '\0') { return tr_strdup(path); } char const* end = path + strlen(path); while (end > path && is_slash(*(end - 1))) { --end; } if (end == path) { return tr_strdup("/"); } char const* name = end; while (name > path && *(name - 1) != ':' && !is_slash(*(name - 1))) { --name; } while (name > path && is_slash(*(name - 1))) { --name; } if (name == path) { return tr_strdup(is_unc ? "\\\\" : "."); } if (name > path && *(name - 1) == ':' && *name != '\0' && !is_slash(*name)) { return tr_strdup_printf("%c:.", path[0]); } return tr_strndup(path, name - path); }
static int16_t final_slash_l(cell *c) { int16_t i; uchar fnt; get_b_lines(c,&bl); if (c->row+c->h>=bl.b3+MIN(3,MAX(1,c->h/10))) return 0; if ((c->flg & (c_f_let|c_f_bad)) == 0) return 0; // AL 940318 if (c->flg & c_f_dust) return 0; // AL 940318 if ((fnt=c->prevl->font|c->nextl->font)&c_fp_ser && !(fnt&c_fp_gelv)) return 0; c->nvers-=MAX(0,c->nvers-(VERS_IN_CELL-4)); c->vers[c->nvers].let='l'; c->vers[c->nvers+1].let='I'; c->vers[c->nvers+2].let='1'; c->vers[c->nvers].prob=c->vers[c->nvers+1].prob=c->vers[c->nvers+2].prob= c->vers[0].prob; for (i=0; i<c->nvers; i++) if (memchr("lI1",c->vers[i].let,3)) c->vers[i].prob=0; c->nvers+=3; c->vers[c->nvers].let=0; if (c->env!=NULL && !is_slash(c)) c->vers[0].prob=MAX(2,c->vers[0].prob-50); sort_vers(c); return 1; }
UInt32 Archive::find_dir(const wstring& path) { if (file_list.empty()) make_index(); ArcFileInfo dir_info; dir_info.is_dir = true; dir_info.parent = c_root_index; size_t begin_pos = 0; while (begin_pos < path.size()) { size_t end_pos = begin_pos; while (end_pos < path.size() && !is_slash(path[end_pos])) end_pos++; if (end_pos != begin_pos) { dir_info.name.assign(path.data() + begin_pos, end_pos - begin_pos); FileIndexRange fi_range = equal_range(file_list_index.begin(), file_list_index.end(), -1, [&] (UInt32 left, UInt32 right) -> bool { const ArcFileInfo& fi_left = left == -1 ? dir_info : file_list[left]; const ArcFileInfo& fi_right = right == -1 ? dir_info : file_list[right]; return fi_left < fi_right; }); if (fi_range.first == fi_range.second) FAIL(HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)); dir_info.parent = *fi_range.first; } begin_pos = end_pos + 1; } return dir_info.parent; }
w_string_piece w_string_piece::dirName() const { for (auto end = e_; end >= s_; --end) { if (is_slash(*end)) { /* found the end of the parent dir */ return w_string_piece(s_, end - s_); } } return nullptr; }
// Compute the basename of path, return that as a string w_string_t *w_string_new_basename_typed(const char *path, w_string_type_t type) { const char *base; base = path + strlen(path); while (base > path && !is_slash(base[-1])) { base--; } return w_string_new_typed(base, type); }
w_string_piece w_string_piece::baseName() const { for (auto end = e_; end >= s_; --end) { if (is_slash(*end)) { /* found the end of the parent dir */ return w_string_piece(end + 1, e_ - (end + 1)); } } return *this; }
w_string_t *w_string_canon_path(w_string_t *str) { int end; int trim = 0; for (end = str->len - 1; end >= 0 && is_slash(str->buf[end]); end--) { trim++; } if (trim) { return w_string_slice(str, 0, str->len - trim); } w_string_addref(str); return str; }
w_string_t *w_string_dirname(w_string_t *str) { int end; /* can't use libc strXXX functions because we may be operating * on a slice */ for (end = str->len - 1; end >= 0; end--) { if (is_slash(str->buf[end])) { /* found the end of the parent dir */ return w_string_slice(str, 0, end); } } return NULL; }
bool tr_sys_path_is_relative (const char * path) { assert (path != NULL); /* UNC path: `\\...`. */ if (is_unc_path (path)) return false; /* Local path: `X:` or `X:\...`. */ if (isalpha (path[0]) && path[1] == ':' && (path[2] == '\0' || is_slash (path[2]))) return false; return true; }
w_string_t *w_string_basename(w_string_t *str) { int end; /* can't use libc strXXX functions because we may be operating * on a slice */ for (end = str->len - 1; end >= 0; end--) { if (is_slash(str->buf[end])) { /* found the end of the parent dir */ return w_string_slice(str, end + 1, str->len - (end + 1)); } } w_string_addref(str); return str; }
bool tr_sys_path_is_relative(char const* path) { TR_ASSERT(path != NULL); /* UNC path: `\\...`. */ if (is_unc_path(path)) { return false; } /* Local path: `X:` or `X:\...`. */ if (isalpha(path[0]) && path[1] == ':' && (path[2] == '\0' || is_slash(path[2]))) { return false; } return true; }
void fix_slashes(char * in,char * out) { int slash_count; for(slash_count=1;in && out && *in;in++) { if(is_slash(*in)) { slash_count++; continue; } else { if(slash_count) { slash_count=0; *out++='/'; } *out++=*in; } } *out='\0'; }
// Return the normalized (lowercase) filename suffix w_string_t *w_string_suffix(w_string_t *str) { int end; char name_buf[128]; char *buf; /* can't use libc strXXX functions because we may be operating * on a slice */ for (end = str->len - 1; end >= 0; end--) { if (str->buf[end] == '.') { if (str->len - end > sizeof(name_buf)) { // Too long return NULL; } buf = name_buf; end++; while ((unsigned)end < str->len) { *buf = (char)tolower((uint8_t)str->buf[end]); end++; buf++; } *buf = '\0'; return w_string_new_typed(name_buf, str->type); } else if (str->len - end >= sizeof(name_buf)) { // We haven't found the '.' yet but the suffix will never fit in our local // buffer return nullptr; } if (is_slash(str->buf[end])) { // No suffix return NULL; } } // Has no suffix return NULL; }
static const char * relocate_path(const char *dir, const char *s) { SB sb; const char *r; const char *execdir = LUA_EXECDIR; int lexecdir = strlen(execdir); int ldir = strlen(dir); sbinit(&sb); while ((r = strstr(s, execdir))) { sbaddn(&sb, s, r-s); sbaddn(&sb, dir, ldir); s = r + lexecdir; while (is_slash(s[0])) { if (is_dot(s[1]) && is_slash(s[2])) { s += 2; continue; } if (is_dot(s[1]) && is_dot(s[2]) && is_slash(s[3]) ) { s += 3; while (sb.buffer && sb.len>0 && is_slash(sb.buffer[sb.len-1])) sb.len -= 1; while (sb.buffer && sb.len>0 && !is_slash(sb.buffer[sb.len-1])) sb.len -= 1; while (sb.buffer && sb.len>0 && is_slash(sb.buffer[sb.len-1])) sb.len -= 1; continue; } break; } } sbaddn(&sb, s, strlen(s)); sbadd1(&sb, 0); #ifdef LUA_WIN r = _strdup(sb.buffer); #else r = strdup(sb.buffer); #endif sbfree(&sb); return r; }
static int16_t final_no_slash(cell *c) { int16_t i; uchar fnt; if (c->env==NULL) return 0; for (i=1; i<c->nvers; i++) if (c->vers[i].let=='/') break; if (i==c->nvers) return 0; if ((fnt=c->prevl->font|c->nextl->font)&c_fp_ser && !(fnt&c_fp_gelv) && !(c->font&c_fp_ser)) { c->vers[i].let=c->vers[0].let; c->vers[0].let='/'; return 1; } if (is_slash(c)) return 0; c->vers[i].prob=0; sort_vers(c); return 1; }
DMZ_INTERNAL void find_character_groups_for_stripe(IplImage *card_y, IplImage *sobel_image, int stripe_base_row, long stripe_sum, GroupedRectsList &expiry_groups, GroupedRectsList &name_groups) { #if DEBUG_EXPIRY_SEGMENTATION_PERFORMANCE dmz_debug_timer_start(1); #endif // "Expanded" stripe is kSmallCharacterHeight + 2 scan lines in height ("expanded" refers to the "+ 2" -- one extra scan line above and below the input stripe) CvSize card_image_size = cvGetSize(sobel_image); int expanded_stripe_top = stripe_base_row - 1; CvRect expanded_stripe_rect = cvRect(0, expanded_stripe_top, card_image_size.width, MIN(kSmallCharacterHeight + 2, card_image_size.height - expanded_stripe_top)); // Any rect whose pixel-sum is less than rectangle_summation_threshold is too dim to care about #define RECT_AVERAGE_THRESHOLD_FACTOR 5 long rect_average_based_on_stripe_sum = ((stripe_sum * kSmallCharacterWidth) / card_image_size.width); float rectangle_summation_threshold = rect_average_based_on_stripe_sum / RECT_AVERAGE_THRESHOLD_FACTOR; // [1] Calculate the pixel-sum for each possible character rectangle within the stripe... CharacterRectList rect_list; float rect_sum_total = 0; float rect_sum_average = 0; long rect_sum = 0; // [1a] Calculate pixel-sum for the leftmost character rect for (int col = 0; col < kSmallCharacterWidth; col++) { for (int row = 0; row < expanded_stripe_rect.height; row++) { rect_sum += CV_IMAGE_ELEM(sobel_image, short, stripe_base_row + row, col); } } // [1b] For each possible character rect... for (int col = 0; col < card_image_size.width - kSmallCharacterWidth + 1; col++) { // Record pixel-sum of current character rect (ignoring excessively dim rects) if (rect_sum > rectangle_summation_threshold) { CharacterRect rect; rect.top = expanded_stripe_rect.y; rect.left = col; rect.sum = rect_sum; rect_list.push_back(rect); rect_sum_total += (float)rect_sum; } if (col < card_image_size.width - kSmallCharacterWidth) { // Update pixels-sum by subtracting the leftmost pixel values and adding the next pixel values to the right for (int row = 0; row < expanded_stripe_rect.height; row++) { rect_sum -= CV_IMAGE_ELEM(sobel_image, short, stripe_base_row + row, col); rect_sum += CV_IMAGE_ELEM(sobel_image, short, stripe_base_row + row, col + kSmallCharacterWidth); } } } if (rect_list.empty()) { return; } rect_sum_average = (rect_sum_total / rect_list.size()); #define RECT_SUM_THRESHOLD_FACTOR 0.8 float rect_sum_threshold = (float) (RECT_SUM_THRESHOLD_FACTOR * rect_sum_average); #if DEBUG_EXPIRY_SEGMENTATION_PERFORMANCE dmz_debug_timer_print("calc all rects", 1); #endif // [2] Sort rectangles descending by sum std::sort(rect_list.begin(), rect_list.end(), CharacterRectCompareSumDescending()); #if DEBUG_EXPIRY_SEGMENTATION_PERFORMANCE char msg[256]; sprintf(msg, "sort %ld non-zero rects", rect_list.size()); dmz_debug_timer_print(msg, 1); #endif // [3] Find the non-overlapping rectangles, ignoring rectangles whose sum is excessively small (compared to the average rect sum) GroupedRectsList non_overlapping_rect_list; bool non_overlapping_rect_mask[expanded_stripe_rect.width]; memset(non_overlapping_rect_mask, 0, sizeof(non_overlapping_rect_mask)); for (CharacterRectListIterator rect = rect_list.begin(); rect != rect_list.end(); ++ rect) { if ((float)rect->sum <= rect_sum_threshold) { break; } if (!non_overlapping_rect_mask[rect->left] && !non_overlapping_rect_mask[rect->left + kSmallCharacterWidth - 1]) { GroupedRects grouped_rect; grouped_rect.top = rect->top; grouped_rect.left = rect->left; grouped_rect.width = kSmallCharacterWidth; grouped_rect.height = expanded_stripe_rect.height; grouped_rect.grouped_yet = false; grouped_rect.sum = rect->sum; grouped_rect.character_width = kSmallCharacterWidth; non_overlapping_rect_list.push_back(grouped_rect); non_overlapping_rect_mask[rect->left + 0] = true; non_overlapping_rect_mask[rect->left + 1] = true; non_overlapping_rect_mask[rect->left + 2] = true; non_overlapping_rect_mask[rect->left + 3] = true; non_overlapping_rect_mask[rect->left + 4] = true; non_overlapping_rect_mask[rect->left + 5] = true; non_overlapping_rect_mask[rect->left + 6] = true; non_overlapping_rect_mask[rect->left + 7] = true; non_overlapping_rect_mask[rect->left + 8] = true; assert(8 == kSmallCharacterWidth - 1); } } #if DEBUG_EXPIRY_SEGMENTATION_PERFORMANCE char msg2[256]; sprintf(msg2, "find %ld non-overlapping rects", non_overlapping_rect_list.size()); dmz_debug_timer_print(msg2, 1); #endif // "local group" = a set of character rects with inter-rect horizontal gaps of less than kSmallCharacterWidth // "super-group" = a set of local groups with inter-group horizontal gaps of less than 2 * kSmallCharacterWidth // // Expiry must be a local group (for now, anyhow). // Name is a super-group (since we'll get firstname and lastname as separate local groups). // [4] Collect character rects into local groups GroupedRectsList local_groups; gather_into_groups(local_groups, non_overlapping_rect_list, kSmallCharacterWidth); #if DEBUG_EXPIRY_SEGMENTATION_PERFORMANCE char msg3[256]; sprintf(msg3, "%ld local groups", local_groups.size()); dmz_debug_timer_print(msg3, 1); #endif // [5] Collect local groups into super-groups GroupedRectsList super_groups; // Let's skip these for the moment, while we're focusing on expiry: // gather_into_groups(super_groups, local_groups, 2 * kSmallCharacterWidth); #if DEBUG_EXPIRY_SEGMENTATION_PERFORMANCE char msg4[256]; sprintf(msg4, "%ld super-groups", super_groups.size()); dmz_debug_timer_print(msg4, 1); #endif GroupedRectsList new_groups; for (GroupedRectsListIterator group = local_groups.begin(); group != local_groups.end(); ++group) { if (group->character_rects.size() >= kMinimumExpiryStripCharacters - 1) { new_groups.push_back(*group); } } local_groups = new_groups; new_groups.clear(); for (GroupedRectsListIterator group = super_groups.begin(); group != super_groups.end(); ++group) { if (group->character_rects.size() >= kMinimumNameStripCharacters - 1) { new_groups.push_back(*group); } } super_groups = new_groups; #if DEBUG_EXPIRY_SEGMENTATION_PERFORMANCE char msg5[256]; sprintf(msg5, "width-filtering -> %ld local groups, %ld super-groups", local_groups.size(), super_groups.size()); dmz_debug_timer_print(msg5, 1); #endif for (GroupedRectsListIterator group = local_groups.begin(); group != local_groups.end(); ++group) { regrid_group(sobel_image, *group); } for (GroupedRectsListIterator group = super_groups.begin(); group != super_groups.end(); ++group) { regrid_group(sobel_image, *group); } #if DEBUG_EXPIRY_SEGMENTATION_PERFORMANCE dmz_debug_timer_print("regrid the groups", 1); #endif for (int index = (int)local_groups.size() - 1; index >= 0; index--) { optimize_character_rects(sobel_image, local_groups[index]); if (local_groups[index].character_rects.size() == 0) { local_groups.erase(local_groups.begin() + index); // dmz_debug_print("Erasing local_group %d, which is now empty.\n", index); } } for (int index = (int)super_groups.size() - 1; index >= 0; index--) { optimize_character_rects(sobel_image, super_groups[index]); if (super_groups[index].character_rects.size() == 0) { super_groups.erase(super_groups.begin() + index); } } #if DEBUG_EXPIRY_SEGMENTATION_PERFORMANCE dmz_debug_timer_print("shrink the character rects", 1); #endif new_groups.clear(); for (GroupedRectsListIterator group = local_groups.begin(); group != local_groups.end(); ++group) { if (group->character_rects.size() >= kMinimumExpiryStripCharacters) { new_groups.push_back(*group); } } local_groups = new_groups; new_groups.clear(); for (GroupedRectsListIterator group = super_groups.begin(); group != super_groups.end(); ++group) { if (group->character_rects.size() >= kMinimumNameStripCharacters) { new_groups.push_back(*group); } } super_groups = new_groups; #if DEBUG_EXPIRY_SEGMENTATION_PERFORMANCE char msg6[256]; sprintf(msg6, "width-filtering -> %ld local groups, %ld super-groups", local_groups.size(), super_groups.size()); dmz_debug_timer_print(msg6, 1); #endif // Add local groups to the passed-in expiry_groups GroupedRectsList, iff they contain a slash in a reasonable position static IplImage *as_float = NULL; if (as_float == NULL) { as_float = cvCreateImage(cvSize(kTrimmedCharacterImageWidth, kTrimmedCharacterImageHeight), IPL_DEPTH_32F, 1); } for (GroupedRectsListIterator group = local_groups.begin(); group != local_groups.end(); ++group) { if (group->character_rects.size() < 5) { continue; } for (size_t firstCharacterIndex = 0; firstCharacterIndex + 4 < group->character_rects.size(); firstCharacterIndex++) { if (is_slash(sobel_image, as_float, &group->character_rects[firstCharacterIndex + 2])) { GroupedRects grouped_5_characters; grouped_5_characters.top = group->character_rects[firstCharacterIndex].top; grouped_5_characters.left = group->character_rects[firstCharacterIndex].left; grouped_5_characters.width = kSmallCharacterWidth; grouped_5_characters.height = kSmallCharacterHeight; grouped_5_characters.grouped_yet = false; grouped_5_characters.sum = 0; grouped_5_characters.character_width = kTrimmedCharacterImageWidth; grouped_5_characters.pattern = ExpiryPatternMMsYY; for (size_t index = 0; index < 5; index++) { CharacterRect char_rect = group->character_rects[firstCharacterIndex + index]; int formerBottom = grouped_5_characters.top + grouped_5_characters.height; grouped_5_characters.top = MIN(char_rect.top, grouped_5_characters.top); grouped_5_characters.width = (char_rect.left + kSmallCharacterWidth) - grouped_5_characters.left; grouped_5_characters.height = MAX(char_rect.top + kSmallCharacterHeight, formerBottom) - grouped_5_characters.top; grouped_5_characters.character_rects.push_back(char_rect); } expiry_groups.push_back(grouped_5_characters); } } } #if DEBUG_EXPIRY_SEGMENTATION_PERFORMANCE dmz_debug_timer_print("insert local groups into expiry_groups param", 1); #endif // Add supergroups to the passed-in name_groups GroupedRectsList name_groups.insert(name_groups.end(), super_groups.begin(), super_groups.end()); #if DEBUG_EXPIRY_SEGMENTATION_PERFORMANCE dmz_debug_timer_print("insert supergroups into name_groups param", 1); #endif }
int CLY_IsUNC(const char* path) { if (!is_slash(path[0]) || !is_slash(path[1]) || is_term(path[2])) return 0; return 1; }
void Archive::make_index() { num_indices = 0; CHECK_COM(in_arc->GetNumberOfItems(&num_indices)); file_list.clear(); file_list.reserve(num_indices); struct DirInfo { UInt32 index; UInt32 parent; wstring name; bool operator<(const DirInfo& dir_info) const { if (parent == dir_info.parent) return lstrcmpiW(name.c_str(), dir_info.name.c_str()) < 0; else return parent < dir_info.parent; } }; typedef set<DirInfo> DirList; map<UInt32, unsigned> dir_index_map; DirList dir_list; DirInfo dir_info; UInt32 dir_index = 0; ArcFileInfo file_info; wstring path; PropVariant prop; for (UInt32 i = 0; i < num_indices; i++) { // is directory? file_info.is_dir = in_arc->GetProperty(i, kpidIsDir, prop.ref()) == S_OK && prop.is_bool() && prop.get_bool(); // file name if (in_arc->GetProperty(i, kpidPath, prop.ref()) == S_OK && prop.is_str()) path.assign(prop.get_str()); else path.assign(get_default_name()); size_t name_end_pos = path.size(); while (name_end_pos && is_slash(path[name_end_pos - 1])) name_end_pos--; size_t name_pos = name_end_pos; while (name_pos && !is_slash(path[name_pos - 1])) name_pos--; file_info.name.assign(path.data() + name_pos, name_end_pos - name_pos); // split path into individual directories and put them into DirList dir_info.parent = c_root_index; size_t begin_pos = 0; while (begin_pos < name_pos) { dir_info.index = dir_index; size_t end_pos = begin_pos; while (end_pos < name_pos && !is_slash(path[end_pos])) end_pos++; if (end_pos != begin_pos) { dir_info.name.assign(path.data() + begin_pos, end_pos - begin_pos); pair<DirList::iterator, bool> ins_pos = dir_list.insert(dir_info); if (ins_pos.second) dir_index++; dir_info.parent = ins_pos.first->index; } begin_pos = end_pos + 1; } file_info.parent = dir_info.parent; if (file_info.is_dir) { dir_info.index = dir_index; dir_info.parent = file_info.parent; dir_info.name = file_info.name; pair<DirList::iterator, bool> ins_pos = dir_list.insert(dir_info); if (ins_pos.second) { dir_index++; dir_index_map[dir_info.index] = i; } else { if (dir_index_map.count(ins_pos.first->index)) file_info.parent = c_dup_index; else dir_index_map[ins_pos.first->index] = i; } } file_list.push_back(file_info); } // add directories that not present in archive index file_list.reserve(file_list.size() + dir_list.size() - dir_index_map.size()); dir_index = num_indices; for_each(dir_list.begin(), dir_list.end(), [&] (const DirInfo& dir_info) { if (dir_index_map.count(dir_info.index) == 0) { dir_index_map[dir_info.index] = dir_index; file_info.parent = dir_info.parent; file_info.name = dir_info.name; file_info.is_dir = true; dir_index++; file_list.push_back(file_info); } }); // fix parent references for_each(file_list.begin(), file_list.end(), [&] (ArcFileInfo& file_info) { if (file_info.parent != c_root_index) file_info.parent = dir_index_map[file_info.parent]; }); // create search index file_list_index.clear(); file_list_index.reserve(file_list.size()); for (UInt32 i = 0; i < file_list.size(); i++) { file_list_index.push_back(i); } sort(file_list_index.begin(), file_list_index.end(), [&] (UInt32 left, UInt32 right) -> bool { return file_list[left] < file_list[right]; }); load_arc_attr(); }
static inline bool is_unc_path (const char * path) { return is_slash (path[0]) && path[1] == path[0]; }
/* Takes as input an arbitrary path. Fixes up the path by: 1. Removing consecutive slashes 2. Removing trailing slashes 3. Making the path absolute if it wasn't already 4. Removing "." in the path 5. Removing ".." entries in the path (and the directory above them) */ void _fixpath(const char *in, char *out) { const char *ip = in; char *op = out; /* Convert ~ to the HOME environment variable */ if (*ip == '~' && (is_slash(ip[1]) || !ip[1])) { const char *home = getenv("HOME"); if (home) { strcpy(op, home); op += strlen(op); ip++; if (!*ip) return; } } /* Convert relative path to absolute */ if (!is_slash(*ip)) { getcurdir(0, op); op += strlen(op); } #if defined(TVOSf_QNX4) /* Skip the first slashes, which are a node number part */ /* Full QNX4 pathname is //node/dirpath/filename */ if ((ip==in) && (is_slash(*ip)) && (is_slash(*(ip+1)))) { *op=*ip; ip++; op++; } #endif // TVOSf_QNX4 /* Step through the input path */ while (*ip) { /* Skip input slashes */ if (is_slash(*ip)) { ip++; continue; } /* Skip "." and output nothing */ if (*ip == '.' && is_term(*(ip + 1))) { ip++; continue; } /* Skip ".." and remove previous output directory */ if (*ip == '.' && *(ip + 1) == '.' && is_term(*(ip + 2))) { ip += 2; /* Don't back up over root '/' */ if (op > out) /* This requires "/" to follow drive spec */ while (!is_slash(*--op)) ; continue; } /* Copy path component from in to out */ *op++ = '/'; while (!is_term(*ip)) *op++ = *ip++; } /* If root directory, insert trailing slash */ if (op == out) *op++ = '/'; /* Null terminate the output */ *op = '\0'; }
/* Takes as input an arbitrary path. Fixes up the path by: 1. Removing consecutive slashes 2. Removing trailing slashes 3. Making the path absolute if it wasn't already 4. Removing "." in the path 5. Removing ".." entries in the path (and the directory above them) 6. Adding a drive specification if one wasn't there 7. Converting all slashes to '/' */ void _fixpath(const char *in, char *out) { int drive_number = 0; const char *ip = in; char *op = out; int unc = CLY_IsUNC(in); /* is a UNC pathname */ /* Add drive specification to output string */ if (((*ip >= 'a' && *ip <= 'z') || (*ip >= 'A' && *ip <= 'Z')) && (*(ip + 1) == ':')) { if (*ip >= 'a' && *ip <= 'z') { drive_number = *ip - 'a'; *op++ = *ip++; } else { drive_number = *ip - 'A'; *op++ = (char)(drive_number + 'a'); ++ip; } *op++ = *ip++; } else if (!unc) { drive_number = __fp_getdisk(); *op++ = (char)(drive_number + 'a'); *op++ = ':'; } /* Convert relative path to absolute */ if (!is_slash(*ip)) { *op++ = '/'; op = __fp_getcurdir(op, drive_number); } /* Handle UNC path */ if (unc) { *op++ = *ip++; } /* Step through the input path */ while (*ip) { /* Skip input slashes */ if (is_slash(*ip)) { ip++; continue; } /* Skip "." and output nothing */ if (*ip == '.' && is_term(*(ip + 1))) { ip++; continue; } /* Skip ".." and remove previous output directory */ if (*ip == '.' && *(ip + 1) == '.' && is_term(*(ip + 2))) { ip += 2; /* Don't back up over drive spec */ if (op > out + 2) { /* This requires "/" to follow drive spec */ --op; while (!is_slash(*op)) --op; } continue; } /* Copy path component from in to out */ *op++ = '/'; while (!is_term(*ip)) *op++ = *ip++; } /* If root directory, insert trailing slash */ if (op == out + 2) *op++ = '/'; /* Null terminate the output */ *op = '\0'; /* Convert backslashes to slashes */ for (op = out; *op; op++) if (*op == '\\') *op = '/'; }
char *maybe_rename_file(const char *original_name) { static char dosified_name[PATH_MAX+1]; static const char illegal_chars_dos[] = ".+, ;=[]|<>\":?*"; const char *illegal_chars = illegal_chars_dos; int idx, dot_idx; const char *s = original_name; char *d = dosified_name; /* Support for Win32 VFAT systems, when available. */ #if defined(__DJGPP__) if (_use_lfn(original_name)) illegal_chars = illegal_chars_dos + 8; #elif (ACC_OS_WIN32 || ACC_OS_WIN64 || ACC_OS_CYGWIN) illegal_chars = illegal_chars_dos + 8; #endif /* Get past the drive letter, if any. */ if (fn_is_drive(s)) { *d++ = *s++; *d++ = *s++; } for (idx = 0, dot_idx = -1; *s; s++, d++) { if (strchr(illegal_chars, *s)) { /* Dots are special on DOS: it doesn't allow them as the leading character, and a file name cannot have more than a single dot. We leave the first non-leading dot alone, unless it comes too close to the beginning of the name: we want sh.lex.c to become sh_lex.c, not sh.lex-c. */ if (*s == '.') { if (idx == 0 && (is_slash(s[1]) || s[1] == '\0' || (s[1] == '.' && (is_slash(s[2]) || s[2] == '\0')))) { /* Copy "./" and "../" verbatim. */ *d++ = *s++; if (*s == '.') *d++ = *s++; *d = *s; } else if (idx == 0) *d = '_'; else if (dot_idx >= 0) { if (dot_idx < 5) /* 5 is merely a heuristic ad-hoc'ery */ { d[dot_idx - idx] = '_'; /* replace previous dot */ *d = '.'; } else *d = '-'; } else *d = '.'; if (*s == '.') dot_idx = idx; } else if (*s == '+' && s[1] == '+') { if (idx - 2 == dot_idx) /* .c++, .h++ etc. */ { *d++ = 'x'; *d = 'x'; } else { /* libg++ etc. */ memcpy (d, "plus", 4); d += 3; } s++; idx++; } else *d = '_'; } else *d = *s; if (is_slash(*s)) { idx = 0; dot_idx = -1; } else idx++; } *d = '\0'; #if defined(S_ISCHR) /* We could have a file in an archive whose name is reserved on MS-DOS by a device driver. Trying to extract such a file would fail at best and wedge us at worst. We need to rename such files. */ if (idx > 0) { struct stat st_buf; char *base = d - idx; int i = 0; /* The list of character devices is not constant: it depends on what device drivers did they install in their CONFIG.SYS. `stat' will tell us if the basename of the file name is a characer device. */ while (stat(base, &st_buf) == 0 && S_ISCHR(st_buf.st_mode)) { size_t blen = strlen(base); /* I don't believe any DOS character device names begin with a `_'. But in case they invent such a device, let us try twice. */ if (++i > 2) return (char *)0; /* Prepend a '_'. */ memmove(base + 1, base, blen + 1); base[0] = '_'; } } #endif return dosified_name; }