From: tomasek@etf.cuni.cz (Petr Tomasek)
Newsgroups: local.list.wine.patches
Subject: Auto reading of labels & serial numbers. (fwd)
Date: 15 Nov 1999 21:22:36 +0100
Organization: home
Lines: 295
Message-ID: <Pine.LNX.4.04.9911151313350.2292-200000@ebed.etf.cuni.cz>
Mime-Version: 1.0
Content-Type: MULTIPART/MIXED; BOUNDARY="1908605701-2102248834-942667042=:1411"
Content-ID: <Pine.LNX.4.04.9911151313351.2292@ebed.etf.cuni.cz>
X-Resent-Date: Mon, 15 Nov 1999 05:16:28 -0700
X-To: wine-patches@winehq.com
X-Resent-Message-ID: <z4vwk.A.na.cm_L4@ursula.gmcl.com>
X-Resent-From: wine-patches@winehq.com
X-Reply-To: wine-devel@winehq.com
X-Mailing-List: <wine-patches@winehq.com> archive/latest/2126
X-Loop: wine-patches@winehq.com
X-Precedence: list
X-Resent-Sender: wine-patches-request@winehq.com


Hello!

I've made a patch, that allows wine to read labels and
serial numbers directly from the device (no more having to
be specified in the wine.conf file).

For doc see Documentation/labels-and-serial-numbers.

One more issue: I had to create procedure named
'PROFILE_ExistWineString' (in profile.c), that checks,
whether certain entry exists in the wine.conf. You may want
to change its name to something better....

Best Wishes

Petr Tomasek

BTW, could I be informed, whether the patch was accepted to
the CVS /Wine release? Thanks!


--
Petr Tomasek, http://www.etf.cuni.cz/~tomasek/

Index: documentation/cdrom-labels
diff -ruN wine-991031/documentation/cdrom-labels wine-991031-new/documentation/cdrom-labels
--- wine-991031/documentation/cdrom-labels	Sun Jun  6 19:28:20 1999
+++ wine-991031-new/documentation/cdrom-labels	Sun Nov 14 14:41:08 1999
@@ -1,3 +1,7 @@
++-----------------------------------------------------------------------------+
+| This doc is obsolate now. See 'labels-and-serial-nubmers' for current info. |
++-----------------------------------------------------------------------------+
+
 *** VOLUME LABEL
 
 If a program depends on the correct label and/or serial number for the
Index: documentation/lables-and-serial-nubers
diff -ruN wine-991031/documentation/lables-and-serial-nubers wine-991031-new/documentation/lables-and-serial-nubers
--- documentation/lables-and-serial-nubers	Thu Jan  1 01:00:00 1970
+++ documentation/lables-and-serial-nubers	Sun Nov 14 16:12:01 1999
@@ -0,0 +1,88 @@
+[FIXME - can someone translate this into (real) english? :)) ]
+[FIXME - update the 'Documentation/config' accordingly]
+
+
+		Drive Labels and Serial Numbers with wine.
+		-----------------------------------------
+
+	Until now, You had to specify drive labels and serial numbers in wine 
+config file manually. For now, wine can read them directly from the device.
+	This may be usefull mainly for programs distributed on CD-Roms, that
+check for volume label at the setup or when accesing the disc.  
+
+WHAT'S SUPPORTED ?
+
+    *	FAT systems (types 'hd' and 'floppy'): reads labels and serial num's.
+    * 	Iso9660 ('cdrom'):                     reads labels only.
+
+HOW TO SET UP ?
+
+	There are two ways: You can either set 'ReadLabelFromDevice=' and
+'ReadSerialFromDevice=' in [Drive X] section in Your wine.conf (~/.winerc) 
+to 'true' or 'false', if want to disable/enable reading label/serial number
+from the device for this drive. Note, that you have to have specified 'Device' 
+and appropriate 'Type' entries!
+
+	If 'ReadLabelFromDevice' and/or 'ReadSerialFromDevice' unspecified, wine
+tries to find out, whether to read labels/serial num's from device by itself.
+It will read them when 'Device' and 'Type' entries specified correctly and 
+appropriate 'Label'/'Serial' section is NOT specified. (In other words 
+specifying 'Label'/'Serial' will cause wine to use specified value rather, 
+than reading it from the device).
+
+
+EXAMPLES
+
+*** Simple example of cdrom and floppy; labels will be read from the device on 
+both, cdrom and floppy; serial numbers on floppy only:
+
+[Drive A]
+Path=/mnt/floppy
+Type=floppy
+Device=/dev/fd0
+Filesystem=msdos
+
+[Drive R]
+Path=/mnt/cdrom
+Type=cdrom
+Device=/dev/hda1
+Filesystem=win95
+
+*** Cdrom. We want to override the label:
+
+[Drive J]
+Path=/mnt/cdrom
+Type=cdrom
+Label=X234GCDSE
+Device=/dev/cdrom
+Filesystem=msdos
+
+*** This is a bit tricky example. It will read label and serial number from the 
+ZIP disk; if this fails (no ZIP disk in drive/ acces denied to the device /
+the disk is not formatted as FAT), it will fall back to the specified values.
+
+[Drive D]
+Path=/mnt/zip
+Type=hd
+Label=*Unknown*
+ReadLabelFromDevice=true
+Serial=00000000
+ReadSerialFromDevice=true
+Device=/dev/hdc4
+Filesystem=msdos
+
+
+TODO / OPEN ISSUES
+
+ - The cdrom-label can be read only if the data track of the disk resides in 
+the first track and the cdrom is iso9660.
+ - Better checking for FAT superblock (it now check's only one byte).
+ - Support for labels/serial num's WRITING.
+ - Can the label be longer than 11 chars? (iso9660 has 32 chars).
+ - What about reading ext2 volume label? ....
+
+
+					Petr Tomasek
+					<tomasek@etf.cuni.cz>
+					Nov 14 1999
+
Index: files/drive.c
diff -ruN wine-991031/files/drive.c wine-991031-new/files/drive.c
--- wine-991031/files/drive.c	Wed Oct 13 15:57:38 1999
+++ wine-991031-new/files/drive.c	Sun Nov 14 16:42:45 1999
@@ -3,6 +3,10 @@
  *
  * Copyright 1993 Erik Bos
  * Copyright 1996 Alexandre Julliard
+ *
+ * Label & Serial-number read support. 
+ *  (c) 1999 Petr Tomasek <tomasek@etf.cuni.cz> 
+ *
  */
 
 #include "config.h"
@@ -59,6 +63,8 @@
     UINT    flags;     /* drive flags */
     dev_t     dev;       /* unix device number */
     ino_t     ino;       /* unix inode number */
+    int       read_label;   /* should disk label be read from device ? */
+    int	      read_serial;  /* should serial number be read ? */
 } DOSDRIVE;
 
 
@@ -187,6 +193,25 @@
                                       buffer, sizeof(buffer) );
             drive->serial = strtoul( buffer, NULL, 16 );
 
+	    /* Should the label be read directly from the device ? */
+            drive->read_label=
+	       ((drive->type==TYPE_FLOPPY) ||
+                 (drive->type==TYPE_HD) ||
+                 (drive->type==TYPE_CDROM)) &&
+		(PROFILE_ExistWineString(  name, "Device")) &&
+	          (PROFILE_ExistWineString(name, "ReadLabelFromDevice") ?
+                  PROFILE_GetWineIniBool(name, "ReadLabelFromDevice", 1) : 
+    	            (!PROFILE_ExistWineString(  name, "Label")));
+
+	    /* Should the serial number be read from the device ? */
+            drive->read_serial=
+	       ((drive->type==TYPE_FLOPPY) ||
+                 (drive->type==TYPE_HD)) &&
+		(PROFILE_ExistWineString( name, "Device")) &&
+	          (PROFILE_ExistWineString(name, "ReadSerialFromDevice") ?
+                  PROFILE_GetWineIniBool(name, "ReadSerialFromDevice", 1) : 
+                    (!PROFILE_ExistWineString( name, "Serial")));
+
             /* Get the filesystem type */
             PROFILE_GetWineIniString( name, "Filesystem", "win95",
                                       buffer, sizeof(buffer) );
@@ -207,6 +232,8 @@
                            name, path, DRIVE_Types[drive->type],
                            drive->label, drive->serial, drive->flags,
                            (int)drive->dev, (int)drive->ino );
+	    TRACE_(dosfs)("%s: label ? %d , serial ? %d\n",name,
+			   drive->read_label, drive->read_serial);
         }
         else WARN_(dosfs)("%s: not defined\n", name );
     }
@@ -395,11 +422,80 @@
 
 
 /***********************************************************************
+ *           DRIVE_ReadFatSuperblock
+ *
+ * Used in DRIVE_GetLabel and DRIVE_GetSerial
+ */
+int DRIVE_ReadFatSuperblock (char * dev, char * buff) 
+{
+int fd;
+#define DRIVE_SUPER 96  /* Number of bytes read from the superblock */
+
+if (memset(buff,0,DRIVE_SUPER)!=buff) return -1;
+if ((fd=open(dev,O_RDONLY))==-1) return -1;
+if (read(fd,buff,DRIVE_SUPER)!=DRIVE_SUPER) return -2;
+if (buff[0x26]!=0x29)  return -3;   /* Check for FAT present */ 
+return close (fd);
+}
+
+
+/***********************************************************************
+ *           DRIVE_ReadIso9660Superblock
+ *
+ * Used in DRIVE_GetLabel
+ */
+int DRIVE_ReadIso9660Superblock (char * dev, char * buff) 
+{
+int block=0;   
+/* FIXME: Maybe we should search for the first data track on the CD,
+    not just assume, that it is the first track. */
+int fd;
+off_t offset;
+offset=(off_t)2048*(16+block);
+
+if (memset(buff,0,DRIVE_SUPER)!=buff) return -1;
+if ((fd=open(dev,O_RDONLY))==-1) return -1;
+if (lseek(fd,offset,SEEK_SET)!=offset) return -4;
+if (read(fd,buff,DRIVE_SUPER)!=DRIVE_SUPER) return -2;
+if (strncmp(&buff[1],"CD001",5)) return -3;   /* Check for iso9660 present */
+return close (fd);
+
+}
+
+
+
+/***********************************************************************
  *           DRIVE_GetLabel
  */
 const char * DRIVE_GetLabel( int drive )
 {
+char buff[DRIVE_SUPER];
+
     if (!DRIVE_IsValid( drive )) return NULL;
+    if (DOSDrives[drive].read_label) {
+      if ((DOSDrives[drive].type == TYPE_FLOPPY) ||
+          (DOSDrives[drive].type == TYPE_HD)) {
+	if (DRIVE_ReadFatSuperblock(DOSDrives[drive].device,(char *) buff))
+           
+	  MESSAGE("Invalid or unreadable superblock on %s (%c:)."
+             " Maybe not FAT?\n" ,DOSDrives[drive].device,(char)(drive+'A'));
+	else {
+		memcpy(DOSDrives[drive].label,buff+0x2b,11);
+		DOSDrives[drive].label[11]='\0';
+	 }
+       }
+      if (DOSDrives[drive].type == TYPE_CDROM) {
+	if (DRIVE_ReadIso9660Superblock(DOSDrives[drive].device,(char *) buff))
+           
+	  MESSAGE("Invalid or unreadable superblock on %s (%c:)."
+           " Maybe not Iso9660?\n" ,DOSDrives[drive].device,(char)(drive+'A'));
+	else {
+/* FIXME: Iso9660 uses 32-bytes long label. Should we do also? */
+		memcpy(DOSDrives[drive].label,buff+40,11);
+		DOSDrives[drive].label[11]='\0';
+	 }
+       }
+     }
     return DOSDrives[drive].label;
 }
 
@@ -409,7 +505,19 @@
  */
 DWORD DRIVE_GetSerialNumber( int drive )
 {
+char buff[DRIVE_SUPER];
+
     if (!DRIVE_IsValid( drive )) return 0;
+    if (DOSDrives[drive].read_serial)
+      if ((DOSDrives[drive].type == TYPE_FLOPPY) ||
+          (DOSDrives[drive].type == TYPE_HD)) {
+	if (DRIVE_ReadFatSuperblock(DOSDrives[drive].device,(char *) buff))
+           
+	  MESSAGE("Invalid or unreadable superblock on %s (%c:)."
+             " Maybe not FAT?\n" ,DOSDrives[drive].device,(char)(drive+'A'));
+	else 
+	DOSDrives[drive].serial=*((DWORD*)(buff+0x27));
+       }
     return DOSDrives[drive].serial;
 }
 
Index: files/profile.c
diff -ruN wine-991031/files/profile.c wine-991031-new/files/profile.c
--- wine-991031/files/profile.c	Sun Oct 31 18:32:57 1999
+++ wine-991031-new/files/profile.c	Sat Nov 13 20:37:29 1999
@@ -708,6 +708,27 @@
 
 
 /***********************************************************************
+ *           PROFILE_ExistWineString
+ *
+ * Tests for tags in the wine.ini file. 
+ */
+int PROFILE_ExistWineString ( const char *section, const char *key_name)
+{
+
+    int	ret;
+
+    EnterCriticalSection( &PROFILE_CritSect );
+
+ret=(PROFILE_Find(&PROFILE_WineProfile, section, key_name, FALSE)!=NULL);
+
+    LeaveCriticalSection( &PROFILE_CritSect );
+
+    return ret;
+}
+
+
+
+/***********************************************************************
  *           PROFILE_GetWineIniString
  *
  * Get a config string from the wine.ini file.
Index: include/options.h
diff -ruN wine-991031/include/options.h wine-991031-new/include/options.h
--- wine-991031/include/options.h	Fri Jul 23 21:19:56 1999
+++ wine-991031-new/include/options.h	Sat Nov 13 20:38:31 1999
@@ -83,6 +83,7 @@
 
 /* Profile functions */
 
+extern int PROFILE_ExistWineString( const char *section ,const char *key_name);
 extern int PROFILE_LoadWineIni(void);
 extern void PROFILE_UsageWineIni(void);
 extern int PROFILE_GetWineIniString( const char *section, const char *key_name,
Index: libtest/volinfo.c
diff -ruN wine-991031/libtest/volinfo.c wine-991031-new/libtest/volinfo.c
--- wine-991031/libtest/volinfo.c	Sat Apr  3 15:52:04 1999
+++ wine-991031-new/libtest/volinfo.c	Sun Nov 14 05:59:18 1999
@@ -13,7 +13,7 @@
 
     printf("Drive Serial     Flags      Filename-Length "
            "Label                 Fsname\n");
-    for (drive = 'C'; drive <= 'Z'; drive++)
+    for (drive = 'A'; drive <= 'Z'; drive++)
     {
         root[0] = drive;
         if (GetVolumeInformation(root,label,labellen,&serial,
