Bug 6116 - Cannot access files in exposed shadow drive in version 3.0.5
Summary: Cannot access files in exposed shadow drive in version 3.0.5
Status: RESOLVED FIXED
Alias: None
Product: rsync
Classification: Unclassified
Component: core (show other bugs)
Version: 3.1.0
Hardware: x86 Windows NT
: P3 normal (vote)
Target Milestone: ---
Assignee: Wayne Davison
QA Contact: Rsync QA Contact
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-02-15 16:18 UTC by Leon V.
Modified: 2011-05-08 21:27 UTC (History)
0 users

See Also:


Attachments
source code for simple test program (1.52 KB, application/octet-stream)
2011-04-20 01:52 UTC, Leon V.
no flags Details
Fix change_dir() to avoid turning "/" into "//subdir". (684 bytes, patch)
2011-05-08 21:27 UTC, Wayne Davison
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Leon V. 2009-02-15 16:18:25 UTC
Hi,

In 3.0.4, I encountered a problem with dot-dir path (e.g. , foo/./bar) inside
a -files-from file when the root of the transfer isn't in the current
directory.  This was fixed in 3.05 (well, partially).  3.0.5 bug fixes
release info:

    - Fixed the use of a dot-dir path (e.g. foo/./bar) inside a --files-from
      file when the root of the transfer isn't the current directory.

3.05 works fine unless the backup is using an exposed shadow.  In this case,
the C: and D: drives are exposed as H: and I: respectively.  I get the
following error:

rsync: change_dir "/cygdrive/H" failed: No such host or network path (136)

This causes zero (0) files to be transferred, and 
   rsync error: some files/attrs were not transferred (see previous

(Repeats for I: drive)

  rsync: change_dir "/cygdrive/I" failed: No such host or network path (136)

and
  rsync error: some files/attrs were not transferred (see previous errors)
(code 23) at main.c(1040) [sender=3.0.5]

Cygwin is able to change_dir into /cygdrive/H and /cygdrive/I with no
problems, so the drives appear to be valid.

This DOES work in 2.6.8.

Leon
Comment 1 Wayne Davison 2011-01-01 14:06:53 UTC
From the cited error messages, rsync is just trying to chdir to /cygdrive/H (or I) and getting a system error.  You will need to investigate why that system error is occurring.  If there is something that rsync should be doing differently, let me know.
Comment 2 Leon V. 2011-01-02 22:33:25 UTC
Thanks to Wayne for his follow-up on this report.  His email got me chasing.  He is correct -- the problem is not rsync.  It seems that changes to Cygwin 1.7 will not allow access to a shadow that is exposed as a drive letter (http://cygwin.com/ml/cygwin/2009-07/msg00954.html for one example of this problem documented on the web).

Best regards,
Leon
Comment 3 Leon V. 2011-04-20 01:52:29 UTC
Created attachment 6419 [details]
source code for simple test program

This is the source for the simple test program I wrote.
Comment 4 Leon V. 2011-04-20 01:54:20 UTC
I hope I am not over-stepping any boundaries with the re-open, but I am now convinced that there is an rsync problem.

I have recently been working on an rsync implementation using shadows on a Windows 7 64 bit machine.  The new work uses diskshadow to create the shadows and expose them as drive letters.  I hit the same problem - cygwin shell can cd into /cygdrive/G (the exposed drive letter) and see everything in it, but rsync fails with 
    rsync: change_dir "/cygdrive/g" failed: No such file or directory (2)

The --from-files for testing contained
    /cygdrive/g/./Downloads/

In testing, I removed the . in the path (leaving /cygdrive/g/Downloads/) and the rsync worked (although it put the files in a location preceeded but the cygdrive/g/, but I expected that).  I took that to mean that rsync could, indeed, access the shadow (G:) drive.

Since the error says 
    rsync: change_dir "/cygdrive/g" failed: No such file or directory (2)
I decided to dig into the source code and see what I could figure out.  I am, at best, a hack C programmer, but I worked through the source code enough to find change_dir, and I believe that function uses chdir(), so I decided to see if a simple C program can chdir into /cygdrive/G.  

I wrote a very simple C program, and it could, indeed chdir into /cygdir/G and open files there-in.  This would seem to indicate that something in the rsync change_dir is malfunctioning.  

I wish I had sufficient skills to compile and debug this, but I seem to have hit the end of my abilities.

Please feel free to contact or email me with any questions.

THANKS!
Leon
Comment 5 Leon V. 2011-04-20 01:56:32 UTC
I forgot to include that I am now using rsync 3.0.7.

Leon
Comment 6 Leon V. 2011-04-20 03:25:53 UTC
I forgot to include that I am now using rsync 3.0.7.

Leon
Comment 7 Leon V. 2011-04-20 23:34:44 UTC
I decided to "hack" at this some more.  I downloaded the source code for 3.0.8 and compiled it, and began to run GDB.  Not sure if this will help, but the call to util.c change_dir() with cygdrive/G (G: is the exposed shadow for C:) 
yeilds some strange behavior that is beyond my expertise.

The global variable curr_dir starts out correctly containing "/cygdrive/c/Downloads/rsync308" but when the call to 
change_dir(cygdir/g) is made, it has been trashed by a NULL character and contains "/\000ygdrive/c/Downloads/rsync308".

While in this section of code (util.c), I cannot get the variable len to print:
    1011            if (len == 1 && *dir == '.')
    (gdb) print len
    No symbol "len" in current context.

When the call to chdir(curr_dir) is made, the curr_dir variable contains
     "//cygdrive/g\000ownloads/rsync308"  (note the double forward slash)

Hoping this will help...

Leon
Comment 8 Matt McCutchen 2011-04-21 00:56:47 UTC
(In reply to comment #7)
> The global variable curr_dir starts out correctly containing
> "/cygdrive/c/Downloads/rsync308" but when the call to 
> change_dir(cygdir/g) is made, it has been trashed by a NULL character and
> contains "/\000ygdrive/c/Downloads/rsync308".

In other words, the null-terminated string "/".  I would imagine that is intentional.

> When the call to chdir(curr_dir) is made, the curr_dir variable contains
>      "//cygdrive/g\000ownloads/rsync308"  (note the double forward slash)

A double slash is a UNC path on Windows, so that would explain the error.  (That sloppiness would go unpunished on Linux.)  The question is where the double slash is coming from.
Comment 9 Leon V. 2011-04-21 03:14:33 UTC
the Windows UNC convention is backslash backslash (\\servername\...) not forward slashes.

As to where the // is coming from, I have never been able to get a gdb variable watch to work on my systems...

Leon
Comment 10 Leon V. 2011-04-22 22:11:40 UTC
I may have figured it out, but I don't have any idea how to "Check-in" a fix.  The problem is in util.c, function change_dir.  Version 3.0.8:

line number 1027 appends a slash to the curr_dir (current directory) variable.
1027    curr_dir[curr_dir_len] = '/';
line number 1028 then appends the dir (new directory)
1028    memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);

The problem is, if you are in the root directory ("/"), line 1027 adds a second slash ("//").

The fix I compiled and tested on my system (granted this is limited testing) is to replace 1027 and 1028 with:

    // if in root, don't add a slash and don't add 
    // one to the current directory length
    if ( ( curr_dir_len == 1 ) && ( curr_dir[0] == '/' ) ) {
        memcpy(curr_dir + curr_dir_len, dir, len + 1);
    }
    else { // add the slash and add one to len curr_dir_len to
           // account for the slash that was added
	curr_dir[curr_dir_len] = '/';
	memcpy(curr_dir + curr_dir_len + 1, dir, len + 1);
    }

Accessing the shadow drive now works fine!

Leon
Comment 11 Wayne Davison 2011-05-08 21:27:12 UTC
Created attachment 6439 [details]
Fix change_dir() to avoid turning "/" into "//subdir".

This was checked into git back on April 22nd.
Comment 12 Wayne Davison 2011-05-08 21:27:51 UTC
This will be fixed in the next release.  Thanks for tracking down the issue!