sftp "cd" command to drive letter under cygwin

Rick Patterson rick.patterson at hotmail.com
Wed Jan 9 07:34:34 EST 2013

Hi, Peter.   Thank you for your reply.

To answer your questions (marked by >> )

> Your quote is "cd d:" but your command is "cd d:/" and those are
> different, so the above part is not very clear. Please clarify.

I am discussing trying to sftp to a "d:/" drive letter specification, as opposed to a d: sub-directory.  But the problem exists either way it is attempted, as far as i can see, whether it is "cd d:" or "cd d:/".

> Why would a behavior change be acceptable? Any change that you make
> must affect only Windows, and nothing else.

I agree.  The proposed change was #ifdef HAVE_CYGWIN, so it would only change existing behaviour under Cygwin.  I was not intending anywhere to imply that existing behaviour needed changing on other platforms, I am only discussing the Cygwin environment.

>> Stop right here. "d:" is *NOT* an absolute path on Windows systems.

Sorry, I meant d:/ which is an absolute path under DOS or Windows, but it is not an absolute path under Cygwin.  In a Cygwin shell, if you are in a directory with a d: sub-directory present, then if you like, you could specify "cd d:/" when referring to the d: sub-directory.   The use of a trailing slash when referring to any directory, whether absolute or relative, is not forbidden on a UNIX file system.    This is the whole problem with Cygwin on windows, there is an ambiguity possible when referring to any 2-character path specification that starts with a single alphabetic character (a-z), and the second character is a colon (:).  Such a sub-directory name is ambiguous with a drive letter specification.  Under Cygwin, the only way to know such an specification is referring to an absolute path is if it looks like an absolute path (i.e. is specified as d:/), and the absolute path (i.e. drive letter) actually exists!  Thus the behaviour of the Cygwin cd command depends on the existence of what stuff it finds! It will cd to an existing d: sub-directory only if a d: drive does not exist.   Thus "d:/" could be an absolute path or it could refer to a (relative path) sub-directory.   This problem does not happen on UNIX, where an absolute path is indicated merely by the presence of the first character being a /., and a relative path on UNIX is any path that does NOT start with a slash.

Since there is an existing way to specifically force an argument to be a relative path (by pre-pending a "./" to it, but there is no way to indicate something is really an absolute path under Cygwin, then a convention of some kind must be a applied.   One convention that seems to make sense is if we have a 2-character "letter-then-colon" specification, such as either "d:" or "d:/" then the argument handler  will look first for a drive specification, and only if it does not exist, then look for a sub-directory name d:.  This is the existing Cygwin command-line behaviour.   Since there is an ambigity possible on Cygwin, which does not occur on UNIX, then a choice must be made how to resolve it, and we have the precedence of the Cygwin command-line handler as a guide. If one really means to refer to a sub-directory named "d:", then they must use "./" in this case.

As indicated in my original post, implementing the same behaviour as the Cygwin command-line handler would likely be preferable, but beyond my capabilities, I was only doing the research into the existing behaviours that I am able to do.  Such a  fix would likely involve the sftp-server as you indicate.  However, it is the sftp-client code I found that is assuming that if a directory specification does not start with a / then it must be relative, which is only true on UNIX, and not under Cygwin, and this code would still have to be fixed in addition to the server side code.


> Date: Tue, 8 Jan 2013 18:35:50 +0100
> From: peter at stuge.se
> To: openssh-unix-dev at mindrot.org
> Subject: Re: sftp "cd" command to drive letter under cygwin
> Rick Patterson wrote:
>> When using sftp under cygwin, a "cd d:" attempt to change to the d:
>> drive, results in the following:
>> sftp> cd d:/
>> Couldn't canonicalise: No such file or directory.
> Your quote is "cd d:" but your command is "cd d:/" and those are
> different, so the above part is not very clear. Please clarify.
>> Since cygwin is supposed to support DOS paths as well as UNIX
>> paths, and the lcd is working, I thought I'd take a look at it. I
>> found the make_absolute function in sftp.c was assuming an absolute
>> path starts with '/', but this is not true on Windows. I think
>> the attached sftp.c.diff file is the fix, for your review, although
>> there is a behavior change I'd like to discuss below.
> Why would a behavior change be acceptable? Any change that you make
> must affect only Windows, and nothing else.
>> Previously, under Cygwin, in sftp, "cd d:" would not work, unless
>> there was a sub-directory in the current working directory that was
>> named "d:", which is allowed on the UNIX file system, as ":" is an
>> allowed file name character. With the proposed change, assuming
>> you want to "cd to d:" (where d: is a drive specification, and
>> therefore an absolute path),
> Stop right here. "d:" is *NOT* an absolute path on Windows systems.
> I'm sure you know that DOS and Windows both keep track of the current
> working directory per drive. "d:" changes working drive, but does NOT
> change current working directory either on the current driver or on d:.
> "d:\" and "d:/" are absolute paths.
>> the cd now works to the absolute path "d:" thereby supporting DOS
>> paths. However, it also changes the previous behavior, as "cd d:"
>> will now not go to the sub-directory "d:" if it exists, unless it
>> is qualified as "./d:"
> I can not understand why you would modify behavior for every other
> platform as well. Isn't it absolutely obvious that whatever change
> you do in order to improve this on Windows must have *NO* effect on
> the vast majority of other operating systems that OpenSSH supports?
>> A "d:" needs to be treated firstly as an absolute path before a
>> sub-directory.
> On Cygwin, "d:" is a path relative to the current working directory
> on drive d. Everywhere else, it is a path relative to the current
> working directory.
>> I agree a batter fix might be that "if d:" does not exist as a
>> drive letter, but there is a "d:" sub-directory, then cd to the
>> d: sub-directory.
> Absolutely not, in my opinion. You are proposing to add a heuristic
> into the user interface. Sorry, but that is just horrible.
>> I've tested the cd command under the Cygwin command line shell - it
>> does appear to be able to conditionally cd to d: as a DOS drive if
>> it exists, ignoring a d: sub-directory that exists. However, if
>> x: does not exist as a drive letter, but does exist as a
>> sub-directory then it does cd to x:. I believe an extra call from
>> the sftp client to the sftp server would be required to do the
>> conditional cd in sftp to be consistent with the Cygwin command
>> line, but this would be beyond my abilities.
> I'd suggest to look at the Cygwin source code to find out how exactly
> chdir() is implemented, and to make sftp-server implement the same
> algorithm. The client shouldn't have to be involved in this at all.
> (Unless Cygwin patches all shells to make multiple chdir() calls, but
> I find that somewhat unlikely.)
> //Peter
> _______________________________________________
> openssh-unix-dev mailing list
> openssh-unix-dev at mindrot.org
> https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev 		 	   		  

More information about the openssh-unix-dev mailing list