mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-22 14:39:24 -05:00
Moderately evil workaround to compensate for a variation in
behaviour of FXP_REALPATH. (Specifically, BSD and GNU realpath(3) disagree over whether to return success when computing the realpath for a putative new file to be created in a valid directory. There's no way we can tell from (say) the OpenSSH version string because OpenSSH might have been compiled to use the local realpath _or_ its own nonbroken one.) [originally from svn r953]
This commit is contained in:
parent
1129d200e4
commit
b10bc57b03
69
psftp.c
69
psftp.c
@ -94,10 +94,77 @@ char *canonify(char *name) {
|
|||||||
if (canonname) {
|
if (canonname) {
|
||||||
sfree(fullname);
|
sfree(fullname);
|
||||||
return canonname;
|
return canonname;
|
||||||
} else
|
} else {
|
||||||
|
/*
|
||||||
|
* Attempt number 2. Some FXP_REALPATH implementations
|
||||||
|
* (glibc-based ones, in particular) require the _whole_
|
||||||
|
* path to point to something that exists, whereas others
|
||||||
|
* (BSD-based) only require all but the last component to
|
||||||
|
* exist. So if the first call failed, we should strip off
|
||||||
|
* everything from the last slash onwards and try again,
|
||||||
|
* then put the final component back on.
|
||||||
|
*
|
||||||
|
* Special cases:
|
||||||
|
*
|
||||||
|
* - if the last component is "/." or "/..", then we don't
|
||||||
|
* bother trying this because there's no way it can work.
|
||||||
|
*
|
||||||
|
* - if the thing actually ends with a "/", we remove it
|
||||||
|
* before we start. Except if the string is "/" itself
|
||||||
|
* (although I can't see why we'd have got here if so,
|
||||||
|
* because surely "/" would have worked the first
|
||||||
|
* time?), in which case we don't bother.
|
||||||
|
*
|
||||||
|
* - if there's no slash in the string at all, give up in
|
||||||
|
* confusion (we expect at least one because of the way
|
||||||
|
* we constructed the string).
|
||||||
|
*/
|
||||||
|
|
||||||
|
int i;
|
||||||
|
char *returnname;
|
||||||
|
|
||||||
|
i = strlen(fullname);
|
||||||
|
if (i > 2 && fullname[i-1] == '/')
|
||||||
|
fullname[--i] = '\0'; /* strip trailing / unless at pos 0 */
|
||||||
|
while (i > 0 && fullname[--i] != '/');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Give up on special cases.
|
||||||
|
*/
|
||||||
|
if (fullname[i] != '/' || /* no slash at all */
|
||||||
|
!strcmp(fullname+i, "/.") || /* ends in /. */
|
||||||
|
!strcmp(fullname+i, "/..") || /* ends in /.. */
|
||||||
|
!strcmp(fullname, "/")) {
|
||||||
return fullname;
|
return fullname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now i points at the slash. Deal with the final special
|
||||||
|
* case i==0 (ie the whole path was "/nonexistentfile").
|
||||||
|
*/
|
||||||
|
fullname[i] = '\0'; /* separate the string */
|
||||||
|
if (i == 0) {
|
||||||
|
canonname = fxp_realpath("/");
|
||||||
|
} else {
|
||||||
|
canonname = fxp_realpath(fullname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canonname)
|
||||||
|
return fullname; /* even that failed; give up */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have a canonical name for all but the last path
|
||||||
|
* component. Concatenate the last component and return.
|
||||||
|
*/
|
||||||
|
returnname = dupcat(canonname,
|
||||||
|
canonname[strlen(canonname)-1] == '/' ? "" : "/",
|
||||||
|
fullname+i+1, NULL);
|
||||||
|
sfree(fullname);
|
||||||
|
sfree(canonname);
|
||||||
|
return returnname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
* Actual sftp commands.
|
* Actual sftp commands.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user