1 From pere@minerva.cc.uit.no Mon Oct 26 18:22:40 1998
2 Received: from minerva.cc.uit.no (pere@nb38.stud.cs.UiT.No [129.242.13.48])
3 by yuubin.games.no (8.8.7/8.8.7) with ESMTP id TAA27004
4 for <pere@games.no>; Mon, 26 Oct 1998 19:22:38 +0100
5 Received: (from pere@localhost)
6 by minerva.cc.uit.no (8.8.7/8.8.7) id TAA09696;
7 Mon, 26 Oct 1998 19:22:40 +0100
8 Date: Mon, 26 Oct 1998 19:22:40 +0100
9 Message-Id: <199810261822.TAA09696@minerva.cc.uit.no>
10 From: Petter Reinholdtsen <pere@localhost.localdomain>
11 To: patches@winehq.com
12 Subject: Read ISO 9660 label from /dev/cdrom
18 * files/drive.c: Petter Reinholdtsen <pere@td.org.uit.no>
19 Changed DRIVE_GetLabel to extract ISO 9660 label from CDROMs. It
20 requires read access to /dev/cdrom and 'Device=/dev/cdrom' and
21 'Type=cdrom' to be set in the [Drive X] section of .winerc.
24 ===================================================================
25 RCS file: /home/wine/wine/files/drive.c,v
26 retrieving revision 1.4
28 --- drive.c 1998/10/20 14:25:50 1.4
29 +++ drive.c 1998/10/26 18:18:58
34 +#define ISO_9660_LABEL_LEN 32 /* 32 */
35 +#define FAT_LABEL_LEN 11 /* 8+3 */
37 +/* Which should we use? */
38 +#define LABEL_LEN ISO_9660_LABEL_LEN
42 char *root; /* root dir in Unix format without trailing / */
43 char *dos_cwd; /* cwd in DOS format without leading or trailing \ */
44 char *unix_cwd; /* cwd in Unix format without leading or trailing / */
45 char *device; /* raw device path */
46 - char label[12]; /* drive label */
47 + char label[LABEL_LEN+1]; /* drive label + terminating 0 */
48 DWORD serial; /* drive serial number */
49 DRIVETYPE type; /* drive type */
50 UINT32 flags; /* drive flags */
52 drive->ino = drive_stat_buffer.st_ino;
54 /* Get the drive label */
55 - PROFILE_GetWineIniString( name, "Label", name, drive->label, 12 );
56 - if ((len = strlen(drive->label)) < 11)
57 + PROFILE_GetWineIniString( name, "Label", name, drive->label,
59 + if ((len = strlen(drive->label)) < LABEL_LEN)
61 /* Pad label with spaces */
62 - memset( drive->label + len, ' ', 11 - len );
63 - drive->label[12] = '\0';
64 + memset( drive->label + len, ' ', LABEL_LEN - len );
65 + drive->label[LABEL_LEN+1] = '\0';
68 /* Get the serial number */
74 TRACE(dosfs, "%s -> drive %c:, root='%s', name='%s'\n",
75 buffer, 'A' + rootdrive,
76 DOSDrives[rootdrive].root, *path );
81 @@ -387,13 +396,100 @@
82 return DOSDrives[drive].unix_cwd;
85 +/***********************************************************************
86 + * DRIVE_iso9660label [internal]
88 + * Extract the 32 bytes label from ISO 9660 CDROM filesystem.
90 + * Requires read access to the raw device (/dev/cdrom).
93 + * Current label in static char *, only valid until next call to
94 + * this method, or NULL if wrong filesystem or something else goes
98 + * When the Unix kernel provides filesystem label using ioctl, this
99 + * method should be changed to use that instead.
101 + * I know nothing about the filesystem layout, and has just been
102 + * quessing about where to find the label based on other source
103 + * (Linux, etc). All this should be verified by someone who knows
104 + * what they are doing. It is tested, and seem to work.
108 +DRIVE_iso9660label(char *device)
110 +#define LABEL_POS 0x8028-0x8001
111 +#define READ_LEN LABEL_POS+ISO_9660_LABEL_LEN+1
112 + const char magic[] = "CD001";
113 + static char buffer[READ_LEN];
116 + if (NULL == device)
120 + * Check if ISO 9660 magic 'CD001' is at absolute sector 16. I hope
121 + * pos 0x8001 corresponds to the correct position. If this is
122 + * correct file system, return the 32 bytes giving the label from pos
125 + dev = fopen(device, "rb");
127 + && 0 == fseek(dev, 0x8001, SEEK_SET)
128 + && READ_LEN == fread(buffer, 1, READ_LEN, dev)
129 + && 0 == memcmp(buffer, magic, sizeof(magic)-1)
133 + buffer[READ_LEN] = 0;
134 + return buffer+LABEL_POS;
137 + /* Something wrong, close and return. */
145 /***********************************************************************
148 + * There is no known way to extract the filesystem label using ioctl
149 + * or any other decent method. I therefore choose this crude way, using
150 + * FS depentend code to read the label from the device file, to extract
151 + * the label and fall back to the preset one.
153 const char * DRIVE_GetLabel( int drive )
155 + char *device = NULL;
157 + TRACE(dosfs, "(%c:)\n", 'A' + drive);
159 if (!DRIVE_IsValid( drive )) return NULL;
161 + device = DOSDrives[drive].device;
163 + if (NULL != device && TYPE_CDROM == DRIVE_GetType(drive))
165 + char *label = DRIVE_iso9660label(device);
170 + static int first_time = 1;
171 + if (first_time) /* It is probably enough to print this once */
173 + "Unable to fetch ISO9660 label from %s. Is it readable? (one-time-warning)\n",
179 return DOSDrives[drive].label;
183 new->root = HEAP_strdupA( SystemHeap, 0, old->root );
184 new->dos_cwd = HEAP_strdupA( SystemHeap, 0, old->dos_cwd );
185 new->unix_cwd = HEAP_strdupA( SystemHeap, 0, old->unix_cwd );
186 - memcpy ( new->label, old->label, 12 );
187 + memcpy ( new->label, old->label, LABEL_LEN+1 );
188 new->serial = old->serial;
189 new->type = old->type;
190 new->flags = old->flags;
192 ##> Petter Reinholdtsen <## | pere@td.org.uit.no