New upstream version 2.20
[debian/cpmtools] / device_libdsk.c
1 /* #includes */ /*{{{C}}}*//*{{{*/
2 #include "config.h"
3
4 #include <assert.h>
5 #include <errno.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9 #include "device.h"
10
11 #ifdef USE_DMALLOC
12 #include <dmalloc.h>
13 #endif
14 /*}}}*/
15
16 static const char *lookupFormat(DSK_GEOMETRY *geom, const char *name)
17 {
18   dsk_format_t fmt = FMT_180K;
19   const char *fname;
20
21   while (dg_stdformat(NULL, fmt, &fname, NULL) == DSK_ERR_OK)
22   {
23     if (!strcmp(name, fname))
24     {
25       dg_stdformat(geom, fmt, &fname, NULL);
26       return NULL;
27     }
28     ++fmt;
29   }
30   return "Unrecognised LibDsk geometry specification";
31 }
32
33 /* Device_open           -- Open an image file                      */ /*{{{*/
34 const char *Device_open(struct Device *this, const char *filename, int mode, const char *deviceOpts)
35 {
36   char *format;
37   char driverName[80];
38   const char *boo;
39   dsk_err_t e;
40
41   /* Assume driver name & format name both fit in 80 characters, rather than
42    * malloccing the exact size */
43   if (deviceOpts == NULL) 
44   {
45     e = dsk_open(&this->dev, filename, NULL, NULL);
46     format = NULL;
47   }
48   else
49   {
50     strncpy(driverName, deviceOpts, 79);
51     driverName[79] = 0;
52     format = strchr(driverName, ',');
53     if (format)
54     {
55       *format = 0;
56       ++format;
57     }
58     e = dsk_open(&this->dev, filename, driverName, NULL);
59   }
60   this->opened = 0;
61   if (e) return dsk_strerror(e);
62   this->opened = 1;
63   if (format) 
64   {
65     boo = lookupFormat(&this->geom, format);
66     if (boo) return boo;
67   }
68   else 
69   {
70     dsk_getgeom(this->dev, &this->geom); 
71   }
72   return NULL;
73 }
74 /*}}}*/
75 /* Device_setGeometry    -- Set disk geometry                       */ /*{{{*/
76 const char *Device_setGeometry(struct Device *this, int secLength, int sectrk, int tracks, off_t offset, const char *libdskGeometry)
77 {
78   char *boo;
79
80   this->secLength=secLength;
81   this->sectrk=sectrk;
82   this->tracks=tracks;
83   /* Must be an even multiple of sector size */
84   assert(offset%secLength==0);
85   this->offset=offset;
86   /* If a geometry is named in diskdefs, use it */
87   if (libdskGeometry && libdskGeometry[0])
88   {
89     return lookupFormat(&this->geom, libdskGeometry);
90   }
91   
92   this->geom.dg_secsize   = secLength;
93   this->geom.dg_sectors   = sectrk;
94   /* Did the autoprobe guess right about the number of sectors & cylinders? */
95   if (this->geom.dg_cylinders * this->geom.dg_heads == tracks) return NULL;
96   /* Otherwise we guess: <= 43 tracks: single-sided. Else double. This
97    * fails for 80-track single-sided if there are any such beasts */
98   if (tracks <= 43) 
99   {
100     this->geom.dg_cylinders = tracks;
101     this->geom.dg_heads     = 1; 
102   }
103   else
104   {
105     this->geom.dg_cylinders = tracks/2;
106     this->geom.dg_heads     = 2; 
107   }
108   return NULL;
109 }
110 /*}}}*/
111 /* Device_close          -- Close an image file                     */ /*{{{*/
112 const char *Device_close(struct Device *this)
113 {
114   dsk_err_t e;
115   this->opened=0;
116   e = dsk_close(&this->dev);
117   return (e?dsk_strerror(e):(const char*)0);
118 }
119 /*}}}*/
120 /* Device_readSector     -- read a physical sector                  */ /*{{{*/
121 const char *Device_readSector(const struct Device *this, int track, int sector, char *buf)
122 {
123   dsk_err_t e;
124   e = dsk_lread(this->dev, &this->geom, buf, (track * this->sectrk) + sector + this->offset/this->secLength);
125   return (e?dsk_strerror(e):(const char*)0);
126 }
127 /*}}}*/
128 /* Device_writeSector    -- write physical sector                   */ /*{{{*/
129 const char *Device_writeSector(const struct Device *this, int track, int sector, const char *buf)
130 {
131   dsk_err_t e;
132   e = dsk_lwrite(this->dev, &this->geom, buf, (track * this->sectrk) + sector + this->offset/this->secLength);
133   return (e?dsk_strerror(e):(const char*)0);
134 }
135 /*}}}*/