home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume38 / awdc / part01 < prev    next >
Encoding:
Text File  |  1993-07-12  |  12.8 KB  |  405 lines

  1. Newsgroups: comp.sources.misc
  2. From: aw1@stade.co.uk (Adrian Wontroba)
  3. Subject: v38i050:  awdc - sector level floppy disc copy, Part01/01
  4. Message-ID: <1993Jul13.044845.17522@sparky.sterling.com>
  5. X-Md4-Signature: e33e8e07cf63d4b60accedabf193168c
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Stade Computers Limited, UK
  8. Date: Tue, 13 Jul 1993 04:48:45 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: aw1@stade.co.uk (Adrian Wontroba)
  12. Posting-number: Volume 38, Issue 50
  13. Archive-name: awdc/part01
  14. Environment: DOS
  15.  
  16. awdc is a floppy disk copy problem with a difference - it copies at a
  17. sector level, ignoring such trivia as the number of sectors per track
  18. and number of tracks.  It stops when it reaches the end of either disc
  19. or encounters a transfer error.
  20.  
  21. It was written to solve a specific problem - transcribing UNIX tar
  22. archive discs from one type of floppy disc to another, on a DOS machine.
  23. --------------------------------------------------------------------------------
  24. #! /bin/sh
  25. # This is a shell archive.  Remove anything before this line, then feed it
  26. # into a shell via "sh file" or similar.  To overwrite existing files,
  27. # type "sh file -c".
  28. # Contents:  awdc.c readme
  29. # Wrapped by kent@sparky on Sun Jul 11 19:25:41 1993
  30. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  31. echo If this archive is complete, you will see the following message:
  32. echo '          "shar: End of archive 1 (of 1)."'
  33. if test -f 'awdc.c' -a "${1}" != "-c" ; then 
  34.   echo shar: Will not clobber existing file \"'awdc.c'\"
  35. else
  36.   echo shar: Extracting \"'awdc.c'\" \(7912 characters\)
  37.   sed "s/^X//" >'awdc.c' <<'END_OF_FILE'
  38. X/* awdc - sector level floppy copy
  39. X
  40. Xawdc is a floppy disk copy problem with a difference - it copies at a
  41. Xsector level, ignoring such trivia as the number of sectors per track
  42. Xand number of tracks.  It stops when it reaches the end of either disc
  43. Xor encounters a transfer error.
  44. X
  45. XIt was written to solve a specific problem - transcribing UNIX tar
  46. Xarchive discs from one type of floppy disc to another, on a DOS machine.
  47. XFor safety, the program will only copy sectors between removable media,
  48. Xso it should leave hard disks alone.  I am not particularly proud of it,
  49. Xbut it solved my problem and may help others, so I am placing it in the
  50. Xpublic domain.  Use it entirely at your own risk.
  51. X
  52. XAdrian Wontroba, Stade Computers Limited.       phone:  (+44) 21 373 9546
  53. Xuucp:   ...!uknet!stade!aw1             other: aw1%stade.co.uk@uknet.ac.uk
  54. Xsnail:  14 Fourlands Avenue, Sutton Coldfield, West Midlands, B72 1YY, UK
  55. X
  56. X*/
  57. X
  58. X#include <stdlib.h>
  59. X#include <stdio.h>
  60. X#include <dos.h>
  61. X#include <ctype.h>
  62. X#include <string.h>
  63. X#undef    NO_WRITE        /* if defined, no writes! */
  64. X#define    BUFFERSIZE    32768    /* size of disk io buffer, max 64k  */
  65. Xchar           *progname;    /* program name */
  66. X
  67. X/*
  68. X * setmessage - output warning about disk parameter blocks
  69. X *
  70. X */
  71. Xvoid
  72. Xsetmessage(void)
  73. X{
  74. X    fprintf(stderr,
  75. X        "The action of this program is strongly influenced by\n"
  76. X      "the content of the Disk Parameter Block for each drive.\n\n");
  77. X    fprintf(stderr,
  78. X        "Before using it (especially with non DOS media), the DPBs\n"
  79. X        "should be initialised by issuing 'DIR x:' commands on the\n"
  80. X        "input and output drives with equivalent DOS media.\n\n");
  81. X    fprintf(stderr,
  82. X        "The output disk must be pre-formatted.\n\n");
  83. X    fprintf(stderr,
  84. X        "As a safety measure, the program will only copy between\n"
  85. X        "removeable media.\n\n");
  86. X}                /* setmessage */
  87. X
  88. X/*
  89. X * usage - output usage message
  90. X * 
  91. X */
  92. Xvoid
  93. Xusage(void)
  94. X{
  95. X    fprintf(stderr, "usage: %s <input drive letter> "
  96. X        "<output drive letter>\n"
  97. X        "eg 'awdc a b' to copy from a to b\n\n",
  98. X        progname);
  99. X    setmessage();
  100. X}                /* usage */
  101. X
  102. X/*
  103. X * myerror - print error message and errno and _doserrno to stderr
  104. X * 
  105. X */
  106. Xvoid
  107. Xmyerror(char *s)
  108. X{
  109. X    int             e = errno;
  110. X    int             d = _doserrno;
  111. X
  112. X    fprintf(stderr, "\n%s: %s: %s (%d/%x), _doserrno = %d\n",
  113. X        progname, s,
  114. X     ((e > 0) && (e <= sys_nerr)) ? sys_errlist[e] : "Unknown error",
  115. X        e, e, d);
  116. X}                /* myerror */
  117. X
  118. X/*
  119. X * get_drive - turn drive letter into drive number for absread/abswrite
  120. X * 0=A, 1=B etc.
  121. X * 
  122. X * Note - most DOS functions use 0=default, 1=A. etc. Beware.
  123. X * 
  124. X * error message and exit(1) on error
  125. X * 
  126. X */
  127. Xint
  128. Xget_drive(char *s)
  129. X{
  130. X    int             c;
  131. X    int             d;
  132. X    union REGS      regs;
  133. X
  134. X    c = toupper(s[0]);
  135. X    if ((c < 'A') || (c > 'Z')) {
  136. X    fprintf(stderr, "Drive '%c' not supported\n", c);
  137. X    exit(1);
  138. X    } else {
  139. X    d = c - 'A';
  140. X    regs.h.ah = 0x44;    /* ioctl */
  141. X    regs.h.al = 0x8;    /* check if block device is removeable */
  142. X    regs.h.bl = d + 1;    /* drive code - 0 def, 1=A, etc */
  143. X    intdos(®s, ®s);
  144. X    if (regs.x.cflag) {
  145. X        fprintf(stderr, "Unable to determine "
  146. X            "exchangeability of %c, "
  147. X            "ioctl error %d\n",
  148. X            c, regs.x.ax);
  149. X        exit(1);
  150. X    }
  151. X    if (regs.x.ax) {
  152. X        fprintf(stderr, "%c is not an exchangeable drive\n",
  153. X            c);
  154. X        exit(1);
  155. X    }
  156. X    /* phew, its exchangeable */
  157. X    }
  158. X    return d;
  159. X}                /* get_drive */
  160. X
  161. X/*
  162. X * copy - copy one logical drive to another, until failure
  163. X * 
  164. X */
  165. Xvoid
  166. Xcopy(int in, int out)
  167. X{
  168. X    union REGS      regs;
  169. X    int             in_sectors;    /* sectors on input drive */
  170. X    int             in_sector_size;    /* sector size */
  171. X    int             out_sectors;/* sectors on output drive */
  172. X    int             out_sector_size;    /* sector size */
  173. X    int             sectors;    /* sectors to copy */
  174. X    int             num;    /* max sectors per transfer */
  175. X    int             n;        /* current sectors per transfer */
  176. X    int             s_read;    /* sectors read */
  177. X    int             s_written;    /* sectors written */
  178. X    int             s;        /* current sector */
  179. X    char           *buff;    /* buffer */
  180. X
  181. X    /* device parameter block */
  182. X    struct DPB {
  183. X    unsigned char   special_functions;
  184. X    unsigned char   device_type;
  185. X    unsigned short int device_attributes;
  186. X    unsigned short int max_cylinders;
  187. X    unsigned char   media_type;
  188. X    unsigned short int bytes_per_sector;
  189. X    unsigned char   sectors_per_au;
  190. X    unsigned short int sectors_reserved;
  191. X    unsigned char   fats;
  192. X    unsigned short int maxroot;
  193. X    unsigned short int sectors;
  194. X    unsigned char   media;
  195. X    unsigned short int sectors_per_fat;
  196. X    unsigned short int sectors_per_track;
  197. X    unsigned short int heads;
  198. X    unsigned long int hidden_sectors;
  199. X    unsigned char   reserved[11];
  200. X    };
  201. X    struct DPB      dpb;
  202. X
  203. X    /* get number of sectors on input drive */
  204. X    memset(&dpb, 0, sizeof dpb);
  205. X    regs.h.ah = 0x44;        /* ioctl */
  206. X    regs.h.al = 0xd;        /* generic i/o control */
  207. X    regs.h.bl = in + 1;        /* drive number */
  208. X    regs.h.ch = 0x8;        /* disk drive */
  209. X    regs.h.cl = 0x60;        /* get drive parameters */
  210. X    regs.x.dx = (unsigned int) &dpb;    /* ugh! */
  211. X    dpb.special_functions = 128;/* return build device driver bpb */
  212. X    intdos(®s, ®s);
  213. X    if (regs.x.cflag) {
  214. X    fprintf(stderr, "Unable to get drive parameters for %c"
  215. X        ", ioctl error %d\n",
  216. X        in + 'A', regs.x.ax);
  217. X    exit(1);
  218. X    }
  219. X    in_sectors = dpb.sectors;
  220. X    in_sector_size = dpb.bytes_per_sector;
  221. X    printf("Input drive %c has %d sectors of %d bytes\n",
  222. X       in + 'A', in_sectors, in_sector_size);
  223. X    /* get number of sectors on output drive */
  224. X    memset(&dpb, 0, sizeof dpb);
  225. X    regs.h.ah = 0x44;        /* ioctl */
  226. X    regs.h.al = 0xd;        /* generic i/o control */
  227. X    regs.h.bl = out + 1;    /* drive number */
  228. X    regs.h.ch = 0x8;        /* disk drive */
  229. X    regs.h.cl = 0x60;        /* get drive parameters */
  230. X    regs.x.dx = (unsigned int) &dpb;    /* ugh! */
  231. X    dpb.special_functions = 128;/* return build device driver bpb */
  232. X    intdos(®s, ®s);
  233. X    if (regs.x.cflag) {
  234. X    fprintf(stderr, "Unable to get drive parameters for %c"
  235. X        ", ioctl error %d\n",
  236. X        out + 'A', regs.x.ax);
  237. X    exit(1);
  238. X    }
  239. X    out_sectors = dpb.sectors;
  240. X    out_sector_size = dpb.bytes_per_sector;
  241. X    printf("Output drive %c has %d sectors of %d bytes\n",
  242. X       out + 'A', out_sectors, out_sector_size);
  243. X    if (in_sector_size != out_sector_size) {
  244. X    fprintf(stderr, "Drives have different sector sizes\n");
  245. X    exit(1);
  246. X    }
  247. X    /* decide how many sectors to copy */
  248. X    if (in_sectors > out_sectors) {
  249. X    fprintf(stderr, "Input drive larger than output\n"
  250. X        "Data may be lost\n");
  251. X    sectors = out_sectors;
  252. X    } else {
  253. X    sectors = in_sectors;
  254. X    }
  255. X    printf("Copying %d sectors\n", sectors);
  256. X    /* get buffer */
  257. X    if ((buff = malloc(BUFFERSIZE)) == NULL) {
  258. X    fprintf(stderr, "malloc failed\n");
  259. X    exit(1);
  260. X    }
  261. X    /* decide how many sectors to handle at a time */
  262. X    num = BUFFERSIZE / in_sector_size;
  263. X    s_read = 0;
  264. X    s_written = 0;
  265. X    s = 0;
  266. X    while (sectors > 0) {
  267. X    n = min(sectors, num);
  268. X    printf("Sectors %5d to %5d\r", s, s + n - 1);
  269. X    if (absread(in, n, s, buff)) {
  270. X        /* read error */
  271. X        myerror("absread");
  272. X        break;
  273. X    } else {
  274. X        s_read += n;
  275. X#ifdef NO_WRITE
  276. X        /* do nothing to output drive ! */
  277. X#else
  278. X        if (abswrite(out, n, s, buff)) {
  279. X        /* write error */
  280. X        myerror("abswrite");
  281. X        break;
  282. X        } else {
  283. X        s_written += num;
  284. X        }
  285. X#endif                /* NO_WRITE */
  286. X    }
  287. X    sectors -= n;
  288. X    s += n;
  289. X    }
  290. X    printf("Sectors read from %c:  %5d\n"
  291. X       "Sectors written to %c: %5d\n",
  292. X       in + 'A', s_read, out + 'A', s_written);
  293. X}                /* copy */
  294. X
  295. X/*
  296. X * main
  297. X */
  298. Xint
  299. Xmain(int argc, char *argv[])
  300. X{
  301. X    int             in_drive;    /* input drive number */
  302. X    int             out_drive;    /* output drive number */
  303. X
  304. X    progname = argv[0];
  305. X    if (argc != 3) {
  306. X    usage();
  307. X    exit(1);
  308. X    }
  309. X    in_drive = get_drive(argv[1]);
  310. X    out_drive = get_drive(argv[2]);
  311. X    setmessage();
  312. X    copy(in_drive, out_drive);
  313. X    printf("OK\n");
  314. X    exit(0);
  315. X}                /* main */
  316. END_OF_FILE
  317.   if test 7912 -ne `wc -c <'awdc.c'`; then
  318.     echo shar: \"'awdc.c'\" unpacked with wrong size!
  319.   fi
  320.   # end of 'awdc.c'
  321. fi
  322. if test -f 'readme' -a "${1}" != "-c" ; then 
  323.   echo shar: Will not clobber existing file \"'readme'\"
  324. else
  325.   echo shar: Extracting \"'readme'\" \(2333 characters\)
  326.   sed "s/^X//" >'readme' <<'END_OF_FILE'
  327. XNew upload - awdc.zip, 13603 bytes.
  328. X
  329. Xawdc is a floppy disk copy problem with a difference - it copies at a
  330. Xsector level, ignoring such trivia as the number of sectors per track
  331. Xand number of tracks.  It stops when it reaches the end of either disc
  332. Xor encounters a transfer error.
  333. X
  334. XIt was written to solve a specific problem - transcribing UNIX tar
  335. Xarchive discs from one type of floppy disc to another, on a DOS machine.
  336. XFor safety, the program will only copy sectors between removable media,
  337. Xso it should leave hard disks alone.  I am not particularly proud of it,
  338. Xbut it solved my problem and may help others, so I am placing it in the
  339. Xpublic domain.  Use it entirely at your own risk.
  340. Xm not particularly proud of it,
  341. Xbut it solved my problem and may help others, so I am placing it in the
  342. Xpublic domain.  Use it entirely at your own risk.
  343. X
  344. XIncluded with this document should be the source and executable code.
  345. XIt is very DOS specific and makes extensive use of intdos().  It was
  346. Xcompiled with Turbo C 2.0.
  347. X
  348. XI believed that there was a DOS port of the FSF GNU version of dd, but
  349. Xthis can only handle DOS files, not raw media.  If I'm wrong, please
  350. Xtell me!
  351. X
  352. XAdrian Wontroba, Stade Computers Limited.       phone:  (+44) 21 373 9546
  353. Xuucp:   ...!uknet!stade!aw1             other: aw1%stade.co.uk@uknet.ac.uk
  354. Xsnail:  14 Fourlands Avenue, Sutton Coldfield, West Midlands, B72 1YY, UK
  355. X
  356. XInstructions
  357. X------------
  358. X
  359. XThese assume that you are copying from A: to B:.  Change as appropriate.
  360. X
  361. XThe next two steps ensure that DOS has the correct idea of the
  362. Xcharacteristics of the discs which are going to be used.  This is
  363. Xachieved by making it read appropriate DOS media.  This is vital!
  364. X
  365. Xo       Take a DOS formatted floppy disc with the same characteristics
  366. X        as the disc you wish to copy from and insert it into the A:
  367. X        drive.  Display the directory.  (dir a:)
  368. X
  369. Xo       Take a DOS formatted floppy disc with the same characteristics
  370. X        as the disc you wish to copy to and insert it into the B: drive.
  371. X        Display the directory.  (dir b:)
  372. X
  373. XRepeat the following three steps for each of the copies.
  374. X
  375. Xo       Insert the source disk in the A: drive.
  376. X
  377. Xo       Write enable and insert the preformatted target disk in the B:
  378. X        drive.
  379. X
  380. Xo       Copy sectors from A: to B: with the supplied program.  (awdc a
  381. X        b).
  382. END_OF_FILE
  383.   if test 2333 -ne `wc -c <'readme'`; then
  384.     echo shar: \"'readme'\" unpacked with wrong size!
  385.   fi
  386.   # end of 'readme'
  387. fi
  388. echo shar: End of archive 1 \(of 1\).
  389. cp /dev/null ark1isdone
  390. MISSING=""
  391. for I in 1 ; do
  392.     if test ! -f ark${I}isdone ; then
  393.     MISSING="${MISSING} ${I}"
  394.     fi
  395. done
  396. if test "${MISSING}" = "" ; then
  397.     echo You have the archive.
  398.     rm -f ark[1-9]isdone
  399. else
  400.     echo You still must unpack the following archives:
  401.     echo "        " ${MISSING}
  402. fi
  403. exit 0
  404. exit 0 # Just in case...
  405.