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