home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Programming / CopyFile / CopyFile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-23  |  7.9 KB  |  375 lines  |  [TEXT/KAHL]

  1. /*
  2.    fiddling with the standard file package and the high level file
  3.    routines.
  4.  
  5.    This is a Generic file copy program.
  6.    
  7.    New File Feb 17 1987
  8.                Feb 20...Fixed bug which would not allow copy if
  9.                      target directory had file with same name
  10.                      as target file.
  11.             Feb 20...Added Alert error messages.
  12.    
  13.    Author:  Jerry LeVan
  14.                325 Boone Trail
  15.                Richmond Ky 40475
  16.    
  17.    Environment: MPW v1.01/MPW C v1.0
  18.                    MacPlus - Finder v5.3/System v3.2
  19.    
  20.    Build Instructions: c gencopy.c
  21.                           rez types.r gencopy.r -o gencopy
  22.                        link gencopy.c.o ∂
  23.                              "{clibraries}"cruntime.o ∂
  24.                              "{clibraries}"cinterface.o ∂
  25.                         -o gencopy
  26.   Exercise for the reader:
  27.     a) Use Alerts to give the user better feedback (done!)
  28.     b) Make sure there is room on the target volume prior to copy
  29.     c) Force the file system to use larger buffers to speed the copy
  30.     d) Make sure I have covered all the error conditions
  31.     
  32.   Warning: This program will delete a file if it has the same name 
  33.              as the target prior to the start of the copy and the file
  34.            is in the same directory. The program will not allow
  35.            a file to be copied over itself.
  36.  
  37. */
  38.  
  39.  
  40. #define BUFSIZ 8192
  41.  
  42. #define MSG_ID 128
  43.  
  44. /**********************************************************************/
  45.  
  46. void InitProgram()
  47. {
  48.     /* Standard Initialization Sequence */
  49.  
  50.     /*UnloadSeg(_DataInit);*/    /* unload the runtime initializer code */
  51.     
  52.     InitGraf(&qd.thePort);    /* set up quickdraw */
  53.     InitFonts();            /* Set up fonts        */
  54. /*    FlushEvents(everyEvent,0);     empty the event queue */
  55.     InitWindows();            /* Set up window manager */
  56.     InitMenus();            /* Set up menus */
  57.     TEInit();                /* Needed for Dialogs */
  58.     InitDialogs(nil);        /* No restart proc */
  59.     InitCursor();
  60. }
  61. /********************************************************************/
  62.  
  63. Boolean GetSourceFile
  64. (SFReply *reply,OSType *creator,OSType *theType,short *flags)
  65. {
  66.     Point loc;
  67.     SFTypeList typeList;
  68.     short ntypes;
  69.     FInfo info;
  70.     
  71.  
  72.     loc.v = 80;
  73.     loc.h = 100;
  74.     
  75.     ntypes = -1; /* all files */
  76.     SFGetFile(loc, 0, 0, ntypes, typeList, 0, reply);
  77.     
  78.     if(reply->good)
  79.     {
  80.        /* we need to get the info for the selected file */
  81.        
  82.         if(GetFInfo(reply->fName,reply->vRefNum,&info))
  83.             return false;
  84.        
  85.         *creator    = info.fdCreator;
  86.         *theType    = info.fdType;        /* actually in the reply record */
  87.         *flags        = info.fdFlags;
  88.        
  89.         return true;
  90.     }
  91.  
  92.     return false;
  93. }
  94.  
  95. /********************************************************************/
  96.    
  97. Boolean GetDestFile
  98. (SFReply *infile,SFReply *reply)
  99. {  
  100.     Point    loc;
  101.       
  102.       
  103.     loc.v = 80;
  104.     loc.h = 100;
  105.       
  106.       
  107.     SFPutFile(loc,(unsigned char *)"\pSelect Target Name",infile->fName, nil, reply);
  108.     
  109.     if(reply->good)
  110.     { 
  111.         /* we can't allow the source and destination to be the same file */
  112.  
  113.         if(EqualString(infile->fName,reply->fName,false,false)&&(infile->vRefNum == reply->vRefNum))
  114.         {
  115.             ParamText((unsigned char*)"Sorry, Source and Destination Can't Be Identical",nil,nil,nil);
  116.             StopAlert(MSG_ID,nil);
  117.             return false;
  118.         }
  119.         
  120.         return true;
  121.     }
  122.     return false;
  123. }
  124.  
  125. /********************************************************************/
  126.  
  127. Boolean CreateTheFile
  128. (SFReply *infile,SFReply *outfile,OSType creator,OSType theType,OSErr *reason)
  129.     FInfo    info;
  130.  
  131.  
  132.     *reason = Create(outfile->fName,outfile->vRefNum,creator,theType);
  133.     if(*reason)
  134.     {
  135.         /* we had an error during the create */
  136.         
  137.         if(*reason == /*dupFNErr*/-48)
  138.         {
  139.             /* try to delete the file */
  140.             
  141.             FSDelete(outfile->fName,outfile->vRefNum);
  142.             *reason=Create(outfile->fName,outfile->vRefNum,creator,theType);
  143.             if(*reason)
  144.                 return false;        /* some other error */
  145.             else
  146.                 return true;        /* sucessful open */
  147.         }
  148.         else
  149.             return false;            /* some other error */
  150.     }
  151.      
  152.      return true;
  153. }
  154.    
  155. /********************************************************************/
  156.  
  157. void CopyAFork
  158. (short inref,short outref,OSErr *err)
  159.     char    buff[BUFSIZ];        /* one cluster buffer */
  160.     long    count;                /* count actually transfered */
  161.     OSErr    ReadErr,WriteErr;    /* error flags */
  162.     
  163.     
  164.     do
  165.     { 
  166.         count = BUFSIZ;    /* blocksize */
  167.         
  168.         ReadErr=FSRead(inref,&count,buff);
  169.         if(ReadErr)
  170.         {
  171.             if(ReadErr!=eofErr)
  172.             {
  173.                 *err = ReadErr;
  174.                 return;
  175.             }
  176.         }
  177.         
  178.         WriteErr = FSWrite(outref,&count,buff);
  179.         if(WriteErr)
  180.         {
  181.             *err = WriteErr;
  182.             return;
  183.         }
  184.     }
  185.     while(ReadErr != eofErr);
  186.     
  187.     *err = noErr;
  188. }
  189.  
  190. /********************************************************************/
  191.  
  192. Boolean CopyDataFork
  193. (SFReply *infile,SFReply *outfile,OSType creator,OSErr *err)
  194. {
  195.     short    inref,outref;
  196.    
  197.    
  198.     /* open the input data fork */
  199.     
  200.     *err = FSOpen(infile->fName,infile->vRefNum,&inref);
  201.     if(*err)
  202.         return false;
  203.    
  204.     /* open the output data fork */
  205.     
  206.     *err = FSOpen(outfile->fName,outfile->vRefNum,&outref);
  207.     if(*err)
  208.     {
  209.         FSClose(inref);
  210.         inref = 0;
  211.         return false;
  212.     }
  213.       
  214.     CopyAFork(inref,outref,err);
  215.  
  216.     FSClose(inref);
  217.     inref = 0;
  218.     FSClose(outref);
  219.     outref = 0;
  220.      
  221.     if(*err)
  222.     {
  223.         FSDelete(outfile->fName,outfile->vRefNum);
  224.         return false;
  225.     }
  226.     else
  227.     {
  228.          return true;
  229.     }
  230. }
  231. /********************************************************************/
  232.  
  233. Boolean CopyResourceFork(SFReply *infile,SFReply *outfile,OSErr *err)
  234. {
  235.     short    inref,outref,theErr;
  236.  
  237.  
  238.     /* open the input resource fork */
  239.     
  240.     *err = OpenRF(infile->fName,infile->vRefNum,&inref);
  241.     if(*err)
  242.         return false;
  243.    
  244.     /* open the output resource fork */
  245.     *err=OpenRF(outfile->fName,outfile->vRefNum,&outref);
  246.     if(*err)
  247.     {
  248.         FSClose(inref);
  249.         inref = 0;
  250.         return false;
  251.     }
  252.       
  253.     /* copy a fork */
  254.     
  255.     CopyAFork(inref,outref,err);
  256.      
  257.     /* clean up */
  258.     
  259.     FSClose(inref);
  260.     inref = 0;
  261.     FSClose(outref);
  262.     outref = 0;
  263.     
  264.     FlushVol(nil,outfile->vRefNum);
  265.     
  266.     if(*err)
  267.     {
  268.         FSDelete(outfile->fName,outfile->vRefNum);
  269.         return false;
  270.     }
  271.     else
  272.     {
  273.         return true;
  274.     }
  275. }
  276.  
  277. /********************************************************************/
  278.  
  279. Boolean SetFileAttributes
  280. (SFReply *outfile,short flags,OSErr *reason)
  281. {
  282.     FInfo info;
  283.     
  284.     
  285.     *reason = GetFInfo(outfile->fName,outfile->vRefNum,&info);
  286.     if(*reason)
  287.         return false;
  288.     
  289.     info.fdFlags = flags;        /* protected bundle etc */
  290.     
  291.     *reason = SetFInfo(outfile->fName,outfile->vRefNum,&info);
  292.     if(*reason)
  293.         return false;
  294.  
  295.     return true;
  296. }
  297.  
  298. /********************************************************************/
  299. void main()
  300. {
  301.     SFReply            infilespec,outfilespec;
  302.     OSType            creator,theType;
  303.     short            flags;                /* finder flags */
  304.     OSErr            reason;                /* system error code on bad return */
  305.     unsigned char    temp[20];            /* storage for numeric conversion */
  306.    
  307.    
  308.     InitProgram();
  309.    
  310.  
  311.     /* get source file spec, quit if user bails out */
  312.     
  313.     if(!GetSourceFile(&infilespec,&creator,&theType,&flags))
  314.         return;
  315.  
  316.     
  317.     /* get destination file spec, quit if user bails out */
  318.     
  319.     if(!GetDestFile(&infilespec,&outfilespec))
  320.         return;
  321.  
  322.  
  323.     /* create the output file (exit on error) */
  324.  
  325.     if(!CreateTheFile(&infilespec,&outfilespec,creator,theType,&reason))
  326.     {
  327.         NumToString(reason,temp);
  328.         ParamText((unsigned char*)"\pCan't Create Output File",(unsigned char*)"\pReason:",temp,nil);
  329.         StopAlert(MSG_ID,nil);
  330.         return;
  331.     }
  332.       
  333.     
  334.     /* copy the data fork exit on error */
  335.    
  336.     if(!CopyDataFork(&infilespec,&outfilespec,creator,&reason))
  337.     { 
  338.         NumToString(reason,temp);
  339.         ParamText((unsigned char*)"\pError Copying Data Fork",(unsigned char*)"\pReason:",temp,nil);
  340.         StopAlert(MSG_ID,nil);
  341.         return;
  342.     }
  343.  
  344.       
  345.     /* copy the resource fork, exit on error */     
  346.  
  347.     if(!CopyResourceFork(&infilespec,&outfilespec,&reason))
  348.     {
  349.         NumToString(reason,temp);
  350.         ParamText((unsigned char*)"\pError Copying Resource Fork",(unsigned char*)"\pReason:",temp,nil);
  351.         StopAlert(MSG_ID,nil);
  352.         return;
  353.     }
  354.  
  355.  
  356.             
  357.     /* set the destination file attributes */
  358.  
  359.     if(!SetFileAttributes(&outfilespec,flags,&reason))
  360.     {
  361.         NumToString(reason,temp);
  362.         ParamText((unsigned char*)"\pError Setting File Attributes",(unsigned char*)"\pReason:",temp,nil);
  363.         StopAlert(MSG_ID,nil);
  364.         return;
  365.     }
  366.     
  367.  
  368.     /* advise user of sucessful completion */
  369.  
  370.     ParamText((unsigned char*)"\pNo Errors Detected...Copy Complete",nil,nil,nil);
  371.     NoteAlert(MSG_ID,nil);
  372. }
  373.