www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - std.file.copy isn't a true copy operation

reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Most of the functions in std.file are written to use OS API functions 
where applicable.  However, for some obscure reason, copy goes out of 
its way not to use any such thing, but instead it loads the file and 
re-saves it.

I knew of a program that transferred movie files like this, though 
probably doing it in chunks rather than all at once.  The consequence 
was that it was rather slow, and screwed up the timestamps.

OTOH, a file copy operation (on MS-DOS and Windows at least) preserves 
timestamps and certain attributes, and (also unlike std.file.copy) will 
work fine on files of arbitrary size (within obvious constraints).

Doing a file copy on Win32 is as straightforward as the other various 
file operations.  Here it is:

----------
void copy(char[] from, char[] to) {
     BOOL result;

     if (useWfuncs) {
         result = CopyFileW(std.utf.toUTF16z(from), std.utf.toUTF16z(to),
           false);
     } else {
         result = CopyFileA(toMBSz(from), toMBSz(to), false);
     }
     if (!result) {
         throw new FileException(to, GetLastErrror());
     }
}
----------

This should be put in version(Win32), and the current implementation 
moved into the version(linux) block.

The CopyFile functions'll also have to be put in std.c.windows.windows:

----------
BOOL CopyFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName,
   BOOL bFailIfExists);
BOOL CopyFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName,
   BOOL bFailIfExists);
----------

I imagine that there's also an OS call on Unix platforms to do it, 
though I haven't as yet found it.

Stewart.

-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on 
the 'group where everyone may benefit.
Feb 24 2005
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message 
news:cvkeme$rps$1 digitaldaemon.com...
 Most of the functions in std.file are written to use OS API functions 
 where applicable.  However, for some obscure reason, copy goes out of 
 its way not to use any such thing, but instead it loads the file and 
 re-saves it.

 I knew of a program that transferred movie files like this, though 
 probably doing it in chunks rather than all at once.  The consequence 
 was that it was rather slow, and screwed up the timestamps.

 OTOH, a file copy operation (on MS-DOS and Windows at least) preserves 
 timestamps and certain attributes, and (also unlike std.file.copy) 
 will work fine on files of arbitrary size (within obvious 
 constraints).

 Doing a file copy on Win32 is as straightforward as the other various 
 file operations.  Here it is:

 ----------
 void copy(char[] from, char[] to) {
     BOOL result;

     if (useWfuncs) {
         result = CopyFileW(std.utf.toUTF16z(from), 
 std.utf.toUTF16z(to),
           false);
     } else {
         result = CopyFileA(toMBSz(from), toMBSz(to), false);
     }
     if (!result) {
         throw new FileException(to, GetLastErrror());
     }
 }
 ----------

 This should be put in version(Win32), and the current implementation 
 moved into the version(linux) block.

 The CopyFile functions'll also have to be put in 
 std.c.windows.windows:

 ----------
 BOOL CopyFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName,
   BOOL bFailIfExists);
 BOOL CopyFileW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName,
   BOOL bFailIfExists);
 ----------

 I imagine that there's also an OS call on Unix platforms to do it, 
 though I haven't as yet found it.

There may be some on individual flavours, but I'm moderately sure it's not a standard UNIX thing. I totally agree about the timestamps, etc.
Feb 28 2005
parent reply Nick <Nick_member pathlink.com> writes:
In article <d0064p$rgm$2 digitaldaemon.com>, Matthew says...
 I imagine that there's also an OS call on Unix platforms to do it, 
 though I haven't as yet found it.

There may be some on individual flavours, but I'm moderately sure it's not a standard UNIX thing.

I'm pretty sure too. For fun I downloaded and checked the source for 'cp' from gnu.org. It looks mighty long and complicated, not as small and elegant a program as you would think. Nick
Mar 01 2005
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Nick wrote:
 In article <d0064p$rgm$2 digitaldaemon.com>, Matthew says...
 
 I imagine that there's also an OS call on Unix platforms to do it, 
 though I haven't as yet found it.

There may be some on individual flavours, but I'm moderately sure it's not a standard UNIX thing.

I'm pretty sure too. For fun I downloaded and checked the source for 'cp' from gnu.org.

Any recollection of the exact URL? I can't seem to find it with a quick look.
 It looks mighty long and complicated, not as small and elegant a 
 program as you would think.

That suggests that a file copy operation on Unix essentially means running this tool. And it seems that on at least some Unices, copying doesn't preserve timestamps. When I try from Mac OS X, there seems to be a grey area - copying from Finder preserves the timestamp, but cp from the shell doesn't. (Does this mean that the correct behaviour of copy depends on whether you're writing a GUI app or a commandline tool?) But both seem to preserve the permissions, something else that std.file.copy doesn't. (OTOH, DOS and Windows copy operations seem to differ in which attributes they preserve, while both preserve the timestamp.) Moreover, ITLR we also need something that'll work on arbitrarily large files, and preferably with O(1) rather than O(n) memory requirement. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Mar 01 2005
parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
GNU cp has a '-p' parameter which preserves timestamps.  But, as you 
say, the default is to no preserve them.

FYI:
One of the things (there are probably many, I'd guess) that makes GNU cp 
complex is the support for sparse files.  Some filesystems have the 
ability to save space by not allocating any disk space for blocks that 
are all zeroes.  GNU cp has the capability to take an existing file, 
detect the 0 blocks in it, and then in the new file only write the 
blocks that are nonzero.

Stewart Gordon wrote:
 Nick wrote:
 
 In article <d0064p$rgm$2 digitaldaemon.com>, Matthew says...

 I imagine that there's also an OS call on Unix platforms to do it, 
 though I haven't as yet found it.

There may be some on individual flavours, but I'm moderately sure it's not a standard UNIX thing.

I'm pretty sure too. For fun I downloaded and checked the source for 'cp' from gnu.org.

Any recollection of the exact URL? I can't seem to find it with a quick look.
 It looks mighty long and complicated, not as small and elegant a 
 program as you would think.

That suggests that a file copy operation on Unix essentially means running this tool. And it seems that on at least some Unices, copying doesn't preserve timestamps. When I try from Mac OS X, there seems to be a grey area - copying from Finder preserves the timestamp, but cp from the shell doesn't. (Does this mean that the correct behaviour of copy depends on whether you're writing a GUI app or a commandline tool?) But both seem to preserve the permissions, something else that std.file.copy doesn't. (OTOH, DOS and Windows copy operations seem to differ in which attributes they preserve, while both preserve the timestamp.) Moreover, ITLR we also need something that'll work on arbitrarily large files, and preferably with O(1) rather than O(n) memory requirement. Stewart.

Mar 01 2005