English Amiga Board


Go Back   English Amiga Board > Coders > Coders. System

 
 
Thread Tools
Old 10 August 2014, 08:59   #1
AGS
XoXo/Tasko Developer
 
AGS's Avatar
 
Join Date: Dec 2013
Location: Munich
Age: 48
Posts: 450
Happy Easy way to copy a file?

Hi,

I noticed I can "copy" a file from one Dir to another by using Rename(), when both Dirs are on the same Volume. If they are not, I think I must use Open() Read()/Write() and Close(). And I must read and write the file in portions as the whole file might not fit into memory. But isn't there an easier method to copy a file from one volume to another?

greets,
A
AGS is offline  
Old 10 August 2014, 10:10   #2
liviux76
Registered User
 
liviux76's Avatar
 
Join Date: Jan 2014
Location: BO/Italy
Posts: 711
I think that you can simply use the command "copy"

Supposing you are in DH0:

copy myfile DH1:Mydir/

You can omit the name of the "new" file if you want to keep the same or specify a new name if you want to change it when copying it.

Please, correct me if I am wrong...
liviux76 is offline  
Old 10 August 2014, 10:14   #3
AGS
XoXo/Tasko Developer
 
AGS's Avatar
 
Join Date: Dec 2013
Location: Munich
Age: 48
Posts: 450
If you did not mean that, I wanted to have a solution to do copying a file from my program side. But it's a good idea to just execute() the copy command in my program.
AGS is offline  
Old 10 August 2014, 11:05   #4
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
Why use execute()? Your original approach in the first post is correct. (What language are you programming in?)

Also, Rename() is more like a "move" than "copy".
alkis is offline  
Old 10 August 2014, 14:02   #5
liviux76
Registered User
 
liviux76's Avatar
 
Join Date: Jan 2014
Location: BO/Italy
Posts: 711
Quote:
Originally Posted by alkis View Post
Why use execute()? Your original approach in the first post is correct. (What language are you programming in?)

Also, Rename() is more like a "move" than "copy".
As far as I know "rename" for AmigaDOS is equal to "mv" in *nix shell so it moves and don't copy.
liviux76 is offline  
Old 10 August 2014, 19:46   #6
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
Well, I was bored...so here is a C implementation.
if return value >=0 then no errors occured. (returns the bytes copied on normal execution)
Otherwise, returns the errors in the defines.
Note: lightly tested (on KS3.1 and on KS1.3), seems to work though.

Code:
#include <exec/types.h>
#include <dos/dos.h>
#include <proto/exec.h>
#include <proto/dos.h>


#define FILECOPY_DEFAULT_BUFFERSIZE	(32768)
#define FILECOPY_SOURCE_FILE_ERROR	(-1)
#define FILECOPY_DESTINATION_FILE_ERROR	(-2)
#define FILECOPY_BUFFER_MEMORY_ERROR	(-3)
#define FILECOPY_READ_WRITE_ERROR	(-4)


LONG FileCopy(STRPTR from, STRPTR to)
{
	LONG readBytes, writtenBytes;
	LONG totalBytes = 0;
	BPTR fromBPTR, toBPTR;
	void *buffer;
	LONG buflen = FILECOPY_DEFAULT_BUFFERSIZE;



	fromBPTR = Open(from, MODE_OLDFILE);
	if (!fromBPTR) {
		//PrintFault(IoErr(),"Open()");	//needs >=KS2.0
		return FILECOPY_SOURCE_FILE_ERROR;
	}
	toBPTR = Open(to, MODE_NEWFILE);		// !!!no overwrite check!!!
	if (!toBPTR) {
		//PrintFault(IoErr(),"Open2()");	//needs >=KS2.0
		Close(fromBPTR);
		return FILECOPY_DESTINATION_FILE_ERROR;
	}

	while (!(buffer = AllocMem(buflen, MEMF_ANY))) {
		buflen >>= 1;
		if (buflen < 1024) { //if there not even a Kb free, shut it down, return error.
			Close(fromBPTR);
			Close(toBPTR);
			return FILECOPY_BUFFER_MEMORY_ERROR;
		}
	}

	while ((readBytes = Read(fromBPTR, buffer, buflen)) > 0) {
		writtenBytes = Write(toBPTR, buffer, readBytes);
		if (writtenBytes == -1 || writtenBytes != readBytes) {
			//PrintFault(IoErr(),"Write()");	//needs >=KS2.0
			break;
		}
		totalBytes += writtenBytes;
	}

	Close(fromBPTR);
	Close(toBPTR);
	FreeMem(buffer, buflen);

	if (readBytes) {
		DeleteFile(to);	//Delete the destination file on read/write error
		return FILECOPY_READ_WRITE_ERROR;
	}
	return totalBytes;
}

Last edited by alkis; 10 August 2014 at 19:51. Reason: Mention KS1.3 combartibility
alkis is offline  
Old 11 August 2014, 13:40   #7
AGS
XoXo/Tasko Developer
 
AGS's Avatar
 
Join Date: Dec 2013
Location: Munich
Age: 48
Posts: 450
Happy

The Rename() DOS library function is good for moving files, however it does not work across different volumes. I hoped that there was a single library function for copying a file somehow (which I could also use for moving a file with one Delete() added).

I am coding in 68k-ASM. The source is now exactly what I need (I can 'compile' it in my mind ). It's a great idea to catch a buffer something like as large as possible and to use the returns of Read() and Write() to handle errors and when the last portion of the file that is shorter than the buffer. The code works perfectly without finding out the actual filesize.

I can easily turn the function you wrote into a "move" when I need that.

How would you handle a progress bar? Check the filesize first, divide it by buffer length and set the result as max (for the bar)? But how handling the last portion? Round up the result of the division (ceil())? The bar may jump from one pos. to the next, but not grow too far or too few in total. Where in your code would you call the current setting of the progress bar?

Thanks.
AGS is offline  
Old 11 August 2014, 14:15   #8
BigFan
Registered User
 
BigFan's Avatar
 
Join Date: Feb 2014
Location: Germany
Posts: 261
Variable "totalBytes" is increased by the amount of bytes written successfully. You could use that in relation to total file size.
No need to divide by bufferlen or any kind of rounding
Last portion will be shown correctly by default.

And i would call the function for progress bar there too.
BigFan is offline  
Old 11 August 2014, 15:02   #9
AGS
XoXo/Tasko Developer
 
AGS's Avatar
 
Join Date: Dec 2013
Location: Munich
Age: 48
Posts: 450
Ah, I see. Thanks.
AGS is offline  
Old 11 August 2014, 19:52   #10
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
Hmmm, you need something like that to get the size prior the actual copying if you want to feed a progress bar. You can call it right before the while(read/write) loop on the source filename. (it will probably fail on destination filename and also is pointless )
Note: if something fails returns 0, so you may want to guard against that.
Code:
LONG GetFileSize(STRPTR filename)
{
	__aligned struct FileInfoBlock fib; // this MUST be alligned on longword
	LONG ret=0;
	BPTR lockFrom;

	if (lockFrom = Lock(filename,ACCESS_READ)) {
		if (Examine(lockFrom,&fib)) {
			ret=fib.fib_Size;
		}
		UnLock(lockFrom);
	}
	return ret;
}
alkis is offline  
Old 11 August 2014, 20:00   #11
AGS
XoXo/Tasko Developer
 
AGS's Avatar
 
Join Date: Dec 2013
Location: Munich
Age: 48
Posts: 450
Another way to get the filesize is to seek for it, just after the file has been opened: Seek once to it's end and then back to start. Result will be the size of the file. Then start reading.
AGS is offline  
Old 11 August 2014, 20:31   #12
AGS
XoXo/Tasko Developer
 
AGS's Avatar
 
Join Date: Dec 2013
Location: Munich
Age: 48
Posts: 450
Lightbulb

Here is the Seek() Variant to get filesize w/o need of a fileinfoblock:

Code:
		move.l	cf_inhandle(a7),d1
		moveq	#0,d2
		move.l	#OFFSET_END,d3
		jsr	_LVOSeek(a6)

		; The result here can only be negativ, or zero,
		; as we started at pos 0. And 0 is exactly what
		; we need in d2 here, as offset for the second seek. 

		move.l	d0,d2
		bmi	.ioerr

		; As Seek()
		; returns the old pos in the file, the whole
		; filesize is returned when we seek from the end.

		move.l	cf_inhandle(a7),d1
		move.l	#OFFSET_START,d3
		jsr	_LVOSeek(a6)

		move.l	d0,cf_filesize(a7)
		bmi	.ioerr

Last edited by AGS; 11 August 2014 at 20:37.
AGS is offline  
Old 11 August 2014, 20:39   #13
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,514
Better use Examine() to get file size because seek method is really slow if file is large and filesystem is OFS or FFS.
Toni Wilen is offline  
Old 11 August 2014, 20:43   #14
AGS
XoXo/Tasko Developer
 
AGS's Avatar
 
Join Date: Dec 2013
Location: Munich
Age: 48
Posts: 450
Good to know!
AGS is offline  
Old 11 August 2014, 20:54   #15
Thorham
Computer Nerd
 
Thorham's Avatar
 
Join Date: Sep 2007
Location: Rotterdam/Netherlands
Age: 47
Posts: 3,761
Use ExamineFH() to get the file info block from a file handle. That way you don't have to Lock() the file first. Allocate space for the file info block with AllocDosObject().
Thorham is offline  
Old 11 August 2014, 20:55   #16
AGS
XoXo/Tasko Developer
 
AGS's Avatar
 
Join Date: Dec 2013
Location: Munich
Age: 48
Posts: 450
AH, very good!
AGS is offline  
Old 11 August 2014, 20:58   #17
Thorham
Computer Nerd
 
Thorham's Avatar
 
Join Date: Sep 2007
Location: Rotterdam/Netherlands
Age: 47
Posts: 3,761
Forgot to add that you should free the memory allocated with AllocDosObject() with FreeDosObject().
Thorham is offline  
Old 11 August 2014, 21:01   #18
AGS
XoXo/Tasko Developer
 
AGS's Avatar
 
Join Date: Dec 2013
Location: Munich
Age: 48
Posts: 450
There is written something that the filesize returned does not reflect the realsize when someone is active in it ...
AGS is offline  
Old 11 August 2014, 21:05   #19
alkis
Registered User
 
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
ExamineFH() kills 1.3 combartibility (don't know if that's an issue, just saying)

Also, no need to AllocDosObject() for two reasons:
- Alligning on longword is enough
- KS1.3 combartibility ;-)
alkis is offline  
Old 11 August 2014, 21:06   #20
AGS
XoXo/Tasko Developer
 
AGS's Avatar
 
Join Date: Dec 2013
Location: Munich
Age: 48
Posts: 450
May I reuse an allocated fib for multiple files?
AGS is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Copy file from PC filesystem to WinUAE harddisk Raizor support.WinUAE 2 10 January 2011 20:44
Copy CF card file to ram:, insert other CF card, copy over? Photon support.Hardware 16 21 July 2009 22:05
Very slow file copy? DDNI support.WinUAE 4 16 March 2009 22:16
Copy file containing control codes to printer? Photon support.Apps 1 10 December 2006 02:36
Problems with massive file copy & JIT jotd support.WinUAE 1 15 November 2006 19:16

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 17:54.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.10505 seconds with 15 queries