--- path.cc.new1 2004-04-04 18:10:26.000000000 -0400 +++ path.cc 2004-04-04 18:43:52.000000000 -0400 @@ -507,7 +507,6 @@ path_conv::check (const char *src, unsig *--tail = '\0'; } char *path_end = tail; - tail[1] = '\0'; /* Scan path_copy from right to left looking either for a symlink or an actual existing file. If an existing file is found, just @@ -518,6 +517,7 @@ path_conv::check (const char *src, unsig int component = 0; // Number of translated components sym.contents[0] = '\0'; + int symlen; for (;;) { const suffix_info *suff; @@ -607,7 +607,7 @@ path_conv::check (const char *src, unsig goto out; } - int len = sym.check (full_path, suff, opt | fs.sym_opt ()); + symlen = sym.check (full_path, suff, opt | fs.sym_opt ()); if (sym.minor || sym.major) { @@ -658,12 +658,12 @@ path_conv::check (const char *src, unsig done now. */ opt |= PC_SYM_IGNORE; } - /* Found a symlink if len > 0. If component == 0, then the + /* Found a symlink if symlen > 0. If component == 0, then the src path itself was a symlink. If !follow_mode then we're done. Otherwise we have to insert the path found into the full path that we are building and perform all of these operations again on the newly derived path. */ - else if (len > 0) + else if (symlen > 0) { saw_symlinks = 1; if (component == 0 && !need_directory && !(opt & PC_SYM_FOLLOW)) @@ -712,56 +712,50 @@ path_conv::check (const char *src, unsig MALLOC_CHECK; - /* The tail is pointing at a null pointer. Increment it and get the length. - If the tail was empty then this increment will end up pointing to the extra - \0 added to path_copy above. */ - int taillen = strlen (++tail); - int buflen = strlen (sym.contents); - if (buflen + taillen > CYG_MAX_PATH) - { - error = ENAMETOOLONG; - strcpy (path, "::ENAMETOOLONG::"); - return; - } - /* Strip off current directory component since this is the part that refers - to the symbolic link. */ - char * p; - if ((p = strrchr (path_copy, '/')) == NULL) - p = path_copy; - else if (p == path_copy) - p++; - *p = '\0'; + /* Place the link content, possibly with head and/or tail, in tmp_buf */ char *headptr; if (isabspath (sym.contents)) headptr = tmp_buf; /* absolute path */ else { - /* Copy the first part of the path and point to the end. */ - strcpy (tmp_buf, path_copy); - headptr = strchr (tmp_buf, '\0'); + /* Copy the first part of the path (with ending /) and point to the end. */ + char *prevtail = tail; + while (--prevtail > path_copy && *prevtail != '/') {} + int headlen = prevtail - path_copy + 1;; + memcpy (tmp_buf, path_copy, headlen); + headptr = &tmp_buf[headlen]; } - /* See if we need to separate first part + symlink contents with a / */ - if (headptr > tmp_buf && headptr[-1] != '/') - *headptr++ = '/'; - - /* Copy the symlink contents to the end of tmp_buf. - Convert slashes. FIXME? */ - for (p = sym.contents; *p; p++) + /* Make sure there is enough space */ + if (headptr + symlen >= tmp_buf + sizeof (tmp_buf)) + { + too_long: + error = ENAMETOOLONG; + strcpy (path, "::ENAMETOOLONG::"); + return; + } + + /* Copy the symlink contents to the end of tmp_buf. + Convert slashes. FIXME? I think it's fine / Pierre */ + for (char *p = sym.contents; *p; p++) *headptr++ = *p == '\\' ? '/' : *p; - - /* Copy any tail component */ - if (tail >= path_end) - *headptr = '\0'; - else - { - *headptr++ = '/'; - strcpy (headptr, tail); + *headptr = '\0'; + + /* Copy any tail component (with the 0) */ + if (tail++ < path_end) + { + /* Add a slash if needed. There is space. */ + if (*(headptr - 1) != '/') + *headptr++ = '/'; + int taillen = path_end - tail + 1; + if (headptr + taillen > tmp_buf + sizeof (tmp_buf)) + goto too_long; + memcpy (headptr, tail, taillen); } - - /* Now evaluate everything all over again. */ + + /* Evaluate everything all over again. */ src = tmp_buf; }