diff --git a/disk.c b/disk.c
index 1f39aea..dc986f6 100644
--- a/disk.c
+++ b/disk.c
@@ -2343,27 +2343,44 @@ disk_update_tlens( libspectrum_disk *d )
  */
 libspectrum_disk_error_t
 libspectrum_disk_open( libspectrum_disk *d, libspectrum_byte *buffer,
-                       size_t length )
+                       size_t length, libspectrum_disk_type_t type2,
+                       const char *filename )
 {
   buffer_t b;
   libspectrum_id_t type;
+  size_t filename_length;
   int error;
 
   if( !d || !buffer ) return LIBSPECTRUM_DISK_BADPARAM;
 
-  b.idx = 0;
-  b.data = buffer;
-  b.len = length;
+  d->data = NULL;
+  d->filename = NULL;
+  d->open_flag = 0; /* reset open flags */
+  d->type = type2;
+
+  if( filename ) {
+    filename_length = strlen( filename ) + 1;
+    d->filename = libspectrum_new( char, filename_length );
+    memcpy( d->filename, filename, filename_length );
+  }
 
   /* TODO: open_log() */
   if( ( d->type == LIBSPECTRUM_DISK_TYPE_NONE && d->filename == NULL ) ||
-        d->type >= LIBSPECTRUM_DISK_LOG )
+        d->type >= LIBSPECTRUM_DISK_LOG ) {
+    libspectrum_free( d->filename ); d->filename = NULL;
     return d->status = LIBSPECTRUM_DISK_UNKNOWN;
+  }
+
+  b.idx = 0;
+  b.data = buffer;
+  b.len = length;
 
   if( d->type == LIBSPECTRUM_DISK_TYPE_NONE ) {
     error = libspectrum_identify_file_raw( &type, d->filename, b.data, b.len );
-    if( error ) return d->status = LIBSPECTRUM_DISK_UNKNOWN;
-    d->type = LIBSPECTRUM_DISK_TYPE_NONE;
+    if( error ) {
+      libspectrum_free( d->filename ); d->filename = NULL;
+      return d->status = LIBSPECTRUM_DISK_UNKNOWN;
+    }
 
     switch( type ) {
     case LIBSPECTRUM_ID_DISK_UDI:
@@ -2391,12 +2408,11 @@ libspectrum_disk_open( libspectrum_disk *d, libspectrum_byte *buffer,
     case LIBSPECTRUM_ID_DISK_D80:
       d->type = LIBSPECTRUM_DISK_D80; break;
     default:
+      libspectrum_free( d->filename ); d->filename = NULL;
       return d->status = LIBSPECTRUM_DISK_UNKNOWN;
     }
   }
 
-  d->open_flag = 0; /* reset open flags */
-
   switch( d->type ) {
   case LIBSPECTRUM_DISK_UDI:
     open_udi( &b, d );
@@ -2430,14 +2446,13 @@ libspectrum_disk_open( libspectrum_disk *d, libspectrum_byte *buffer,
     open_d40_d80( &b, d );
     break;
   default:
-    return d->status = LIBSPECTRUM_DISK_UNKNOWN;
+    d->status = LIBSPECTRUM_DISK_UNKNOWN;
+    break;
   }
 
   if( d->status != LIBSPECTRUM_DISK_OK ) {
-    if( d->data != NULL ) {
-      libspectrum_free( d->data );
-      d->data = NULL;
-    }
+    libspectrum_free( d->data ); d->data = NULL;
+    libspectrum_free( d->filename ); d->filename = NULL;
     return d->status;
   }
 
@@ -3179,6 +3194,7 @@ libspectrum_disk_write( libspectrum_disk *d, libspectrum_byte **buffer,
   }
 
   if( d->status != LIBSPECTRUM_DISK_OK ) {
+    libspectrum_free( b.data );
     *buffer = NULL;
     *length = 0;
     return d->status;
diff --git a/doc/libspectrum.txt b/doc/libspectrum.txt
index a4a9910..3bd6995 100644
--- a/doc/libspectrum.txt
+++ b/doc/libspectrum.txt
@@ -1900,19 +1900,19 @@ LIBSPECTRUM_DISK_UDI is recommended.
 
 libspectrum_disk_error_t
 libspectrum_disk_open( libspectrum_disk *d, libspectrum_byte *buffer,
-                       size_t length )
+                       size_t length, libspectrum_disk_type_t type,
+                       const char *filename )
 
 Open a disk image from buffer. Identifies the disk type and rebuilds
 internally the disk geometry.
 
-Prior to the call to this function, some fields of libspectrum_disk should
-be set, e.g., the filename of the file (d->filename) and the type (d->type)
-of image. In the case of LIBSPECTRUM_DISK_TYPE_NONE, the format is guessed
+In the case of LIBSPECTRUM_DISK_TYPE_NONE type, the format is guessed
 from the filename extension in `filename' parameter.
 
 The geometry can be tune-up through flags (d->flag), e.g., if
-LIBSPECTRUM_DISK_FLAG_PREIDX is set and the disk type is not UDI, then
-a pre-index gap is generated with index mark (0xfc).
+LIBSPECTRUM_DISK_FLAG_PREIDX is set (prior to the call to this function)
+and the disk type is not UDI, then a pre-index gap is generated with
+index mark (0xfc).
 
 void
 libspectrum_disk_close( libspectrum_disk *d )
diff --git a/libspectrum.h.in b/libspectrum.h.in
index 3d1e580..20b1baf 100644
--- a/libspectrum.h.in
+++ b/libspectrum.h.in
@@ -1187,7 +1187,8 @@ libspectrum_disk_new( libspectrum_disk *d, int sides, int cylinders,
 */
 WIN32_DLL libspectrum_disk_error_t
 libspectrum_disk_open( libspectrum_disk *disk, libspectrum_byte *buffer,
-                       size_t length );
+                       size_t length, libspectrum_disk_type_t type,
+                       const char *filename );
 
 /* merge two one sided disk (d1, d2) to a two sided one (d),
    after merge closes d1 and d2
