I submitted this a while back, no comments were made but it was not included either. Changelog: 1 - Fix incorrect reporting of no media in floppy drive as permissions problem. 2 - Provide partial workaround for very long delays (c. 40 sec per lookup, about 7 minutes to set up file browser) on lookups to floppy drive not physically present (e.g. laptop with floppy or CD setup) Index: wine/files/drive.c =================================================================== RCS file: /home/wine/wine/files/drive.c,v retrieving revision 1.74 diff -u -r1.74 drive.c --- wine/files/drive.c 20 Jun 2002 23:21:27 -0000 1.74 +++ wine/files/drive.c 2 Jul 2002 18:19:38 -0000 @@ -7,6 +7,7 @@ * Label & serial number read support. * (c) 1999 Petr Tomasek <tomasek@etf.cuni.cz> * (c) 2000 Andreas Mohr (changes) + * (c) 2002 Keith Matthews (changes) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -36,6 +37,7 @@ #include <fcntl.h> #include <errno.h> #include <unistd.h> +#include <time.h> #ifdef HAVE_SYS_PARAM_H # include <sys/param.h> @@ -541,26 +543,126 @@ #define DRIVE_SUPER 96 int fd; off_t offs; + struct stat dev_data; + uid_t user; + gid_t group; + time_t call_start, call_end; + double time_diff; int ret = 0; if (memset(buff,0,DRIVE_SUPER)!=buff) return -1; - if ((fd=open(DOSDrives[drive].device,O_RDONLY)) == -1) + + if ((DOSDrives[drive].flags & DRIVE_DISABLED)) + return 0; /* should not get DEIVE_DISABLED here except as part of + * non-existing floppy kludge + */ + if (!DOSDrives[drive].device) { - struct stat st; - if (!DOSDrives[drive].device) - ERR("No device configured for drive %c: !\n", 'A'+drive); - else - ERR("Couldn't open device '%s' for drive %c: ! (%s)\n",DOSDrives[drive].device, 'A'+drive, - (stat(DOSDrives[drive].device, &st)) ? - "not available or symlink not valid ?" : "no permission"); - ERR("Can't read drive volume info ! Either pre-set it or make sure the device to read it from is accessible !\n"); + ERR("No Device Configured for drive %c: !\n",'A'+drive); PROFILE_UsageWineIni(); return -1; } + if (( stat(DOSDrives[drive].device,&dev_data)) == -1) + { + if (errno == ENOENT || errno == ENOTDIR || errno == ELOOP || errno == ENAMETOOLONG ) + { + ERR("Device ('%s) Configured for drive %c: is not a valid device path!\n",DOSDrives[drive].device,'A'+drive); + return -1; + } else if ( errno == EACCES ) + ERR("Permissions problem on device for drive %c: !\n", 'A'+drive); + PROFILE_UsageWineIni(); + return -1; + } else + { + user = getuid(); + group = getgid(); + if ( user == dev_data.st_uid) + { + /* We are running as the device owner - check those perms */ + if ( (dev_data.st_mode & S_IRUSR) == 0 ) + { + /* owner does not have read perms - stupid but */ + ERR("Permissions problem on device for drive %c: - user does not have read access !\n", 'A'+drive); + PROFILE_UsageWineIni(); + return -1; + } + } else if ( group == dev_data.st_gid ) + { + if ( (dev_data.st_mode & S_IRGRP) == 0 ) + { + /* group does not have read perms */ + ERR("Permissions problem on device for drive %c: - group does not have read access !\n", 'A'+drive); + PROFILE_UsageWineIni(); + return -1; + } + + } else if ( (dev_data.st_mode & S_IROTH) == 0 ) + { + /* not owning user or group and no perms */ + ERR("Permissions problem on device for drive %c: - effective user does not have read access !\n", 'A'+drive); + PROFILE_UsageWineIni(); + return -1; + + } + } + + time(&call_start); + /******************************************************************************* + * start of kludge to trap situation where attempt is madeto address /dev/fd0 + * (or some such) and it is not actually present. Should never happen in + * desktop machine but could well happen on laptop. + * + * Kludge only necessary as open thinks it can really open the file and + * takes 39 seconds to do it. + * + *******************************************************************************/ + + if ((fd=open(DOSDrives[drive].device,O_RDONLY)) == -1) + { + if (DOSDrives[drive].type == DRIVE_REMOVABLE ) + { + /***************************************************************************** + * OK, we've checked just about everything we can, it's a removeable media + * device, so assume no media since that gives same response + * + * Wrong if not running as root and user does not have read to device but + * we've already checked for that above + * + **************************************************************************/ + + DOSDrives[drive].flags = DOSDrives[drive].flags |DRIVE_NO_MEDIA; + +/* ++++++++++++++++ should we be down here for CD's also ? also what about Jazz drives etc ?+++++++++++++++++++++++ */ + + } else { + /**************************************************************************** + * + * Not removeable media device - must be permissions problem + * + ***************************************************************************/ + ERR("Couldn't open device '%s' for drive %c: ! (%s)\n", DOSDrives[drive].device, 'A'+drive, + "no permission"); + ERR("Can't read drive volume info ! Either pre-set it or make sure the device to read it from is accessible !\n"); + PROFILE_UsageWineIni(); + return -1; + + } + } + + time(&call_end); + time_diff = difftime(call_end, call_start); + if (time_diff > 5 ) + { + /* open took more that 5 sec. - error situation described above */ + DOSDrives[drive].flags = DOSDrives[drive].flags | DRIVE_DISABLED; + return 0; /* no point in erroring, act as if no media */ + } + switch(DOSDrives[drive].type) { case DRIVE_REMOVABLE: + /* leaves offs unset - is this critical ? */ case DRIVE_FIXED: offs = 0; break; @@ -572,15 +674,17 @@ break; } - if ((offs) && (lseek(fd,offs,SEEK_SET)!=offs)) - { - ret = -4; - goto the_end; - } - if (read(fd,buff,DRIVE_SUPER)!=DRIVE_SUPER) + if ((offs) && (lseek(fd,offs,SEEK_SET)!=offs)) return -4; + if (read(fd,buff,DRIVE_SUPER)!=DRIVE_SUPER) { - ret = -2; - goto the_end; + if (DOSDrives[drive].type != DRIVE_REMOVABLE) + { + return -2; + } else { + DOSDrives[drive].flags = DOSDrives[drive].flags | DRIVE_NO_MEDIA; + return 0; + } + } switch(DOSDrives[drive].type)