Exemple #1
0
/* see if a file is normal file or it is a "shell symlink"
 If directory+filename exists do nothing return false
 If it doesn't but direstory+filename+".lnk" exists then
 try to read it. On reading success return true with lnk
 filename value as resolved. See resolve_shell_shortcut also.
 > filename: resolving file name
 < resolved: buffer for resolved path and filename.
 < result: shell_shortcut_notresolved if file exists or link is invalid.
           otherwise - shortcut target status */
static shell_shortcut_target_t
resolve_shell_symlink (LPCSTR filename, LPSTR resolved)
{
  char pathname[_MAX_PATH];
  DWORD fileattr;

  strcpy(pathname,filename);
  fileattr = GetFileAttributes(pathname);
  if (fileattr != 0xFFFFFFFF) return shell_shortcut_notresolved;
  strcat(pathname,".lnk");
  fileattr = GetFileAttributes(pathname);
  if (fileattr == 0xFFFFFFFF) return shell_shortcut_notresolved;
  return resolve_shell_shortcut_more(pathname,resolved);
}
Exemple #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;
}
Exemple #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;
}