示例#1
0
/* Uses the base from filename to augment pathname.
   Return false when (pathname is relative AND filename doesn't
   contain the base), so pathname (contained in shortcut)
   cannot be referenced other than to current directory
   what is wrong. */
static BOOL augment_relative_pathname(LPCSTR filename, LPSTR pathname) {
  /* check if pathname is absolute */
  /* what to do with "/bar/foo" pathnames ?*/
  if (cpslashp(pathname[0])) return FALSE; /* let's panic */
  if (((pathname[0] >= 'a' && pathname[0] <= 'z')
    || (pathname[0] >= 'A' && pathname[0] <= 'Z'))
    && pathname[1] == ':' && cpslashp(pathname[2])) return TRUE;
  if (pathname[0] == '\\' && pathname[1] == '\\') return TRUE;
  {
    int fl = strlen(filename);
    int pl = strlen(pathname);
    const char * cp = filename + fl - 1;
    /* find the last slash */
    for (;!cpslashp(*cp) && cp > filename;cp--);
    if (!cpslashp(*cp)) return FALSE; /* no slash */
    memmove(pathname + (cp - filename + 1),pathname,pl + 1);
    memmove(pathname,filename,cp - filename + 1);
  }
  return TRUE;
}
示例#2
0
/* the ultimate shortcut megaresolver
   style inspired by directory_search_scandir
 > namein: absolute filename pointing to file or directory
            wildcards (only asterisk) may appear only as filename
 < nameout: filename with directory and file shortcuts resolved
             on failure holds filename resolved so far
 < result:  true if resolving succeeded */
BOOL real_path (LPCSTR namein, LPSTR nameout) {
  WIN32_FIND_DATA wfd;
  HANDLE h = NULL;
  char * nametocheck;
  char * nametocheck_end;
  int    name_len;
  /* drive|dir1|dir2|name
           ^nametocheck
               ^nametocheck_end */
  char saved_char;
  BOOL next_name = 0;/* if we found an lnk and need to start over */
  int try_counter = 33;
  if ((name_len = strlen(namein)) >= MAX_PATH) return FALSE;
  strcpy(nameout,namein);
  do { /* whole file names */
    next_name = FALSE;
    if (!*nameout) return FALSE;
    /* skip drive or host or first slash */
    nametocheck = nameout;
    if (((*nametocheck >= 'a' && *nametocheck <= 'z')
         || (*nametocheck >= 'A' && *nametocheck <= 'Z'))
        && nametocheck[1] == ':')
    { if (cpslashp(nametocheck[2])) {
        /* drive */
        nametocheck += 3;
      } else {
        /* default directory on drive */
        char drive[4] = "C:.", *name;
        int default_len;
        drive[0] = namein[0];
        if (!GetFullPathName(drive,_MAX_PATH,nameout,&name)
            || (default_len = strlen(nameout)) + name_len
               >= _MAX_PATH) return FALSE;
        nameout[default_len] = '\\';
        strcpy(nameout + default_len + 1, namein + 2);
        name_len += default_len - 1; /* Was C:lisp.exe
                                        Now C:\clisp\lisp.exe
                                        removed 2
                                        added default_len + 1 chars */
        nametocheck += default_len + 1;
    } }
    else if (nametocheck[0]=='\\' && nametocheck[1]=='\\') {
      int i;
      /* host */
      nametocheck+=2;
      for (i=0;i<2;i++) {/* skip host and sharename */
        while (*nametocheck && !cpslashp(*nametocheck))
          nametocheck++;
        if (*nametocheck) nametocheck++; else return FALSE;
      }
    } else if (cpslashp(*nametocheck)) nametocheck++;
    /* prefix skipped; start checking */
    do { /* each component after just skipped */
      int dots_only = 0;
      int have_stars = 0;
      /* separate a component */
      for (nametocheck_end = nametocheck;
           *nametocheck_end && !cpslashp(*nametocheck_end);
           nametocheck_end++);
      if (*nametocheck_end && nametocheck_end == nametocheck)
        return FALSE;/* two slashes one after another */
      /* save slash or zero */
      saved_char = *nametocheck_end;
      *nametocheck_end = 0;
      /* Is it . or .. ? FFF handles this strange way */
      { char * cp = nametocheck;
        for (;*cp=='.';cp++);
        dots_only = !(*cp) && cp > nametocheck; }
      /* Asterisks in the middle of filename: error
         Asterisks as pathname: success */
      { char * cp = nametocheck;
        for (;*cp && *cp!='*';cp++);
        have_stars = *cp == '*'; }
      if (have_stars && saved_char) return FALSE;
      if (!have_stars) {
        if (dots_only || !*nametocheck) {
          /* treat 'start/./end', 'drive/', 'host/' specially */
          /* search for ....\.\* */
          char saved[2];
          if (nametocheck_end - nameout + 2 > MAX_PATH) return FALSE;
          saved[0] = nametocheck_end[1]; saved[1] = nametocheck_end[2];
          /* !*nametocheck here means there was "something\" before */
          strcpy(nametocheck_end,*nametocheck?"\\*":"*");
          h = FindFirstFile(nameout,&wfd);
          nametocheck_end[1] = saved[0]; nametocheck_end[2] = saved[1];
          nametocheck_end[0] = 0;
          if (h != INVALID_HANDLE_VALUE) {
            FindClose(h); /* don't substitute */
          } else return FALSE; /* don't try lnk */
        } else {/* not only dots */
          h = FindFirstFile(nameout,&wfd);
          if (h != INVALID_HANDLE_VALUE) {
            /* make space for full (non 8.3) name component */
            int     l = strlen(wfd.cFileName),
                 oldl = nametocheck_end - nametocheck,
                 new_name_len = name_len + l - oldl;
            FindClose(h);
            if (new_name_len >= _MAX_PATH) return FALSE;
            if (l != oldl) {
              int restlen =
                saved_char?(name_len - (nametocheck_end - nameout)):0;
              memmove(nametocheck+l,nametocheck_end,restlen+1);
            }
            strncpy(nametocheck,wfd.cFileName,l);
            nametocheck_end = nametocheck + l;
            name_len = new_name_len;
          } else {/* try shortcut
                     Note: something\cyglink.lnk doesn't resolve to the contents
                           of cyglink.lnk so one can read/write symlink .lnk
                           files although they are not present in DIRECTORY output.
                           Is it bug or feature? */
            char saved[4];
            char resolved[MAX_PATH];
            int  resolved_len;
            shell_shortcut_target_t rresult;
            if (nametocheck_end - nameout + 4 > MAX_PATH) return FALSE;
            strncpy(saved,nametocheck_end+1,4);
            strncpy(nametocheck_end,".lnk",5);
            rresult = resolve_shell_shortcut_more(nameout,resolved);
            strncpy(nametocheck_end+1,saved,4);
            *nametocheck_end = 0;
            /* use saved_char as directory indicator */
            if (rresult == shell_shortcut_notresolved
                || rresult == shell_shortcut_notexists
                || (saved_char ? rresult == shell_shortcut_file
                    : rresult == shell_shortcut_directory))
              return FALSE;
            resolved_len = strlen(resolved);
            if (saved_char) {
              /*need to subst nameout..nametocheck-1 with resolved path */
              int l2 = name_len - (nametocheck_end - nameout);
              if (resolved_len + l2 + 2 > MAX_PATH) return FALSE;
              strncpy(resolved + resolved_len, nametocheck_end + 1, l2);
              name_len = l2 - 1;
            }
            name_len += resolved_len;
            strcpy(nameout,resolved);
            next_name = TRUE;
          }
        }
      }
      if (!next_name) {
        *nametocheck_end = saved_char;
        nametocheck = nametocheck_end;
        if (*nametocheck) nametocheck++;
      }
    } while (!next_name && *nametocheck);
    if (!(--try_counter)) return FALSE;
  } while (next_name);
  return TRUE;
}
示例#3
0
/* the ultimate shortcut megaresolver
   style inspired by directory_search_scandir
 > namein: absolute filename pointing to file or directory
            wildcards (only asterisk) may appear only as filename
 < nameout: filename with directory and file shortcuts resolved
             on failure holds filename resolved so far
 < result:  true if resolving succeeded */
BOOL real_path (LPCSTR namein, LPSTR nameout) {
  WIN32_FIND_DATA wfd;
  HANDLE h = NULL;
  char * nametocheck;
  char * nametocheck_end;
  /* drive|dir1|dir2|name
           ^nametocheck
               ^nametocheck_end */
  char saved_char;
  BOOL next_name = 0;/* if we found an lnk and need to start over */
  int try_counter = 33;
  if (strlen(namein) >= MAX_PATH) return FALSE;
  strcpy(nameout,namein);
  do { /* whole file names */
    next_name = FALSE;
    if (!*nameout) return FALSE;
    /* skip drive or host or first slash */
    nametocheck = nameout;
    if (((*nametocheck >= 'a' && *nametocheck <= 'z')
         || (*nametocheck >= 'A' && *nametocheck <= 'Z'))
        && nametocheck[1] == ':' && cpslashp(nametocheck[2]))
      /* drive */
      nametocheck += 3;
    else if (nametocheck[0]=='\\' && nametocheck[1]=='\\') {
      int i;
      /* host */
      nametocheck+=2;
      for (i=0;i<2;i++) {/* skip host and sharename */
        while (*nametocheck && !cpslashp(*nametocheck))
          nametocheck++;
        if (*nametocheck) nametocheck++; else return FALSE;
      }
    } else if (cpslashp(*nametocheck)) nametocheck++;
    /* prefix skipped; start checking */
    do { /* each component after just skipped */
      int dots_only = 0;
      int have_stars = 0;
      /* separate a component */
      for (nametocheck_end = nametocheck;
           *nametocheck_end && !cpslashp(*nametocheck_end);
           nametocheck_end++);
      if (*nametocheck_end && nametocheck_end == nametocheck)
        return FALSE;/* two slashes one after another */
      /* save slash or zero */
      saved_char = *nametocheck_end;
      *nametocheck_end = 0;
      /* Is it . or .. ? FFF handles this strange way */
      { char * cp = nametocheck;
        for (;*cp=='.';cp++);
        dots_only = !(*cp) && cp > nametocheck; }
      /* Stars in the middle of filename: error
         Stars as pathname: success */
      { char * cp = nametocheck;
        for (;*cp && *cp!='*';cp++);
        have_stars = *cp == '*'; }
      if (have_stars && saved_char) return FALSE;
      if (!have_stars) {
        if (dots_only || !*nametocheck) {
          /* treat 'start/./end', 'drive/', 'host/' specially */
          /* search for ....\.\* */
          char saved[2];
          if (nametocheck_end - nameout + 2 > MAX_PATH) return FALSE;
          saved[0] = nametocheck_end[1]; saved[1] = nametocheck_end[2];
          /* !*nametocheck here means there was "something\" before */
          strcpy(nametocheck_end,*nametocheck?"\\*":"*");
          h = FindFirstFile(nameout,&wfd);
          nametocheck_end[1] = saved[0]; nametocheck_end[2] = saved[1];
          nametocheck_end[0] = 0;
          if (h != INVALID_HANDLE_VALUE) {
            FindClose(h); /* don't substitute */
          } else return FALSE; /* don't try lnk */
        } else {/* not only dots */
          h = FindFirstFile(nameout,&wfd);
          if (h != INVALID_HANDLE_VALUE) {
            /* make space for full (non 8.3) name component */
            int l = strlen(wfd.cFileName);
            FindClose(h);
            if (l != (nametocheck_end - nametocheck)) {
              int restlen =
                saved_char?(strlen(nametocheck_end+1)
                            +1/*saved_char*/+1/*zero byte*/)
                :0;
              if (nametocheck - nameout + restlen + l + 2 > MAX_PATH)
                return FALSE;
              if (restlen) memmove(nametocheck+l,nametocheck_end,restlen);
            }
            strncpy(nametocheck,wfd.cFileName,l);
            nametocheck_end = nametocheck + l;
          } else {/* try shortcut */
            char saved[4];
            char resolved[MAX_PATH];
            shell_shortcut_target_t rresult;
            if (nametocheck_end - nameout + 4 > MAX_PATH) return FALSE;
            strncpy(saved,nametocheck_end+1,4);
            strncpy(nametocheck_end,".lnk",5);
            rresult = resolve_shell_shortcut_more(nameout,resolved);
            strncpy(nametocheck_end+1,saved,4);
            *nametocheck_end = 0;
            /* use saved_char as directory indicator */
            if (rresult == shell_shortcut_notresolved
                || rresult == shell_shortcut_notexists
                || (saved_char ? rresult == shell_shortcut_file
                    : rresult == shell_shortcut_directory))
              return FALSE;
            if (saved_char) {
              /*need to subst nameout..nametocheck-1 with resolved path */
              int l1 = strlen(resolved);
              int l2 = strlen(nametocheck_end + 1);
              if (l1 + l2 + 2 > MAX_PATH) return FALSE;
              strncat(resolved,nametocheck_end + 1,l2+1);
            }
            strcpy(nameout,resolved);
            next_name = TRUE;
          }
        }
      }
      if (!next_name) {
        *nametocheck_end = saved_char;
        nametocheck = nametocheck_end;
        if (*nametocheck) nametocheck++;
      }
    } while (!next_name && *nametocheck);
    if (!(--try_counter)) return FALSE;
  } while (next_name);
  return TRUE;
}