I've been working lately on rehauling the file handling in Wine.
The current output is a large patch, available here: http://perso.wanadoo.fr/pouech-eric/ep-file.diff.gz (400 KB uncompressed)
It's not completly ready yet for inclusion, however some ongoing discussions could overlap with what I've currently done (like how to configure drive without a config file, SMB handling...). So better discuss it widely (yet another flame war).
The benefit of the patch: - all file creation, opening, directory browsing is now done in ntdll instead of kernel32 - file IO management can be cleanly separated between kernel32 and ntdll (1) - files/ directory could be removed (not done in the patch (also nuked include/drive.h and include/file.h) - homogenous drive & device handling (we no longer store those objects in the server). Drive and device are now standard file handles (from a Windows point of view). - a few current Wine bugs have been fixed (see the todo_wine removed in the tests subdirs) - we no longer rely on the Wine config dir for the drive settings - partial NT volume management implementation - most of the volume related information (& ioctl) are done on the real unix device attached to the volume
What has been removed (from current implementation): - file system options (all FS are considered case insensitive) - per drive code page (all drives are now handled with the wine specfic UNIXCP code page)
What still need some improvement - fix all the introduced bugs (even if all the current tests actually pass) - setting a first default environment (even if tools/winefs provides it - see below)
Drives (and all their attributes - mount points, labels...) are defined this way:
1 Volumes & drives ------------------
Every volume on each available volume (partition on a physical disk) on the system will be listed in ${WINEPREFIX}/device directory. This directory will also be populated by other needed devices (serial, parallel, physical disks). Each item in this devices list will be stored as a subdirectory of ${WINEPREFIX}/device. Each subdirectory will contain various files & symlinks related to this device. Every volume will be named volume{XXX} where XXX is the actual unix device name. We're using this syntax so that we can distinguish from other (non-volume) devices and because under windows, volumes are named as Volume{<UID>} where <UID> is the unique identifier of the volume.
Every DOS drive letter will be known from a (directory) entry in ${WINEPREFIX}/dosdevices. This directory will also contains entries for VxDs. A drive letter entry will in fact be a symlink to $WINEPREFIX/device/volume{XXX}/mount. This later will be another symlink to the actual mount point of volume XXX. This double indirection is needed: a DOS drive can be mounted either at the root of a volume, or as a subdirectory on that volume. The first symlink (in the dosdevices directory) will point to subdirectory we want to mount on, and the second will hold where the volume itself is mounted.
For convenience reasons, we also list, for every DOS drive, the volume on which it is mounted, by creating a symlink between ${WINEPREFIX}/device/x: and ${WINEPREFIX}/device/volume{XXX}
2 Example --------- Unix side: /dev/scd0 on /mnt/cdrom /dev/fd0 on /mnt/floppy /dev/hda1 on /mnt/ntfs /dev/hda5 on /mnt/windows /dev/hda6 on / /dev/hda8 on /opt /dev/hda9 on /home
Note, from now on, all paths are relative to ${WINEPREFIX} From this, we will define this hierarchy: device/ volume{fd0}/ device -> /dev/fd0 mount -> /mnt/floppy/ volume{hda1}/ device -> /dev/hda1 mount -> /mnt/ntfs/ volume{hda5}/ device -> /dev/hda5 mount -> /mnt/windows/ volume{hda6}/ device -> /dev/hda6 mount -> / volume{hda8}/ device -> /dev/hda8 mount -> /opt/ volume{hda9}/ device -> /dev/hda9 mount -> /home/ volume{scd0}/ device -> /dev/scd0 mount -> /mnt/cdrom/ This hierarchy doesn't depend on what's actually mounted (both on unix side and windows side), it's just the volume definition.
We also define a few more disks related entries: device/ harddisk0/ device -> /dev/hda and some other devices as well: device/ null/ device -> /dev/null parallel0/ device -> /dev/lp0 serial0/ device -> /dev/ttyS0
Now, assume we want to define our DOS drives as follow: a: -> /mnt/fd0/ c: -> /home/eric/.wine/c_copy/ d: -> /opt/winapps/ e: -> /mnt/cdrom/ f: -> /tmp g: -> /home/eric/ m: -> /mnt/windows/
We will create two new symlinks per drive: one in $WINEPREFIX/device which will point to the device of the volume, another one in $WINEPREFIX/dosdevices which will point to the unix root we want for the drive.
device/ a: -> volume{fd0} c: -> volume{hda9} d: -> volume{hda8} e: -> volume{scd0} f: -> volume{hda6} g: -> volume{hda9} m: -> volume{hda5} dosdevices/ a: -> ../device/volume{fd0}/mount/ c: -> ../device/volume{hda9}/mount/eric/.wine/c_copy/ d: -> ../device/volume{hda8}/mount/winapps/ e: -> ../device/volume{scd0}/mount/ f: -> ../device/volume{hda6}/mount/tmp/ g: -> ../device/volume{hda9}/mount/eric/ m: -> ../device/volume{hda5}/mount/
We also define some more DOS devices (for the other devices we defined): dosdevices/ com1 -> ../device/serial0/device lpt1 -> ../device/parallel0/device nul -> ../device/null/device physicaldrive0 -> ../device/harddisk0/device
3 More details on volumes -------------------------
In a volume subdirectory in ${WINEPREFIX}/volume{XXX} we can also find some other files used for: - getting volume label. We try to get information in the following order: 1/ read it from device (done for disks with FAT partition, and AUDIO or data CDROM - mixed mode is not supported) 2/ if 1/ fails, read the file .windows-label at (unix) root of volume (handy for hard, floppy disks) 3/ if 2/ fails, read the file label from the file ${WINEPREFIX}/device/volume{XXX}/label - getting volume serial number. We try to get information in the following order: 1/ read it from device (done for disks with FAT partition, and CDROMs) 2/ if 1/ fails, read the file .windows-serial at (unix) root of volume (handy for hard, floppy disks) 3/ if 2/ fails, read the file label from the file ${WINEPREFIX}/device/volume{XXX}/serial - some specific attributes are stored in ${WINEPREFIX}/device/volume{XXX}/flags. This file stores an unsigned value, which high word is the device characteristics, while its low word is the device type (from include/winioctl.h FILE_DEVICE_????).
The VxDs and TSRs will be defined as an empty file (which name is VxD or TSR name) in ${WINEPREFIX}/dosdevices.
Every filename will be case insensitive (device, VxD, TSR...) as we always do case insensitive matching.
4 Example of the full configuration -----------------------------------
-> is a symlink to <> contains
device/ a: -> volume{fd0} c: -> volume{hda9} d: -> volume{hda8} e: -> volume{scd0} f: -> volume{hda6} g: -> volume{hda9} harddisk0/ device -> /dev/hda m: -> volume{hda5} null/ device -> /dev/null parallel0/ device -> /dev/lp0 serial0/ device -> /dev/ttyS0 volume{fd0}/ device -> /dev/fd0 flags <> FILE_DEVICE_DISK + FILE_REMOVABLE_MEDIA|FILE_FLOPPY_DISKETTE mount -> /mnt/floppy/ volume{hda1}/ device -> /dev/hda1 flags <> FILE_DEVICE_DISK mount -> /mnt/ntfs/ volume{hda5}/ device -> /dev/hda5 flags <> FILE_DEVICE_DISK label <> VolumeC mount -> /mnt/windows/ volume{hda6}/ device -> /dev/hda6 flags <> FILE_DEVICE_DISK mount -> / volume{hda8}/ device -> /dev/hda8 flags <> FILE_DEVICE_DISK mount -> /opt/ volume{hda9}/ device -> /dev/hda9 flags <> FILE_DEVICE_DISK mount -> /home/ volume{scd0}/ device -> /dev/scd0 flags <> FILE_DEVICE_CD_ROM + FILE_READ_ONLY_DEVICE|FILE_REMOVABLE_DEVICE mount -> /mnt/cdrom/ dosdevices/ a: -> ../device/volume{fd0}/mount/ afilter awredir aux -> ../dosdevices/com1 bios bios_ext bioshook biosxlat blockdev c: -> ../device/volume{hda9}/mount/eric/.wine/standalone/c_copy/ chbios com1 -> ../device/serial0/device configmg d: -> ../device/volume{hda8}/mount/winapps/ debug debugcmd dosmgr dosnet dragcli dragsrv dsvxd dwcfgmg e: -> ../device/volume{scd0}/mount/ ebios efax efilter eisa emmxxxx0 enable eten f: -> ../device/volume{hda6}/mount/tmp/ ffilter filesec g: -> ../device/volume{hda9}/mount/eric/ hasp95 hpscan ifsmgr int13 irlamp isapnp logger lpt1 -> ../device/parallel0/device m: -> ../device/volume{hda5}/mount/ mca_pos memprobe mmdevldr monodebg.vxd mrci2 msodisup ndis ndis2sup nscl nul -> ../device/null/device nwlink nwredir nwserver nwsup pagefile pageswap parity pccard pci peloader perf physicaldrive0 -> ../device/harddisk0/device ppp reboot scsi scsifd scsimgr$ scsiport secprov server shell splitter spooler stat80 tfilter tsrload v86mmgr vasync vbrowse vcache vcd vcdfsd vcomm vcond vdd vdd2 vdhcp vdmad vfat vfbackup vfd vhbiosd vime vip vkd20 vmcpd vmd vmm vmpoll vmsgd vnb vnbt vnetbios vnetsup vnwlink vpd vpend vpicd vpowerd vppid vprod vredir vsd vshare vtcp vtd vtdapi vtdi vudp vwin32 vxdldr win32s windebug winload winsock wsipx wsock wstcp
5 Configuration --------------- All this configuration is done automatically by a new tool: tools/winefs. This tool : a/ creates (in all cases) from the /etc/fstab entries (and the known VxD and TSR) all possible entries in ~/.wine/device and ~/.wine/dosdevice b/ will try to define the DOS drives depending on various sources
You can run it in several fashions: 1/ winefs ~/.wine Will get all possible information from the current ~/.wine/config for Wine drive settings (mount points, device, labels, serial number...) 2/ winefs ~/.wine --bios-assign Will do as previously, but creating the DOS drive assignments as the BIOS would do 3/ winefs ~/.wine --no-assign Will only provide step a/ Beware, rerunning winefs will erase all your previous settings.
Have fun !! A+
(1): not entirely true in this patch => the volume management (even if most of the code exists in ntdll) doesn't work as expected from ntdll. So the current kernel32 implementation remains