New upstream version 2.20
[debian/cpmtools] / device_libdsk.c
index 739a3acb14b3c07315795a6af0459695eb264921..51dcc01e34899aff0730097e6bb0e6ee1a0628f0 100644 (file)
 #endif
 /*}}}*/
 
+static const char *lookupFormat(DSK_GEOMETRY *geom, const char *name)
+{
+  dsk_format_t fmt = FMT_180K;
+  const char *fname;
+
+  while (dg_stdformat(NULL, fmt, &fname, NULL) == DSK_ERR_OK)
+  {
+    if (!strcmp(name, fname))
+    {
+      dg_stdformat(geom, fmt, &fname, NULL);
+      return NULL;
+    }
+    ++fmt;
+  }
+  return "Unrecognised LibDsk geometry specification";
+}
+
 /* Device_open           -- Open an image file                      */ /*{{{*/
 const char *Device_open(struct Device *this, const char *filename, int mode, const char *deviceOpts)
 {
-  dsk_err_t e = dsk_open(&this->dev, filename, deviceOpts, NULL);
+  char *format;
+  char driverName[80];
+  const char *boo;
+  dsk_err_t e;
+
+  /* Assume driver name & format name both fit in 80 characters, rather than
+   * malloccing the exact size */
+  if (deviceOpts == NULL) 
+  {
+    e = dsk_open(&this->dev, filename, NULL, NULL);
+    format = NULL;
+  }
+  else
+  {
+    strncpy(driverName, deviceOpts, 79);
+    driverName[79] = 0;
+    format = strchr(driverName, ',');
+    if (format)
+    {
+      *format = 0;
+      ++format;
+    }
+    e = dsk_open(&this->dev, filename, driverName, NULL);
+  }
   this->opened = 0;
   if (e) return dsk_strerror(e);
   this->opened = 1;
-  dsk_getgeom(this->dev, &this->geom); 
+  if (format) 
+  {
+    boo = lookupFormat(&this->geom, format);
+    if (boo) return boo;
+  }
+  else 
+  {
+    dsk_getgeom(this->dev, &this->geom); 
+  }
   return NULL;
 }
 /*}}}*/
 /* Device_setGeometry    -- Set disk geometry                       */ /*{{{*/
-void Device_setGeometry(struct Device *this, int secLength, int sectrk, int tracks, off_t offset)
+const char *Device_setGeometry(struct Device *this, int secLength, int sectrk, int tracks, off_t offset, const char *libdskGeometry)
 {
+  char *boo;
+
   this->secLength=secLength;
   this->sectrk=sectrk;
   this->tracks=tracks;
   /* Must be an even multiple of sector size */
   assert(offset%secLength==0);
   this->offset=offset;
+  /* If a geometry is named in diskdefs, use it */
+  if (libdskGeometry && libdskGeometry[0])
+  {
+    return lookupFormat(&this->geom, libdskGeometry);
+  }
   
   this->geom.dg_secsize   = secLength;
   this->geom.dg_sectors   = sectrk;
   /* Did the autoprobe guess right about the number of sectors & cylinders? */
-  if (this->geom.dg_cylinders * this->geom.dg_heads == tracks) return;
+  if (this->geom.dg_cylinders * this->geom.dg_heads == tracks) return NULL;
   /* Otherwise we guess: <= 43 tracks: single-sided. Else double. This
    * fails for 80-track single-sided if there are any such beasts */
   if (tracks <= 43) 
@@ -50,6 +105,7 @@ void Device_setGeometry(struct Device *this, int secLength, int sectrk, int trac
     this->geom.dg_cylinders = tracks/2;
     this->geom.dg_heads     = 2; 
   }
+  return NULL;
 }
 /*}}}*/
 /* Device_close          -- Close an image file                     */ /*{{{*/