Bug 5531 - Robocopy utility does not skip unchanged files when copying to SAMBA server
Robocopy utility does not skip unchanged files when copying to SAMBA server
Status: RESOLVED FIXED
Product: Samba 3.0
Classification: Unclassified
Component: File Services
3.0.25
Other Linux
: P3 normal
: none
Assigned To: Samba Bugzilla Account
Samba QA Contact
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2008-06-09 17:36 UTC by Hames Kurma
Modified: 2008-06-20 15:26 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Hames Kurma 2008-06-09 17:36:22 UTC
The robocopy application from Microsoft can be used to copy files along with attributes, security, ... etc from one server to another. If the robocopy application is used from a server to SAMBA based server and then the command is executed again, robocopy copies all the files again, as robocopy finds the source files newer than the files on the SAMBA server, even though the source files are not changed.

This bug is due to incorrect converion of 64-bit NTTIME into Unix time "struct timespec" in nt_time_to_unix_timespec. The calculation of time in nano seconds is incorrect, truncating the actual time in nano seconds by an order of magnitude.

The bug is fixed by correcting the calculation:

struct timespec nt_time_to_unix_timespec(NTTIME *nt)
{
	int64 d;
	struct timespec ret;

	if (*nt == 0 || *nt == (int64)-1) {
		ret.tv_sec = 0;
		ret.tv_nsec = 0;
		return ret;
	}

	d = (int64)*nt;
	/* d is now in 100ns units, since jan 1st 1601".
	   Save off the ns fraction. */
	
#ifdef BUGFIX
	/*
	 * Take the last seven decimal digits and multiply by 100.
	 */
	ret.tv_nsec = (long) ((d % (1000 * 1000 * 10)) * 100);
#else
	/*
	 * Original SAMBA code.
	 */
	ret.tv_nsec = (long) ((d % 100) * 100);
#endif /* BUGFIX */

	/* Convert to seconds */
	d /= 1000*1000*10;

	/* Now adjust by 369 years to make the secs since 1970 */
	d -= TIME_FIXUP_CONSTANT_INT;

	if (d <= (int64)TIME_T_MIN) {
		ret.tv_sec = TIME_T_MIN;
		ret.tv_nsec = 0;
		return ret;
	}

	if (d >= (int64)TIME_T_MAX) {
		ret.tv_sec = TIME_T_MAX;
		ret.tv_nsec = 0;
		return ret;
	}

	ret.tv_sec = (time_t)d;
	return ret;
}
Comment 1 Jeremy Allison 2008-06-20 15:26:35 UTC
Perfectly correct - thanks ! Pushed in all git trees. Thanks a lot for this fix.
Jeremy.