home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / CMDS / mtools_3.6.src.lzh / MTOOLS_3.6 / mcopy.c < prev    next >
Text File  |  1997-11-12  |  9KB  |  408 lines

  1. /*
  2.  * mcopy.c
  3.  * Copy an MSDOS files to and from Unix
  4.  *
  5.  */
  6.  
  7.  
  8. #define LOWERCASE
  9.  
  10. #include "sysincludes.h"
  11. #include "msdos.h"
  12. #include "mtools.h"
  13. #include "vfat.h"
  14. #include "mainloop.h"
  15. #include "plain_io.h"
  16. #include "nameclash.h"
  17. #include "file.h"
  18. #include "fs.h"
  19.  
  20. #ifdef _OSK
  21. #define S_ISDIR(x) (x&S_IFDIR)
  22. #define S_ISREG(x) (!(x&S_IFDIR))
  23. #endif
  24.  
  25. /*
  26.  * Preserve the file modification times after the fclose()
  27.  */
  28.  
  29. static void set_mtime(const char *target, long mtime)
  30. {
  31. #ifdef HAVE_UTIMES
  32.     struct timeval tv[2];
  33.  
  34.     if (mtime != 0L) {
  35.         tv[0].tv_sec = mtime;
  36.         tv[0].tv_usec = 0;
  37.         tv[1].tv_sec = mtime;
  38.         tv[1].tv_usec = 0;
  39.         utimes(target, tv);
  40.     }
  41. #else
  42. #ifdef HAVE_UTIME
  43.     struct utimbuf utbuf;
  44.  
  45.     if (mtime != 0L) {
  46.         utbuf.actime = mtime;
  47.         utbuf.modtime = mtime;
  48.         utime(target, &utbuf);
  49.     }
  50. #endif
  51. #endif
  52.     return;
  53. }
  54.  
  55. typedef struct Arg_t {
  56.     int preserve;
  57.     char *target;
  58.     int textmode;
  59.     int needfilter;
  60.     int nowarn;
  61.     int single;
  62.     int verbose;
  63.     int type;
  64.     MainParam_t mp;
  65.     ClashHandling_t ch;
  66.     Stream_t *sourcefile;
  67.     Stream_t *targetDir;
  68. } Arg_t;
  69.  
  70. static int read_file(Stream_t *Dir, MainParam_t *mp, int entry, 
  71.              int needfilter)
  72. {
  73.     Arg_t *arg=(Arg_t *) mp->arg;
  74.     long mtime;
  75.     Stream_t *File=mp->File;
  76.     Stream_t *Target, *Source;
  77.     struct stat stbuf;
  78.     int ret;
  79.     char errmsg[80];
  80.  
  81.     File->Class->get_data(File, &mtime, 0, 0, 0);
  82.     
  83.     if (!arg->preserve)
  84.         mtime = 0L;
  85.  
  86.     /* if we are creating a file, check whether it already exists */
  87.     if (!arg->nowarn && arg->target && strcmp(arg->target, "-") && 
  88.         !access(arg->target, 0)){
  89.         if( ask_confirmation("File \"%s\" exists, overwrite (y/n) ? ",
  90.                      arg->target,0))
  91.             return MISSED_ONE;
  92.         
  93.         /* sanity checking */
  94.         if (!stat(arg->target, &stbuf) && !S_ISREG(stbuf.st_mode)) {
  95.             fprintf(stderr,"\"%s\" is not a regular file\n",
  96.                 arg->target);            
  97.             return MISSED_ONE;
  98.         }
  99.     }
  100.  
  101.     if(!arg->type)
  102.         fprintf(stderr,"Copying %s\n", mp->outname);
  103.     if(got_signal)
  104.         return MISSED_ONE;
  105.     if ((Target = SimpleFileOpen(0, 0, arg->target,
  106.                      O_WRONLY | O_CREAT | O_TRUNC,
  107.                      errmsg, 0))) {
  108.         ret = 0;
  109.         if(needfilter && arg->textmode){
  110.             Source = open_filter(COPY(File));
  111.             if (!Source)
  112.                 ret = -1;
  113.         } else
  114.             Source = COPY(File);
  115.  
  116.         if (ret == 0 )
  117.             ret = copyfile(Source, Target);
  118.         FREE(&Source);
  119.         FREE(&Target);
  120.         if(ret < -1){
  121.             unlink(arg->target);
  122.             return MISSED_ONE;
  123.         }
  124.         if(arg->target && strcmp(arg->target,"-"))
  125.             set_mtime(arg->target, mtime);
  126.         return GOT_ONE;
  127.     } else {
  128.         fprintf(stderr,"%s\n", errmsg);
  129.         return MISSED_ONE;
  130.     }
  131. }
  132.  
  133. static  int dos_read(Stream_t *Dir, MainParam_t *mp, int entry)
  134. {
  135.     return read_file(Dir, mp, entry, 1);
  136. }
  137.  
  138.  
  139. static  int unix_read(char *name, MainParam_t *mp)
  140. {
  141.     return read_file(0, mp, -1, 0);
  142. }
  143.  
  144.  
  145. /*
  146.  * Open the named file for read, create the cluster chain, return the
  147.  * directory structure or NULL on error.
  148.  */
  149. static struct directory *writeit(char *dosname,
  150.                  char *longname,
  151.                  void *arg0,
  152.                  struct directory *dir)
  153. {
  154.     Stream_t *Target;
  155.     time_t now;
  156.     int type, fat, ret;
  157.     long date;
  158.     size_t filesize, newsize;
  159.     Arg_t *arg = (Arg_t *) arg0;
  160.  
  161.     if (arg->mp.File->Class->get_data(arg->mp.File,
  162.                       & date, &filesize, &type, 0) < 0 ){
  163.         fprintf(stderr, "Can't stat source file\n");
  164.         return NULL;
  165.     }
  166.  
  167.     if (type){
  168.         if (arg->verbose)
  169.             fprintf(stderr, "\"%s\" is a directory\n", longname);
  170.         return NULL;
  171.     }
  172.  
  173.     if (!arg->single)
  174.         fprintf(stderr,"Copying %s\n", longname);
  175.     if(got_signal)
  176.         return NULL;
  177.  
  178.     /* will it fit? */
  179.     if (!getfreeMin(arg->targetDir, filesize)) {
  180.         fprintf(stderr,"Disk full\n");
  181.         return NULL;
  182.     }
  183.     
  184.     /* preserve mod time? */
  185.     if (arg->preserve)
  186.         now = date;
  187.     else
  188.         time(&now);
  189.  
  190.     mk_entry(dosname, 0x20, 0, 0, now, dir);
  191.     Target = open_file(arg->targetDir, dir);
  192.     if(!Target){
  193.         fprintf(stderr,"Could not open Target\n");
  194.         exit(1);
  195.     }
  196.     if (arg->needfilter & arg->textmode)
  197.         Target = open_filter(Target);
  198.     ret = copyfile(arg->mp.File, Target);
  199.     GET_DATA(Target, 0, &newsize, 0, &fat);
  200.     FREE(&Target);
  201.     if(ret < 0 ){
  202.         fat_free(arg->targetDir, fat);
  203.         return NULL;
  204.     } else {
  205.         mk_entry(dosname, 0x20, fat, newsize, now, dir);
  206.         return dir;
  207.     }
  208. }
  209.  
  210.  
  211. static int write_file(Stream_t *Dir, MainParam_t *mp, int entry,
  212.               int needfilter)
  213. /* write a messy dos file to another messy dos file */
  214. {
  215.     int result;
  216.     Arg_t * arg = (Arg_t *) (mp->arg);
  217.  
  218.     arg->needfilter = needfilter;
  219.     if (arg->targetDir == Dir){
  220.         arg->ch.ignore_entry = -1;
  221.         arg->ch.source = entry;
  222.     } else {
  223.         arg->ch.ignore_entry = -1;
  224.         arg->ch.source = -2;
  225.     }
  226.     result = mwrite_one(arg->targetDir, arg->target, 0,
  227.                 writeit, (void *)arg, &arg->ch);
  228.     if(result == 1)
  229.         return GOT_ONE;
  230.     else
  231.         return MISSED_ONE;
  232. }
  233.  
  234.  
  235. static int dos_write(Stream_t *Dir, MainParam_t *mp, int entry)
  236. {
  237.     return write_file(Dir, mp, entry, 0);
  238. }
  239.  
  240. static int unix_write(char *name, MainParam_t *mp)
  241. /* write a Unix file to a messy DOS fs */
  242. {
  243.     return write_file(0, mp, 0, 1);
  244. }
  245.  
  246.  
  247. static void usage(void)
  248. {
  249.     fprintf(stderr,
  250.         "Mtools version %s, dated %s\n", mversion, mdate);
  251.     fprintf(stderr,
  252.         "Usage: %s [-tnmvV] sourcefile targetfile\n", progname);
  253.     fprintf(stderr,
  254.         "       %s [-tnmvV] sourcefile [sourcefiles...] targetdirectory\n", 
  255.         progname);
  256.     exit(1);
  257. }
  258.  
  259. void mcopy(int argc, char **argv, int mtype)
  260. {
  261.     Stream_t *SubDir,*Dir;
  262.     int have_target;
  263.     Arg_t arg;
  264.     int c, ret, fastquit;
  265.     char filename[VBUFSIZE];
  266.     char spareOutname[VBUFSIZE];
  267.     
  268.     struct stat stbuf;
  269.  
  270.     /* get command line options */
  271.  
  272.     init_clash_handling(& arg.ch);
  273.  
  274.     /* get command line options */
  275.     arg.preserve = 0;
  276.     arg.nowarn = 0;
  277.     arg.textmode = 0;
  278.     arg.verbose = 0;
  279.     arg.type = mtype;
  280.     fastquit = 0;
  281.     while ((c = getopt(argc, argv, "tnmvorsamQORSAM")) != EOF) {
  282.         switch (c) {
  283.             case 't':
  284.                 arg.textmode = 1;
  285.                 break;
  286.             case 'n':
  287.                 arg.nowarn = 1;
  288.                 break;
  289.             case 'm':
  290.                 arg.preserve = 1;
  291.                 break;
  292.             case 'v':    /* dummy option for mcopy */
  293.                 arg.verbose = 1;
  294.                 break;
  295.             case 'Q':
  296.                 fastquit = 1;
  297.                 break;
  298.             case '?':
  299.                 usage();
  300.             default:
  301.                 if(handle_clash_options(&arg.ch, c))
  302.                     usage();
  303.                 break;
  304.         }
  305.     }
  306.  
  307.     if (argc - optind < 1)
  308.         usage();
  309.  
  310.     /* only 1 file to copy... */
  311.     arg.single = SINGLE;
  312.     
  313.     init_mp(&arg.mp);
  314.     arg.mp.fast_quit = fastquit;
  315.     arg.mp.arg = (void *) &arg;
  316.     arg.mp.openflags = O_RDONLY;
  317.  
  318.     arg.targetDir = NULL;
  319.     if(mtype){
  320.  
  321.         /* Mtype = copying to stdout */
  322.  
  323.         have_target = 0;
  324.         arg.target = 0;
  325.         arg.mp.outname = filename;
  326.         arg.single = 0;        
  327.         arg.mp.callback = dos_read;
  328.         arg.mp.unixcallback = unix_read;
  329.     } else if(argc - optind >= 2 && 
  330.           argv[argc-1][0] && argv[argc-1][1] == ':'){
  331.  
  332.         /* Copying to Dos */
  333.         
  334.         have_target = 1;
  335.         Dir = open_subdir(&arg.mp, argv[argc-1], O_RDWR, 0, 0);
  336.         if(!Dir){
  337.             fprintf(stderr,"Bad target\n");
  338.             exit(1);
  339.         }
  340.         get_name(argv[argc-1], filename, arg.mp.mcwd);
  341.         SubDir = descend(Dir, filename, 0, 0, 0);
  342.         if (!SubDir){
  343.             /* the last parameter is a file */
  344.             if (argc - optind != 2){
  345.                 fprintf(stderr,
  346.                     "%s: Too many arguments, or destination directory omitted\n",
  347.                     argv[0]);
  348.                 FREE(&Dir);
  349.                 exit(1);
  350.             }
  351.             arg.targetDir = Dir;
  352.             arg.mp.outname = 0; /* toss away source name */
  353.             arg.target = filename; /* store near name given as
  354.                         * target */
  355.             arg.single = 1;
  356.         } else {
  357.             arg.targetDir = SubDir;
  358.             FREE(&Dir);
  359.             arg.mp.outname = filename;
  360.             arg.target = filename;
  361.             arg.single = 0;
  362.         }
  363.         arg.mp.callback = dos_write;
  364.         arg.mp.unixcallback = unix_write;
  365.     } else {
  366.         /* Copying to Unix */
  367.         have_target = 1;
  368.         if (argc - optind == 1){
  369.             /* one argument: copying to current directory */
  370.             arg.single = 0;
  371.             have_target = 0;
  372.             arg.target = filename;
  373.             arg.mp.outname = filename;
  374.         } else if (strcmp(argv[argc-1],"-") && 
  375.                !stat(argv[argc-1], &stbuf) &&
  376.                S_ISDIR(stbuf.st_mode)){
  377.             char *tmp;
  378.             tmp = (char *) safe_malloc(VBUFSIZE + 1 + 
  379.                            strlen(argv[argc-1]));
  380.             strcpy(tmp, argv[argc-1]);
  381.             strcat(tmp,"/");
  382.             arg.mp.outname = tmp+strlen(tmp);
  383.             arg.target = tmp;
  384.         } else if (argc - optind != 2) {
  385.             /* last argument is not a directory: we should only
  386.              * have one source file */
  387.             fprintf(stderr,
  388.                 "%s: Too many arguments or destination directory omitted\n", 
  389.                 argv[0]);
  390.             exit(1);
  391.         } else {
  392.             arg.target = argv[argc-1];
  393.             arg.mp.outname = filename;
  394.         }
  395.  
  396.         arg.mp.callback = dos_read;
  397.         arg.mp.unixcallback = unix_read;
  398.     }
  399.     if(!arg.mp.outname)
  400.         arg.mp.outname = spareOutname;
  401.  
  402.     arg.mp.lookupflags = ACCEPT_PLAIN | DO_OPEN | NO_DOTS | arg.single;
  403.     ret=main_loop(&arg.mp, argv + optind, argc - optind - have_target);
  404.     FREE(&arg.targetDir);
  405.  
  406.     exit(ret);
  407. }
  408.