TweetFollow Us on Twitter

CopyFile XCMD
Volume Number:5
Issue Number:10
Column Tag:HyperChat™

Related Info: File Manager

XCMD Corner: CopyFile

By Donald Koscheka, Arthur Young & Co., MacTutor Contributing Editor

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

CopyFile XCMD

From time to time I monitor the developer forums on AppleLink and MacNet to see what the rest of the Macintosh development community is up to. Recently, Richard Greenawalt of Foremost Computer Systems issued a request for some help. It seems he needed a routine that copies Macintosh files, data fork, resource fork and finder information.

Not one to miss an opportunity to write an interesting XCMD, I 'linked Rick back and told him that I would be happy to write the routine for him.

The moral of the story is: ask and you might receive. If you need some help with an XCMD or if this column just doesn’t do it for you, let me know; I will be more than happy to help you out. Although I am up on AppleLink, I prefer to use MacNet (KOSCHEKA). If you don’t have access to a modem, write me care of MacTutor.

Copying a Macintosh file is not difficult as long as you keep in mind that Mac files are really two files in one. Each file on the Macintosh has a split personality - the data fork and the resource fork. Although the two forks act as one entity, the file manager treats them as separate files.

CopyFile is a handy little XCMD that lets you copy files from Hypercard. Actually the routine is written to work from any programming milieu which is why I’ve split it into two listings. The first consists of the Hypercard interface. Note that you need to pass both the file name and the working directory id. The second listing contains the actual code, void of any references to Hypercard. This approach lets me build libraries of usable routines that I can use with or without Hypercard, and I intend to use it for all future listings.

The CopyFile function expects to see the name of the input file, the name of the output file and the working directory id’s of both. This gives you some flexibility in naming the copy as well as deciding what folder to put it in. For example, you can concatenate the name of the input file to “copy of “ so that the duplicated file is called “copy of file”. Put this concept in a loop and you get the finder like capability of creating files and naming them “copy of ... “ , “copy of copy of ...” and so on. I chose not to implement this approach because I think the user should have the opportunity to specify the name of the copied file.

Although there are several ways to go about copying a file, I chose a path that goes something like this: First, get the collective size of the data and resource fork along with the finder information about the input file. Using this information, attempt to create a file that is as large as the input file (ie as large as the data and resource fork combined). If the space can be allocated, then copy each fork in turn. If not, delete the newly created file and quit.

Space for each fork is allocated before we do the copy so that we can determine a priori whether the file will fit. To be safe, we reposition the file mark at the beginning of the file before we start copying. If, for any reason, the file copy fails, delete what remains of the file and return the error message to the caller.

The real work is done by the function, CopyFork. This routine will attempt to read the entire fork into a single buffer. Failing that, it divides the size in half until enough memory can be allocated to read some of the fork. Note that copyfork attempts to allocate a buffer large enough to read the entire fork into memory. If that much memory is not available, it keeps dividing the original size by two until a large enough buffer can be allocated.

That’s file copying in a nutshell. It’s not particularly difficult once you realize that you’re really copying two files - the data fork and the resource fork. I’ve tried it with files up to 4 megabytes in size and it works fine.

/**********************************/
/* File: FileCopy.c*/
/* param0 = file reference num*/
/* ( file is open) IN:    */
/* params[0]= name of input */
/* params[1]= wdid of input */
/* params[2]   = name of output  */
/* params[3]   = wdid of output  */
/**********************************/
#include<MacTypes.h>
#include<OSUtil.h>
#include<MemoryMgr.h>
#include<FileMgr.h>
#include<ResourceMgr.h>
#include<pascal.h>
#include<string.h>
#include  “HyperXCMD.h”
#include“HyperUtils.h”

pascal void main( paramPtr )
 XCmdBlockPtr  paramPtr;
/*****************************
*params[0]= name of input 
*params[1]= wdid of input 
*params[2]  = name of output
*params[3]  = wdid of output
*****************************/
{ OSErr err;
 short  inWD;
 short  outWD;
 long   temp;
 Str31  errCode;
 char   inFile[256];
 char   outFile[256];
 paramPtr->returnValue = 0L;
 /*** (1) Get input parameters     ***/
 HLock( paramPtr->params[0] );
 ZeroToPas( paramPtr, *(paramPtr->params[0]), &inFile );
 HUnlock( paramPtr->params[0] );
 inWD = (short)paramtoNum( paramPtr, 1 );
 HLock( paramPtr->params[2] );
 ZeroToPas( paramPtr, *(paramPtr->params[2]), &outFile );
 HUnlock( paramPtr->params[2] );
 outWD = (short)paramtoNum( paramPtr, 3 );
 temp = (long)CopyFile( inFile, inWD, outFile, outWD );
 /*** Flush the output volume ***/
 err = FlushVol( 0L, 0 );
 NumToStr( paramPtr, temp, &errCode );
 paramPtr->returnValue = PasToZero( paramPtr, &errCode );
}

LISTING 1: CopyFile XCMD.


OSErr CopyFork( inref, outref, siz )
 short  inref;   short  outref;  longsiz;
/*****************************
* Given that the caller has opened
* a fork and passed you the names of 
* the input, copy the number of bytes
* from the input fork to the output 
* fork.
* The input mark should be set to 
* start of fork.
* We use a “semi-smart” algorithm
* to do the copy.  If the entire
* fork can be copied, we try doing 
* that, otherwise, we keep dividing
* the size by two until we get enough
* room to read some data in.
******************************/
{
 OSErr  rd_err   = noErr;
 OSErr  wrt_err  = noErr;
 long   rd_len;  /*** actual bytes read ***/
 Ptr    inbuf;
 /*** make sure that the size is even ***/
 if( siz % 2 )
 ++siz;
 if( siz > 0 ){
 do{
 inbuf = NewPtr( siz );
 if( !inbuf )
 siz = ( siz >> 1 );
 }while( !inbuf );
 /*** inbuf is the buffer that we  ***/
 /*** read the data into. If not   ***/
 /*** allocated, don’t attempt to do ***/
 /*** the read   ***/
 if( inbuf ){
 do{
 rd_len = siz;
 rd_err = FSRead( inref, &rd_len, inbuf );
 wrt_err= FSWrite( outref, &rd_len, inbuf );
 }while( !rd_err && !wrt_err );
 
 DisposPtr( inbuf );
 }
 }
 return( wrt_err );
}

OSErr CopyFile( inFile, inWD, outFile, outWD )
 char   *inFile;
 short  inWD; char *outFile;
 short  outWD;
/*****************************
* (1) Determine the size of the input 
* file. 
* (2) Attempt to allocate that 
* much space for the output file.
* (3) If allocation successful,
* create the output file.
* (4) Once the file is created,
* copy the data fork, the resource
* fork and the finder information
* from the input file.
* The file will be called “copy of...”
* Each time we create the file, first
* see if that name exists, if so, keep
* sticking “copy of” onto the name.
******************************/
{
 OSErr  err;
 OSErr  err2;
 short  inref;
 short  outref;
 long   data_eof = 0L;
 long   rsrc_eof = 0L;
 FInfo  fndrinfo;
 /*** (2) Determine how big the input file is ***/
 if( (err = FSOpen( inFile, inWD, &inref )) == noErr){
 err = GetEOF( inref, &data_eof );
 err = FSClose( inref );
 } 
 if( (err = OpenRF( inFile, inWD, &inref )) == noErr ){
 err = GetEOF( inref, &rsrc_eof );
 err = FSClose( inref );  
 }
 /*** (2) Create  output file and allocate space***/
 if( ( err = GetFInfo( inFile, inWD, &fndrinfo ) ) != noErr )
 return( err );
 if( ( err = Create( outFile, inWD, fndrinfo.fdCreator, fndrinfo.fdType 
)) != noErr )
 return( err );
 /*** (3) Try to allocate enough space for both***/
 /*** forks. Note that if we get enough space. ***/
 if( (err = FSOpen( outFile, outWD, &outref )) != noErr)
 return( err );
 if( (err = SetEOF( outref, data_eof  )) != noErr ){
 err2 = FSClose( outref );
 err2 = FSDelete( outFile, outWD );
 return( err );
 }
 err2   = FSClose( outref );
 err  = OpenRF( outFile, outWD, &outref );
 if( (err = SetEOF( outref, rsrc_eof  )) != noErr ){
 err2 = FSClose( outref );
 err2 = FSDelete( outFile, outWD );
 return( err );
 }
 err2 = FSClose( outref );
 /*** (4) Copy the Data fork***/
 err  = FSOpen( inFile, inWD, &inref );
 if( !err ){
 err2   = SetFPos( inref, fsFromStart, 0L );
 err    = CopyFork( inref, outref, data_eof );
 err2   = FSClose( inref );
 err2   = FSClose( outref );
 }
 if( err ){
 err2 = FSDelete( outFile, outWD );
 return( err );
 }
 /*** (5) Now copy the resource fork ***/
 err  = OpenRF( inFile, inWD, &inref );
 if( !err ){
 err2   = SetFPos( inref, fsFromStart, 0L );
 err  = OpenRF( outFile, outWD, &outref );
 err    = CopyFork( inref, outref, rsrc_eof );
 err2   = FSClose( inref );
 err2   = FSClose( outref );
 }
 if( err ){
 err2 = FSDelete( outFile, outWD );
 return( err );
 }
 return( noErr );
}

LISTING 2: CopyFile and CopyFork Functions.

 
AAPL
$96.02
Apple Inc.
-2.13
MSFT
$43.34
Microsoft Corpora
-0.24
GOOG
$573.60
Google Inc.
-13.82

MacTech Search:
Community Search:

Software Updates via MacUpdate

Ember 1.8 - Versatile digital scrapbook....
Ember (formerly LittleSnapper) is your digital scrapbook of things that inspire you: websites, photos, apps or other things. Just drag in images that you want to keep, organize them into relevant... Read more
OmniPlan 2.3.6 - Robust project manageme...
With OmniPlan, you can create logical, manageable project plans with Gantt charts, schedules, summaries, milestones, and critical paths. Break down the tasks needed to make your project a success,... Read more
Command-C 1.1.1 - Clipboard sharing tool...
Command-C is a revolutionary app which makes easy to share your clipboard between iOS and OS X using your local WiFi network, even if the app is not currently opened. Copy anything (text, pictures,... Read more
Knock 1.1.7 - Unlock your Mac by knockin...
Knock is a faster, safer way to sign in. You keep your iPhone with you all the time. Now you can use it as a password. You never have to open the app -- just knock on your phone twice, even when it's... Read more
Mellel 3.3.6 - Powerful word processor w...
Mellel is the leading word processor for OS X and has been widely considered the industry standard since its inception. Mellel focuses on writers and scholars for technical writing and multilingual... Read more
LibreOffice 4.3.0.4 - Free Open Source o...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
Freeway Pro 7.0 - Drag-and-drop Web desi...
Freeway Pro lets you build websites with speed and precision... without writing a line of code! With it's user-oriented drag-and-drop interface, Freeway Pro helps you piece together the website of... Read more
Drive Genius 3.2.4 - Powerful system uti...
Drive Genius is an OS X utility designed to provide unsurpassed storage management. Featuring an easy-to-use interface, Drive Genius is packed with powerful tools such as a drive optimizer, a... Read more
Vitamin-R 2.15 - Personal productivity t...
Vitamin-R creates the optimal conditions for your brain to work at its best by structuring your work into short bursts of distraction-free, highly focused activity alternating with opportunities for... Read more
Toast Titanium 12.0 - The ultimate media...
Toast Titanium goes way beyond the very basic burning in the Mac OS and iLife software, and sets the standard for burning CDs, DVDs, and now Blu-ray discs on the Mac. Create superior sounding audio... Read more

Latest Forum Discussions

See All

Puzzle Roo Review
Puzzle Roo Review By Jennifer Allen on July 31st, 2014 Our Rating: :: PUZZLE-BASED TWISTUniversal App - Designed for iPhone and iPad A different take on the usual block dropping puzzle game, Puzzle Roo is quite pleasant.   | Read more »
Super Crossfire Re-Release Super Crossfi...
Super Crossfire Re-Release Super Crossfighter Coming Soon, Other Radiangames Titles Go 50% Off Posted by Ellis Spice on July 31st, 2014 [ | Read more »
Hexiled Review
Hexiled Review By Rob Thomas on July 31st, 2014 Our Rating: :: HEX SELLSUniversal App - Designed for iPhone and iPad In space, no one can hear you… spell? Hexiled is a neat concept for a word scramble puzzle, but it doesn’t go too... | Read more »
Despicable Me: Minion Rush is One Year O...
Despicable Me: Minion Rush is One Year Old, Gets its Biggest Update Yet Posted by Jennifer Allen on July 31st, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Plants vs. Zombies 2 Enters the Second H...
Plants vs. Zombies 2 Enters the Second Half of the Dark Ages Posted by Ellis Spice on July 31st, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Why Does It Spin? (Games)
Why Does It Spin? 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: THERE'S ONLY ONE RULE: DON'T TOUCH THE WALLS! Do you think you're able to follow this simple rule even if you would have to... | Read more »
Ice Wings Plus (Games)
Ice Wings Plus 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: THE GREAT ENDLESS RUNNER OF COMBAT JETS IS BACK !! With more than 680.000 downloads in the App Store, Ice Wings: Skies of Steel... | Read more »
Murl the Squirrel (Games)
Murl the Squirrel 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: Meet Murl. He is teased by a group of flying squirrels because he can't fly. Determined to show them he's can fly, he meets... | Read more »
Celleste (Games)
Celleste 0.1 Device: iOS Universal Category: Games Price: $2.99, Version: 0.1 (iTunes) Description: Lots of cute action with amazing 3D graphics and a new type of gameplay! Take control over the forces of the universe to help a group... | Read more »
Super Heavy Sword (Games)
Super Heavy Sword 0.0.1 Device: iOS Universal Category: Games Price: $.99, Version: 0.0.1 (iTunes) Description: Get Ready to Get HEAVY! Monster Robot Studios presents SUPER Heavy Sword! The sequel to the smash hit HEAVY sword which... | Read more »

Price Scanner via MacPrices.net

Save up to $130 on an iPad mini with Apple re...
The Apple Store has Certified Refurbished 2nd generation iPad minis with Retina Displays available for up to $130 off the cost of new models, starting at $339. Apple’s one-year warranty is included... Read more
iPad Cannibalization Threat “Overblown”
Seeking Alpha’s Kevin Greenhalgh observes that while many commentators think Apple’s forthcoming 5.5-inch panel iPhone 6 will cannibalize iPad sales, in his estimation, these concerns are being... Read more
Primate Labs Releases July 2014 MacBook Pro P...
Primate Labs’ John Poole has posted Geekbench 3 results for most of the new MacBook Pro models that Apple released on Tuesday. Poole observes that overall performance improvements for the new MacBook... Read more
Apple Re-Releases Bugfixed MacBook Air EFI Fi...
Apple has posted a bugfixed version EFI Firmware Update 2.9 a for MacBook Air (Mid 2011) models. The update addresses an issue where systems may take longer to wake from sleep than expected, and... Read more
Save $50 on the 2.5GHz Mac mini, plus free sh...
B&H Photo has the 2.5GHz Mac mini on sale for $549.99 including free shipping. That’s $50 off MSRP, and B&H will also include a free copy of Parallels Desktop software. NY sales tax only. Read more
Save up to $140 on an iPad Air with Apple ref...
Apple is offering Certified Refurbished iPad Airs for up to $140 off MSRP. Apple’s one-year warranty is included with each model, and shipping is free. Stock tends to come and go with some of these... Read more
$250 price drop on leftover 15-inch Retina Ma...
B&H Photo has dropped prices on 2013 15″ Retina MacBook Pros by $250 off original MSRP. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.3GHz Retina MacBook Pro: $2249, $250 off... Read more
More iPad Upgrade Musings – The ‘Book Mystiqu...
Much discussed recently, what with Apple reporting iPad sales shrinkage over two consecutive quarters, is that it had apparently been widely assumed that tablet users would follow a two-year hardware... Read more
13-inch 2.5GHz MacBook Pro on sale for $999,...
Best Buy has the 13″ 2.5GHz MacBook Pro available for $999.99 on their online store. Choose free shipping or free instant local store pickup (if available). Their price is $100 off MSRP. Price is... Read more
Save up to $300 on an iMac with Apple refurbi...
The Apple Store has Apple Certified Refurbished iMacs available for up to $300 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free. These are the best prices on... Read more

Jobs Board

Sr. Product Leader, *Apple* Store Apps - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
Sr Software Lead Engineer, *Apple* Online S...
Sr Software Lead Engineer, Apple Online Store Publishing Systems Keywords: Company: Apple Job Code: E3PCAK8MgYYkw Location (City or ZIP): Santa Clara Status: Full Read more
Sr Software Lead Engineer, *Apple* Online S...
Sr Software Lead Engineer, Apple Online Store Publishing Systems Keywords: Company: Apple Job Code: E3PCAK8MgYYkw Location (City or ZIP): Santa Clara Status: Full Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Sr. Product Leader, *Apple* Store Apps - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.