diff --git a/COPYING b/COPYING index a43ea21..da037af 100644 --- a/COPYING +++ b/COPYING @@ -1,339 +1,17 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. +The dmsdos package is distributed under the terms and conditions of the +GNU General Public License. The original text of this License can be found +in file GPL. This means, in short words, you may use, modify and/or +redistribute the package given that you include full source code, the +names of all authors, and the original License text. - Preamble +For the dmsdos library there's an exception: you may, at your choice, use +it under the terms and conditions of the GNU Library General Public License +instead. The original text of this License can be found in file LGPL. +The difference is, in short words, the LGPL allows you to distribute a +program linked with the library under your own license terms. - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. +If you do not accept the License, the software is subject to Copyright Law. +This means you may still use it, but you may not modify or redistribute it. - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. +Please read the files GPL and LGPL for details. diff --git a/INSTALL.TXT b/INSTALL.TXT index 0606900..57ad4b7 100644 --- a/INSTALL.TXT +++ b/INSTALL.TXT @@ -1,81 +1,234 @@ DMSDOS + CVF-FAT installation - -0. Preparing installation -------------------------- - -Upgrade from dmsdosfs 0.8.x(.y) or earlier: *** WARNING *** - If you have an earlier version of the dmsdos filesystem installed (i.e. - dmsdos 0.8.x), you'd better throw away your kernel sources and get fresh - ones. You must remove all old dmsdos sources, especially header files, and - executables or modules. The new code doesn't install the dmsdos module in - the kernel source tree, so this is very important. To be sure, do a - 'find / -name "*dmsdos*" -print', or check your path for old executables - and your /lib/modules/* directories for old modules. Okay, I promise that - this kind of cleanup will no longer be necessary for further upgrades :) - -Upgrade from 0.9.0(.x) or higher: - You don't need to reconfigure or recompile your kernel. You don't - need to patch the kernel again. Just compile the new dmsdos module - and the updated dmsdos utilities. - -Fresh installation: - If you have never used an older version of dmsdos before, you don't - have to remove anything :) But, depending on your kernel version, you - may have to patch your kernel sources. You may also have to reconfigure - and recompile your kernel even if there's no patch needed. - -For brave people only: - Though this is still experimental, dmsdos can perform most parts of - the installation automatically. (This was already a hidden feature in - previous versions.) If you just type 'make', it performs steps 1, 2, 3, - and optionally 8 (it will ask you) below. This is for people with a - standard kernel who do not want to care about all the details. If - your kernel has to be recompiled the procedure stops just after - recompiling your kernel and your modules. A text appears asking you - to install the new kernel and the new modules by hand and reboot with - the new kernel. You can do that now, but you can also do it later. - Then enter a 'make' again, and it should continue with the rest. - You can still run the second 'make' without installing the new kernel - and modules and without rebooting; dmsdos will compile in spite of that. - But dmsdos will not run correctly or not run at all unless you have - rebooted with the new kernel and the new modules. - -------------------------------------------------------------------------- - -1. Check kernel for CVF-FAT and install it if it is missing ------------------------------------------------------------ - - Make sure you have a kernel version 2.0.29 or newer from the 2.0 series - or a kernel version 2.1.94 or newer from the 2.1 development series. - Older kernels may work too, but this has never been tested. If you are - using older kernels and run into problems please don't expect me to fix - them - it's too much work to keep a multi-kernel dmsdos package work with - all old and new kernels :) - - Dmsdos version 0.9.0 and higher depend on the CVF-FAT interface in the - kernel. This interface is already present in kernels 2.1.80 and newer, - and it is also compatible with UMSDOS in 2.1.xx since 2.1.94. - So if you have 2.1.80 or newer you can skip the rest of this section. - - For 2.0.xx kernels you need to apply a patch. Dmsdos comes with a - collection of patches for different setups. If you are brave you can - enter a 'make patch'. This starts a script that tries to find out - automatically whether you need a patch and which one, and it installs - the patches it thinks you need. Be warned, the script is not perfect. - It is known to work if you do not have an unusual setup (well, it works - for a plain 2.0.33 kernel, also with a fat32 patched 2.0.33 kernel and - with the new 2.0.34 and 2.0.35). - - If automatic patching fails or if your setup is a highly patched or hacked - kernel you might want to take a look at further instructions. Please read - the file DIFFS.TXT to find out which patch you need and how to install it. - ----------------------------------------------------------------------------- - -2. Check kernel configuration ----------------------------- - For dmsdos you need: +*** These are installation instructions for use under LINUX. If you want to + install dmsdos in a Dos/Win32 environment see file PORT_TO_WIN32. *** + + +If you want to install dmsdos without bothering all the details, please +read at least the chapter 'Easy Installation'. If that does not work for +you, try 'Manual Installation'. + +*** FAT DRIVER BUG WARNING: + + * FAT32 kernels earlier than 2.0.36 have a serious rmdir bug + that causes filesystem corruption in a msdos filesystem. + See file patches/DIFFS.TXT where to find a patch to fix this + (patches/msdos-rmdir-bugfix.diff). + + * All current kernels from the 2.0, 2.1 and 2.2 series have a bug that + can do write access to a FAT filesystem though it is mounted read-only. + Though it only occurs in a rare situation, this bug can especially be + triggered by dmsdos. Also see file patches/DIFFS.TXT where to find a + patch to fix this (patches/fat-truncate-bugfix.diff). + + * All current 2.2 kernels (this means at least up to 2.2.2; 2.2.3 has + not been released yet at the time of writing) (and maybe late 2.1 + kernels too) have a serious bug in the vfat driver that can cause + system hang ("kernel panic: VFS: LRU list corrupted") due to filesystem + buffer list corruption. Also see file patches/DIFFS.TXT where to find a + patch to fix this (patches/vfat-brelse-bugfix.diff). IT IS VITAL FOR + USING DMSDOS IN A VFAT PARTITION TO HAVE THIS BUG FIXED. + + These bugs are not fixed automatically during installation. If you are + in doubt, please check the diff files and your kernel source. You can use + dmsdos without these bugfixes, but you may crash or hang your system or + lose data. YOU HAVE BEEN WARNED. + + +A. Easy Installation +==================== + + Dmsdos comes with a set of scripts for automatic installation. If you do not + like some scripts poke around in your system, see chapter 'Manual + Installation' :) + + Okay, just a small warning: automatic installation can never be perfect. + For a 2.0.xx kernel I recommend to make a backup copy of your kernel sources + if you cannot restore it easily. Dmsdos needs to patch the 2.0.xx kernels + a bit. This is not a problem if you are using unmodified kernel sources + from 2.0.29 to 2.0.36 (others are currently not tested), but if your kernel + is highly hacked or patched the patch might go wrong and need manual + correction. If you are not familiar with hacking around in failed patches, + I think, you will be lucky to restore the old state :) + + 2.1 and 2.2 kernels do not need a patch, but you may choose to update the + CVF-FAT interface (though it still works with the old one). The updated + files have not been included into the official kernel yet (at the time of + writing, current=2.2.2). I hope they go into 2.2.3 or 2.2.4. :) A + description of how and what to update can be found in patches/cvf.c.README. + + And, of course, you should ensure you have fixed the kernel FAT driver bugs + listed above :) + + + 1. Prepare automatic installation: + ---------------------------------- + + You need, of course, full kernel sources in /usr/src/linux (which may be a + symbolic link to the real kernel source directory). No discussion here, + I say you _need_ or automatic installation refuses to start. You should + also ensure that the kernel version that you are currently running and the + sources in /usr/src/linux do match. Dmsdos may install the module at a + wrong place if they don't match, which does no harm but somewhat confuses + both the module subsystem and the system administrator :) + + * If you have installed a previous dmsdos version: + + Check the version number. If it's 0.8.x or lower you have a problem. + You must completely uninstall that version before. How to do so, see the + documentation of that old version (it should have some sripts for that + purpose). If you really can't uninstall it, throw away your old kernel + sources and get fresh ones and remove the old dmsdos binaries that may + be lying around in directories in your path. + + Dmsdos 0.9.0 and newer need not be uninstalled prior to an upgrade. + + + 2. Beginning installation: + -------------------------- + + Go into the directory where the dmsdos sources untarred and enter a + 'make'. That should do it. The installation script will ask some + questions. The script always waits for your confirmation before it + changes anything in your kernel sources or your system. You can exit + with CTRL-C at any stage (and continue with manual installation). + Be also prepared that the script calls kernel configuration and + recompiles your kernel (that depends on your system setup). + + * If problems arise: + + Automatic installation stops if it finds that something has gone wrong + (i.e. a patch failed). + + * If the script calls kernel configuration: + + This means something that is necessary for dmsdos to work correctly + has been turned off in your kernel configuration. For dmsdos you need: + + - Module support + - Loopback block device (may be compiled as module) + *** NOTE: This one can be found under 'Additional block devices'. + It has nothing in common with the network loopback interface + so please don't mix them up :) + - FAT filesystem (may be compiled as module) + - MSDOS or VFAT filesystem (may be compiled as module) + - since 2.0.34 also NLS support (but this is already required by FAT) + + * If the sript stops and asks for kernel and module installation and + for reboot: + + Well I hate scripts that install new kernels and reboot automatically. + So the dmsdos installation refuses to do that. Usually, the script wants + you to do + + cd /usr/src/linux + make zlilo + make modules_install + reboot + + or similar commands that have the same effect. You can do that + immediately, but you can also continue without rebooting. But, please + remember to do that before _using_ dmsdos the first time :) + + YOU SHOULD KNOW WHAT YOU ARE DOING. If not, read for example + the KERNEL-HOWTO or related documentation. + + Note that dmsdos installation is not complete yet. Rerun 'make' in the + directory where the dmsdos sources untarred. + + * If it asks strange questions about dmsdos configuration: + + Consult the "online" help or accept the default settings if you don't + understand what you are doing. You can rerun the dmsdos configuration + script again at any time later if you want to play with the options. + See 'Manual instalation' section 'Compiling the sources' for details. + + + 3. Completing installation + -------------------------- + + Okay, if all has completed without errors, it's time for the first test. + If the script asked for kernel and modules installation and for reboot + but you haven't done it yet, please do it now. + + The first test and everything beyond that is described in part + 'C. The first test'. + + +B. Manual Installation +====================== + + 1. Preparing installation + ------------------------- + + * Upgrade from dmsdosfs 0.8.x(.y) or earlier: *** WARNING *** + + If you have an earlier version of the dmsdos filesystem installed (i.e. + dmsdos 0.8.x), you'd better throw away your kernel sources and get fresh + ones. You must remove all old dmsdos sources, especially header files, and + executables or modules. The new code doesn't install the dmsdos module in + the kernel source tree, so this is very important. To be sure, do a + 'find / -name "*dmsdos*" -print', or check your path for old executables + and your /lib/modules/* directories for old modules. Okay, I promise that + this kind of cleanup will no longer be necessary for further upgrades :) + + * Upgrade from 0.9.0(.x) or higher: + + You don't need to reconfigure or recompile your kernel. You don't + need to patch the kernel again. Just compile the new dmsdos module + and the updated dmsdos utilities. + + * Fresh installation: + + If you have never used an older version of dmsdos before, you don't + have to remove anything :) But, depending on your kernel version, you + may have to patch your kernel sources. You may also have to reconfigure + and recompile your kernel even if there's no patch needed. + + *** Please ensure to have the kernel FAT driver bugs fixed (the bugs are + listed at the beginning of this ducument). + + + 2. Check kernel for CVF-FAT and install it if it is missing + ----------------------------------------------------------- + + Make sure you have a kernel version 2.0.29 or newer from the 2.0 series + or a kernel version 2.1.94 or newer from the 2.1 development series or + any 2.2.x kernel. Older kernels may work too, but this has never been + tested. If you are using older kernels and run into problems please don't + expect me to fix them - it's too much work to keep a multi-kernel dmsdos + package work with all old and new kernels :) + + Dmsdos version 0.9.0 and higher depend on the CVF-FAT interface in the + kernel. This interface is already present in kernels 2.1.80 and newer, + and it is also compatible with UMSDOS in 2.1.xx since 2.1.94. + So if you have 2.1.80 or newer you do not need a patch. But you may want + to update the CVF-FAT interface. The new interface has been suggested to + be included in newer kernels, but at the time of writing this it has not + yet gone in. See patches/cvf.c.README for instructions how and what to + update. Note that you do _not_ have to update - the old interface still + works (but it has a minor bug and lacks kerneld or kmod support). + + For 2.0.xx kernels you need to apply at least one of the CVF-FAT patches. + Dmsdos comes with a collection of patches for different setups. If you + are brave you can enter a 'make patch'. This starts a script that tries + to find out automatically whether you need a patch and which one, and it + installs the patches it thinks you need. Be warned, the script is not + perfect. It is known to work if you do not have an unusual setup (well, + it works for a plain 2.0.33 kernel, also with a fat32 patched 2.0.33 + kernel and with the newer 2.0.34 up to 2.0.36). + + If automatic patching fails or if your setup is a highly patched or hacked + kernel you might want to take a look at further instructions. Please read + the file patches/DIFFS.TXT to find out which patch you need and how to + install it. + + + 3. Check kernel configuration + ----------------------------- + + For dmsdos you need: - Module support - Loopback block device (may be compiled as module) @@ -86,190 +239,240 @@ For brave people only: - MSDOS or VFAT filesystem (may be compiled as module) - since 2.0.34 also NLS support (but this is already required by FAT) - If you don't know whether all of them are present you can enter a - 'make kernelconf'. This calls a script that checks your kernel - configuration and calls the interactive kernel 'Configure' script if - something is missing. In that case, just go through the questions, - mostly accepting the defaults, but be sure to say Y for module support, - Y or M for loopback block device, Y or M for FAT filesystem support, - and Y or M for the MSDOS or VFAT filesystem. Then the script tries to - compile your kernel. In some cases the script tends to recompile your - kernel though it isn't really necessary. So don't be surprised - it's - a dumb script. :) Note that the script does not *install* the new kernel - and the new modules. - - Refer to the kernel documentation for details about kernel configuration. - - If you do not want to let the dmsdos Makefile call the script but you - want to do it 'by hand' you can do this: - - cd /usr/src/linux - make config (or 'make menuconfig' if you prefer) - make dep - make clean - make zImage (or 'make bzImage' if you need it) - make modules - - When the kernel and the modules have been compiled, they must be - installed. This is usually done with these commands: - - cd /usr/src/linux - make zlilo - make modules_install - reboot - ---------------------------------------------------------------------------- - -3. Compile the dmsdos sources ------------------------------ + If you don't know whether all of them are present you can enter a + 'make kernelconf'. This calls a script that checks your kernel + configuration and calls the interactive kernel 'Configure' script if + something is missing. In that case, just go through the questions, + mostly accepting the defaults, but be sure to say Y for module support, + Y or M for loopback block device, Y or M for FAT filesystem support, + and Y or M for the MSDOS or VFAT filesystem. Then the script tries to + compile your kernel. In some cases the script tends to recompile your + kernel though it isn't really necessary. So don't be surprised - it's + a dumb script. :) Note that the script does not *install* the new kernel + and the new modules. + + Refer to the kernel documentation for details about kernel configuration. + + If you do not want to let the dmsdos Makefile call the script but you + want to do it 'by hand' you can do something like this: - Go into the directory where the dmsdos package untarred and do + cd /usr/src/linux + make config (or 'make menuconfig' if you prefer) + make dep + make clean + make zImage (or 'make bzImage' if you need it) + make modules - cd src - make config (or 'make menuconfig' if you prefer) + When the kernel and the modules have been compiled, they must be + installed. This is usually done with these commands: - Yes, there's a configuration script that asks some questions now. - You very likely know this procedure from the Linux kernel. In fact, - the scripts have been copied from the kernel and a bit hacked :-) - Well, there's no xconfig (I think this is overkill). + cd /usr/src/linux + make zlilo + make modules_install + reboot - If you have no clue what to answer to the questions, consult the online - help or accept the defaults (which should be safe and work for all - systems). - For convenience, there are some pre-configured files which can be loaded - with the 'Load an Alternate Configuration File' menu item during - 'make menuconfig'. Currently, these files are available: + 4. Compile the dmsdos sources + ----------------------------- + + Go into the directory where the dmsdos package untarred and do + + cd src + make config (or 'make menuconfig' if you prefer) + + Yes, there's a configuration script that asks some questions now. + You very likely know this procedure from the Linux kernel. In fact, + the scripts have been copied from the kernel and a bit hacked :-) + Well, there's no xconfig (I think this is overkill). + + If you have no clue what to answer to the questions, consult the online + help or accept the defaults (which should be safe and work for all + systems). As I have received a lot of mail about that, the dmsdos + configuration has now a normal and an expert mode. In normal mode, + only the most important questions (which should be understood by a + novice without problems) show up. + + For convenience, there are some pre-configured files which can be loaded + with the 'Load an Alternate Configuration File' menu item during + 'make menuconfig'. Currently, these files are available: config.small-module - for a small dmsdos module (e.g. for bootdisk) config.low-traffic-write - for low-traffic write access to a CVF config.high-traffic-write - for high-traffic write access to a CVF config.debug - for safe low-level dmsdos debugging - After loading the alternate config file you'd better check the settings - (just walk through all the menus). Especially if you want a small module - exclude the CVF format drivers you don't need. + After loading the alternate config file you'd better check the settings + (just walk through all the menus). Especially if you want a small module + exclude the CVF format drivers you don't need. - The text-based 'make config' can also use a pre-configured file. Just copy - the config.what-you-like to .config and run 'make config'. + The text-based 'make config' can also use a pre-configured file. Just copy + the config.what-you-like to .config and run 'make config'. - Then continue with these steps: + Then continue with these steps: - make dep - make clean - make + make dep + make clean + make - The last line starts compiling the sources. You may see some warnings - about 'unused variables' which can be ignored. + The last line starts compiling the sources. - There have been compile-time problems under certain gcc or libc systems - (notably glibc2/libc6). dmsdos should now fully compile under libc6, but - this is not thoroughly tested. There were also problems with some old - versions of binutils reported. Have a look at the Makefile for some hacks. + There were problems with some old versions of binutils reported (it's a + bug in old GNU assembler versions). Have a look at the Makefile for some + hacks. - If compiling the whole dmsdos package fails, you can try a 'make min' - which compiles a minimal dmsdos subsystem. Please note that glibc2/libc6 - causes *no* run-time problems (well, dmsdos is a kernel module and doesn't - use any system libraries). + If you want a shared dmsdos library instead of a static one you have + to edit the Makefile. Using the shared library is currently strongly + discouraged (well _not_ because of bugs). See the documentation for + the reasons. - If you run into strange problems, you can try to compile each part of - dmsdos separately: + If you run into strange problems, you can try to compile each part of + dmsdos separately: make dmsdos.o - compiles the dmsdos module dmsdos.o (required) make dutil - compiles the dmsdos utility dutil (useful) make dmsdosd - compiles the external dmsdos daemon (nice) - make libdmsdos.a - compiles the dmsdos library (experimental) - make dcread - compiles a sample program using libdmsdos (toy) + make libdmsdos.a - compiles the dmsdos library + make dcread - compiles a sample program using libdmsdos make dmsdosfsck - Ahh... it's there :) + make mcdmsdos - compiles a mc external fs interface tool + + If you can't get the external daemon compiled try the internal daemon + (though most people never need the daemon). It can be enabled during + configuration ('make config'). - If you can't get the external daemon compiled try the internal daemon - (though most people never need the daemon). It can be enabled during - configuration ('make config'). - - If you can't get it compiled at all, have a look at the Makefile in the - src directory. It has some switches to work around some problems (gas - bugs, unusual systems, switch off cpu specific optimization, switch off - inline assembler statements, etc). This should not be necessary, but some - systems might need it. - - If you still can't get it compiled, please send a bug report including a - detailed description of your system (version of kernel, gcc, binutils etc) - and what error messages are shown. If you know how to fix the problem - please also let me know :) A checklist about the details I usually need - for tracing down a problem can be found in doc/dmsdos.doc. - ---------------------------------------------------------------------------- - -4. Check whether the module loads correctly: - - insmod -m dmsdos > /tmp/dmsdos.map - - Check the file /tmp/dmsdos.map for error messages. - - If the module fails to load, make sure you are using the right insmod - version (there are lots of modutils versions for 2.1.xx - most don't - work correctly under all kernel versions; some are even said not to work - at all). If it still fails, try to load the fat module (and since kernel - 2.0.34 also the nls module) before. If it complains about a missing symbol, - try to find out which part of the kernel the symbol belongs to, and load - the appropriate module before or compile that part into your kernel. - If it continues to fail this is a bug. - - Please always load the module with the -m flag and redirect the - output, which contains a symbol table, to a file. This file is needed - in case there is a crash with a register dump. Please use this symbol - table to find the function where the problem occured. (Unfortunately, - this table usually differs from one insmod time to another depending on - actually free memory pages, so you can't just create the table once and - then use it for all dumps later.) If you don't know how to interpret a - register dump, please have a look at Linus' excellent instructions for - that in the file README in /usr/src/linux. It is really important that - *you* try to interpret the register dump since it is absolutely system - dependent. THIS IS NOT DIFFICULT. YOU DO NOT HAVE TO KNOW C PROGRAMMING - FOR THAT. - - Let me repeat this. I just cannot track down register dumps since they - are just some numbers, even to me :) Those numbers only make sense in - conjunction with the symbol table that was printed by insmod when the - module was loaded the last time before the crash. Thus, bug reports - without your interpretation by means of the symbol table are Really - Worthless and will be ignored. - ----------------------------------------------------------------------------- - -5. The first test ------------------ - - For the first test be sure to have the loop module, the fat module, - the dmsdos module and the msdos or vfat module loaded. If you are using - kerneld you might not have to care about most of them. Just the fat - module may have to be loaded manually in that case in order to load - the dmsdos module. + If you can't get it compiled at all, have a look at the Makefile in the + src directory. It has some switches to work around some problems (gas + bugs, unusual systems, switch off cpu specific optimization, switch off + inline assembler statements, etc). This should not be necessary, but some + systems might need it. + + If you still can't get it compiled, please send a bug report including a + detailed description of your system (version of kernel, gcc, binutils etc) + and what error messages are shown. If you know how to fix the problem + please also let me know :) A checklist about the details I usually need + for tracing down a problem can be found in doc/dmsdos.doc. + + +C. The first test +================= + + 1. Check whether the module loads correctly: + -------------------------------------------- + + Try a + + insmod -m dmsdos > /tmp/dmsdos.map + + Check the file /tmp/dmsdos.map for error messages. + Depending on your modutils version, you may have to use depmod or + modprobe instead of insmod. (Please forgive me, I never understood the + difference. Maybe I should read the documentation some day :) ) + + If the module fails to load, make sure you are using the right insmod + version (there are lots of modutils versions for 2.1.xx - most don't + work correctly under all kernel versions; some are even said not to work + at all). If it still fails, try to load the fat module (and since kernel + 2.0.34 also the nls module) before. If it complains about a missing symbol, + try to find out which part of the kernel the symbol belongs to, and load + the appropriate module before or compile that part into your kernel. + If it continues to fail this is a bug. If it prints out strange errors + like "kernel_version needed ...blah..." and you are using a 2.2.x kernel + get the latest module utilities for 2.1.xx kernels (I ran into this + problem too :) ). + + Note that, for a mixed 2.0/2.2 system, I need modutils-2.1.121 (compiled + against 2.2.x headers) but I must keep the kerneld binary from + modutils-2.0.0 (compiled against 2.0.x headers). Ughly, but the newer + kerneld provided with modutils-2.1.121 breaks my 2.0.x system :( + + Please always load the module with the -m flag and redirect the + output, which contains a symbol table, to a file. This file is needed + in case there is a crash with a register dump. Please use this symbol + table to find the function where the problem occured. (Unfortunately, + this table usually differs from one insmod time to another depending on + actually free memory pages, so you can't just create the table once and + then use it for all dumps later.) If you don't know how to interpret a + register dump, please have a look at Linus' excellent instructions for + that in the file README in /usr/src/linux. It is really important that + *you* try to interpret the register dump since it is absolutely system + dependent. THIS IS NOT DIFFICULT. YOU DO NOT HAVE TO KNOW C PROGRAMMING + FOR THAT. + + Let me repeat this. I just cannot track down register dumps since they + are just some numbers, even to me :) Those numbers only make sense in + conjunction with the symbol table that was printed by insmod when the + module was loaded the last time before the crash. Thus, bug reports + without your interpretation by means of the symbol table are Really + Worthless and will be ignored. + + + 2. Test whether dmsdos can read a CVF + ------------------------------------- + + For the first test be sure to have the loop module, the fat module, + the dmsdos module and the msdos or vfat module loaded. If you are using + kerneld you might not have to care about most of them. Just the fat + module may have to be loaded manually in that case in order to load + the dmsdos module. - Mount your Dos/Win95 partition that is the host for a compressed drive - as usual (if you haven't done this already). + Mount your Dos/Win95 partition that is the host for a compressed drive + as usual (if you haven't done this already). - Assuming the large Compressed Volume File (CVF) is /DOS/dblspace.001 and - you want to mount it under /mnt, try this (it mounts READ-ONLY): + Assuming the large Compressed Volume File (CVF) is /DOS/dblspace.001 and + in doublespace format and you want to mount it under /mnt, try this + (it mounts READ-ONLY): - mount -t msdos -o ro,loop /DOS/dblspace.001 /mnt + mount -t msdos -o ro,loop,cvf_format=dblspace /DOS/dblspace.001 /mnt - If the filesystem contains long filenames, you may want to use the VFAT - filesystem instead of the plain MSDOS driver: + Please also use the "cvf_format=dblspace" option for drivespace drives. + If the drive is in stacker format and the CVF is /DOS/stacvol.001 the + command looks like this: - mount -t vfat -o ro,loop /DOS/dblspace.001 /mnt + mount -t msdos -o ro,loop,cvf_format=stacker /DOS/stacvol.001 /mnt - Now you can go into the /mnt directory and do some read access tests. - If there are some problems, the dmsdos driver becomes very noisy and logs - a lot of messages in the syslog. Not all of them are real errors, though. - Some are just information about the kind of CVF detected and the results - of some probing functions. Yes, there are different kinds of CVF formats - throughout the Dos/Win95 versions :) + If the _compressed_ filesystem contains long filenames, you may want + to use the VFAT driver instead of the MSDOS driver: ------------------------------------------------------------------------------ + mount -t vfat -o ro,loop,cvf_format=dblspace /DOS/dblspace.001 /mnt -6. Permanent installation -------------------------- + Note that you can leave out the "cvf_format=xxx" option. In that case, + dmsdos automatically detects the CVF format. But it is recommended to + specify always a "cvf_format=xxx" option. + + (If you leave out the "cvf_format=xxx" option there can be a strange + error condition that is not immediately visible and causes awful + trouble some time later: + + If you leave out the "cvf_format=xxx" option and the dmsdos module + has not been loaded the plain FAT driver gets the compressed + filesystem, which it cannot handle. Unfortunately, a compressed FAT + filesystem looks very similar to an uncompressed one, so the FAT + driver may not refuse to mount the filesystem with an error message. + + *** This means, the mount command may succeed even if the dmsdos + module is not present. In that case, the FAT driver - wrongly - + assumes the mounted filesystem is _not_ compressed and it can + crash, hang or destroy the filesystem later when you try to + access it. + + So, *please*, always specify a "cvf_format=xxx" option for safety, + as it just prints an error if the dmsdos module is not loaded.) + + Now you can go into the /mnt directory and do some read access tests. + If there are some problems, the dmsdos driver becomes very noisy and logs + a lot of messages in the syslog. Not all of them are real errors, though. + Some are just information about the kind of CVF detected and the results + of some probing functions. Yes, there are different kinds of CVF formats + throughout the Dos/Win95 versions :) + + Note that, at mount time, for all doublespace and drivespace format CVFs + one (and only one) loop device error like "access beyond end of device" + or similar appears. This is normal and results from dmsdos working around + a limitation in the loop driver. This is *not* a dmsdos bug. + + +D. Permanent installation +========================= *** WARNING *** If you are upgrading from a dmsdos release in the range 0.9.0 to 0.9.1.1, @@ -292,124 +495,221 @@ For brave people only: the Makefile for the locations). All the files that are copied by 'make install' are removed by 'make uninstall'. - If 'make install' fails because the code cannot be compiled completely, - try a 'make install-min' instead to install a minimal but functional - dmsdos subsystem (which has been compiled by 'make min'). - ------------------------------------------------------------------------------ - -7. Some BUG WARNINGS important to know for installation -------------------------------------------------------- - - - UMSDOS related bugs: - - *** IN SOME 2.1.XX KERNELS UMSDOS SUPPORT IS COMPLETELY BROKEN *** - For some kernels, UMSDOS doesn't compile at all, for others it is - incompatible with dmsdos. Please do not use UMSDOS and dmsdos at the - same time under kernels 2.1.80 up to 2.1.93 (it cannot work). Use a - kernel from the 2.0.xx series or get at least 2.1.94. - If the UMSDOS module fails to load and complains about two - missing symbols 'fat_readpage' and 'fat_dir_ioctl': - I forgot to add some symbols to the export list in older cvf.diffs for - kernel 2.0.33. This bug also went in 2.1.80 when CVF-FAT was included. - In order to fix the problem, edit file linux/fs/fat/fatfs_syms.c and - append the missing symbols 'fat_readpage' and 'fat_dir_ioctl' to the - export list. Look how the other symbols are listed there and put in the - missing ones in the same way. (You don't need to know C programming for - that. Just use your common sense. You'll know what to do when you see - what's in that the file.) Then recompile the fat module (or the kernel - if your fat support isn't modular). - ------------------------------------------------------------------------------ - -8. Using kerneld to load dmsdos -------------------------------- - - I've received lots of mails about this. It seems still not working on - all systems. - - This is an installation tip for the convenient system hacker. It is - not the default installation, and it is only recommended for dmsdos - versions that are known to be stable. The reason is: this way does not - produce a symbol map for debugging :) - - If you do not know what kerneld is and what it does, please skip this - section (or read the KERNELD-MINI-HOWTO, for example). - - Apply the diff 'kerneld-autoload.diff' to your kernel sources and - recompile and reinstall your modules. If your FAT support is not modular - but a fix part of the kernel, you must recompile and reinstall your - kernel instead (and reboot). - - These changes just trigger kerneld to load dmsdos each time a fat based - filesystem is mounted. This ensures the detect_cvf routines are present - when they are needed to determine whether the filesystem is a CVF. If - it's not a CVF the dmsdos module will unload again after some time. - - Please do *not* add a line like 'post-install fat insmod -k dmsdos' or - 'alias fat dmsdos' to /etc/modules.conf (or /etc/conf.modules) any longer. - (Though some dmsdos users reported that it works for them.) I must warn, - it just causes headache. The problem is, if only fat gets used, dmsdos is - unloaded after 1 minute by kerneld. If you mount a CVF after that, dmsdos - will not be reloaded because fat gets not reloaded (well fat is present). - So the fat driver tries to handle a CVF by itself (and horribly fails and - starts printing possibly tons of errors to syslog). Argh. On the other - hand, if you leave out the -k flag from the insmod statement above, - dmsdos will never be unloaded and fat can never be unloaded because dmsdos - is using it. - - The autoload feature can be temporarily switched off by placing - 'alias dmsdos off' in /etc/modules.conf (or /etc/conf.modules) and - sending a SIGHUP to kerneld. - - The autoload patch enables a second feature: If a CVF is mounted with the - cvf_format=xxx mount option, a module xxx is requested before. So it just - can load other CVF modules too. (Do they exist? Just let me know.) - If you want to add support for loading other CVF modules without having - to specify the format, add 'request_module("name_of_module");' statements - to linux/fs/fat/cvf.c near the 'request_module("dmsdos");' statement. - ---------------------------------------------------------------------------- - -9. Mounting CVFs from /etc/fstab at boot time ---------------------------------------------- - - It may be a bit tricky to get CVFs mounted at boot time. An /etc/fstab - entry for a CVF usually looks like this: - - /DOS/drvspace.001 /DOSF msdos loop 1 0 - - It is really important that the sixth field (the 'pass number') is zero - in order to prevent the filesystem from being checked at boot time. - (If you really want to check dos partitions *and* CVFs at boot time you - very likely must hack your bootup scripts. This is not recommended, - however, unless you are an experienced system administrator and know in - detail how your bootup scripts work. This is not explained in the dmsdos - documentation.) - - In the usual one-pass 'mount -a' procedure, I noticed a strangeness - regarding the order in /etc/fstab: The filesystems seem to be - mounted in reverse order. Thus - - /DOS/drvspace.001 /DOSF msdos loop 1 0 - /dev/hda1 /DOS msdos defaults 1 0 - - works on my system while - - /dev/hda1 /DOS msdos defaults 1 0 - /DOS/drvspace.001 /DOSF msdos loop 1 0 - - doesn't. So just be prepared to play around a bit with the fstab. - ----------------------------------------------------------------------------- - -10. Further information ------------------------ - - The main dmsdos documentation is in doc/dmsdos.doc. Some other files in - the doc directory may be useful, too. Take a look at them if you want to - know more details or technical information on how dmsdos works. Please - also take a look at the documentation if you run into problems before - sending a bug report. Yes, there is a list with common problems and their - solutions :) +D. Other things to notice +========================= + + 1. Some BUG WARNINGS important to know for installation + ------------------------------------------------------- + + * UMSDOS related bugs: + + a) *** IN SOME 2.1.XX KERNELS UMSDOS SUPPORT IS COMPLETELY BROKEN *** + Please avoid kernels from 2.1.0 to 2.1.93. Use 2.1.94 or newer. + Even better: Upgrade to 2.2. + + b) If the UMSDOS module fails to load and complains about two + missing symbols 'fat_readpage' and 'fat_dir_ioctl': + I forgot to add some symbols to the export list in older cvf.diffs for + kernel 2.0.33. This bug also went in 2.1.80 when CVF-FAT was included. + In order to fix the problem, edit file linux/fs/fat/fatfs_syms.c and + append the missing symbols 'fat_readpage' and 'fat_dir_ioctl' to the + export list. Look how the other symbols are listed there and put in the + missing ones in the same way. (You don't need to know C programming for + that. Just use your common sense. You'll know what to do when you see + what's in that the file.) Then recompile the fat module (or the kernel + if your fat support isn't modular). + + I have seen that the problem is fixed in 2.1.128, but I did not verify + older kernels. Well that shouldn't matter as you always should use the + latest kernel if you want a development kernel :)) + + * FAT driver bugs: + + See the list above at the beginning of this document. + + + 2. Using kerneld or kmod to load dmsdos + --------------------------------------- + + This is an installation tip for the convenient system hacker. It is + not the default installation, and it is only recommended for dmsdos + versions that are known to be stable. + + Please note that in latest 2.1.xx kernels kerneld has been replaced by + kmod. This does not make a difference for dmsdos. + + In dmsdos-0.9.2.0 kerneld-autoload behaviour again has been changed. The + new behaviour is now believed to be the "right" way :-) If you are using + a CVF-FAT patch from an older dmsdos version (0.9.2.0-pre-3 and older) or + a kernel 2.2.2 or older you should update the CVF-FAT interface + (see patches/cvf.c.README) - otherwise it may not work. The updated files + have been suggested to be included into the kernel, but have not yet + gone in. + + If you do not know what kerneld or kmod is and what it does, please read + the KERNELD-MINI-HOWTO, for example, or refer to the documentation that + comes with the Linux kernel sources (for kmod). + + CVF-FAT now triggers kerneld or kmod to load missing CVF modules + according to the following rules: + + 1. If a fat based filesystem is mounted with the mount option + "cvf_format=autoload", a module with the name "cvf_autoload" is + requested. Well, such a module never exists. This does however + make sense together with a special modules configuration. + + 2. If a fat based filesystem is mounted with the mount option + "cvf_format=xxx" (where xxx has to be replaced with the name of + the format) a module "xxx" is requested. + + Usually there is a difference between the CVF format name and the + module name. This can be corrected with 'alias' statements in the + modules configuration file /etc/modules.conf (or /etc/conf.modules, + both file names are common). + + For dmsdos, you need the lines + + alias stacker dmsdos + alias dblspace dmsdos + alias cvf_autoload dmsdos + + in the configuration file. Note that kerneld needs a signal SIGHUP in + order to re-read the configuration file. Also note that this setup + directly loads the module and does not generate a symbol table (which is + required for debugging, for example to analyse a crash somewhere in the + module). + + If you need a symbol table from CVF module loading, you are out of luck. + Load the modules manually in that case, please. + + If you want to add support for loading other CVF modules (do they exist? + Let me know) with auto-detection (cvf_format=autoload), add "pre-install" + lines for them, e.g. + + pre-install cvf_autoload insmod -k cvf_mod1 + pre-install cvf_autoload insmod -k cvf_mod2 + ... + (untested, should work in theory. I do not know other CVF modules.). + + Problems with automatic loading of CVF modules should be solved by + hacking /etc/modules.conf. It is not recommended to fix them by changing + the dmsdos or kernel sources. If it does not work at all try another + kerneld version. Not every kerneld version runs correctly under + every kernel version. (Well this was probably one of the inofficial + reasons to replace it with kmod in latest 2.1.xx kernels...) + + + 3. Using dmsdos as external filesystem for Midnight Commander + ------------------------------------------------------------- + + Dmsdos comes with an interface utility that accepts standard Midnight + Commander commands for reading archive files. The utility is named + 'mcdmsdos' and is compiled during usual dmsdos compile process. + The utility is currently read-only. It follows the specification of + Midnight Commander version 3.0. + + Please refer to the documentation of Midnight Commander for further + information on how to configure an external filesystem. + + You may want to write a small shell script as a wrapper around mcdmsdos + in order to suppress output to stderr distorting the screen. For + example, this (in the same directory where mcdmsdos resides), as it + does not need to know the absolute path: + + #!/bin/bash + MCDMSDOS=`dirname $0`/mcdmsdos + $MCDMSDOS $* 2>/dev/null + + + 4. Compiling dmsdos as a fix part of the kernel + ----------------------------------------------- + + For some purpose it may be desired to compile dmsdos as a fix part of + the kernel (i.e. not as a loadable kernel module) so dmsdos is present + immediately at bootup. This would probably be useful for a boot disk or + an emergency rescue disk, for example. (This saves you all the work to + setup an initrd disk which is somewhat complex.) + + BE WARNED. This is not the default installation. This is not well tested. + The patches for that setup have been created under Linux 2.0.35 and may + fail for other kernels (that's unlikely because they are small, just a + few lines, and it's easy to repair manually if they do fail.) + + Okay, if you really want to do this, just install dmsdos as usual. + Test whether it works. I'd also recommend to _write_ _down_ the dmsdos + configuration settings, especially if you use expert mode (because the + default values are not available later on when you might need them - + due to my lazyness). + + After that, run the shell script 'in-kernel.sh' which just copies the + dmsdos sources into the kernel source tree and patches some files to + hang dmsdos in (have a look at the in-kernel*.diff if you want to know + exactly what is changed). You _very_ likely want to create a backup of + kernel sources before :) + + Then reconfigure your kernel. Answer 'Y' for loopback block device and + for the fat filesystem (also for NLS since Linux 2.0.34). Then enable + DMSDOS support. You'll see the usual dmsdos configuration after that, but + you won't have any default values (this is a limitation of the 2.0.xx + configuration scripts and I am too lazy to create a workaround diff). + Don't forget to say 'Y' for the MSDOS or VFAT driver after that. + + Just some further warnings about that setup: + + * There's no easy way back. If you installed dmsdos as a fix part of the + kernel the best way to get rid of it is getting fresh kernel sources. + Well, you can disable it in kernel configuration. You can also try + to run the script 'in-kernel-uninstall.sh', but no promise. + + * dmsdos may no longer compile in its own directory due to macro + redefinitions in the kernel include files. But dmsdos can now be + compiled as module in the same way like all other kernel modules + (i.e. run kernel configuration, answer 'M' to DMSDOS support, do + 'make modules' and 'make modules_install'). + + * This setup is not recommended at all. YOU HAVE BEEN WARNED :) + + + 5. Mounting CVFs from /etc/fstab at boot time + --------------------------------------------- + + It may be a bit tricky to get CVFs mounted at boot time. An /etc/fstab + entry for a CVF usually looks like this: + + /DOS/drvspace.001 /DOSF msdos loop,cvf_format=dblspace 1 0 + or + /DOS/stacvol.001 /DOSF msdos loop,cvf_format=stacker 1 0 + + It is really important that the sixth field (the 'pass number') is zero + in order to prevent the filesystem from being checked at boot time. + (If you really want to check dos partitions *and* CVFs at boot time you + very likely must hack your bootup scripts. This is not recommended, + however, unless you are an experienced system administrator and know in + detail how your bootup scripts work. This is not explained in the dmsdos + documentation.) + + In the usual one-pass 'mount -a' procedure, I noticed a strangeness + regarding the order in /etc/fstab: The filesystems seem to be + mounted in reverse order. Thus + + /DOS/drvspace.001 /DOSF msdos loop,cvf_format=dblspace 1 0 + /dev/hda1 /DOS msdos defaults 1 0 + + works on my system while + + /dev/hda1 /DOS msdos defaults 1 0 + /DOS/drvspace.001 /DOSF msdos loop,cvf_format=dblspace 1 0 + + doesn't. So just be prepared to play around a bit with the fstab. + + + 6. Further information + ---------------------- + + The main dmsdos documentation is in doc/dmsdos.doc. Some other files in + the doc directory may be useful, too. Take a look at them if you want to + know more details or technical information on how dmsdos works. Please + also take a look at the documentation if you run into problems before + sending a bug report. Yes, there is a list with common problems and their + solutions :) diff --git a/Makefile b/Makefile index 8427a24..7dd2fb8 100644 --- a/Makefile +++ b/Makefile @@ -10,14 +10,22 @@ kernelconf: patch compile: kernelconf make -C src -install: compile +install: + make -C src make -C src install + make -C man install sh magic.sh uninstall: make -C src uninstall + make -C man uninstall mrproper: rm -f *~ rm -f doc/*~ + rm -f man/*~ + rm -f patches/*~ make -C src mrproper + +dist: + sh mkdist.sh diff --git a/README b/README index 13d833e..77fb964 100644 --- a/README +++ b/README @@ -15,7 +15,14 @@ any more. List of files to read: ---------------------- -README this file -INSTALL.TXT how to install CVF-FAT and dmsdos -DIFFS.TXT description of kernel patches ("when do I use which one") -doc/* various documentation +README this file +INSTALL.TXT how to install CVF-FAT and dmsdos +patches/DIFFS.TXT description of kernel patches ("when do I use which one") +PORT_TO_WIN32 if you want to run dmsdos utilities in a Win32 environment + +Other directories: + +doc/ various documentation +man/ man pages for dmsdos utilities +src/ complete source code for dmsdos +patches/ kernel patches and updates for the CVF-FAT interface diff --git a/dmsdos.lsm b/dmsdos.lsm index b73ba0c..8911051 100644 --- a/dmsdos.lsm +++ b/dmsdos.lsm @@ -1,35 +1,39 @@ Begin3 Title: dmsdos -Version: 0.9.1.5 -Entered-date: 18AUG1998 +Version: 0.9.2.2 +Entered-date: 04DEC1999 Description: dmsdos: reads and writes compressed dos filesystems (CVF-FAT) * read and write access to compressed partitions (files like dblspace.xxx, drvspace.xxx and stacvol.xxx). The following configurations are supported: - DoubleSpace / DriveSpace (msdos 6.x) - - DoubleSpace / DriveSpace (win95) - - DriveSpace 3 (win95 with Plus! pack) + - DoubleSpace / DriveSpace (older win95 releases) + - DriveSpace 3 (win95 with Plus! pack or newer win95) - Stacker 3 - Stacker 4 * Works with FAT32, NLS, codepages etc. (tested with fat32 patches version 0.2.8 under Linux 2.0.33 and with fat32 in - standard 2.1.xx kernels and 2.0.34+35) + standard 2.1.xx kernels and 2.0.[34-36], also tested with + 2.2.[0-2] kernels). Tested with patched 2.2.13 and 2.3.30. * Dmsdos can run together with vfat or umsdos for long filenames. * Dmsdos has been redesigned to be ready for SMP. - * Dmsdos should now compile completely under libc6. + * Dmsdos compiles both under libc5 and libc6. + * The dmsdos library and some dmsdos tools compile even in a + 32 bit Dos/Windows environment. Keywords: filesystem compression doublespace drivespace stacker Author: gockel@sent13.uni-duisburg.de (Frank Gockel) pisa@cvlinux.felk.cvut.cz (Pavel Pisa) Maintained-by: gockel@sent13.uni-duisburg.de (Frank Gockel) pisa@cvlinux.felk.cvut.cz (Pavel Pisa) Primary-site: sunsite.unc.edu /pub/Linux/system/Filesystems/dosfs - 230 kB dmsdos-0.9.1.5.tgz + 262 kB dmsdos-0.9.2.1.tgz Alternate-site: ftp.uni-stuttgart.de /pub/systems/linux/local/system - 230 kB dmsdos-0.9.1.5.tgz + 262 kB dmsdos-0.9.2.1.tgz fb9nt.uni-duisburg.de /pub/linux/dmsdos - 230 kB dmsdosfs-0.9.1.5.tgz + 262 kB dmsdosfs-0.9.2.1.tgz Original-site: -Platforms: Linux 2.0.xx (xx>=29), 2.1.yy (yy>=94), msdos 6.x, win95 +Platforms: Linux 2.0.29 up to 2.0.36, 2.1.94+, 2.2.0+, 2.2.13+, + msdos 6.x, msdos 7.x, win95, winnt 4.0 Copying-policy: GPL End diff --git a/doc/FAQ b/doc/FAQ index 7f8ba04..56f6e0b 100644 --- a/doc/FAQ +++ b/doc/FAQ @@ -203,3 +203,13 @@ under kernel 2.0.34. In that case, you may share one precompiled dmsdos module with several kernels. But please don't overuse it. You should not, for example, use the same compiled object code of a dmsdos module for kernel 2.0.34 and 2.1.105 - this is very likely to cause problems :) + + + +Where does the name "DMSDOS" come from ? + +It has historical reasons. The first piece of dmsdos code was written in +times of MSDos 6.2 when Doublespace became very popular. Thus, dmsdos was +meant as something like "doublespaced msdos". Today, it supports a lot of +more compressed Dos filesystems, and a better name would be "cmsdos" for +"compressed msdos". But you never change the name of a successful project :) diff --git a/doc/cvf-fat.doc b/doc/cvf-fat.doc index d94dd88..ef064f2 100644 --- a/doc/cvf-fat.doc +++ b/doc/cvf-fat.doc @@ -1,217 +1,4 @@ -cvf-fat.doc -This is the main documentation for the CVF-FAT filesystem extension. 31DEC1997 - - -Table of Contents: - -1. The idea of CVF-FAT -2. Restrictions -3. Mount options -4. Installation -5. Description of the CVF-FAT interface -6. Authors and email addresses - ------------------------------------------------------------------------------- - - -1. The idea of CVF-FAT ------------------------------------------------------------------------------- - -CVF-FAT is a FAT filesystem extension that provides a generic interface for -Compressed Volume Files in FAT partitions. Popular CVF software, for -example, are Microsoft's Doublespace/Drivespace and Stac's Stacker. -Using the CVF-FAT interface, it is possible to load a module that handles -all the low-level disk access that has to do with on-the-fly compression -and decompression. All other part of FAT filesystem access is still handled -by the FAT, MSDOS or VFAT or even UMSDOS driver. - -CVF access works by redirecting certain low-level routines from the FAT -driver to a loadable, CVF-format specific module. This module must fake -a normal FAT filesystem to the FAT driver while doing all the extra stuff -like compression and decompression silently. - - -2. Restrictions ------------------------------------------------------------------------------- - -- BMAP problems - - CVF filesystems cannot do bmap. It's impossible by principle. Thus - all actions that require bmap do not work (swapping). Writable mmapping - should work via readpage, but is untested. Does anyone know an application - that is doing writable mmaps? This would be needed for tests :) - -- DOSEMU users attention - - You may have to unmount all CVF partitions before running DOSEMU depending - on your configuration. If DOSEMU is configured to use wholedisk or - partition access (this is often the case to let DOSEMU access - compressed partitions) there's a risk of destroying your compressed - partitions or crashing your system because of confused drivers. - - Note that it is always safe to redirect the compressed partitions with - lredir or emufs.sys. Refer to the DOSEMU documentation for details. - - -3. Mount options ------------------------------------------------------------------------------- - -The CVF-FAT extension currently adds the following options to the FAT -driver's standard options: - - cvf_format=xxx - Forces the driver to use the CVF module "xxx" instead of auto-detection. - This is only necessary if the CVF format is not recognized correctly - because of bugs or incompatibilities in the CVF modules. (It skips - the detect_cvf call.) "xxx" may be the text "none" (without the quotes) - to inhibit using any of the loaded CVF modules, just in case a CVF - module insists on mounting plain FAT filesystems by misunderstanding :) - - cvf_options=yyy - Option string passed to the CVF module. I.e. only the "yyy" is passed - (without the quotes). The documentation for each CVF module should - explain it since it is interpreted only by the CVF module. Note that - the string must not contain a comma (",") - this would lead to - misinterpretation by the FAT driver, which would recognize the text - after a comma as a FAT driver option and might get confused or print - strange error messages. The documentation for the CVF module should - offer a different seperation symbol, for example the dot ".", which - is only valid inside the string "yyy". - - -4. Installation ------------------------------------------------------------------------------- - -Just apply the diff cvf.diff-x.y.z to your kernel. I hope the diff will -make it into the standard kernel some day, but it's not up to me to decide -this :) Note that the diff has been created using kernel x.y.z so it might -fail or need manual interaction for other kernels. Modified diffs for -other kernels welcome :) - -Well, you also need a CVF module to load. Otherwise CVF-FAT is quite useless -to you :) dmsdos is such a module. - - -5. Description of the CVF-FAT interface ------------------------------------------------------------------------------- - -Assuming you want to write your own CVF module, you need to write a lot of -interface funtions. Most of them are covered in the kernel documentation -you can find on the net, and thus won't be described here. They have been -marked with "[...]" :-) Take a look at include/linux/fat_cvf.h. - -struct cvf_format -{ int cvf_version; - char* cvf_version_text; - unsigned long int flags; - int (*detect_cvf) (struct super_block*sb); - int (*mount_cvf) (struct super_block*sb,char*options); - int (*unmount_cvf) (struct super_block*sb); - [...] - void (*cvf_zero_cluster) (struct inode*inode,int clusternr); -} - -This structure defines the capabilities of a CVF module. It must be filled -out completely by a CVF module. Consider it as a kind of form that is used -to introduce the module to the FAT/CVF-FAT driver. - -It contains... - - cvf_version: - A version id which must be uniqe. Choose one. - - cvf_version_text: - A human readable version string that should be one short word - describing the CVF format the module implements. This text is used - for the cvf_format option. This name must also be uniqe. - - flags: - Bit coded flags, currently only used for a readpage/mmap hack that - provides both mmap and readpage functionality. If CVF_USE_READPAGE - is set, mmap is set to generic_file_mmap and readpage is caught - and redirected to the cvf_readpage function. If it is not set, - readpage is set to generic_readpage and mmap is caught and redirected - to cvf_mmap. - - detect_cvf: - A function that is called to decide whether the filesystem is a CVF of - the type the module supports. The detect_cvf function must return 0 - for "NO, I DON'T KNOW THIS GARBAGE" or anything !=0 for "YES, THIS IS - THE KIND OF CVF I SUPPORT". The function must maintain the module - usage counters for safety, i.e. do MOD_INC_USE_COUNT at the beginning - and MOD_DEC_USE_COUNT at the end. The function *must not* assume that - successful recognition would lead to a call of the mount_cvf function - later. - - mount_cvf: - A function that sets up some values or initializes something additional - to what has to be done when a CVF is mounted. This is called at the - end of fat_read_super and must return 0 on success. Definitely, this - function must increment the module usage counter by MOD_INC_USE_COUNT. - This mount_cvf function is also responsible for interpreting a CVF - module specific option string (the "yyy" from the FAT mount option - "cvf_options=yyy") which cannot contain a comma (use for example the - dot "." as option separator symbol). - - unmount_cvf: - A function that is called when the filesystem is unmounted. Most likely - it only frees up some memory and calls MOD_DEC_USE_COUNT. The return - value might be ignored (it currently is ignored). - - [...]: - All other interface functions are "caught" FAT driver functions, i.e. - are executed by the FAT driver *instead* of the original FAT driver - functions. NULL means use the original FAT driver functions. - If you really want "no action", write a function that does nothing and - hang it in instead. - WARNING: Do not call a fat driver function from these routines without - looking at the fat driver source code first. You might end up in an - endless recursion. :( - - cvf_zero_cluster: - The cvf_zero_cluster function is called when the fat driver wants to - zero out a (new) cluster. This is important for directories (mkdir). - If it is NULL, the FAT driver defaults to overwriting the whole - cluster with zeros. Note that clusternr is absolute, not relative - to the provided inode. - -Notes: - 1. The cvf_bmap function should be ignored. It really should never - get called from somewhere. I recommend redirecting it to a panic - or fatal error message so bugs show up immediately. - 2. The cvf_writepage function is ignored. This is because the fat - driver doesn't support it. This might change in future. I recommend - setting it to NULL (i.e use default). - -int register_cvf_format(struct cvf_format*cvf_format); - If you have just set up a variable containing the above structure, - call this function to introduce your CVF format to the FAT/CVF-FAT - driver. This is usually done in init_module. Be sure to check the - return value. Zero means success, everything else causes a kernel - message printed in the syslog describing the error that occured. - Typical errors are: - - a module with the same version id is already registered or - - too many CVF formats. Hack fs/fat/cvf.c if you need more. - -int unregister_cvf_format(struct cvf_format*cvf_format); - This is usually called in cleanup_module. Return value =0 means - success. An error only occurs if you try to unregister a CVF format - that has not been previously registered. The code uses the version id - to distinguish the modules, so be sure to keep it uniqe. - -Refer to the dmsdos module (the successor of the dmsdos filesystem) for a -sample implementation. - - -6. Authors and email addresses: ------------------------------------------------------------------------------- - -The CVF-FAT extensions are the official successor of the dmsdos filesystem. -The dmsdos filesystem was initially written by Frank Gockel. Stacker support -was added by Pavel Pisa. Meanwhile, it contains several parts of code that -was directly provided or code that is based on the ideas from a lot of people -over the net in order to fix bugs, to improve performance, and to add features. - -The code is distributed under the GNU General Public Licence (see file -COPYING). - -The code is currently maintained by Pavel Pisa and me, Frank Gockel. - -Pavel's email address is pisa@cvlinux.felk.cvut.cz, -my email address is gockel@sent13.uni-duisburg.de. - -If you want to contact me via email, please write in English or take a close -look at the country code in the email address :-) +Documentation for the CVF-FAT interface is part of the Linux kernel +(either directly in 2.1.xx or after applying the CVF-FAT patch for 2.0.xx). +It can be found in file linux/Documentation/filesystems/fat_cvf.txt. diff --git a/doc/dmsdos.doc b/doc/dmsdos.doc index dd58af9..50ac6fe 100644 --- a/doc/dmsdos.doc +++ b/doc/dmsdos.doc @@ -1,16 +1,16 @@ dmsdos.doc -This is the main documentation for the DMSDOS CVF module. 18AUG1998 +This is the main documentation for the DMSDOS CVF module. 01MAR1999 ------------------------------------------------------------------------------ - This is version 0.9.1.5. + This is version 0.9.2.1. -This version has been designed for Linux 2.0.35, but it should run with all -kernels from 2.0.29 to 2.0.35. It very likely also works with older ones, -but it has at least been reported to fail with 2.0.0. For the 2.1.xx series -you need at least 2.1.80 though it is recommended to use 2.1.94 or newer. -Has 2.2 been released yet? :) +This version has been designed for Linux 2.2.2, but it should run under all +2.2.x kernels. It also works with kernels from 2.0.29 to 2.0.36. It very +likely also works with older ones, but it has at least been reported to fail +with 2.0.0. For the 2.1.xx series you need at least 2.1.80 though it is +recommended to use 2.1.94 or newer. Installation notes see file ../INSTALL.TXT. @@ -29,7 +29,8 @@ Contents: 10. The dmsdos daemon 'dmsdosd' 11. The dmsdos library 'libdmsdos.a' 12. The dmsdos filesystem checker 'dmsdosfsck' -13. Authors and email addresses +13. The dmsdos Midnight Commander external filesystem utility 'mcdmsdos' +14. Authors and email addresses ------------------------------------------------------------------------------ @@ -49,8 +50,9 @@ Contents: * simple internal fs check on mount (can be switched off) * dmsdos daemon for compressing data in the background * works with all drivers that base on the fat driver, also with FAT32 - * stand-alone dmsdos library for CVF related programming (experimental) + * stand-alone dmsdos library for CVF related programming * stand-alone dmsdosfsck (experimental) + * various other utilities [**] No, don't really think of burning a CVF onto a cdrom. Dos cannot read it unless you copy it to your hard disk. REALLY BAD. Linux+dmsdos can. @@ -82,8 +84,9 @@ In detail: believe that M$ simply copied (bought?) Superstore and renamed it to Doublespace without further modifications... - Dmsdos runs now *below* the msdos/fat filesystem. This makes it compatible - with all fat based filesystems including FAT32, NLS and other things :) + Since version 0.9.0, dmsdos runs *below* the msdos/fat filesystem. This + makes it compatible with all fat based filesystems including FAT32, NLS + and other things :) Dmsdos does a lot of internal caching in order to reach a reasonable speed with a compressed (and really badly organised, but simple) filesystem. As @@ -115,7 +118,8 @@ In detail: 'Stand-alone' means that it works independently from the dmsdos kernel module, on *raw* CVFs (i.e. those large files lying around in an uncompressed host partition). It's the same source code, though, just - compiled in a slightly different way. :) + compiled in a slightly different way. Meanwhile, it compiles even under + Windows :) 2. Restrictions @@ -139,7 +143,7 @@ In detail: sudden system freezes reported. Reasons for this include (in rising order): * Decompressing the data takes some time, but that is supposed to be - minimal. + minimal. You will probably not notice it. * Badly written programs issuing many redundant reads. Such programs kill performance on every filesystem, but it's extremely bad under @@ -151,29 +155,29 @@ In detail: there are tons of fat access necessary to find the end.) * Huge directories. It's again the fat access problem like above. (In - 2.1.xx kernels it's faster due to the gain from dentry caching.) + 2.1/2.2 kernels it's faster due to the gain from dentry caching.) * Compression on write access. Compression speed depends heavily on the data to compress. In general you can say, the better the data compress the faster the compression. - * Compressing incompressible data. This only wastes time since the - driver throws the compressed data away and uses the uncompressed - data if the compressed data turn out to be in fact larger. The only - thing you can do against this is disabling compression if you know - the data you want to write don't compress any more (e.g. when - writing already compressed files). - - * Highly fragmented (at internal MDFAT level) filesystems. This - puts the search algorithm that searches for free space in a long - loop finding a fitting hole for data to be written. This is probably - the most important reason for sudden system freezes. It's also the - most annoying one since there's really nothing to do against it. - This kind of fragmentation is normal to every compressed filesystem - and cannot be avoided. The more you write the worse it becomes. - (See below for details on that kind of fragmentation. Note that it's - very different from that FAT level fragmentation known from FAT - based filesystems.) + * Compressing incompressible data (on write access). This only wastes + time since the driver throws the compressed data away and uses the + uncompressed data if the compressed data turn out to be in fact + larger. The only thing you can do against this is disabling + compression if you know the data you want to write don't compress + any more (e.g. when writing already compressed files). + + * Highly fragmented (at internal MDFAT level) filesystems on write + access. This puts the search algorithm that searches for free space + in a long loop finding a fitting hole for data to be written. This is + probably the most important reason for sudden system freezes. It's + also the most annoying one since there's really nothing to do against + it. This kind of fragmentation is normal to every compressed + filesystem and cannot be avoided. The more you write the worse it + becomes. (See below for details on that kind of fragmentation. Note + that it's very different from that FAT level fragmentation known from + FAT based filesystems.) Compression and free sector finding may be fine-tuned with some of the dmsdos options. This is not really explained here, see mount @@ -227,8 +231,8 @@ In detail: Of course, they can be read. But currently, they cannot be written. If dmsdos needs to rewrite data that are stored in a fragmented or suballocated cluster it currently deletes the old data and saves the new - data in the usual linear order. Fragmentation write may come soon, - suballocation write is more complex and currently considered not very + data in the usual linear order. Fragmented write may come soon, + suballocated write is more complex and currently considered not very important for dmsdos. We'll see... Swapping to a file on the compressed partition @@ -243,17 +247,17 @@ In detail: has to do in order to access the *end* of a large file... yeah, tons of fat access...) - DOSEMU users attention - ---------------------- + attention, DOSEmu users + ----------------------- You may have to unmount all fat based partitions before running - DOSEMU depending on your configuration. If DOSEMU is configured to use - wholedisk or partition access (this is often the case to let DOSEMU access + DOSEmu depending on your configuration. If DOSEmu is configured to use + wholedisk or partition access (this is often the case to let DOSEmu access compressed partitions) there's a risk of destroying your compressed partitions or crashing your system because of confused drivers. Let me explain why. Dmsdos does a lot of internal caching, but cache - contents won't be up to date if DOSEMU directly modifies the disk. This + contents won't be up to date if DOSEmu directly modifies the disk. This confuses dmsdos and may mess up your data. On the other hand, dos dblspace/drvspace.bin also has a kind of caching mechanism that gets confused by the Linux dmsdos driver's write access. Confusion even @@ -263,7 +267,7 @@ In detail: lredir or emufs.sys. Refer to this table for configurations that are safe (marked with +) and which are dangerous (marked with -): - DOSEMU: Linux fat-based filesystems: + DOSEmu: Linux fat-based filesystems: -------------- -------------------------------- not mounted mounted mounted ro rw @@ -292,7 +296,22 @@ In detail: Win98 compatibility ------------------- - Has someone tried? Just let me know :) + HEY! Windows People ! + Everyone uses it in the Windows World(TM) :)) Let me know whether + it works, please. (I refuse to buy Win98 just for such a test.) + Or have you all switched to WinNT yet ? + + WinNT compatibility + ------------------- + + No, WinNT does not support compressed FAT partitions. But... + :)) + There's meanwhile a small chance to port dmsdos to WinNT. This is + somewhat interesting because neither Doublespace nor Stacker runs under + WinNT. But I can't do it myself because of lack of knowledge :( For more + information, see file PORT_TO_WIN32. The trick is hacking in the dmsdos + library so it compiles under that operating system... I just managed to + compile one dmsdos utility, mcdmsdos, under WinNT... Last but least -------------- @@ -300,8 +319,8 @@ In detail: Dmsdos has been written for dos/win95 compatibility. It's just a relict from the time when I programmed some software that had to run both under dos and Linux and I had to compress my drive because hard disk space was - rather expensive. Times and prices have changed a lot since then, but - dmsdos has still been improved for fun. + rather expensive. Times and prices have changed a lot since then (at least + in the country where I live), but dmsdos has still been improved for fun. If you don't need dos/win95 compatibility, i.e. if you want to compress Linux-only data, let me say: DON'T DO IT. Clean up your disk, or buy a @@ -332,6 +351,17 @@ In detail: 3. Mount options ------------------------------------------------------------------------------ +CVF related mount options are usually surrounded by the CVF-FAT interface +options. These are "cvf_format=xxx" and "cvf_options=yyy". The string "xxx" +can be "dblspace" for a doublespace or drivespace CVF and "stacker" for a +stacker CVF. For more information about the "cvf_format=xxx" option, +especially in cooperation with kerneld and automatic module loading, see +the dmsdos installation instructions (file INSTALL.TXT) and the generic +CVF-FAT documentation (file linux/Documentation/filesystems/fat_cvf.txt). + +When we speak about dmsdos mount options, we usually mean the string "yyy" in +"cvf_options=yyy". That's what this chapter describes. + Summary: -------- @@ -339,7 +369,7 @@ The dmsdos driver currently recognizes the following options: comp:xxx, cf:xxx, bitfaterrs:xxx, loglevel:xxx, speedup:xxx -(for backwards compatibility, also comp=xxx, cf=xxx, bitfaterrs=xxx and +(for backwards compatibility also comp=xxx, cf=xxx, bitfaterrs=xxx and loglevel=xxx, speedup=xxx are accepted) The xxx has to be replaced by an appropriate parameter, of course. All @@ -562,7 +592,7 @@ as option separator symbol. dangers let it cleared. Only set it if you really know what you are doing. - bit #7: Use daemon if present + bit #7: Use daemon for background conpression if present Use the daemon for delayed compression in the background. This bit is for users of the internal daemon since the internal daemon cannot be disabled by simply killing it. @@ -581,7 +611,7 @@ as option separator symbol. hole' that is large enough for the data. Speedup Bit#8 controls what to do in that case. If this bit is set dmsdos just returns a 'no space left on device' error and - refuses to write to the CVF any more. + refuses to write to the CVF. Drivespace 3 and Stacker know a hack for that situation: they allow storing the data of one cluster in several fragments on the disk. If the bit is clear, the driver @@ -625,9 +655,11 @@ Note: The parameters that the dmsdos module allows for 'xxx' are 'dblspace' (for all doublespace and drivespace versions) and 'stacker' (for all stacker versions). Usually you don't care about them since the formats - are detected automatically. In short terms: simply never use them. - For details about the CVF-FAT interface take a look at - linux/Documentation/filesystems/fat_cvf.txt. + are detected automatically. They may, however, be useful in order to + trigger kerneld to load the dmsdos module on demand. For details please + look at the dmsdos installation instructions (file INSTALL.TXT) and the + generic CVF-FAT interface documentation (file + linux/Documentation/filesystems/fat_cvf.txt). And now a warning: If you want to mount a CVF *be sure* to have the dmsdos module loaded. The plain FAT driver also mounts some CVFs without @@ -637,6 +669,9 @@ Note: CVF at mount time (and e.g. print an error) when the dmsdos module is not loaded. + *** If you always specify a "cvf_format=something" option you never + run into that problem. + Some simple examples: 1. Your msdos partition that contains CVFs is on /dev/hda1. You want to mount it under /DOS and the CVF under /mnt. @@ -959,7 +994,8 @@ in INSTALL.TXT so see there for details, please. 11. The dmsdos library 'libdmsdos.a' ----------------------------------------------------------------------------- -This feature is currently highly experimental. +This feature is currently experimental, but begins to become more and more +interesting. The dmsdos library is intended to provide some low-level dmsdos functions to user processes. The library is not new source code - it's just the @@ -968,7 +1004,8 @@ The dmsdos library aims towards working with raw CVFs, not filesystems. It is usable only for *not* mounted CVFs. Well, for mounted ones there's the dmsdos module :) -Rudimentary documentation can be found in file libdmsdos.doc. +Documentation (including a detailed description of the interface functions) +can be found in file libdmsdos.doc. 12. The dmsdos filesystem checker 'dmsdosfsck' @@ -1043,7 +1080,52 @@ script does. Change it to your requirements. Then replace the link in /sbin/fsck.msdos (or /etc/fs/fsck.msdos) by a link to the script :) -13. Authors and email addresses: +13. The dmsdos Midnight Commander external filesystem utility 'mcdmsdos' +------------------------------------------------------------------------------ + +Dmsdos comes with an interface utility that accepts standard Midnight +Commander commands for reading archive files. The utility is named +'mcdmsdos' and is compiled during usual dmsdos compile process. +The utility is currently read-only. + +Please refer to the documentation of Midnight Commander for further +information on how to configure an external filesystem. +You may want to write a small shell script as a wrapper around mcdmsdos +in order to suppress output to stderr distorting the screen, e.g. + + #!/bin/sh + exec /usr/local/bin/mcdmsdos $@ 2> /dev/null + +Furthermore, mcdmsdos can be used as a utility to quickly look at what is +inside the CVF and to extract single files from a CVF. Today mcdmsdos even +works in a Win32 environment, so it may be worth to learn its command line +parameters :)) + + mcdmsdos list + + lists (recursively) the contents of the CVF, i.e. the names of all + files that are in that compressed partition are printed. + + mcdmsdos copyout + + extracts the file from the CVF and + writes it to (which must be a real file, not stdout). + + mcdmsdos copyin + + is expected to copy into the CVF at + according to Midnight Commander documentation. + This command is currently not implemented as the utility is + read-only. + +If documentation of newer versions of Midnight Commander wants some more +commands consider the respective operations to fail. I expect something +like remove, rmdir, mkdir etc. which are missing in the current standard +(I wrote this utility according to Midnight Commander 3.0 documentation). +But that doesn't matter as long as mcdmsdos is read-only :) + + +14. Authors and email addresses: ------------------------------------------------------------------------------ CVF-FAT/dmsdos is the official successor of the former dmsdos filesystem. The diff --git a/doc/libdmsdos.doc b/doc/libdmsdos.doc index dc9269d..8d4ce70 100644 --- a/doc/libdmsdos.doc +++ b/doc/libdmsdos.doc @@ -1,4 +1,4 @@ -This is documentation for the dmsdos library. 22Apr1998 +This is documentation for the dmsdos library. 10Sep1998 The dmsdos library, libdmsdos.a, provides the dmsdos interface that is known @@ -7,38 +7,38 @@ dmsdos code simply in a different way (well, with some rather dirty tricks). The library is intended to export the following functions: -open_cvf -close_cvf - -Well, these two ones above are new, but the rest should be well known to -you: - -dbl_bitfat_value -dbl_fat_nextcluster -dbl_mdfat_value -dmsdos_read_cluster -dmsdos_write_cluster -raw_bread -raw_brelse -raw_getblk -raw_mark_buffer_dirty -raw_set_uptodate -simple_check -stac_bitfat_state + open_cvf + close_cvf + dbl_bitfat_value + dbl_fat_nextcluster + dbl_mdfat_cluster2sector + dbl_mdfat_value + dmsdos_read_cluster + dmsdos_write_cluster + raw_bread + raw_brelse + raw_getblk + raw_mark_buffer_dirty + raw_set_uptodate + simple_check + stac_bitfat_state In fact, it exports much more, but only these listed here are guaranteed to be kept in future versions. Well, one thing should be important to know: The library does NOT export virtual sector management. It will never do. The functions are just used like in the kernel. For prototypes, see file -dmsdos.h. How to use them see the sources. :) Seriously, if you aren't -a dmsdos hacker forget about the library. +dmsdos.h. How to use them see the sources. There's some example code +how to use the library (dcread.c). The first two, open_cvf and close_cvf, are special. They are called instead of mounting and unmounting the CVF. How to "mount" a CVF (example code): + #include "lib_interface.h" + #include "dmsdos.h" + struct super_block*sb; sb=open_cvf("CVF_Filename",rwflag /*0=RDONLY or 1=RDWR*/); if(sb==NULL) @@ -64,22 +64,18 @@ Notes: uses flock in order to detect such situations and just denies access in that case. You can however use different CVFs in parallel, even read-write, even in one program. - * You should use this library only to access a CVF that is currently not - mounted. You *cannot* use it on a CVF that is mounted read-write. If - the CVF is currently mounted read-only, the library allows read-only - access to the CVF. The library scans /etc/mtab in order to check this. - This check is not perfect, though. It also does not prevent mount - from mounting a CVF that is used by the library. So just be careful. - * You must not touch CVFs that are currently used by dosemu with - wholedisk or partition access. I don't know how to test for that - situation, so the library doesn't check for this. Well, as dosemu - refuses to run if the underlying dos partition is mounted, that - situation should never occur :) + * You should use this library only to access a CVF that is currently + _not_ mounted. There's a high risk of destroying the CVF or even + crashing the system otherwise. + * You should not touch CVFs that are currently used by dosemu with + wholedisk or partition access. Again there's a high risk of destroying + the CVF or crashing dosemu otherwise. * If you do not intend to write to the CVF, open it in read-only mode. Then the CVF is not locked exclusively and other processes are allowed to read the CVF at the same time. * The library prints the "kernel" messages to stderr. It obeys the - loglevel variable. + loglevel variable. The only way to make libdmsdos quiet is to + direct stderr into a file or to /dev/null. * The first call of open_cvf initializes the library and prints some version information to stderr. * open_cvf does not do a filesystem check. If you do want the same @@ -93,32 +89,526 @@ Notes: calling open_cvf to be sure. * To compile your application using the dmsdos library you should under no cirumstances define the macro __KERNEL__ for the whole program. - It causes problems with libc6. Just define __KERNEL__ for those - include files that don't work without and undefine it afterwards. + It causes problems with libc6. As an idea what the dmsdos library might be good for: - * A mtools clone for CVFs, for example called dtools. - * A fsck.dmsdos. - * A defragmentation program. + * A mtools clone for CVFs, for example called dtools. (A simple program, + dcread, exists but its quatilty cannot be compared to mtools. Sorry.) + * A fsck.dmsdos. (An incomplete alpha test version exists.) + * A defragmentation program. (Not yet written.) * For debugging dmsdos at user level (it's the same source code). - * An external fs for midnight commander. + * An external fs for midnight commander. (A read-only interface program, + mcdmsdos, exists.) * ... add your favourite idea here :) + * ... I've even received mail about whether it would be possible to + port libdmsdos to Win32 and use it for a Win95/98/NT driver :)) Support for a shared dmsdos library ----------------------------------- -libdmsdos can now be compiled as a shared library. Just enter a -'make libdmsdos.so' in the src directory. Note that the default installation -does not compile the shared library. This is intended. If you are not -an experienced shared library hacker please be careful. It's easy to screw -up some binaries with shared libraries :) +libdmsdos can be compiled as a shared library. You must edit the +Makefile in the src directory for that purpose. Note that the default +installation does not compile the shared library. This is intended. If +you are not an experienced shared library hacker please be careful. It's +easy to screw up some binaries with shared libraries :) You should not use the dmsdos shared library for now as there's currently no standard that ensures that future versions will be backwards compatible. Link statically with libdmsdos.a unless disk space or memory is very critical. WARNING: If there's a shared dmsdos library lying around, gcc defaults to -link *dynamically* all programs that need this library. For example, if +linking *dynamically* all programs that need this library. For example, if libdmsdos.so is present and you recompile dmsdosfsck, the binary will be -dynamically linked with that library. This can be very confusing :( +dynamically linked against that library. This can be very confusing and may +not do what you want :( + +Built-in direct translation access mode +--------------------------------------- + +This feature has been added to the library for convenience. It only works +for FAT12 or FAT16 MSDOS filesystems. It does not work, for example, for +CVFs on a cdrom or in a FAT32 or non-FAT filesystem. + +The dmsdos library can access a CVF that resides in an uncompressed FAT12 or +FAT16 MSDOS host partition even if the uncompressed host partition is not +mounted (this was programmed in fact by cut'n'paste of some old dmsdosfs +functions). If there are more than one CVF in that partition, the first +valid CVF found in the root directory of the uncompressed host partition +is used. If you want to select one of more CVFs, append a colon and the +extension of the CVF to the filename. + +For example, if your uncompressed host partition is /dev/hda1 and you want +to access the CVF DRVSPACE.001 on that partition, use "/dev/hda1:001" as +filename when calling open_cvf. If DRVSPACE.001 is the only CVF inside +/dev/hda1 you can even use "/dev/hda1" and it will find the CVF. + +This special feature allows, for example, dmsdosfsck to check a CVF in +a partition that has not yet been mounted. This may be useful at boot time +to check CVFs :) + +Standard C library functions that libdmsdos needs +------------------------------------------------- + +If you want to use libdmsdos in an environment where the standard C library +functions are not available then you must write an emulation for all these +functions and link your code against it instead of the standard C library. +The emulation needn't be full-featured like the C library. Look at the source +if you are in doubt. + + close (4) + errno + exit (3) + flock (only if compiled with -DUSE_FLOCK) (4) + sopen (only if compiled with -DUSE_SOPEN) (4) (8) + fprintf (2) + free (6) + lseek (1) (7) + malloc (6) + memcpy + memmove + memset + open (only if _not_ compiled with -DUSE_SOPEN) (8) + read (1) + strcat + strerror + strncat + strncmp + strncpy + strrchr + time (5) + vsprintf (2) (9) + write (1) + + (1) only used in aligned 512 byte blocks + (2) only used for logging to stderr, no other files are used + (3) used for abort in case of fatal error + (4) locking may be left out + (5) a time-proportional counter would be enough, needn't be exact + (6) called quite often, be aware of possible memory fragmentation + (7) only used on 512 byte boundaries with SEEK_SET, also used to find out + file size with SEEK_END + (8) must parse filename (invent your own syntax if necessary) + (9) a free, portable emulation is in linux/lib/vsprint.c + +If possible, please avoid hacking around in dmsdos kernel code if the library +does not work in your environment (unless it's a bug). The only files that +should be modified due to OS or compiler differences are lib_interface.c and +lib_interface.h. Please surround your changes with appropriate #ifdef's so +the modified code still compiles under all those environments where it worked +before. Please do not violate portability of the code. Hardware comes and +goes, OSses are born and die, but portable code survives :) + + +dmsdos library reference guide +------------------------------ + +All functions need the header files lib_interface.h and dmsdos.h. Error +checking is not always possible. This is because some of the low-level kernel +functions dmsdos calls when running as kernel module never fail. In user +space, there may be failures, however. This means, libdmsdos is currently +not 100% error-safe. As a workaround (that works under the standard C library) +you can set errno to NO_ERROR before calling the function and afterwards +check whether it has changed to an error value. + + open_cvf: + + struct super_block* open_cvf(char*filename,int rwflag) + + Opens CVF described by filename. rwflag is 0 for read-only, otherwise + the file is opened read-write. The file is locked read-only or + read-write, depending on rwflag (by calling flock or sopen). + + filename is interpreted in a special way if it contains a colon. + See chapter 'Built-in direct translation access mode' above. The colon + and the rest of the string after it are stripped off before the filename + is forwarded to the libc function open or sopen. + + Return Value: Pointer to valid super_block structure (which can be + interpreted as a kind of file handle), NULL if failed. + + Note: Keep the super_block pointer. Most dmsdos functions need it in + order to identify the CVF. + + Note: The CVF may be opened read-only though you opened it in read-write + mode. This happens if the dmsdos code detects unexpected errors in the + CVF. Please check sb->s_flags for the MS_RDONLY bit after calling + open_cvf. + + close_cvf: + + void close_cvf(struct super_block*sb) + + Closes the CVF. If necessary, the file is unlocked before. + + dbl_bitfat_value: + + int dbl_bitfat_value(struct super_block*sb,int sectornr,int*new) + + Reads or writes bitfat value that belongs to sector sectornr. + *** This is a low-level function you are probably never interested in. + Bitfat values are CVF format specific. You do not need to know them + unless debugging write access :)) + + If new is NULL the value is read and returned. + Otherwise the actual value is replaced with that one found in *new. + + Return value: read access: read value. write access: undefined. A + negative value indicates an error. + + dbl_fat_nextcluster: + + int dbl_fat_nextcluster(struct super_block*sb,int clusternr,int*new) + + Reads or writes the FAT entry for cluster clusternr. (You should know + what a FAT is, otherwise please read a good book on Dos disk access.) + + If new is NULL the value is read and returned. + Otherwise the actual value is replaced with that one found in *new. + + Return value: read access: read value. write access: undefined. + -1 means the cluster is marked as last cluster in a file or an error + occured. Errors may also be represented by other negative results. + + Note: -1 can also be used for write access in order to indicate end of + file mark. It is automatically converted to the right value for the FAT + size. + + Note: if clusternr is invalid a -1 is returned. This usually makes + runaway FAT reading loops break as if there was an EOF in the cluster + chain. There's no means to find out whether a -1 is an error or an EOF + except making sure a valid cluster number is given. + + dbl_mdfat_cluster2sector: + + int dbl_mdfat_cluster2sector(struct super_block*sb,int clusternr) + + This is a low-level function that reads the mdfat and extracts the + starting sector information from it. It may be useful for write + access with dmsdos_write_cluster. It returns the starting sector number + of cluster clusternr. + *** Do not use the standard formula that is used in a normal FAT + filesystem (multiplying the cluster number with the number of sectors + per cluster and adding some offsets) - that formula is not valid in a + compressed filesystem. Use dbl_mdfat_cluster2sector instead. + + Return value: starting sector of the cluster clusternr. If negative, + an error occured. + + Note: see dmsdos_write_cluster what this function is useful for. + + dbl_mdfat_value: + + int dbl_mdfat_value(struct super_block* sb,int clusternr, + Mdfat_entry*new,Mdfat_entry*mde) + + Reads or writes the mdfat/allocmap entry that belongs to cluster + clusternr. + *** This is a low-level function you are probably never interested in. + Mdfat values are CVF format specific. You do not need to know them + unless debugging dmsdos :)) + + If new is NULL the value is read and stored in *mde. + Otherwise the actual value is replaced with that one found in *new. + + Return value: A negative value indicates an error. + Note: consider *mde as undefined after write access. + + dmsdos_read_cluster: + + int dmsdos_read_cluster(struct super_block*sb, + unsigned char*clusterd, int clusternr) + + Reads cluster clusternr in clusterd. The dmsdos library handles all + low-level access including decompression of the data. + + *** Be sure to have reserved enough memory for the data that this + function writes into clusterd. Usually, use a full cluster size. + How to determine the full cluster size see the dcread example code. + + Return value: number of bytes actually read (clusters may be shorter + than the full size in a CVF, which is not possible in an uncompressed + FAT filesystem). Usually, you can ignore this unless you use write + access. (A cluster may even have length zero.) Just in case, if the + cluster is shorter than full size the unused slack is zero'd out. On + error, a negative value is returned. + + Note: This function cannot read the root directory (cluster 0). You must + use low-level disk access for that (i.e. raw_bread). See also the dcread + example code. + + dmsdos_write_cluster: + + int dmsdos_write_cluster(struct super_block*sb, unsigned char* clusterd, + int length, int clusternr, int near_sector, + int ucflag) + + Writes cluster clusternr from clusterd back to disk. The dmsdos + library handles all low-level disk access including compression. + + length is the position of the last valid byte plus 1 in clusterd. + This is usually the value that dmsdos_read_cluster returned when you + read this cluster before unless you modified some bytes beyond that + value. The idiot-proof value is always the full cluster size. + *** Warning: if length is too low, the data may be truncated during + write access. If it is too high disk space is wasted. + + ucflag is a flag that indicates whether libdmsdos should try to + compress the data. 0 means try to compress, 1 means write the data + without compression. Please do not use other values than 0 and 1 + (they do exist but have some very special meanings). + + near_sector can be used to control where libdmsdos tries to place + the data on disk. For good performance on large files, it should + be set to the start sector value of the cluster that preceeds the + actual cluster in the file. The start sector value can be obtained with + dbl_mdfat_cluster2sector on that preceeding cluster. (This way actually + helps avoiding low-level fragmentation _and_ file data fragmentation in + the CVF.) + *** Do not use the standard formula that is used in a normal FAT + filesystem (multiplying the cluster number with the number of sectors + per cluster and adding some offsets) - that formula is not valid in a + compressed filesystem. + + The near_sector value is just meant as a hint. If there's not enough + free space on the disk around near_sector, dmsdos writes the data + somewhere else. If near_sector is set to zero, dmsdos uses an internal + way to find out a good value that avoids low-level fragmentation but + that is not necessarily good for performance on the file that is being + written. Nevertheless, 0 always works. + + WARNING: If you are writing a directory cluster you should not compress + the data (it would hurt performance a lot). Some of the original CVF Dos + software versions never compress directories, so you shouldn't do + either (it may cause compatibility problems otherwise). You also should + always use full cluster size for directories on some CVF versions. In + order to feel safe you can use the DIR_MAY_BE_COMPRESSED and + DIR_MAY_BE_SHORT macros. Have a look at their definition in file + dmsdos.h. + + Return value: A negative value indicates an error. + + Note: The data in clusterd are not destroyed by this function. + + raw_bread: + + struct buffer_head* raw_bread(struct super_block*sb,int block) + + Read a 512 byte block from the CVF. The data are read without further + modification. Block numbering scheme begins with zero. + + Return value: pointer to a buffer_head structure that contains the 512 + bytes of data that represent the data block. The data are in + buffer_head->b_data in an unsigned character array (see the dcread + example). On error, NULL is returned. + + Note: The data are returned in dynamically allocated memory. If you + do not need the data any more, you must free them by calling raw_brelse + in the buffer_head structure pointer. + + Note: You may modify the data. You must call raw_mark_buffer_dirty + after modification (this writes the data back to disk) and before + raw_brelse. + + Note: If you want to overwrite the whole block, use raw_getblk instead + of raw_bread (this leaves out the unnecessary disk read access). + + raw_brelse: + + void raw_brelse(struct super_block*sb,struct buffer_head*bh) + + Release dynamic memory for the data read by raw_bread. + + raw_getblk: + + struct buffer_head* raw_getblk(struct super_block*sb,int block) + + Like raw_bread, but leaves out the actual disk access. This is intended + to leave out unnecessary disk read access if you want to overwrite the + whole block. Consider the data as undefined. See raw_bread. + + Note: raw_getblk should be followed by a call of raw_set_uptodate + for compatibility. See there. + + raw_mark_buffer_dirty: + + void raw_mark_buffer_dirty(struct super_block*sb,struct buffer_head*bh, + int dirty_val) + + Write data back to disk after they have been modified. + + dirty_val must be always 1 (due to a misunderstanding/bug in dmsdos). + + Note: This function does not indicate an error. This is bad, but it is + because the Linux kernel interface also does not return error codes with + this function. As a hack (that works with libc) you can set errno to + NO_ERROR and check it afterwards, but note that this will not work in + the dmsdos kernel driver. Usually, there cannot be an error during that + kind of write access unless the disk has bad sectors. + + raw_set_uptodate: + + void raw_set_uptodate(struct super_block*sb,struct buffer_head*bh,int v) + + No longer used (does nothing in libdmsdos). + + For compatibility with the kernel driver, this should be called with + v=1 after raw_getblk on the buffer_head pointer that raw_getblk returned + (unless it's NULL due to failure). + + simple_check: + + int simple_check(struct super_block*sb,int repair) + + Check some internal filesystem tables for consistency. + + If repair is 1 libdmsdos tries to correct errors (the CVF must have been + opened read-write in that case). If it is 0 the tables are just checked. + + Return value: a negative value indicates an error, i.e. either the + tables are inconsistent or the errors, if any, could not be repaired. + + Note: It is strongly recommended to run simple_check immediately after + opening the CVF if you want to write to it. Do not write to a CVF if + simple_check fails on it (you may detroy some files in the CVF). As + CVFs are known to be very prone to so-called bitfat errors, you probably + want to give the program that you are writing a kind of "expert option" + that lets simple_check run with repair=1. The same warnings apply as to + the dmsdos mount option bitfaterrs:repair :)) + + stac_bitfat_state: + + int stac_bitfat_state(struct super_block*sb,int new_state) + + Stacker has a kind of clean/dirty flag that indicates whether the CVF + was correctly unmounted. This function can be used to manipulate it. + *** This is a low-level function you should not use unless you are a + dmsdos and Stacker expert. See the dmsdos source code. + + Note: Do not call this function on non-Stacker CVFs. + + +Programming notes +----------------- + +In a normal libdmsdos application, you open the CVF with open_cvf. If you +intend to write to the CVF later, you should call simple_check after that +and refuse write access if an error is found. + +Then you use dmsdos_read_cluster and dmsdos_write_cluster to access the +CVF. Only for the root directory you need raw_bread, raw_mark_buffer_dirty +and raw_brelse. For following files you need to read the FAT with +dbl_fat_nextcluster. + +You write to the FAT with dbl_fat_nextcluster in order to truncate files or +append data to them, or even to delete files and directories and to create +new ones - all like in a usual FAT filesystem. + +If you are done, don't forget to close the CVF with close_cvf. + +Here is a simple example that illustrates the usage of all important +libdmsdos functions. You should not compile and execute this example as +it's not always correct C syntax. Things like error handling have been left +out to simplify the code (which is not good). Furthermore, the program just +pokes around in the CVF which would be bad for your data :) + + + #include "lib_interface.h" + #include "dmsdos.h" + + struct super_block*sb; + struct Dblsb*dblsb; + + /* open the CVF read-write */ + sb=open_cvf("dblspace.001",1); + if(sb==NULL)...error... + + /* check the CVF */ + if(simple_check(sb,0)<0)...error... + + /* read and display cluster 2 as hex numbers */ + int i; + int size; + int full_size; + unsigned char* clusterd; + + /* determine full size */ + dblsb=MSDOS_SB(sb)->private_data; + full_size=dblsp->s_sectperclust*512; + + clusterd=malloc(full_size); + if(clusterd==NULL)...error... + + size=dmsdos_read_cluster(sb,clusterd,2); + if(size<0)...error... + for(i=0;iprivate_data; + number=dblsb->s_rootdirentries*32/512; + startblock=dblsb->s_rootdir; + + data=malloc(number*512); + if(data==NULL)...error... + + for(i=0;ib_data,512); + raw_brelse(sb,bh); + } + /* complete root directory is now in data */ + + /* modify root directory */ + ...modify data where you like... + + /* write it back completely */ + for(i=0;idata,data+i*512,512); + raw_mark_buffer_dirty(sb,bh,1); + raw_brelse(sb,bh); + } + + free(data); /* free memory that is no longer needed */ + + /* we are done */ + close_cvf(sb); + + +For a piece of code that actually compiles and runs and does something +eventually useful and ... does not kill your data :-)) see the dcread +example program (file dcread.c). diff --git a/doc/messages.doc b/doc/messages.doc index 88de99e..71c6294 100644 --- a/doc/messages.doc +++ b/doc/messages.doc @@ -848,6 +848,19 @@ DMSDOS: unable to read emulated boot block DMSDOS: zero_new_cluster: ch_noread failed??? O/B: Don't know. Really. This shouldn't happen. +VFS: LRU list corrupted +VFS: free list corrupted +(or similar) + P/B/O: You are very suffering from the vfat brelse bug (this is a serious + bug in some 2.2.x and maybe late 2.1.x kernels). This bug is triggered + by dmsdos. Ensure you have applied the vfat-brelse-bugfix.diff or you + are using a kernel where the bug is fixed (in 2.2.2 it is not yet fixed). + See file patches/DIFFS.TXT or INSTALL.TXT for details. + + If not, this indicates probably a leak in dmsdos virtual sector code. + Please send a bug report to the current dmsdos maintainer and be prepared + to be asked for some tests in order to track down the bug. + (*) ['no memory' messages:] There was a problem in previous dmsdos versions that caused these messages rarely though there was enough memory free. I've tried to fix diff --git a/doc/troubleshooting.doc b/doc/troubleshooting.doc index 43dd51e..5d15ad4 100644 --- a/doc/troubleshooting.doc +++ b/doc/troubleshooting.doc @@ -51,6 +51,17 @@ for some hints (thanks a lot to all of you!). missing ones in the same way. Then recompile the fat module (or the kernel if your fat support isn't modular). +- It causes a kernel panic with the message "VFS: LRU list corrupted". + + You are very suffering from the vfat brelse bug (this is a serious + bug in some 2.2.x and maybe late 2.1.x kernels). This bug is triggered + by dmsdos. Ensure you have applied the vfat-brelse-bugfix.diff. + See file patches/DIFFS.TXT or INSTALL.TXT for details. + + If not, this indicates probably a leak in dmsdos virtual sector code. + Please send a bug report to the current dmsdos maintainer and be prepared + to be asked for some tests in order to track down the bug. + - It crashes and writes a register dump to the syslog. If you did not load the module with the -m flag this time, you are out diff --git a/magic.sh b/magic.sh index fb83d23..b1fd1ba 100644 --- a/magic.sh +++ b/magic.sh @@ -19,7 +19,7 @@ echo -n "Do you want me to do this ? (Y/N) " read ANS junk if [ "$ANS" = y -o "$ANS" = Y ]; then - cat magic >> /etc/magic + cat patches/magic >> /etc/magic fi exit 0 diff --git a/patch.sh b/patch.sh index 39be1ed..a96b8e0 100644 --- a/patch.sh +++ b/patch.sh @@ -15,27 +15,72 @@ rm /tmp/help.$$ VPS=`echo "$VERSION.$PATCHLEVEL.$SUBLEVEL"` VP=`echo "$VERSION.$PATCHLEVEL"` +if [ "$VERSION" -lt 2 ]; +then + echo "Kernel version $VPS is not supported. Need 2.0.29 or newer from 2.0 series" + echo "or 2.1.80 or newer." + exit 1 +fi + echo "Now I'm trying to find out whether your kernel needs some patches for dmsdos." echo "If something is patched, a log file '*.log' will be written to /tmp." -echo -n "Removing possibly old *.rej files..." -( cd /usr/src/linux; find . -name "*.rej" -exec rm {} \; ) -echo " ok." + +echo -n "Scanning for *.rej files..." +REJ=`( cd /usr/src/linux; find . -name "*.rej" -print )` +if [ ! -z "$REJ" ]; +then + echo + echo "There are *.rej files lying around in your kernel sources. Can't continue." + echo "$REJ" + echo "This usually means that you tried to patch your kernel some time ago but" + echo "that failed horribly. If you haven't repaired this by hand your kernel" + echo "sources are screwed up. Either throw them away and install fresh sources or" + echo "just delete the *.rej files in order to make me believe everything is ok :)" + exit 1 +fi + +echo " not found, ok." if [ -f /usr/src/linux/fs/fat/cvf.c ]; then echo "Kernel has already CVF-FAT support." + grep CVF-FAT-VERSION-ID /usr/src/linux/fs/fat/cvf.c > /dev/null + if [ $? = 1 ]; + then + echo "But the CVF-FAT version in your kernel is an older version." + echo "You may want to update it. I will _not_ do this for you." + echo "See the installation instructions for details." + echo + echo "Press Enter to continue." + read junk + fi else if [ "$VP" = "2.0" ]; then + if [ "$SUBLEVEL" -lt 29 ]; + then + echo "Kernel version $VPS is not supported. Need 2.0.29 or newer from 2.0 series" + echo "or 2.1.80 or newer." + fi #check for fat32 if [ -f /usr/src/linux/fs/nls.c ]; then echo "Kernel 2.0.$SUBLEVEL with FAT32 support detected." + if [ $SUBLEVEL -lt 36 ]; + then + echo "WARNING: FAT32 kernels earlier than 2.0.36 have a serious rmdir bug" + echo "that causes filesystem corruption in a msdos filesystem. This is not" + echo "a dmsdos problem but it is known to damage compressed filesystems too." + echo "Please upgrade to 2.0.36 or apply the msdos-rmdir-bugfix.diff manually" + echo "if you haven't repaired the bug otherwise. (I will not fix this bug.)" + echo "Press Enter to continue." + read junk + fi echo "I'm going to install the CVF-FAT patches for FAT32 now." echo "If you do not want me to do this, press CTRL-C now." echo "To continue, press enter." read junk - ( cd /usr/src/linux; patch -p1 ) < cvf.diff-2.0.33+fat32-0.2.8 >& /tmp/cvf.diff.log + ( cd /usr/src/linux; patch -p1 ) < patches/cvf.diff-2.0.33+fat32-0.2.8 >& /tmp/cvf.diff.log else echo "Kernel 2.0.$SUBLEVEL without FAT32 detected." echo "I'm going to install the CVF-FAT patches now." @@ -44,7 +89,7 @@ else echo "install the FAT32 patches before installing dmsdos." echo "To continue, press enter." read junk - ( cd /usr/src/linux; patch -p1 ) < cvf.diff-2.0.33 >& /tmp/cvf.diff.log + ( cd /usr/src/linux; patch -p1 ) < patches/cvf.diff-2.0.33 >& /tmp/cvf.diff.log fi if [ -d /usr/src/linux/fs/uvfat ]; then @@ -53,56 +98,15 @@ else echo "If you do not want me to do this, press CTRL-C now." echo "To continue, press enter." read junk - ( cd /usr/src/linux; patch -p1 ) < cvf-uvfat.diff-2.0.33 >& /tmp/cvf-uvfat.diff.log + ( cd /usr/src/linux; patch -p1 ) < patches/cvf-uvfat.diff-2.0.33 >& /tmp/cvf-uvfat.diff.log fi else - if [ "$VP" != "2.1" ]; + if [ "$VP" = "2.1" -a "$PATCHLEVEL" -lt 80 ]; then - echo "could not detect kernel version" + echo "Kernel version $VPS is not supported. Need 2.0.29 or newer from 2.0 series" + echo "or 2.1.80 or newer." exit 1 fi - if [ $PATCHLEVEL -lt 80 ]; - then - echo "kernel version not supported, need >= 2.1.80" - exit 1 - fi - if [ $PATCHLEVEL -gt 79 ]; - then - echo "kernel >= 2.1.80, no patch needed" - fi - fi -fi - -#search for kerneld-autoload hack -echo "Checking for kerneld-autoload hack..." -grep 'request_module(\"dmsdos\")' /usr/src/linux/fs/fat/inode.c > /dev/null -if [ $? = 0 ]; -then - echo "ERROR: old kerneld-autoload hack in inode.c detected." - echo "Can't continue. Please remove that." - echo "See the installation instructions for details." - exit 1 -fi - -grep 'request_module(\"dmsdos\")' /usr/src/linux/fs/fat/cvf.c > /dev/null -if [ $? = 0 ]; -then - echo "kerneld-autoload diff is already present." -else - echo "kerneld-autoload diff is not installed." - echo "If you want to have kerneld automatically load dmsdos you need" - echo "this patch. If you want me to install the patch now, say Y and" - echo "press Enter. You can at any time later install the patch manually." - echo "If you do not know what you are doing, say N and press Enter." - echo "See the installation instructions for details." - echo - echo -n "Do you want me to install the kerneld-autoload patch now ? (Y/N) " - read ANS junk - if [ "$ANS" = y -o "$ANS" = Y ]; - then - ( cd /usr/src/linux; patch -p1 ) < kerneld-autoload.diff >& /tmp/kerneld-autoload.diff.log - #this one must be recompiled later :) - rm -f /usr/src/linux/fs/fat/cvf.o fi fi diff --git a/src/Configure b/src/Configure index b0d4035..f080f42 100644 --- a/src/Configure +++ b/src/Configure @@ -399,7 +399,7 @@ if [ "$1" = "-d" ] ; then shift fi -CONFIG_IN=./config.in +CONFIG_IN=./Config.in if [ "$1" != "" ] ; then CONFIG_IN=$1 fi diff --git a/src/Configure.help b/src/Configure.help index 47e73a0..fca412f 100644 --- a/src/Configure.help +++ b/src/Configure.help @@ -10,340 +10,356 @@ # #' are ignored. To be nice to menuconfig, limit your lines to 70 # characters. +Detailed DMSDOS configuration (expert mode) +DMSDOS_EXPERT + Say Y if you want a detailed setup (then a lot of things that you + may not be familiar with unless you are a dmsdos expert will be + asked). If you say N most dmsdos internal values are set to safe + defaults which should be sufficient for most systems. (Yes, you + _can_ change everything. But you'll have to understand what you do.) + Dos 6.0-6.22/Win95 Doublespace/Drivespace DMSDOS_CONFIG_DBLSP_DRVSP -Say Y if you want support for this kind of CVFs. This kind of CVF -format is built into MSDOS 6.0-6.22 and older versions of Win95. -If unsure, saying Y won't hurt except making the module larger. + Say Y if you want support for this kind of CVFs. This kind of CVF + format is built into MSDOS 6.0-6.22 and older versions of Win95. + If unsure, saying Y won't hurt except making the module larger. -Win95 Drivespace 3 from Plus Pack +Win95 Drivespace 3 DMSDOS_CONFIG_DRVSP3 -Say Y if you want support for this kind of CVFs. Note that -Drivespace 3 has been sold seperately from Win95 for some time, but -newer versions of Win95 seem to have Drivespace 3 built in. -The software should tell its version number in the Help/Info menu -under Win95. If unsure, saying Y won't hurt except making the module -larger. + Say Y if you want support for this kind of CVFs. Note that + Drivespace 3 has been sold seperately from Win95 for some time, but + newer versions of Win95 seem to have Drivespace 3 built in. + The software should tell its version number in the Help/Info menu + under Win95. If unsure, saying Y won't hurt except making the module + larger. Stacker version 3 DMSDOS_CONFIG_STAC3 -Say Y if you want support for this kind of CVFs. If unsure, saying Y -won't hurt except making the module larger. + Say Y if you want support for this kind of CVFs. If unsure, saying Y + won't hurt except making the module larger. Stacker version 4 DMSDOS_CONFIG_STAC4 -Say Y if you want support for this kind of CVFs. If unsure, saying Y -won't hurt except making the module larger. + Say Y if you want support for this kind of CVFs. If unsure, saying Y + won't hurt except making the module larger. Use vmalloc instead of kmalloc USE_VMALLOC -The kernel knows to memory allocation interfaces - kmalloc and -vmalloc. kmalloc is faster but more likely to fail (i.e. claim that -the system is out of memory) - vmalloc very rarely fails but memory -is swappable and it is surely not a good idea to swap the cluster -cache to the disk... -If you have a system with lots of physical RAM you might want to -try kmalloc for better performance. vmalloc is always the safe -solution. If you are not sure, say Y, which is always safe. YOU ARE -STRONLY ENCOURAGED TO ENABLE VMALLOC WHEN DEBUGGING NEW CODE. + The kernel knows to memory allocation interfaces - kmalloc and + vmalloc. kmalloc is faster but more likely to fail (i.e. claim that + the system is out of memory) - vmalloc very rarely fails but memory + is swappable and it is surely not a good idea to swap the cluster + cache to the disk... + If you have a system with lots of physical RAM you might want to + try kmalloc for better performance. vmalloc is always the safe + solution. If you are not sure, say Y, which is always safe. YOU ARE + STRONLY ENCOURAGED TO ENABLE VMALLOC WHEN DEBUGGING NEW CODE. Advanced memory allocation USE_XMALLOC -Enables optimized memory allocation routine - it decides itself -whether to use kmalloc or vmalloc depending on the requested size -and on what the system can provide. -WARNING: this does not work for all kernels. I've got reports about -problems with some 2.1.XX kernels and xmalloc. If you get a message -(maybe even a kernel panic) saying "please disable XMALLOC" it is -broken in your kernel. -You may receive *lots* of "Couldn't get a free page" messages in -the syslog which can be safely ignored - they result from the -driver's memory allocation strategy. -DON'T USE XMALLOC WHEN DEBUGGING NEW CODE. -Say N to feel safe. + Enables optimized memory allocation routine - it decides itself + whether to use kmalloc or vmalloc depending on the requested size + and on what the system can provide. + WARNING: this does not work for all kernels. It is known to work + for 2.0.xx kernels. But I've got reports about problems with some + 2.1.XX kernels and xmalloc. Maybe it also fails under 2.2.x. If + you get a message (maybe even a kernel panic) saying "please + disable XMALLOC" it is broken under your kernel. + You may receive *lots* of "Couldn't get a free page" messages in + the syslog which can be safely ignored - they result from the + driver's memory allocation strategy. + DON'T USE XMALLOC WHEN DEBUGGING NEW CODE. + Say N to feel safe. Size of daemon cache LISTSIZE -Maximum number of clusters that can be delayed for compression - -this is for the dmsdos compression daemon, not for write-back -caching. A value larger than 4096 seems to slow down your system -more than not using the daemon since the driver is busy with -maintaining the cache most of the time. Still good performance: -1024, which is also the recommended value. + Maximum number of clusters that can be delayed for compression - + this is for the dmsdos compression daemon, not for write-back + caching. A value larger than 4096 seems to slow down your system + more than not using the daemon since the driver is busy with + maintaining the cache most of the time. Still good performance: + 1024, which is also the recommended value. Idle acache timeout MAX_CACHE_TIME -Time (in seconds) after which idle MDFAT/DFAT/BITFAT buffers are -returned to the kernel. Default is 60. (This time has only an effect -if the dmsdos daemon is running.) + Time (in seconds) after which idle MDFAT/DFAT/BITFAT buffers are + returned to the kernel. Default is 60. (This time has only an effect + if the dmsdos daemon is running.) Max MDFAT cache size MDFATCACHESIZE -mdfat cache sizes -- please note that these number of fs buffers are -*permanently* held in memory - keep small on systems that are short -on memory. Default value: 40 (i.e. 20KB), which represents the MDFAT -space needed for approx. 5000 clusters (4000 on drivespace 3), i.e. -40MB (or 160MB on 32K clusters) of compressed data. + mdfat cache sizes -- please note that these number of fs buffers are + *permanently* held in memory - keep small on systems that are short + on memory. Default value: 40 (i.e. 20KB), which represents the MDFAT + space needed for approx. 5000 clusters (4000 on drivespace 3), i.e. + 40MB (or 160MB on 32K clusters) of compressed data. Max DFAT cache size DFATCACHESIZE -dfat cache sizes -- please note that these number of fs buffers are -*permanently* held in memory - keep small on systems that are short -on memory. Default value: 20 (i.e. 10KB), which represents the DFAT -space for approx. 5000 clusters, i.e. 40MB (160MB on 32K clusters) -of compressed data. + dfat cache sizes -- please note that these number of fs buffers are + *permanently* held in memory - keep small on systems that are short + on memory. Default value: 20 (i.e. 10KB), which represents the DFAT + space for approx. 5000 clusters, i.e. 40MB (160MB on 32K clusters) + of compressed data. Max BITFAT cache size BITFATCACHESIZE -bitfat cache sizes -- please note that these number of fs buffers -are *permanently* held in memory - keep small on systems that are -short on memory. Default value: 10 (i.e. 5KB), which represents the -BITFAT size for 400000 (200000 on stacker 4) compressed sectors, -i.e. 200MB (100MB on stacker 4) of compressed data. + bitfat cache sizes -- please note that these number of fs buffers + are *permanently* held in memory - keep small on systems that are + short on memory. Default value: 10 (i.e. 5KB), which represents the + BITFAT size for 400000 (200000 on stacker 4) compressed sectors, + i.e. 200MB (100MB on stacker 4) of compressed data. Enable write access DBL_WRITEACCESS -Say Y to compile in low-level write access code. If you say N all -low-level write access is replaced by an error written to syslog. -Say N if you want to build a read-only dmsdos module. + Say Y to compile in low-level write access code. If you say N all + low-level write access is replaced by an error written to syslog. + Say N if you want to build a read-only dmsdos module. Default loglevel DEFAULT_LOGLEVEL -Bit-coded field for debug messages (expert use only). Usually set -this to 0. Please read the documentation before changing this value. -The log level can also be changed at run time via dutil (see manpage) -or with a mount option. + Bit-coded field for debug messages (expert use only). Usually set + this to 0. Please read the documentation before changing this value. + The log level can also be changed at run time via dutil (see manpage) + or with a mount option. Default compression level DEFAULT_CF -Select between: - 0=least efficient but fastest compression - 11=most efficient but slowest compression -For slow processors you may want to use a lower value. -The compression level can be changed at run time with dutil (see -manpage) or with a mount option. If you are unsure say 11. + Select between: + 0=least efficient but fastest compression + 11=most efficient but slowest compression + For slow processors you may want to use a lower value. + The compression level can be changed at run time with dutil (see + manpage) or with a mount option. If you are unsure say 11. Cluster cache size CCACHESIZE -Sets the maximum number of clusters dmsdos can keep in its cluster -cache. Keep small on systems with low memory - otherwise dmsdos may -eat up too much memory and slow down your system by causing great -swapping. -Every cluster uses 8KB (32KB on drivespace 3 and sometimes on -Stacker 4). You shouldn't exceed approx. 1/4 of your physical RAM, -so use 64 if you have only 4MB or if you have only 16MB and you are -using drivespace 3. -WARNINGS: -1. If this value is too low, applications using files on a -compressed partition lock out each other. If it is much too low, -they may even lock out themselves and thus lock up the whole system. -Values below 64 are supposed critical, values below 32 are -supposed dangerous. -2. You might cause a system lockup also if you use more cache than -you have physical RAM. + Sets the maximum number of clusters dmsdos can keep in its cluster + cache. Keep small on systems with low memory - otherwise dmsdos may + eat up too much memory and slow down your system by causing great + swapping. + Every cluster uses 8KB (32KB on drivespace 3 and sometimes on + Stacker 4). You shouldn't exceed approx. 1/4 of your physical RAM, + so use 64 if you have only 4MB or if you have only 16MB and you are + using drivespace 3. + WARNINGS: + 1. If this value is too low, applications using files on a + compressed partition lock out each other. If it is much too low, + they may even lock out themselves and thus lock up the whole system. + Values below 64 are supposed critical, values below 32 are + supposed dangerous. + 2. You might cause a system lockup also if you use more cache than + you have physical RAM. Idle cluster cache timeout MAX_CCACHE_TIME -Time in seconds after which unused clusters are removed from the -cluster cache. Default is 240. (This time has only an effect if the -dmsdos daemon is running.) + Time in seconds after which unused clusters are removed from the + cluster cache. Default is 240. (This time has only an effect if the + dmsdos daemon is running.) Maximum number of blocks to read ahead MAX_READA -Maximum number of sectors to read-ahead at once - default is 64 in -order to let a 32KB cluster fit in. This parameter has only an -effect if read-ahead is enabled in the speedup tricks & hacks section -below. + Maximum number of sectors to read-ahead at once - default is 64 in + order to let a 32KB cluster fit in. This parameter has only an + effect if read-ahead is enabled in the speedup tricks & hacks section + below. Enable advanced read-ahead USE_READA_LIST -Use experimental (faster) read-ahead code in order to bypass -wait_on_buffer. If you say N the standard (slower) kernel read-ahead -code is used. Usually say Y unless you encounter strange problems. -This option only has an effect if read-ahead is turned on in the -speedup tricks & hacks section below. + Use experimental (faster) read-ahead code in order to bypass + wait_on_buffer. If you say N the standard (slower) kernel read-ahead + code is used. Usually say Y unless you encounter strange problems. + This option only has an effect if read-ahead is turned on in the + speedup tricks & hacks section below. Size of read-ahead list READA_LIST_SIZE -Fine-tune advanced read-ahead code. I always set this to 256. I -don't know whether changing this value really speeds up something -- my own benchmarks didn't lead to a clear result. -This option has only an effect if read-ahead is turned on and -advanced read-ahead is enabled. + Fine-tune advanced read-ahead code. I always set this to 256. I + don't know whether changing this value really speeds up something + - my own benchmarks didn't lead to a clear result. + This option has only an effect if read-ahead is turned on and + advanced read-ahead is enabled. Read-ahead threshold READA_THRESHOLD -Read-ahead is only done when more than this amount of bytes are read -at once. This prevents a badly written program from issuing thousands -of useless read-aheads. 4095 is a good value since this allows -read-ahead just for a memory page (mmap gets the data in 4096 byte -blocks and should have a gain from read-ahead). Lower values may -cause clustersize/(value+1)-1 useless read-aheads per cluster. -This option has only an effect if read-ahead is turned on in the -speedup tricks & hacks section below. + Read-ahead is only done when more than this amount of bytes are read + at once. This prevents a badly written program from issuing thousands + of useless read-aheads. 4095 is a good value since this allows + read-ahead just for a memory page (mmap gets the data in 4096 byte + blocks and should have a gain from read-ahead). Lower values may + cause clustersize/(value+1)-1 useless read-aheads per cluster. + This option has only an effect if read-ahead is turned on in the + speedup tricks & hacks section below. Leave directories uncompressed SP_BIT0 -Speedup Bit#0: avoids compression of directories. If it is set, -dmsdos never compresses directories for drivespace 3 and stacker -(others don't support compressed directories at all). Note that -directories are accessed very often and otherwise had to be -decompressed and compressed again after each access. Say Y. + Speedup Bit#0: avoids compression of directories. If it is set, + dmsdos never compresses directories for drivespace 3 and stacker + (others don't support compressed directories at all). Note that + directories are accessed very often and otherwise had to be + decompressed and compressed again after each access. Say Y. Leave umsdos EMD file uncompressed SP_BIT1 -Speedup Bit#1 is for umsdos upon dmsdos. If set, the driver never -compress the --linux-.--- special file (it contains extended -directory information). Setting this bit is strongly recommended. -The special file is even more often written than a directory -since it contains the access times (the directory contains only -the modification times). You will regret compressing this file, -even if you own the fastest computer of the world. Say Y. + Speedup Bit#1 is for umsdos upon dmsdos. If set, the driver never + compress the --linux-.--- special file (it contains extended + directory information). Setting this bit is strongly recommended. + The special file is even more often written than a directory + since it contains the access times (the directory contains only + the modification times). You will regret compressing this file, + even if you own the fastest computer of the world. Say Y. Skip exact search on BITFAT allocation SP_BIT2 -Speedup Bit#2: controls the free sector searching algorithm. If set, -dmsdos searchs faster but less carefully for free space in the CVF -at the cost of more fragmentation (this is *not* FAT level, but an -internal lower level and very awful fragmentation). If you say Y, -write access on large CVFs is faster (sometimes really notably -faster). Be warned, a CVF that is too fragmented will be set to -read-only, so you will have to boot Dos from time to time and run -the CVF maintainance tools over it. Usually say N, but saying Y -is not dangerous and may make you happier when writing much to a -CVF. + Speedup Bit#2: controls the free sector searching algorithm. If set, + dmsdos searchs faster but less carefully for free space in the CVF + at the cost of more fragmentation (this is *not* FAT level, but an + internal lower level and very awful fragmentation). If you say Y, + write access on large CVFs is faster (sometimes really notably + faster). Be warned, a CVF that is too fragmented will be set to + read-only, so you will have to boot Dos from time to time and run + the CVF maintainance tools over it. Usually say N, but saying Y + is not dangerous and may make you happier when writing much to a + CVF. Fast unmount SP_BIT3 -Speedup Bit#3: speeds up CVF unmount. If set, the driver writes dirty -clusters that are in the cache immediately without compressing them -before when the filesystem is to be unmounted. This way the unmount -procedure will be quite fast. In contrast, if you say N the clusters -are compressed before. Note that compression may take some time and -thus blocks the system until it is ready. Since most people who -haven't read these lines tend to press the reset button when a -filesystem unmount takes somewhat longer (especially on a shutdown -or reboot), the default is Y. If you can tolerate the time to wait -and you are prepared to wait, say N. + Speedup Bit#3: speeds up CVF unmount. If set, the driver writes dirty + clusters that are in the cache immediately without compressing them + before when the filesystem is to be unmounted. This way the unmount + procedure will be quite fast. In contrast, if you say N the clusters + are compressed before. Note that compression may take some time and + thus blocks the system until it is ready. Since most people who + haven't read these lines tend to press the reset button when a + filesystem unmount takes somewhat longer (especially on a shutdown + or reboot), the default is Y. If you can tolerate the time to wait + and you are prepared to wait, say N. Enable write-back cluster caching (instead of write-through) SP_BIT4 -Speedup Bit#4 enables write-back cluster caching. If this bit is set -the data in the cluster cache that have been changed by an -application and have to be written back to disk are not written -back immediately - they are kept some time in memory just in order -to save disk access when the application again changes the data. -This usually causes a significant speedup for write access, -especially because dmsdos also delays compression and free space -allocation in that case. To be honest, there's a small risk of data -loss if the system happens to crash before the data are written -back - but since your operating system is Linux a crash is rather -unlikely :) So say Y. + Speedup Bit#4 enables write-back cluster caching. If this bit is set + the data in the cluster cache that have been changed by an + application and have to be written back to disk are not written + back immediately - they are kept some time in memory just in order + to save disk access when the application again changes the data. + This usually causes a significant speedup for write access, + especially because dmsdos also delays compression and free space + allocation in that case. To be honest, there's a small risk of data + loss if the system happens to crash before the data are written + back - but since your operating system is Linux a crash is rather + unlikely :) So say Y. Enable read-ahead SP_BIT5 -Speedup Bit#5 enables cluster read-ahead in general. If you say Y, -this causes the driver to initiate a low-level disk access for some -data when it thinks they are most likely needed in a short time -later. This usually speeds up read access a little. The trick is -that the driver doesn't wait for the read-ahead disk access -to finish. So the disk can position its head (and so on) while the -system can do something else. Most likely the disk access has -finished when the data are actually needed - this saves some time -we otherwise had to wait. Well, at least this is the nice idea -of read-ahead. However, since read-ahead relies on a prediction, -there may be situations when it is useless or even a loss. -Just say Y. + Speedup Bit#5 enables cluster read-ahead in general. If you say Y, + this causes the driver to initiate a low-level disk access for some + data when it thinks they are most likely needed in a short time + later. This usually speeds up read access a little. The trick is + that the driver doesn't wait for the read-ahead disk access + to finish. So the disk can position its head (and so on) while the + system can do something else. Most likely the disk access has + finished when the data are actually needed - this saves some time + we otherwise had to wait. Well, at least this is the nice idea + of read-ahead. However, since read-ahead relies on a prediction, + there may be situations when it is useless or even a loss. + Just say Y. Fast BITFAT allocation SP_BIT6 -Speedup Bit#6 controls the free sector searching algorithm similar -to Speedup Bit#2, but in a more drastic way (it simply switches it -off). If this bit is set, free space allocation is very fast but -does not care about avoiding fragmentation at all. This is not -recommended. BE WARNED, it can cause *much* fragmentation in very -short time. The "filesystem almost full" warning is suppressed. -This switch is meant as a last resort if you cannot tolerate -system slowdowns at all. Don't fill the compressed filesystem -up to more than 3/4 when this switch is set. Write access may -fail horribly and cause data loss due to too high fragmentation. -(Well, this is Dos/Win95 strategy - never tell the disadvantages) -Usually say N. If unsure about the dangers, say N also. Only say Y -if you really know what you are doing. + Speedup Bit#6 controls the free sector searching algorithm similar + to Speedup Bit#2, but in a more drastic way (it simply switches it + off). If this bit is set, free space allocation is very fast but + does not care about avoiding fragmentation at all. This is not + recommended. BE WARNED, it can cause *much* fragmentation in very + short time. The "filesystem almost full" warning is suppressed. + This switch is meant as a last resort if you cannot tolerate + system slowdowns at all. Don't fill the compressed filesystem + up to more than 3/4 when this switch is set. Write access may + fail horribly and cause data loss due to too high fragmentation. + (Well, this is Dos/Win95 strategy - never tell the disadvantages) + Usually say N. If unsure about the dangers, say N also. Only say Y + if you really know what you are doing. Use daemon if present SP_BIT7 -Speedup Bit#7 controls what jobs the dmsdos daemon has to do (if it -is running). If set, the daemon takes over all the compression of -data that have to be written to disk. This can make your system -respond a little faster on write access as compression will be -mostly done when the system is idle. This is recommended for systems -usually running at high processor load, or in general for slow -processors. In contrast, if you say N the daemon is just used for -dmsdos internal memory management. If unsure, say Y. + Speedup Bit#7 controls what jobs the dmsdos daemon has to do (if it + is running). If set, the daemon takes over all the compression of + data that have to be written to disk. This can make your system + respond a little faster on write access as compression will be + mostly done when the system is idle. This is recommended for systems + usually running at high processor load, or in general for slow + processors. In contrast, if you say N the daemon is just used for + dmsdos internal memory management. If unsure, say Y. Avoid fragmented writes SP_BIT8 -Speedup Bit#8 controls what to do when the filesystem is too -fragmented for normal write access. Usually all data for one cluster -are stored in contiguous sectors, but if the filesystem is too -fragmented there may not be a 'free hole' that is large enough for -the data. Speedup Bit#8 controls what to do in that case. If this -bit is set dmsdos just returns a 'no space left on device' error and -refuses to write to the CVF any more. -Drivespace 3 and Stacker know a hack for that situation: they allow -storing the data of one cluster in several fragments on the disk. -If the bit is clear, the driver tries to write the data in several -fragments. Be warned, this makes future filesystem access slower as -it needs more disk head movements to read fragmented clusters. -*** Note that for Stacker this is currently not implemented *** -The default answer is N. + Speedup Bit#8 controls what to do when the filesystem is too + fragmented for normal write access. Usually all data for one cluster + are stored in contiguous sectors, but if the filesystem is too + fragmented there may not be a 'free hole' that is large enough for + the data. Speedup Bit#8 controls what to do in that case. If this + bit is set dmsdos just returns a 'no space left on device' error and + refuses to write to the CVF any more. + Drivespace 3 and Stacker know a hack for that situation: they allow + storing the data of one cluster in several fragments on the disk. + If the bit is clear, the driver tries to write the data in several + fragments. Be warned, this makes future filesystem access slower as + it needs more disk head movements to read fragmented clusters. + *** Note that for Stacker this is currently not implemented *** + The default answer is N. Use internal daemon INTERNAL_DAEMON -For convenience, the compression daemon may be compiled into the -module instead of running as a user process. When the internal -daemon is used, the external dmsdosd won't run though you can -compile it - it always exits with a "no permission" error message. -The internal daemon compresses faster (because the data needn't be -copied from kernel space to user space and back), but seems to eat -up much system time - use it only on *really fast* machines. Also, -it is started automatically by the system when it is needed (and -killed when it is no longer needed). On the other hand, the external -daemon eats up minimal system time and ressources, but must be -started and killed by hand. Say N if unsure. + Dmsdos can start a daemon that does delayed compression in the + background when the system is idle. It also reduces dmsdos memory + consumption when the driver has nothing to do for a long time. + The daemon exists in two variants: One is a user-level program and + the other one is a kernel process. The user-level program is called + "external daemon" while the other is the "internal daemon". + When the internal daemon is used, the external one won't run. + The internal daemon compresses faster (because the data needn't be + copied from kernel space to user space and back), but seems to eat + up much system time - use it only on *really fast* machines. Also, + it is started automatically by the system when it is needed (and + killed when it is no longer needed). On the other hand, the external + daemon eats up minimal system time and ressources, but must be + started and killed by hand. + *** If you have a fast processor and lots of memory (_real RAM_) + you probably don't need any dmsdos daemon at all. + Say N if unsure. Internal daemon wakeup time IDMSDOSD_TIME -Time interval in seconds for internal daemon - it awakes -periodically and looks for data or idle cache in this interval. -Set it to 30 if you are unsure. This option has only an effect if -the internal compression daemon is used. + Time interval in seconds for internal daemon - it awakes + periodically and looks for data to compress or memory to free up + in this interval. Set it to 30 if you are unsure. This option has + only an effect if the internal compression daemon is used. Disable logging completely NOLOG -Say Y if you need a really small module - this leaves out the -logging messages from the object code of the module. You cannot -use a loglevel other than 0 in this case. Usually say N. -Especially say N when debugging. + Say Y if you need a really small module - this leaves out the + logging messages from the object code of the module. You cannot + use a loglevel other than 0 in this case. Usually say N. + Especially say N when debugging. Sequence number logging SEQLOG -Say Y to generate a sequence number for each log line. The numbers -are guaranteed to be uniqe and in order of call. This is for -debugging in order to be sure no messages have been lost (There seem -to be some black holes in syslog that eat messages when they occur -massively.) -Say N if you are not debugging. If you find that messages are lost, -change the #define LOG_BUF_LEN to at least 65536 in file -linux/kernel/printk.c and recompile your kernel. Please note that -the LOG_BUF_LEN value is expected to be a power of 2 by the Linux -kernel code. + Say Y to generate a sequence number for each log line. The numbers + are guaranteed to be uniqe and in order of call. This is for + debugging in order to be sure no messages have been lost (There seem + to be some black holes in syslog that eat messages when they occur + massively.) + Say N if you are not debugging. If you find that messages are lost, + change the #define LOG_BUF_LEN to at least 65536 in file + linux/kernel/printk.c and recompile your kernel. Please note that + the LOG_BUF_LEN value is expected to be a power of 2 by the Linux + kernel code. Writable mmap support DMSDOS_USE_READPAGE -Say Y to use the standard readpage interface (for writable mmap). -Say N to use old mmap interface which is read-only. Say Y except -you run into strange problems with writable mmaps. -WARNING: Old mmap interface is broken in dmsdos for some newer -kernels (it doesn't compile). It may be removed from dmsdos some day. + Say Y to use the standard readpage interface (for writable mmap). + Say N to use old mmap interface which is read-only. Say Y except + you run into strange problems with writable mmaps. + WARNING: Old mmap interface is broken in dmsdos under some newer + 2.1.xx and 2.2.x kernels (it doesn't compile). It may be removed + from dmsdos some day. diff --git a/src/Makefile b/src/Makefile index 6a77ca0..61ab1b6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,4 +1,3 @@ - # If you want or need to change something herein, please look approx. 30 lines # below for the 'User Config Section' @@ -21,9 +20,17 @@ endif ifeq ($(CONFIG_M586),y) CPUFLAGS= -m486 -DCPU=586 -DUSE_ASM endif +# this one is new in 2.2.x kernels... +ifeq ($(CONFIG_M586TSC),y) +CPUFLAGS= -m486 -DCPU=586 -DUSE_ASM +endif ifeq ($(CONFIG_M686),y) CPUFLAGS= -m486 -DCPU=686 -DUSE_ASM endif +# this one is new in 2.3.x kernels... +ifeq ($(CONFIG_MK7),y) +CPUFLAGS= -m486 -DCPU=686 -DUSE_ASM +endif # # Okay, that's it :) ######################################################################## @@ -52,6 +59,10 @@ CC=gcc ifeq ($(SMP),1) CPUFLAGS+= -D__SMP__ endif +# 2.2.x kernels have this one... +ifeq ($(CONFIG_SMP),y) +CPUFLAGS+= -D__SMP__ +endif # # The next lines are for libc6 and enable some compatibility hacks - # uncomment the line with -D__FOR_LIBC6 if the code does not compile @@ -77,8 +88,10 @@ DCFLAGS+= $(CPUFLAGS) # # CFLAGS for the dmsdos library # note: some macro expansions require at least -O -LCFLAGS= -Wall -O -ggdb -D__DMSDOS_LIB__ +LCFLAGS= -Wall -O -ggdb -D__DMSDOS_LIB__ -DUSE_FLOCK LCFLAGS+= $(CPUFLAGS) $(LIBC6FLAGS) +# uncomment the next line if you want a shared library +# LIB_SHARED = 1 # # locations where to install the module, the executables and the manpages # note: `uname -r` expands to the *currently running* kernel version - if it @@ -86,7 +99,6 @@ LCFLAGS+= $(CPUFLAGS) $(LIBC6FLAGS) MODULE_PREFIX=/lib/modules/`uname -r`/fs #MODULE_PREFIX=/lib/modules/misc EXEC_PREFIX=/usr/local/bin -MAN_PREFIX=/usr/local/man # # Okay, that's the end of the User Config Section. ########################################################################## @@ -94,7 +106,8 @@ MAN_PREFIX=/usr/local/man ########################################################################## # The rest of this file are rules how to build which programs. -all: dmsdos-config.h dmsdos.o dutil dmsdosd libdmsdos.a dcread dmsdosfsck +all: dmsdos-config.h dmsdos.o dutil dmsdosd $(LIBDMSDOS) dcread dmsdosfsck \ + mcdmsdos cvflist cvftest min: dmsdos-config.h dmsdos.o dutil @@ -118,14 +131,17 @@ depend: @touch depend DBL_OBJS = dblspace_compr.o dblspace_tables.o \ - dblspace_alloc.o dblspace_dec.o dblspace_virtual.o \ - dblspace_buffer.o dblspace_methsq.o \ - dblspace_chk.o dblspace_interface.o \ - dstacker_alloc.o dstacker_compr.o dstacker_dec.o \ - dblspace_fileops.o dblspace_ioctl.o + dblspace_alloc.o dblspace_dec.o dblspace_virtual.o \ + dblspace_buffer.o dblspace_methsq.o \ + dblspace_chk.o dblspace_interface.o \ + dstacker_alloc.o dstacker_compr.o dstacker_dec.o \ + dblspace_fileops.o dblspace_ioctl.o $(DBL_OBJS): dmsdos.h dmsdos-config.h +dblspace_fileops.o : dblspace_fileops.c dblspace_fileops.c-2.0.33 \ + dblspace_fileops.c-2.1.80 dblspace_fileops.c-2.3.10 + dmsdos.o: $(DBL_OBJS) ld -r -o dmsdos.o $(DBL_OBJS) @@ -133,7 +149,7 @@ dutil: dutil.c dmsdos.h dmsdos-config.h $(CC) $(DCFLAGS) -o dutil dutil.c DAEMON_OBJS = daemon_actions.do dblspace_compr.do dstacker_compr.do \ - dblspace_methsq.do + dblspace_methsq.do $(DAEMON_OBJS): dmsdos.h dmsdos-config.h @@ -143,7 +159,8 @@ dmsdosd: $(DAEMON_OBJS) $(CC) -o dmsdosd $^ clean: - rm -f *.o *.a *.i *.s *.lo *.do *.so dutil dmsdosd dcread dmsdosfsck cvftest + rm -f *.o *.a *.i *.s *.lo *.do *.so *.so.* dutil dmsdosd dcread \ + dmsdosfsck cvftest cvflist mcdmsdos mrproper: clean rm -f core *~ depend @@ -155,24 +172,23 @@ install: all install dutil $(EXEC_PREFIX)/dutil install dmsdosd $(EXEC_PREFIX)/dmsdosd install dmsdosfsck $(EXEC_PREFIX)/dmsdosfsck - install dutil.1 -m 644 $(MAN_PREFIX)/man1/dutil.1 - install dmsdosd.1 -m 644 $(MAN_PREFIX)/man1/dmsdosd.1 - install dmsdosfsck.8 -m 644 $(MAN_PREFIX)/man8/dmsdosfsck.8 + install mcdmsdos $(EXEC_PREFIX)/mcdmsdos + install cvflist $(EXEC_PREFIX)/cvflist + install cvftest $(EXEC_PREFIX)/cvftest install-min: min ./check.sh install dmsdos.o $(MODULE_PREFIX)/dmsdos.o install dutil $(EXEC_PREFIX)/dutil - install dutil.1 -m 644 $(MAN_PREFIX)/man1/dutil.1 uninstall: rm -f $(MODULE_PREFIX)/dmsdos.o rm -f $(EXEC_PREFIX)/dutil rm -f $(EXEC_PREFIX)/dmsdosd rm -f $(EXEC_PREFIX)/dmsdosfsck - rm -f $(MAN_PREFIX)/man1/dutil.1 - rm -f $(MAN_PREFIX)/man1/dmsdosd.1 - rm -f $(MAN_PREFIX)/man8/dmsdosfsck.8 + rm -f $(EXEC_PREFIX)/mcdmsdos + rm -f $(EXEC_PREFIX)/cvflist + rm -f $(EXEC_PREFIX)/cvftest messages: grep DMSDOS ../doc/messages.doc | sort -d -b -f > /tmp/messdoc @@ -180,31 +196,47 @@ messages: diff -d -U 0 -w /tmp/messdoc /tmp/messsrc | grep DMSDOS LIB_OBJS = lib_interface.lo dblspace_interface.lo dblspace_dec.lo \ - dblspace_compr.lo dblspace_methsq.lo dblspace_alloc.lo \ - dblspace_chk.lo dblspace_tables.lo dstacker_compr.lo \ - dstacker_dec.lo dstacker_alloc.lo + dblspace_compr.lo dblspace_methsq.lo dblspace_alloc.lo \ + dblspace_chk.lo dblspace_tables.lo dstacker_compr.lo \ + dstacker_dec.lo dstacker_alloc.lo $(LIB_OBJS): dmsdos.h dmsdos-config.h lib_interface.h +ifndef LIB_SHARED + +LIBDMSDOS = libdmsdos.a + %.lo: %.c ; $(CC) -o $@ $(LCFLAGS) -c $< -dmsdos_library.lo: $(LIB_OBJS) - ld -r -o dmsdos_library.lo $^ +$(LIBDMSDOS): $(LIB_OBJS) + ar rcs $(LIBDMSDOS) $^ + ranlib $(LIBDMSDOS) + +else + +%.lo: %.c ; $(CC) --shared -o $@ $(LCFLAGS) -c $< -libdmsdos.a: dmsdos_library.lo - ar rcs libdmsdos.a dmsdos_library.lo +LIBDMSDOS = libdmsdos.so.0.9.2 -libdmsdos.so: dmsdos_library.lo - ld -shared -o libdmsdos.so dmsdos_library.lo +$(LIBDMSDOS): $(LIB_OBJS) + ld --shared --soname=$(LIBDMSDOS) -o $(LIBDMSDOS) $^ + ln -s $(LIBDMSDOS) libdmsdos.so -dcread: dcread.c libdmsdos.a dmsdos.h dmsdos-config.h +endif + +dcread: dcread.c $(LIBDMSDOS) dmsdos.h dmsdos-config.h $(CC) -Wall -ggdb -o dcread dcread.c -L. -ldmsdos -dmsdosfsck: dmsdosfsck.c libdmsdos.a dmsdos.h dmsdos-config.h +mcdmsdos: mcdmsdos.c $(LIBDMSDOS) dmsdos.h dmsdos-config.h + $(CC) -Wall -ggdb -o mcdmsdos mcdmsdos.c -L. -ldmsdos + +dmsdosfsck: dmsdosfsck.c $(LIBDMSDOS) dmsdos.h dmsdos-config.h $(CC) -Wall -o dmsdosfsck dmsdosfsck.c -L. -ldmsdos cvftest: cvftest.c - @echo "WARNING: Using cvftest is discouraged. Use file(1) instead." $(CC) -Wall -o cvftest cvftest.c +cvflist: cvflist.c + $(CC) -Wall -o cvflist cvflist.c + -include depend diff --git a/src/Makefile.cygwinb20 b/src/Makefile.cygwinb20 old mode 100644 new mode 100755 diff --git a/src/Makefile.old b/src/Makefile.old new file mode 100644 index 0000000..69eb38c --- /dev/null +++ b/src/Makefile.old @@ -0,0 +1,215 @@ + +# If you want or need to change something herein, please look approx. 30 lines +# below for the 'User Config Section' + +######################################################################## +# The next lines are hacks for automatic detection of different kernel setups. +# These things must happen first, please don't change them here. They can be +# overridden later. +# +# we try to guess some settings from kernel configuration :) +-include /usr/src/linux/.config +# +# guess some special flags for CPU type - used for optimization only +CPUFLAGS= +ifeq ($(CONFIG_M386),y) +CPUFLAGS= -m386 -DCPU=386 -DUSE_ASM +endif +ifeq ($(CONFIG_M486),y) +CPUFLAGS= -m486 -DCPU=486 -DUSE_ASM +endif +ifeq ($(CONFIG_M586),y) +CPUFLAGS= -m486 -DCPU=586 -DUSE_ASM +endif +ifeq ($(CONFIG_M686),y) +CPUFLAGS= -m486 -DCPU=686 -DUSE_ASM +endif +# +# Okay, that's it :) +######################################################################## + +######################################################################## +# *** User Config Section *** +# Here you can look for settings to change if the code refuses to compile +# out of the box. There are so many different systems. So many versions +# of compilers. So many different bugs. :( +# +# Select compiler +CC=gcc +# +# If cpu specific optimization fails, uncomment the next line to switch it +# off - there are some gas versions around that don't like the cpu specific +# asm instructions in dmsdos... +# CPUFLAGS= +# +# Some gnu assembler versions have a bug in the syntax for the xlat +# instruction. This enables a workaround. It should only be needed for very +# old binutils versions. I don't know for which ones :( +# CPUFLAGS+= -DGAS_XLAT_BUG +# +# The next lines should detect SMP configuration automatically. +# Comment them out or set it manually if it fails. +ifeq ($(SMP),1) +CPUFLAGS+= -D__SMP__ +endif +# +# The next lines are for libc6 and enable some compatibility hacks - +# uncomment the line with -D__FOR_LIBC6 if the code does not compile +# *** Currently not used - code should compile under libc6 without hacks +LIBC6FLAGS= +#LIBC6FLAGS= -D__FOR_LIBC6 +# +# CFLAGS for dmsdos module +# note: some macro expansions require at least -O +CFLAGS= -Wall -Wstrict-prototypes -O3 -fomit-frame-pointer -D__KERNEL__ -DMODULE +CFLAGS+= $(CPUFLAGS) +# +# The next lines add some stuff automatically for people using modversions +# if they fail, comment them out and set the required flags manually +ifeq ($(CONFIG_MODVERSIONS),y) +CFLAGS+= -DMODVERSIONS -include /usr/include/linux/modversions.h +endif +# +# CFLAGS for the dmsdos daemon +# note: some macro expansions require at least -O +DCFLAGS= -Wall -O3 -D__DMSDOS_DAEMON__ +DCFLAGS+= $(CPUFLAGS) +# +# CFLAGS for the dmsdos library +# note: some macro expansions require at least -O +LCFLAGS= -Wall -O -ggdb -D__DMSDOS_LIB__ +LCFLAGS+= $(CPUFLAGS) $(LIBC6FLAGS) +# +# locations where to install the module, the executables and the manpages +# note: `uname -r` expands to the *currently running* kernel version - if it +# is different from that in /usr/src/linux you'd better edit the next line :) +MODULE_PREFIX=/lib/modules/`uname -r`/fs +#MODULE_PREFIX=/lib/modules/misc +EXEC_PREFIX=/usr/local/bin +# +# Okay, that's the end of the User Config Section. +########################################################################## + +########################################################################## +# The rest of this file are rules how to build which programs. + +all: dmsdos-config.h dmsdos.o dutil dmsdosd libdmsdos.a dcread dmsdosfsck \ + mcdmsdos cvflist cvftest + +min: dmsdos-config.h dmsdos.o dutil + +dmsdos-config.h: + /bin/bash conf-wrapper.sh + make dep + +config: + /bin/bash Configure + make dep + +menuconfig: + /bin/bash Menuconfig + make dep + +dep: + ./check.sh + $(CC) -w -E -MM -D__KERNEL__ -D__MODULE__ -DMODULE dblspace*.c dstacker*.c > depend + +depend: + @touch depend + +DBL_OBJS = dblspace_compr.o dblspace_tables.o \ + dblspace_alloc.o dblspace_dec.o dblspace_virtual.o \ + dblspace_buffer.o dblspace_methsq.o \ + dblspace_chk.o dblspace_interface.o \ + dstacker_alloc.o dstacker_compr.o dstacker_dec.o \ + dblspace_fileops.o dblspace_ioctl.o + +$(DBL_OBJS): dmsdos.h dmsdos-config.h + +dmsdos.o: $(DBL_OBJS) + ld -r -o dmsdos.o $(DBL_OBJS) + +dutil: dutil.c dmsdos.h dmsdos-config.h + $(CC) $(DCFLAGS) -o dutil dutil.c + +DAEMON_OBJS = daemon_actions.do dblspace_compr.do dstacker_compr.do \ + dblspace_methsq.do + +$(DAEMON_OBJS): dmsdos.h dmsdos-config.h + +%.do: %.c ; $(CC) -o $@ $(DCFLAGS) -c $< + +dmsdosd: $(DAEMON_OBJS) + $(CC) -o dmsdosd $^ + +clean: + rm -f *.o *.a *.i *.s *.lo *.do *.so dutil dmsdosd dcread \ + dmsdosfsck cvftest cvflist mcdmsdos + +mrproper: clean + rm -f core *~ depend + rm -f .config* dmsdos-config.h .menuconfig* + +install: all + ./check.sh + install dmsdos.o -m 644 $(MODULE_PREFIX)/dmsdos.o + install dutil $(EXEC_PREFIX)/dutil + install dmsdosd $(EXEC_PREFIX)/dmsdosd + install dmsdosfsck $(EXEC_PREFIX)/dmsdosfsck + install mcdmsdos $(EXEC_PREFIX)/mcdmsdos + install cvflist $(EXEC_PREFIX)/cvflist + install cvftest $(EXEC_PREFIX)/cvftest + +install-min: min + ./check.sh + install dmsdos.o $(MODULE_PREFIX)/dmsdos.o + install dutil $(EXEC_PREFIX)/dutil + +uninstall: + rm -f $(MODULE_PREFIX)/dmsdos.o + rm -f $(EXEC_PREFIX)/dutil + rm -f $(EXEC_PREFIX)/dmsdosd + rm -f $(EXEC_PREFIX)/dmsdosfsck + rm -f $(EXEC_PREFIX)/mcdmsdos + rm -f $(EXEC_PREFIX)/cvflist + rm -f $(EXEC_PREFIX)/cvftest + +messages: + grep DMSDOS ../doc/messages.doc | sort -d -b -f > /tmp/messdoc + ./listmsg.sh -LOG > /tmp/messsrc + diff -d -U 0 -w /tmp/messdoc /tmp/messsrc | grep DMSDOS + +LIB_OBJS = lib_interface.lo dblspace_interface.lo dblspace_dec.lo \ + dblspace_compr.lo dblspace_methsq.lo dblspace_alloc.lo \ + dblspace_chk.lo dblspace_tables.lo dstacker_compr.lo \ + dstacker_dec.lo dstacker_alloc.lo + +$(LIB_OBJS): dmsdos.h dmsdos-config.h lib_interface.h + +%.lo: %.c ; $(CC) -o $@ $(LCFLAGS) -c $< + +dmsdos_library.lo: $(LIB_OBJS) + ld -r -o dmsdos_library.lo $^ + +libdmsdos.a: dmsdos_library.lo + ar rcs libdmsdos.a dmsdos_library.lo + +libdmsdos.so: dmsdos_library.lo + ld -shared -o libdmsdos.so dmsdos_library.lo + +dcread: dcread.c libdmsdos.a dmsdos.h dmsdos-config.h + $(CC) -Wall -ggdb -o dcread dcread.c -L. -ldmsdos + +mcdmsdos: mcdmsdos.c libdmsdos.a dmsdos.h dmsdos-config.h + $(CC) -Wall -ggdb -o mcdmsdos mcdmsdos.c -L. -ldmsdos + +dmsdosfsck: dmsdosfsck.c libdmsdos.a dmsdos.h dmsdos-config.h + $(CC) -Wall -o dmsdosfsck dmsdosfsck.c -L. -ldmsdos + +cvftest: cvftest.c + $(CC) -Wall -o cvftest cvftest.c + +cvflist: cvflist.c + $(CC) -Wall -o cvflist cvflist.c + +-include depend diff --git a/src/Menuconfig b/src/Menuconfig index 87d581f..196b4fa 100644 --- a/src/Menuconfig +++ b/src/Menuconfig @@ -1114,7 +1114,7 @@ trap "cleanup ; rm -f .menuconfig ; exit 1" 1 2 15 # DEFAULTS="dmsdos-config.default" -CONFIG_IN="${1:-./config.in}" +CONFIG_IN="${1:-./Config.in}" _CONFIG="${2:-.config}" diff --git a/src/check.sh b/src/check.sh old mode 100644 new mode 100755 diff --git a/src/cvftest.c b/src/cvftest.c index 8c25a6f..ede517c 100644 --- a/src/cvftest.c +++ b/src/cvftest.c @@ -1,3 +1,31 @@ +/* +cvftest.c + +DMSDOS: doublespace/drivespace/stacker CVF identification tool. + +****************************************************************************** +DMSDOS (compressed MSDOS filesystem support) for Linux +written 1995-1998 by Frank Gockel and Pavel Pisa + + (C) Copyright 1995-1998 by Frank Gockel + (C) Copyright 1996-1998 by Pavel Pisa + +Some code of dmsdos has been copied from the msdos filesystem +so there are the following additional copyrights: + + (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem) + (C) Copyright 1994,1995 by Jacques Gelinas (mmap code) + (C) Copyright 1992-1995 by Linus Torvalds + +DMSDOS was inspired by the THS filesystem (a simple doublespace +DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann. + +The DMSDOS code is distributed under the Gnu General Public Licence. +See file COPYING for details. +****************************************************************************** + +*/ + #include #include @@ -5,17 +33,29 @@ int main(int argc, char*argv[]) { unsigned char sb[512]; int i; FILE*f; + char*fn; - if(argc!=2) - { fprintf(stderr,"usage: %s filename\n",argv[0]); + if(argc<2||argc>3) + { + usage: + fprintf(stderr,"usage: %s filename [-v]\n",argv[0]); fprintf(stderr,"detect CVFs according to header\n"); + fprintf(stderr," -v: be verbose i.e. print result to stdout\n"); + fprintf(stderr," \"-\" as filename means read data from stdin\n"); fprintf(stderr,"exit code: 0 = CVF detected, 1 = no CVF, >1 = some error occured\n"); exit(20); } - if(strcmp(argv[1],"-")==0)f=stdin; + fn=argv[1]; + + if(argc==3) + { if(strcmp(argv[1],"-v")==0)fn=argv[2]; + else if(strcmp(argv[2],"-v")!=0)goto usage; + } + + if(strcmp(fn,"-")==0)f=stdin; else - { f=fopen(argv[1],"rb"); + { f=fopen(fn,"rb"); if(f==NULL) { perror("open failed"); exit(4); @@ -25,12 +65,56 @@ int main(int argc, char*argv[]) for(i=0;i<512;++i)sb[i]=fgetc(f); if(fgetc(f)==EOF) - { perror("error reading file"); - exit(3); + { if(ferror(f)) + { perror("error reading file"); + exit(3); + } + if(argc==3)goto nocvf; + return 1; } - + + if(argc==2) + { if(strncmp(sb+3,"MSDBL6.0",8)==0||strncmp(sb+3,"MSDSP6.0",8)==0 ||strncmp(sb,"STACKER",7)==0)return 0; return 1; + } + + if(strncmp(sb+3,"MSDBL6.0",8)==0||strncmp(sb+3,"MSDSP6.0",8)==0) + { if(sb[51]==2&&sb[13]==16)printf("drivespace CVF (version 2)\n"); + else if((sb[51]==3||sb[51]==0)&&sb[13]==64)printf("drivespace 3 CVF\n"); + else if(sb[51]<2&&sb[13]==16)printf("doublespace CVF (version 1)\n"); + else printf("unknown (new? damaged?) doublespace or drivespace CVF\n"); + return 0; + } + else if(strncmp(sb,"STACKER",7)==0) + { int i; + unsigned char b,c; + unsigned char * p; + int StacVersion; + + /* decode super block */ + for(i=0x30,p=sb+0x50,b=sb[0x4c];i--;p++) + { b=0xc4-b; + b=b<0x80?b*2:b*2+1; + b^=c=*p; + *p=b;b=c; + } + if(sb[0x4e]!=0xa||sb[0x4f]!=0x1a) + printf("unknown (new? damaged?) stacker CVF\n"); + else + { StacVersion=sb[0x60]; + StacVersion&=0xff; + StacVersion|=sb[0x61]<<8; + StacVersion&=0xffff; + if(StacVersion>=410)printf("stacker version 4 CVF\n"); + else printf("stacker version 3 CVF\n"); + } + return 0; + } + + nocvf: + printf("not a known CVF\n"); + return 1; } diff --git a/src/daemon_actions.c b/src/daemon_actions.c index e862ac0..89e15e8 100644 --- a/src/daemon_actions.c +++ b/src/daemon_actions.c @@ -277,8 +277,8 @@ int main(int argc, char*argv[]) close(fd); return 1; } - if(ret<0x00000901) - { printf("\nSorry, this program requires at least DMSDOS driver version 0.9.1.\n"); + if(ret<0x00000902) + { printf("\nSorry, this program requires at least DMSDOS driver version 0.9.2.\n"); close(fd); return 1; } diff --git a/src/dblspace_alloc.c b/src/dblspace_alloc.c index 99b9d7c..ab6c18a 100644 --- a/src/dblspace_alloc.c +++ b/src/dblspace_alloc.c @@ -414,11 +414,11 @@ void log_found_statistics() } #ifdef DMSDOS_CONFIG_DRVSP3 -int try_fragmented(struct super_block*sb,int near,int nr, +int try_fragmented(struct super_block*sb,int anear,int nr, unsigned char*fraglist) { int i; - int sector=near; + int sector=anear; Dblsb*dblsb=MSDOS_SB(sb)->private_data; int again=1; int frags; @@ -436,9 +436,9 @@ int try_fragmented(struct super_block*sb,int near,int nr, } printk(KERN_DEBUG "DMSDOS: trying to allocate fragmented space...\n"); - LOG_ALLOC("DMSDOS: try_fragmented: start, near=%d nr=%d\n",near,nr); + LOG_ALLOC("DMSDOS: try_fragmented: start, anear=%d nr=%d\n",anear,nr); - if(near==0)sector=dblsb->s_lastnear; + if(anear==0)sector=dblsb->s_lastnear; if(sectors_datastart||sector>dblsb->s_dataend) { sector=dblsb->s_datastart; @@ -609,7 +609,7 @@ int dbl_replace_existing_cluster(struct super_block*sb, int cluster, LOG_ALLOC("DMSDOS: dbl_replace_existing_cluster: same fragmented size, ok.\n"); goto mdfat_update; } - check_failed: + check_failed: ; /*Win32 compiler wants a semicolon here */ /* fall through */ } } diff --git a/src/dblspace_compr.c b/src/dblspace_compr.c index 3815876..e403d58 100644 --- a/src/dblspace_compr.c +++ b/src/dblspace_compr.c @@ -45,7 +45,7 @@ extern unsigned long dmsdos_speedup; extern int cfaktor; void panic(char*); #include -#include +#include #include #define MALLOC malloc #define FREE free @@ -57,14 +57,18 @@ void panic(char*); #include"lib_interface.h" #include #include -#include #endif int c_maxtrycount[12]={ 1, 2, 3, 4, 6, 8,10,14,18,22,28,40}; +#ifdef __GNUC__ #define INLINE static inline +#else +/* non-gnu compilers do not like inline */ +#define INLINE static +#endif -#if !defined(cpu_to_le16) && defined(__i386__) +#if !defined(cpu_to_le16) /* for old kernel versions - works only on i386 */ #define cpu_to_le16(v) (v) #endif diff --git a/src/dblspace_dec.c b/src/dblspace_dec.c index 0718117..cec2d76 100644 --- a/src/dblspace_dec.c +++ b/src/dblspace_dec.c @@ -51,10 +51,14 @@ See file COPYING for details. #include #include #include -#include #endif +#ifdef __GNUC__ #define INLINE static inline +#else +/* non-gnu compilers may not like inline */ +#define INLINE static +#endif /* we always need DS decompression */ @@ -75,7 +79,10 @@ __asm__ /*__volatile__*/(\ #else +#ifdef __GNUC__ +/* non-gnu compilers may not like warning directive */ #warning USE_GNU_ASM_I386 not defined, using "C" equivalent +#endif #define M_MOVSB(D,S,C) for(;(C);(C)--) *((__u8*)(D)++)=*((__u8*)(S)++) diff --git a/src/dblspace_fileops.c b/src/dblspace_fileops.c index f983e8f..fb37e8a 100644 --- a/src/dblspace_fileops.c +++ b/src/dblspace_fileops.c @@ -30,9 +30,13 @@ See file COPYING for details. #include"dmsdos.h" -#ifdef __FOR_KERNEL_2_1_80 -#include"dblspace_fileops.c-2.1.80" -#else -#include"dblspace_fileops.c-2.0.33" +#ifdef __FOR_KERNEL_2_3_10 + #include "dblspace_fileops.c-2.3.10" +#else + #ifdef __FOR_KERNEL_2_1_80 + #include "dblspace_fileops.c-2.1.80" + #else + #include "dblspace_fileops.c-2.0.33" + #endif #endif diff --git a/src/dblspace_interface.c b/src/dblspace_interface.c index d93ada7..39aade8 100644 --- a/src/dblspace_interface.c +++ b/src/dblspace_interface.c @@ -47,7 +47,7 @@ See file COPYING for details. # include # define MAJOR(x) 0 # define MINOR(x) 0 - extern long int blk_size[0][0]; + extern long int blk_size[1][1]; #endif extern Acache mdfat[]; @@ -263,7 +263,7 @@ int detect_dblspace(struct super_block*sb) { struct buffer_head*bh; MOD_INC_USE_COUNT; - bh=raw_bread(sb,0); + bh=raw_bread(sb,0); if(bh==NULL) { printk(KERN_ERR "DMSDOS: unable to read super block\n"); MOD_DEC_USE_COUNT; @@ -280,6 +280,27 @@ int detect_dblspace(struct super_block*sb) return 0; } +/* setup fresh dblsb structure */ +Dblsb* malloc_dblsb(void) +{ Dblsb*dblsb; + + dblsb=kmalloc(sizeof(Dblsb),GFP_KERNEL); + if(dblsb==NULL)return NULL; + dblsb->mdfat_alloc_semp=NULL; + + return dblsb; +} + +/* ensure all memory is released */ +void free_dblsb(Dblsb*dblsb) +{ if(dblsb==NULL)return; + if(dblsb->mdfat_alloc_semp) + { kfree(dblsb->mdfat_alloc_semp); + dblsb->mdfat_alloc_semp=NULL; + } + kfree(dblsb); +} + int mount_dblspace(struct super_block*sb,char*options) { struct buffer_head*bh; struct buffer_head*bh2; @@ -292,27 +313,14 @@ int mount_dblspace(struct super_block*sb,char*options) MOD_INC_USE_COUNT; LOG_REST("DMSDOS: dblspace/drvspace module mounting...\n"); - bh=raw_bread(sb,0); - if(bh==NULL) - { printk(KERN_ERR "DMSDOS: unable to read super block\n"); - MOD_DEC_USE_COUNT; - return -1; - } - if(strncmp(bh->b_data+3,"MSDBL6.0",8)&&strncmp(bh->b_data+3,"MSDSP6.0",8)) - { printk(KERN_ERR "DMSDOS: MSDBL/MSDSP signature not found, CVF skipped\n"); - raw_brelse(sb,bh); - MOD_DEC_USE_COUNT; - return -1; - } - dblsb=kmalloc(sizeof(Dblsb),GFP_KERNEL); + + dblsb=malloc_dblsb(); if(dblsb==NULL) { printk(KERN_ERR "DMSDOS: mount_dblspace: out of memory\n"); - raw_brelse(sb,bh); MOD_DEC_USE_COUNT; return -1; } MSDOS_SB(sb)->private_data=dblsb; - /*dblsb->mdfat_alloc_sem=MUTEX;*/ #ifdef __KERNEL__ { struct semaphore* sem; @@ -320,29 +328,46 @@ int mount_dblspace(struct super_block*sb,char*options) sem=kmalloc(sizeof(struct semaphore),GFP_KERNEL); if(sem==NULL) { printk(KERN_ERR "DMSDOS: mount_dblspace: out of memory\n"); - raw_brelse(sb,bh); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; MOD_DEC_USE_COUNT; return -1; } - *sem=MUTEX; + init_MUTEX(sem); dblsb->mdfat_alloc_semp=sem; } #endif - - /* find out size */ - dblsb->s_dataend=blk_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]*2; - + dblsb->s_comp=GUESS; dblsb->s_cfaktor=DEFAULT_CF; if(parse_dmsdos_options(options,dblsb,&repair)) { + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; + MOD_DEC_USE_COUNT; + return -1; + } + + dblsb->s_dataend=blk_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]*2; + + bh=raw_bread(sb,0); + if(bh==NULL) + { printk(KERN_ERR "DMSDOS: unable to read super block\n"); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; + MOD_DEC_USE_COUNT; + return -1; + } + if(strncmp(bh->b_data+3,"MSDBL6.0",8)&&strncmp(bh->b_data+3,"MSDSP6.0",8)) + { printk(KERN_ERR "DMSDOS: MSDBL/MSDSP signature not found, CVF skipped\n"); raw_brelse(sb,bh); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; MOD_DEC_USE_COUNT; return -1; } - if(sb->s_flags & MS_RDONLY)dblsb->s_comp=READ_ONLY; printk(KERN_INFO "DMSDOS: mounting CVF on device 0x%x %s...\n", sb->s_dev, @@ -380,6 +405,8 @@ int mount_dblspace(struct super_block*sb,char*options) if(dblsb->s_cvf_version<=DRVSP) { printk(KERN_ERR "DMSDOS: support for doublespace/drivespace(<3) not compiled in.\n"); raw_brelse(sb,bh); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; MOD_DEC_USE_COUNT; return -1; } @@ -388,6 +415,8 @@ int mount_dblspace(struct super_block*sb,char*options) if(dblsb->s_cvf_version==DRVSP3) { printk(KERN_ERR "DMSDOS: support for drivespace 3 not compiled in.\n"); raw_brelse(sb,bh); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; MOD_DEC_USE_COUNT; return -1; } @@ -397,6 +426,8 @@ int mount_dblspace(struct super_block*sb,char*options) if(bh2==NULL) { printk(KERN_ERR "DMSDOS: unable to read emulated boot block\n"); raw_brelse(sb,bh); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; MOD_DEC_USE_COUNT; return -1; } @@ -407,6 +438,8 @@ int mount_dblspace(struct super_block*sb,char*options) { printk(KERN_ERR "DMSDOS: CVF has FAT32 signature, not mounted. Please report this.\n"); raw_brelse(sb,bh2); raw_brelse(sb,bh); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; MOD_DEC_USE_COUNT; return -1; } @@ -543,6 +576,12 @@ int mount_dblspace(struct super_block*sb,char*options) MSDOS_SB(sb)->fat_bits=dblsb->s_16bitfat?16:12; } MSDOS_SB(sb)->cluster_size=dblsb->s_sectperclust; + #ifdef HAS_SB_CLUSTER_BITS + for(MSDOS_SB(sb)->cluster_bits=0; + (1<cluster_bits)cluster_size;) + MSDOS_SB(sb)->cluster_bits++; + MSDOS_SB(sb)->cluster_bits+=SECTOR_BITS; + #endif /* these *must* always match */ if(dblsb->s_comp==READ_ONLY)sb->s_flags |= MS_RDONLY; @@ -556,9 +595,7 @@ int mount_dblspace(struct super_block*sb,char*options) int unmount_dblspace(struct super_block*sb) { int j; -#if defined(__KERNEL__)||defined(DMSDOS_CONFIG_STAC) Dblsb*dblsb=MSDOS_SB(sb)->private_data; -#endif LOG_REST("DMSDOS: CVF on device 0x%x unmounted.\n",sb->s_dev); @@ -611,9 +648,12 @@ int unmount_dblspace(struct super_block*sb) kill_reada_list_dev(sb->s_dev); #endif /* this is unused in the library */ - kfree(dblsb->mdfat_alloc_semp); + /* looks like we don't need this here... */ + /*kfree(dblsb->mdfat_alloc_semp);*/ + /*dblsb->mdfat_alloc_semp=NULL;*/ #endif - kfree(MSDOS_SB(sb)->private_data); + /*kfree(MSDOS_SB(sb)->private_data);*/ + free_dblsb(dblsb); MSDOS_SB(sb)->private_data=NULL; /*MSDOS_SB(sb)->cvf_format=NULL;*/ /*this causes a segfault in dec_cvf_format_use_count_by_version*/ @@ -663,10 +703,49 @@ int mount_stacker(struct super_block*sb,char*options) MOD_INC_USE_COUNT; LOG_REST("DMSDOS: stacker 3/4 module mounting...\n"); + dblsb=malloc_dblsb(); + if(dblsb==NULL) + { printk(KERN_ERR "DMSDOS: mount_stacker: out of memory\n"); + MOD_DEC_USE_COUNT; + return -1; + } + MSDOS_SB(sb)->private_data=dblsb; + +#ifdef __KERNEL__ + { struct semaphore* sem; + + sem=kmalloc(sizeof(struct semaphore),GFP_KERNEL); + if(sem==NULL) + { printk(KERN_ERR "DMSDOS: mount_stacker: out of memory\n"); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; + MOD_DEC_USE_COUNT; + return -1; + } + init_MUTEX(sem); + dblsb->mdfat_alloc_semp=sem; + } +#endif + + dblsb->s_comp=GUESS; + dblsb->s_cfaktor=DEFAULT_CF; + + if(parse_dmsdos_options(options,dblsb,&repair)) + { + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; + MOD_DEC_USE_COUNT; + return -1; + } + + dblsb->s_dataend=blk_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]*2; + LOG_REST("DMSDOS: reading super block...\n"); bh=raw_bread(sb,0); if(bh==NULL) { printk(KERN_ERR "DMSDOS: unable to read super block of CVF\n"); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; MOD_DEC_USE_COUNT; return -1; } @@ -675,6 +754,8 @@ int mount_stacker(struct super_block*sb,char*options) if(strncmp(pp,"STACKER",7)!=0) { printk(KERN_ERR "DMSDOS: STACKER signature not found\n"); raw_brelse(sb,bh); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; MOD_DEC_USE_COUNT; return -1; } @@ -691,48 +772,12 @@ int mount_stacker(struct super_block*sb,char*options) if(buf[0x4e]!=0xa||buf[0x4f]!=0x1a) { printk(KERN_ERR "DMSDOS: Stacker 0x1A0A signature not found\n"); raw_brelse(sb,bh); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; MOD_DEC_USE_COUNT; return -1; } - dblsb=kmalloc(sizeof(Dblsb),GFP_KERNEL); - if(dblsb==NULL) - { printk(KERN_ERR "DMSDOS: mount_stacker: out of memory\n"); - raw_brelse(sb,bh); - MOD_DEC_USE_COUNT; - return -1; - } - MSDOS_SB(sb)->private_data=dblsb; - /*dblsb->mdfat_alloc_sem=MUTEX;*/ - -#ifdef __KERNEL__ - { struct semaphore* sem; - - sem=kmalloc(sizeof(struct semaphore),GFP_KERNEL); - if(sem==NULL) - { printk(KERN_ERR "DMSDOS: mount_stacker: out of memory\n"); - raw_brelse(sb,bh); - MOD_DEC_USE_COUNT; - return -1; - } - *sem=MUTEX; - dblsb->mdfat_alloc_semp=sem; - } -#endif - - /* find out size */ - dblsb->s_dataend=blk_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)]*2; - - dblsb->s_comp=GUESS; - dblsb->s_cfaktor=DEFAULT_CF; - - if(parse_dmsdos_options(options,dblsb,&repair)) - { - raw_brelse(sb,bh); - MOD_DEC_USE_COUNT; - return -1; - } - if(sb->s_flags & MS_RDONLY)dblsb->s_comp=READ_ONLY; printk(KERN_NOTICE "DMSDOS: mounting CVF on device 0x%x %s...\n", sb->s_dev, @@ -760,6 +805,8 @@ int mount_stacker(struct super_block*sb,char*options) if(dblsb->s_cvf_version==STAC3) { printk(KERN_ERR "DMSDOS: support for stacker 3 not compiled in.\n"); raw_brelse(sb,bh); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; MOD_DEC_USE_COUNT; return -1; } @@ -768,6 +815,8 @@ int mount_stacker(struct super_block*sb,char*options) if(dblsb->s_cvf_version==STAC4) { printk(KERN_ERR "DMSDOS: support for stacker 4 not compiled in.\n"); raw_brelse(sb,bh); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; MOD_DEC_USE_COUNT; return -1; } @@ -778,6 +827,8 @@ int mount_stacker(struct super_block*sb,char*options) if(bh2==NULL) { printk(KERN_ERR "DMSDOS: unable to read emulated boot block of CVF\n"); raw_brelse(sb,bh); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; MOD_DEC_USE_COUNT; return -1; } @@ -820,6 +871,8 @@ int mount_stacker(struct super_block*sb,char*options) { printk(KERN_ERR "DMSDOS: BB_ClustCnt=0x%x impossible (FAT32?)\n",BB_ClustCnt); raw_brelse(sb,bh2); raw_brelse(sb,bh); + free_dblsb(dblsb); + MSDOS_SB(sb)->private_data=NULL; MOD_DEC_USE_COUNT; return -1; } @@ -891,6 +944,12 @@ int mount_stacker(struct super_block*sb,char*options) MSDOS_SB(sb)->fat_bits=dblsb->s_16bitfat?16:12; } MSDOS_SB(sb)->cluster_size=dblsb->s_sectperclust; + #ifdef HAS_SB_CLUSTER_BITS + for(MSDOS_SB(sb)->cluster_bits=0; + (1<cluster_bits)cluster_size;) + MSDOS_SB(sb)->cluster_bits++; + MSDOS_SB(sb)->cluster_bits+=SECTOR_BITS; + #endif /* error test */ if(repair!=-1) /* repair==-1 means do not even check */ @@ -966,7 +1025,9 @@ struct cvf_format dblspace_format = { dblspace_fat_access, /* fat_access */ NULL, /* statfs */ dblspace_bmap, /* bmap */ + #ifndef __FOR_KERNEL_2_3_10 dblspace_smap, /* smap */ + #endif dblspace_file_read, /* file_read */ dblspace_file_write, /* file_write */ MMAP, /* mmap */ @@ -995,7 +1056,9 @@ struct cvf_format stacker_format = { dblspace_fat_access, /* fat_access */ NULL, /* statfs */ dblspace_bmap, /* bmap */ + #ifndef __FOR_KERNEL_2_3_10 dblspace_smap, /* smap */ + #endif dblspace_file_read, /* file_read */ dblspace_file_write, /* file_write */ MMAP, /* mmap */ @@ -1006,14 +1069,14 @@ struct cvf_format stacker_format = { }; #endif -int init_module(void) +int init_dmsdos(void) { int i; do_spc_init(); #ifdef DMSDOS_CONFIG_DBL i=register_cvf_format(&dblspace_format); if(i<0) - { printk(KERN_ERR "register_cvf_format failed, module not loaded successfully\n"); + { printk(KERN_ERR "register_cvf_format failed, dmsdos not loaded successfully\n"); do_spc_exit(); return i; } @@ -1021,7 +1084,7 @@ int init_module(void) #ifdef DMSDOS_CONFIG_STAC i=register_cvf_format(&stacker_format); if(i<0) - { printk(KERN_ERR "register_cvf_format failed, module not loaded successfully\n"); + { printk(KERN_ERR "register_cvf_format failed, dmsdos not loaded successfully\n"); do_spc_exit(); #ifdef DMSDOS_CONFIG_DBL unregister_cvf_format(&dblspace_format); @@ -1034,6 +1097,11 @@ int init_module(void) return 0; } +#ifdef MODULE +int init_module(void) +{ return init_dmsdos(); +} + void cleanup_module(void) { do_spc_exit(); #ifdef DMSDOS_CONFIG_DBL @@ -1043,6 +1111,7 @@ void cleanup_module(void) unregister_cvf_format(&stacker_format); #endif } +#endif /* MODULE */ #endif /* ifndef __DMSDOS_LIB__ */ char seq[]="000000"; @@ -1052,7 +1121,7 @@ char seq[]="000000"; void lock_prseq(void) {} void unlock_prseq(void) {} #else -struct semaphore prseq_sem=MUTEX; /* Must be initialized to green light */ +DECLARE_MUTEX(prseq_sem); /* Must be initialized to green light */ void lock_prseq(void) {down(&prseq_sem);} void unlock_prseq(void) {up(&prseq_sem);} #endif diff --git a/src/dblspace_ioctl.c b/src/dblspace_ioctl.c index 5c4244e..6eecc28 100644 --- a/src/dblspace_ioctl.c +++ b/src/dblspace_ioctl.c @@ -56,8 +56,8 @@ int rlist=0; int wlist=0; #ifdef INTERNAL_DAEMON -struct wait_queue * daemon_wait = NULL; -struct wait_queue * daemon_exit_wait=NULL; +DECLARE_WAIT_QUEUE_HEAD(daemon_wait); +DECLARE_WAIT_QUEUE_HEAD(daemon_exit_wait); int daemon_go_home=0; int internal_daemon_counter=0; #else @@ -68,7 +68,7 @@ int daemon_task_nr; void dumpcache(void); void dump_ccache(void); -struct semaphore listaccess_sem=MUTEX; /* Must be initialized to green light */ +DECLARE_MUTEX(listaccess_sem); /* Must be initialized to green light */ void lock_listaccess(void) {down(&listaccess_sem);} void unlock_listaccess(void) {up(&listaccess_sem);} diff --git a/src/dblspace_methsq.c b/src/dblspace_methsq.c index 67ea437..43422b1 100644 --- a/src/dblspace_methsq.c +++ b/src/dblspace_methsq.c @@ -53,14 +53,16 @@ extern int debug; #include"lib_interface.h" #include #include -#include -#include #endif - #ifdef DMSDOS_CONFIG_DRVSP3 -#define INLINE static inline +#ifdef __GNUC__ +#define INLINE static inline +#else +/* non-gnu compilers may not like inline */ +#define INLINE static +#endif /* store and load __u16 in any byteorder on any */ /* address (odd or even). */ @@ -110,11 +112,14 @@ __asm__ /*__volatile__*/(\ #else +#ifdef __GNUC__ +/* non-gnu compilers may not like warning directive */ #warning USE_GNU_ASM_I386 not defined, using "C" equivalent +#endif #define M_MOVSB(D,S,C) for(;(C);(C)--) *((__u8*)(D)++)=*((__u8*)(S)++) #define M_FIRSTDIFF(D,S,C) for(;(*(__u8*)(D)==*(__u8*)(S))&&(C);\ - (__u8*)(D)++,(__u8*)(S)++,(C)--) + (__u8*)(D)++,(__u8*)(S)++,(C)--) #endif @@ -130,10 +135,10 @@ __asm__ /*__volatile__*/(\ /* for reading and writting from/to bitstream */ typedef struct { - __u32 buf; /* bit buffer */ - int pb; /* already readed bits from buf */ - __u16 *pd; /* first not readed input data */ - __u16 *pe; /* after end of data */ + __u32 buf; /* bit buffer */ + int pb; /* already readed bits from buf */ + __u16 *pd; /* first not readed input data */ + __u16 *pe; /* after end of data */ } bits_t; const unsigned sq_bmsk[]= @@ -179,25 +184,25 @@ INLINE unsigned sq_rdn(bits_t *pbits,int n) /*==============================================================*/ /* huffman decoding */ -#define MAX_SPDA_BITS 10 -#define MAX_SPDA_LEN (1<(__u8*)bits.pe) {FREE(work_mem);return 0;}; - if(p+replen>pend) {FREE(work_mem);return 0;}; + if(r+replen>(__u8*)bits.pe) {FREE(work_mem);return 0;}; + if(p+replen>pend) {FREE(work_mem);return 0;}; M_MOVSB(p,r,replen); /* copy/repeat function */ if((unsigned)r&1) bits.pb=32; else {bits.pb=32+8;r--;}; +#if 0 + /* some compilers seem to be confused by this (???) */ bits.pd=(typeof(bits.pd))r; - break; +#else + bits.pd=(__u16*)r; +#endif + break; case 1: - printk(KERN_NOTICE "DMSDOS: sq_dec: submethod not tested - fixed huffman\n"); - /* 0x90*8 0x70*9 0x18*7 8*8 sqt_repbln sqt_repbas 0x101 0x120h */ - /* 0x1E*5 offset sqt_offbln sqt_offbas 0 0x1Eh */ - bn_max=9; - count_1=0x120; - count_2=0x20; - i=0; - while(i<0x90) code_bln[i++]=8; - while(i<0x100) code_bln[i++]=9; - while(i<0x118) code_bln[i++]=7; - while(i<0x120) code_bln[i++]=8; - while(i<0x140) code_bln[i++]=5; - goto case_1_cont; + printk(KERN_NOTICE "DMSDOS: sq_dec: submethod not tested - fixed huffman\n"); + /* 0x90*8 0x70*9 0x18*7 8*8 sqt_repbln sqt_repbas 0x101 0x120h */ + /* 0x1E*5 offset sqt_offbln sqt_offbas 0 0x1Eh */ + bn_max=9; + count_1=0x120; + count_2=0x20; + i=0; + while(i<0x90) code_bln[i++]=8; + while(i<0x100) code_bln[i++]=9; + while(i<0x118) code_bln[i++]=7; + while(i<0x120) code_bln[i++]=8; + while(i<0x140) code_bln[i++]=5; + goto case_1_cont; case 2: - LOG_DECOMP("DMSDOS: sq_dec: submethod huffman\n"); - count_1=sq_rdn(&bits,5)+0x101; - LOG_DECOMP("DMSDOS: count_1 %d\n",count_1); - if(count_1>0x11E) - { printk(KERN_INFO "DMSDOS: sq_dec: huff count_1 too big\n"); - FREE(work_mem);return(0); - }; - count_2=sq_rdn(&bits,5)+1; - LOG_DECOMP("DMSDOS: count_2 %d\n",count_2); - if(count_2>0x1E) - { printk(KERN_INFO "DMSDOS: sq_dec: huff count_2 too big\n"); - FREE(work_mem);return(0); - }; - count_3=sq_rdn(&bits,4)+4; - LOG_DECOMP("DMSDOS: count_3 %d\n",count_3); - bn_max=0; - for(i=0;ibn_max)bn_max=u; - }; - while(i<19) code_bln[code_index_1[i++]]=0;code_bln[19]=0xFF; - i=sq_rdhufi(huf1,19,bn_max,code_bln); - if(!i) - { printk(KERN_INFO "DMSDOS: sq_dec: huff error in helper table\n"); - FREE(work_mem);return 0; - }; - mask=sq_bmsk[huf1->bn]; u1=0; bn_max=0; - for(i=0;ichln[u&mask].ln; - u=huf1->chln[u&mask].ch; - switch(u) - { case 16: /* 3 to 6 repeats of last */ - u=sq_rdn(&bits,2)+3; - while(u--) code_bln[i++]=u1; - break; - case 17: /* 3 to 10 repeats of 0 */ - u=sq_rdn(&bits,3)+3; u1=0; - while(u--) code_bln[i++]=u1; - break; - case 18: /* 11 to 139 repeats of 0 */ - u=sq_rdn(&bits,7)+11; u1=0; - while(u--) code_bln[i++]=u1; - break; - default: - code_bln[i++]=u; - u1=u; - if(u>bn_max) bn_max=u; - }; - }; + LOG_DECOMP("DMSDOS: sq_dec: submethod huffman\n"); + count_1=sq_rdn(&bits,5)+0x101; + LOG_DECOMP("DMSDOS: count_1 %d\n",count_1); + if(count_1>0x11E) + { printk(KERN_INFO "DMSDOS: sq_dec: huff count_1 too big\n"); + FREE(work_mem);return(0); + }; + count_2=sq_rdn(&bits,5)+1; + LOG_DECOMP("DMSDOS: count_2 %d\n",count_2); + if(count_2>0x1E) + { printk(KERN_INFO "DMSDOS: sq_dec: huff count_2 too big\n"); + FREE(work_mem);return(0); + }; + count_3=sq_rdn(&bits,4)+4; + LOG_DECOMP("DMSDOS: count_3 %d\n",count_3); + bn_max=0; + for(i=0;ibn_max)bn_max=u; + }; + while(i<19) code_bln[code_index_1[i++]]=0;code_bln[19]=0xFF; + i=sq_rdhufi(huf1,19,bn_max,code_bln); + if(!i) + { printk(KERN_INFO "DMSDOS: sq_dec: huff error in helper table\n"); + FREE(work_mem);return 0; + }; + mask=sq_bmsk[huf1->bn]; u1=0; bn_max=0; + for(i=0;ichln[u&mask].ln; + u=huf1->chln[u&mask].ch; + switch(u) + { case 16: /* 3 to 6 repeats of last */ + u=sq_rdn(&bits,2)+3; + while(u--) code_bln[i++]=u1; + break; + case 17: /* 3 to 10 repeats of 0 */ + u=sq_rdn(&bits,3)+3; u1=0; + while(u--) code_bln[i++]=u1; + break; + case 18: /* 11 to 139 repeats of 0 */ + u=sq_rdn(&bits,7)+11; u1=0; + while(u--) code_bln[i++]=u1; + break; + default: + code_bln[i++]=u; + u1=u; + if(u>bn_max) bn_max=u; + }; + }; case_1_cont: - /* code_bln+count_1 0x96 count_2 sqt_offbln sqt_offbas */ - code_bln[count_1+count_2]=0xFF; - i=sq_rdhufi(huf2,0x100,8,code_bln+count_1); - if(!i) - { printk(KERN_INFO "DMSDOS: sq_dec: huff error in offset table\n"); - FREE(work_mem);return 0; - }; - - /* code_bln 0x100 count_1 sqt_repbln sqt_repbas */ - code_bln[count_1]=0xFF; - i=sq_rdhufi(huf1,0x100,bn_max,code_bln); - if(!i) - { printk(KERN_INFO "DMSDOS: sq_dec: huff error in char and len table\n"); - FREE(work_mem);return 0; - }; - - while((u=sq_rdh(&bits,huf1,&p,pend))!=0) - { if(u==OUT_OVER){u=sq_rdh1(&bits,huf1)-0x100;break;}; - u--; - replen=sqt_repbas[u]+sq_rdn(&bits,sqt_repbln[u]); - u=sq_rdh1(&bits,huf2); - repoffs=sqt_offbas[u]+sq_rdn(&bits,sqt_offbln[u]); - if(!repoffs) - { printk("DMSDOS: sq_dec: bad repoffs !!!\n\n"); - FREE(work_mem);return(0); - }; - if ((__u8*)pout+repoffs>p) - { repoffs=p-(__u8*)pout; - printk(KERN_INFO "DMSDOS: sq_dec: huff offset UNDER\n"); - }; - if (p+replen>pend) - { replen=pend-p; - printk(KERN_INFO "DMSDOS: sq_dec: huff offset OVER\n"); - }; - r=p-repoffs; M_MOVSB(p,r,replen); /* copy/repeat function */ - }; + /* code_bln+count_1 0x96 count_2 sqt_offbln sqt_offbas */ + code_bln[count_1+count_2]=0xFF; + i=sq_rdhufi(huf2,0x100,8,code_bln+count_1); + if(!i) + { printk(KERN_INFO "DMSDOS: sq_dec: huff error in offset table\n"); + FREE(work_mem);return 0; + }; + + /* code_bln 0x100 count_1 sqt_repbln sqt_repbas */ + code_bln[count_1]=0xFF; + i=sq_rdhufi(huf1,0x100,bn_max,code_bln); + if(!i) + { printk(KERN_INFO "DMSDOS: sq_dec: huff error in char and len table\n"); + FREE(work_mem);return 0; + }; + + while((u=sq_rdh(&bits,huf1,&p,pend))!=0) + { if(u==OUT_OVER){u=sq_rdh1(&bits,huf1)-0x100;break;}; + u--; + replen=sqt_repbas[u]+sq_rdn(&bits,sqt_repbln[u]); + u=sq_rdh1(&bits,huf2); + repoffs=sqt_offbas[u]+sq_rdn(&bits,sqt_offbln[u]); + if(!repoffs) + { printk("DMSDOS: sq_dec: bad repoffs !!!\n\n"); + FREE(work_mem);return(0); + }; + if ((__u8*)pout+repoffs>p) + { repoffs=p-(__u8*)pout; + printk(KERN_INFO "DMSDOS: sq_dec: huff offset UNDER\n"); + }; + if (p+replen>pend) + { replen=pend-p; + printk(KERN_INFO "DMSDOS: sq_dec: huff offset OVER\n"); + }; + r=p-repoffs; M_MOVSB(p,r,replen); /* copy/repeat function */ + }; - if(u) - { printk(KERN_INFO "DMSDOS: sq_dec: huff BAD last token %x\n",u); - FREE(work_mem);return 0; - }; - break; + if(u) + { printk(KERN_INFO "DMSDOS: sq_dec: huff BAD last token %x\n",u); + FREE(work_mem);return 0; + }; + break; case 3: - printk(KERN_INFO "DMSDOS: sq_dec: unknown submethod - 3\n"); - FREE(work_mem); - return(0); + printk(KERN_INFO "DMSDOS: sq_dec: unknown submethod - 3\n"); + FREE(work_mem); + return(0); }; } while((!final_flag)&&(pMAX_REP-2) match=MAX_REP-2; pd=pi+2; pc=hash_cur+2; - M_FIRSTDIFF(pd,pc,match); /* compare */ - match=pd-pi; /* found match length */ + M_FIRSTDIFF(pd,pc,match); /* compare */ + match=pd-pi; /* found match length */ if((match>max_match)&&((match>3)||(pi-hash_cur<=MAX_OFFS_BLN8))) { - max_hash=hash_cur; /* found maximal hash */ + max_hash=hash_cur; /* found maximal hash */ max_match=match; - if(match==MAX_REP)break; /* longer match cannot be encoded */ - if(pd>pend+1)break; /* match to end of block */ + if(match==MAX_REP)break; /* longer match cannot be encoded */ + if(pd>pend+1)break; /* match to end of block */ }; }; pc=hash_cur; @@ -912,7 +922,7 @@ unsigned sq_complz(void* pin,int lin,void* pout,int lout,int flg, { delay_best=0; while((delay_cnMAX_OFFS) break; /* longer offsets are not allowed */ if((hash_cur[max_match]==pi[max_match])&& - (hash_cur[max_match-1]==pi[max_match-1])&& - (hash_cur[0]==pi[0])&&(hash_cur[1]==pi[1])&& - /* pi[2]=hash_cur[2] from hash function */ - (hash_cur!=max_hash+delay_cn-delay_best)) + (hash_cur[max_match-1]==pi[max_match-1])&& + (hash_cur[0]==pi[0])&&(hash_cur[1]==pi[1])&& + /* pi[2]=hash_cur[2] from hash function */ + (hash_cur!=max_hash+delay_cn-delay_best)) { /* do not test actual max match */ match=pend-pi; /* length of rest of data */ if(match>MAX_REP-2) match=MAX_REP-2; @@ -934,10 +944,10 @@ unsigned sq_complz(void* pin,int lin,void* pout,int lout,int flg, match=pd-pi; /* found match length */ if((match>max_match+delay_cn)&&((match>3)||(pi-hash_cur<=MAX_OFFS_BLN8))) { - max_hash=hash_cur;max_match=match; /* find maximal hash */ - delay_best=delay_cn; - if(match==MAX_REP)break;/* longer match cannot be encoded */ - if(pd>pend+1)break; /* match to end of block */ + max_hash=hash_cur;max_match=match; /* find maximal hash */ + delay_best=delay_cn; + if(match==MAX_REP)break;/* longer match cannot be encoded */ + if(pd>pend+1)break; /* match to end of block */ }; }; pc=hash_cur; @@ -961,20 +971,21 @@ unsigned sq_complz(void* pin,int lin,void* pout,int lout,int flg, pi+=max_match; /* skip repeated bytes */ /* store information about match len into *po */ - token=find_token(max_match,sqt_repbas,29); /* for max match */ + token=find_token(max_match,sqt_repbas,29); /* for max match */ ch_cn[token+0x101]++; *po++=token+1; if(sqt_repbln[token]) *po++=max_match-sqt_repbas[token]; /* store information about match offset into *po */ - token=find_token(cn,sqt_offbas,30); /* for history offset */ + token=find_token(cn,sqt_offbas,30); /* for history offset */ offs_cn[token]++; *po++=token; if(sqt_offbln[token]) + { if(sqt_offbln[token]<=8) *po++=cn-sqt_offbas[token]; else C_ST_u16(po,cn-sqt_offbas[token]); - + }; if(hash_skiped&&(pia.lz_tabs); + ch_cn,offs_cn,work_mem->a.lz_tabs); LOG_DECOMP("DMSDOS: sq_comp: lz_length %d\n",lz_length); if(lz_length==0) {FREE(work_mem);return(0);}; @@ -1155,8 +1166,8 @@ int sq_comp(void* pin,int lin, void* pout, int lout, int flg) sq_wrn(&bits,'S',8); sq_wrn(&bits,'Q',8); sq_wrn(&bits,0,16); - sq_wrn(&bits,1,1); /* final flag */ - sq_wrn(&bits,2,2); /* huffman */ + sq_wrn(&bits,1,1); /* final flag */ + sq_wrn(&bits,2,2); /* huffman */ sq_wrn(&bits,count_1-0x101,5); sq_wrn(&bits,count_2-1,5); sq_wrn(&bits,count_3-4,4); @@ -1179,7 +1190,7 @@ int sq_comp(void* pin,int lin, void* pout, int lout, int flg) case 16: sq_wrn(&bits,*pi++,2); break; case 17: sq_wrn(&bits,*pi++,3); break; case 18: sq_wrn(&bits,*pi++,7); break; - default: + default: ; } } } @@ -1223,8 +1234,10 @@ int sq_comp(void* pin,int lin, void* pout, int lout, int flg) cod=*(lz_pos++); sq_wrh(&bits,offs_huf,cod); if(sqt_offbln[cod]) + { if(sqt_offbln[cod]<=8) sq_wrn(&bits,*(lz_pos++),sqt_offbln[cod]); else { C_LD_u16(lz_pos,len);sq_wrn(&bits,len,sqt_offbln[cod]);}; + }; }; } sq_wrh(&bits,ch_huf,TK_END+0x100); diff --git a/src/dblspace_tables.c b/src/dblspace_tables.c index 6251929..492e3ff 100644 --- a/src/dblspace_tables.c +++ b/src/dblspace_tables.c @@ -76,15 +76,15 @@ void unlock_bitfat(void) {} #else -struct semaphore mdfat_sem=MUTEX; /* Must be initialized to green light */ +DECLARE_MUTEX(mdfat_sem); /* Must be initialized to green light */ void lock_mdfat(void) {down(&mdfat_sem);} void unlock_mdfat(void) {up(&mdfat_sem);} -struct semaphore dfat_sem=MUTEX; /* Must be initialized to green light */ +DECLARE_MUTEX(dfat_sem); /* Must be initialized to green light */ void lock_dfat(void) {down(&dfat_sem);} void unlock_dfat(void) {up(&dfat_sem);} -struct semaphore bitfat_sem=MUTEX; /* Must be initialized to green light */ +DECLARE_MUTEX(bitfat_sem); /* Must be initialized to green light */ void lock_bitfat(void) {down(&bitfat_sem);} void unlock_bitfat(void) {up(&bitfat_sem);} @@ -350,7 +350,7 @@ int dbl_mdfat_value(struct super_block* sb,int clusternr, raw_brelse(sb,bh); } } - give_up: + give_up: ; } unlock_mdfat(); @@ -549,7 +549,7 @@ LOG_DFAT("DMSDOS: FAT lookup: cluster=%d value(low=%d high=%d)\n", raw_brelse(sb,bh); } } - give_up: + give_up: ; } unlock_dfat(); if(dblsb->s_16bitfat)return res>=0xFFF7 ? -1 : res; @@ -669,17 +669,30 @@ int dblspace_fat_access(struct super_block*sb, int clusternr, int newval) if(sb->s_flags&MS_RDONLY) { printk(KERN_ERR "DMSDOS: dblspace_fat_access: READ-ONLY filesystem\n"); - return -EROFS; + /* This is a bad hack in order to work around a problem with the + FAT driver: The FAT driver assumes fat_access never fails. Thus + returning -EROFS results in an endless loop (i.e. system hang) + at least in fat_free. We return -1 here in order to simulate EOF + which should break any loop in the FAT driver. */ + return /* -EROFS */ -1; } if(newval==0)delete_cache_cluster(sb,clusternr); dbl_fat_nextcluster(sb,clusternr,&newval); + if(cl<0)return -1; /* see comment above -- just to be sure :) */ + /* if cl _is_ -1 (EOF) this is ok. */ + /* if it is a negative error it is replaced by EOF. */ return cl; } int dblspace_bmap(struct inode*inode, int block) -{ printk(KERN_WARNING "DMSDOS: bmap called, unsupported!\n"); +{ + #ifdef __FOR_KERNEL_2_3_10 + return dblspace_smap(inode,block); + #else + printk(KERN_WARNING "DMSDOS: bmap called, unsupported!\n"); return -EIO; + #endif } int dblspace_smap(struct inode*inode, int block) diff --git a/src/dblspace_virtual.c b/src/dblspace_virtual.c index 6c708a7..7c386bd 100644 --- a/src/dblspace_virtual.c +++ b/src/dblspace_virtual.c @@ -52,11 +52,11 @@ extern unsigned long int dmsdos_speedup; /* cluster caching ... */ Cluster_head ccache[CCACHESIZE]; -struct semaphore ccache_sem=MUTEX; /* Must be initialized to green light */ +DECLARE_MUTEX(ccache_sem); /* Must be initialized to green light */ void lock_ccache(void) {down(&ccache_sem);} void unlock_ccache(void) {up(&ccache_sem);} -struct wait_queue * fullwait=NULL; +DECLARE_WAIT_QUEUE_HEAD(fullwait); int help_ccache=0; @@ -102,13 +102,26 @@ Cluster_head* find_in_ccache(struct super_block*sb, return NULL; } +int count_error_clusters(void) +{ int i; + int errs=0; + + for(i=0;ic_errors>MAX_ERRORS) + if(ch->c_errors>MAX_ERRORS||count_error_clusters()>MAX_ERROR_CLUSTERS) { /* get rid of the cluster to prevent dmsdos crash due to endless loops */ /* this shouldn't hurt much since the filesystem is already damaged */ printk(KERN_CRIT "DMSDOS: dirty cluster %d on dev 0x%x removed, data are lost\n", @@ -125,8 +138,8 @@ void handle_error_cluster(Cluster_head*ch) } } else - { printk(KERN_CRIT "DMSDOS: cannot write dirty cluster %d on dev 0x%x, trying again later\n", - ch->c_clusternr,ch->c_sb->s_dev); + { printk(KERN_CRIT "DMSDOS: cannot write dirty cluster %d on dev 0x%x c_error=%d, trying again later\n", + ch->c_clusternr,ch->c_sb->s_dev,ch->c_errors); } } @@ -452,7 +465,7 @@ void ccache_init() { ccache[i].c_flags=C_FREE; ccache[i].c_time=0; ccache[i].c_count=0; - ccache[i].c_sem=MUTEX; + init_MUTEX(&ccache[i].c_sem); ccache[i].c_errors=0; } } @@ -742,6 +755,7 @@ struct buffer_head* dblspace_bread(struct super_block*sb,int vsector) { err: printk(KERN_ERR "DMSDOS: illegal virtual sector %d, can't map to real sector\n", vsector); + *(int*)0=0; return NULL; } dbl_clust=((vsector-FAKED_DATA_START_OFFSET)/dblsb->s_sectperclust)+2; @@ -877,7 +891,7 @@ void dblspace_ll_rw_block ( #ifdef USE_READA_LIST -struct semaphore reada_sem=MUTEX; /* Must be initialized to green light */ +DECLARE_MUTEX(reada_sem); /* Must be initialized to green light */ void lock_reada(void) {down(&reada_sem);} void unlock_reada(void) {up(&reada_sem);} struct diff --git a/src/dcread.c b/src/dcread.c index 9c68f72..48b62e0 100644 --- a/src/dcread.c +++ b/src/dcread.c @@ -2,14 +2,40 @@ dcread.c +DMSDOS: example program illustrating how to use the dmsdos library. + +****************************************************************************** +DMSDOS (compressed MSDOS filesystem support) for Linux +written 1995-1998 by Frank Gockel and Pavel Pisa + + (C) Copyright 1995-1998 by Frank Gockel + (C) Copyright 1996-1998 by Pavel Pisa + +Some code of dmsdos has been copied from the msdos filesystem +so there are the following additional copyrights: + + (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem) + (C) Copyright 1994,1995 by Jacques Gelinas (mmap code) + (C) Copyright 1992-1995 by Linus Torvalds + +DMSDOS was inspired by the THS filesystem (a simple doublespace +DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann. + +The DMSDOS code is distributed under the Gnu General Public Licence. +See file COPYING for details. +****************************************************************************** + + This is an example how to use the dmsdos library. This program displays a cluster on the screen in one of several formats (hexdump, text, etc.). It can also search a file through the directories. +For documentation about the dmsdos library see file libdmsdos.doc. + Warning: This utility is not perfect. It does not check file end properly. -It does not even distinguish between files and directories. And the file -name conversion to 8.3 name space is far away from good. But example -code has never to be perfect :) +It does not even distinguish between files and directories. It does not +support long file names. And the file name conversion to 8.3 name space is +far away from good. But example code never has to be perfect :) There's also no documentation how to use this program except the usage line. Example code never has documentation. Well, yes, you are expected @@ -131,7 +157,7 @@ int display_cluster(int nr, int mode) pp=&(data[j+24]); x=CHS(pp); - printf(" %02d.%02d.%02d",x&31,(x>>5)&15,(x>>9)+80); + printf(" %02d.%02d.%04d",x&31,(x>>5)&15,(x>>9)+1980); /* y2k compliant :) */ pp=&(data[j+26]); printf(" %5d",CHS(pp)); @@ -207,6 +233,7 @@ int scan_dir(char*entry,int start) else for(i=0;i<11;++i) { if(*entry=='.'&&i<=7){i=7;++entry;continue;} + if(*entry=='.'&&i==8){i=7;++entry;continue;} if(*entry=='.')break; if(*entry=='\0')break; buf[i]=toupper(*entry); @@ -230,7 +257,7 @@ int scan_dir(char*entry,int start) size=i/32; next=dbl_fat_nextcluster(sb,start,NULL); if(next==0) - fprintf(stderr,"warning: cluster %d is maked as unused in FAT\n", + fprintf(stderr,"warning: cluster %d is marked as unused in FAT\n", next); } } diff --git a/src/dmsdos-config.default b/src/dmsdos-config.default index d8d5d7e..c402af5 100644 --- a/src/dmsdos-config.default +++ b/src/dmsdos-config.default @@ -57,7 +57,7 @@ IDMSDOSD_TIME=30 SP_BIT0=y SP_BIT1=y # SP_BIT2 is not set -SP_BIT3=y +# SP_BIT3 is not set SP_BIT4=y SP_BIT5=y # SP_BIT6 is not set diff --git a/src/dmsdos.h b/src/dmsdos.h index 6898579..5606f52 100644 --- a/src/dmsdos.h +++ b/src/dmsdos.h @@ -33,18 +33,43 @@ See file COPYING for details. #define LVC(x,y,z) ((x)*65536+(y)*256+(z)) #ifdef __KERNEL__ + #ifndef LINUX_VERSION_CODE -#include + #include +#endif +#if LINUX_VERSION_CODE == LVC(2,2,1) + /* this works around a bug in Linux 2.2.1 */ + #include +#endif #include #include +#if LINUX_VERSION_CODE < LVC(2,3,3) + #define init_MUTEX(sem) (*sem=MUTEX) + #define DECLARE_MUTEX(name) struct semaphore name=MUTEX + #define DECLARE_WAIT_QUEUE_HEAD(name) \ + struct wait_queue * name=NULL #endif #if LINUX_VERSION_CODE >= LVC(2,1,78) #define __FOR_KERNEL_2_1_80 - #if LINUX_VERSION_CODE >= LVC(2,1,80) - #define FAT_GET_CLUSTER - #else + #if LINUX_VERSION_CODE < LVC(2,1,80) #define READPAGE_DENTRY + #else + #define FAT_GET_CLUSTER + #if LINUX_VERSION_CODE < LVC(2,3,0) + #define READPAGE_INODE + #else + #if LINUX_VERSION_CODE < LVC(2,3,10) + #define READPAGE_FILE + #else + #define __FOR_KERNEL_2_3_10 + #if LINUX_VERSION_CODE >= LVC(2,3,30) + #define __FOR_KERNEL_2_3_30 + #define READPAGE_DENTRY + #define HAS_SB_CLUSTER_BITS + #endif + #endif + #endif #endif #endif #if (LINUX_VERSION_CODE >= LVC(2,1,0)) && (LINUX_VERSION_CODE < LVC(2,1,78)) @@ -59,46 +84,146 @@ See file COPYING for details. #include "dmsdos-config.h" /* hacks for new Configure */ +#ifndef DMSDOS_EXPERT +#define USE_VMALLOC +#define LISTSIZE 1024 +#define MDFATCACHESIZE 40 +#define DFATCACHESIZE 20 +#define BITFATCACHESIZE 10 +#define MAX_CACHE_TIME 60 +#define CCACHESIZE 64 +#define MAX_CCACHE_TIME 240 +#define MAX_READA 64 +#define USE_READA_LIST +#define READA_LIST_SIZE 256 +#define READA_THRESHOLD 4095 +#define DEFAULT_LOGLEVEL 0 +#define DEFAULT_CF 11 +#define DMSDOS_USE_READPAGE +#define IDMSDOSD_TIME 30 +#define SP_BIT0 /* never compress dir */ +#define SP_BIT1 /* never compress EMD */ +#define SP_BIT4 /* write-back caching */ +#define SP_BIT5 /* read-ahead */ +#define SP_BIT7 /* daemon compresses */ +#endif /* DMSDOS_EXPERT */ + #ifndef SP_BIT0 #define SP_BIT0 0 +#else +#undef SP_BIT0 +#define SP_BIT0 1 #endif + #ifndef SP_BIT1 #define SP_BIT1 0 +#else +#undef SP_BIT1 +#define SP_BIT1 1 #endif + #ifndef SP_BIT2 #define SP_BIT2 0 +#else +#undef SP_BIT2 +#define SP_BIT2 1 #endif + #ifndef SP_BIT3 #define SP_BIT3 0 +#else +#undef SP_BIT3 +#define SP_BIT3 1 #endif + #ifndef SP_BIT4 #define SP_BIT4 0 +#else +#undef SP_BIT4 +#define SP_BIT4 1 #endif + #ifndef SP_BIT5 #define SP_BIT5 0 +#else +#undef SP_BIT5 +#define SP_BIT5 1 #endif + #ifndef SP_BIT6 #define SP_BIT6 0 +#else +#undef SP_BIT6 +#define SP_BIT6 1 #endif + #ifndef SP_BIT7 #define SP_BIT7 0 +#else +#undef SP_BIT7 +#define SP_BIT7 1 #endif + #ifndef SP_BIT8 #define SP_BIT8 0 +#else +#undef SP_BIT8 +#define SP_BIT8 1 #endif + #ifndef DEFAULT_SPEEDUP -#define DEFAULT_SPEEDUP ((SP_BIT7<<7)|(SP_BIT6<<6)|(SP_BIT5<<5)|(SP_BIT4<<4)|(SP_BIT3<<3)|(SP_BIT2<<2)|(SP_BIT1<<1)|(SP_BIT0)) +#define DEFAULT_SPEEDUP ((SP_BIT8<<8)|(SP_BIT7<<7)|(SP_BIT6<<6)|(SP_BIT5<<5)|(SP_BIT4<<4)|(SP_BIT3<<3)|(SP_BIT2<<2)|(SP_BIT1<<1)|(SP_BIT0)) #endif #ifndef DEFAULT_COMP #define DEFAULT_COMP GUESS #endif +#ifndef LISTSIZE +#define LISTSIZE 1024 +#endif +#ifndef MDFATCACHESIZE +#define MDFATCACHESIZE 40 +#endif +#ifndef DFATCACHESIZE +#define DFATCACHESIZE 20 +#endif +#ifndef BITFATCACHESIZE +#define BITFATCACHESIZE 10 +#endif +#ifndef MAX_CACHE_TIME +#define MAX_CACHE_TIME 60 +#endif +#ifndef CCACHESIZE +#define CCACHESIZE 64 +#endif +#ifndef MAX_CCACHE_TIME +#define MAX_CCACHE_TIME 240 +#endif +#ifndef MAX_READA +#define MAX_READA 64 +#endif +#ifndef READA_LIST_SIZE +#define READA_LIST_SIZE 256 +#endif +#ifndef READA_THRESHOLD +#define READA_THRESHOLD 4095 +#endif +#ifndef DEFAULT_LOGLEVEL +#define DEFAULT_LOGLEVEL 0 +#endif +#ifndef DEFAULT_CF +#define DEFAULT_CF 11 +#endif +#ifndef IDMSDOSD_TIME +#define IDMSDOSD_TIME 30 +#endif + #define DMSDOS_MAJOR 0 #define DMSDOS_MINOR 9 -#define DMSDOS_ACT_REL 1 -#define DMSDOS_COMP_REL 1 -#define DMSDOS_PL "5" -#define DMSDOS_EXTRA "(beta test)" +#define DMSDOS_ACT_REL 2 +#define DMSDOS_COMP_REL 2 +#define DMSDOS_PL "2" +#define DMSDOS_EXTRA "(alpha test)" #define DMSDOS_VERSION ((DMSDOS_MAJOR<<16)|(DMSDOS_MINOR<<8)|DMSDOS_ACT_REL) #define DMSDOS_LOWEST_COMPATIBLE_VERSION ((DMSDOS_MAJOR<<16)|(DMSDOS_MINOR<<8)|DMSDOS_COMP_REL) @@ -212,7 +337,6 @@ typedef struct { int s_lastnear; int s_lastbig; int s_free_sectors; -/* struct semaphore mdfat_alloc_sem;*/ void * mdfat_alloc_semp; } Dblsb; @@ -279,8 +403,13 @@ int stac_replace_existing_cluster(struct super_block*sb, int cluster, Mdfat_entry*); int dbl_compress(unsigned char* clusterk, unsigned char* clusterd, int size, int method,int); +#if 0 int stac_compress(void* pin,int lin, void* pout, int lout, int method, int cfaktor); +#else +int stac_compress(unsigned char* pin,int lin, unsigned char* pout, int lout, + int method, int cfaktor); +#endif int sq_comp(void* pin,int lin, void* pout, int lout, int flg); int dbl_decompress(unsigned char*clusterd, unsigned char*clusterk, Mdfat_entry*mde); @@ -480,11 +609,21 @@ int dblspace_file_write(struct inode *inode,struct file *filp,const char *buf, int dblspace_mmap(struct inode*inode,struct file*file, struct vm_area_struct*vma); #endif + #ifdef READPAGE_DENTRY -int dblspace_readpage(struct dentry*dentry, struct page *page); + int dblspace_readpage(struct dentry*dentry, struct page *page); #else -int dblspace_readpage(struct inode *inode, struct page *page); + #ifdef READPAGE_FILE + int dblspace_readpage(struct file *file, struct page *page); + #else + #ifdef READPAGE_INODE + int dblspace_readpage(struct inode *inode, struct page *page); + #else + #error Unknown readpage parameters + #endif + #endif #endif + int dmsdos_ioctl_dir(struct inode *dir,struct file *filp, unsigned int cmd, unsigned long data); #endif /* __KERNEL__ */ diff --git a/src/dmsdosfsck.c b/src/dmsdosfsck.c index 879ac75..8e66b7f 100644 --- a/src/dmsdosfsck.c +++ b/src/dmsdosfsck.c @@ -2,7 +2,28 @@ dmsdosfsck.c -Uhh... Warning this is very experimental code ... :)) +DMSDOS: filesystem check utility for CVFs. + +****************************************************************************** +DMSDOS (compressed MSDOS filesystem support) for Linux +written 1995-1998 by Frank Gockel and Pavel Pisa + + (C) Copyright 1995-1998 by Frank Gockel + (C) Copyright 1996-1998 by Pavel Pisa + +Some code of dmsdos has been copied from the msdos filesystem +so there are the following additional copyrights: + + (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem) + (C) Copyright 1994,1995 by Jacques Gelinas (mmap code) + (C) Copyright 1992-1995 by Linus Torvalds + +DMSDOS was inspired by the THS filesystem (a simple doublespace +DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann. + +The DMSDOS code is distributed under the Gnu General Public Licence. +See file COPYING for details. +****************************************************************************** */ @@ -220,7 +241,7 @@ int check_direntry(int dirstartclust, unsigned char*data, int*need_write, unsigned int x; unsigned char*pp; unsigned long size; - int cluster; + int cluster, prevcluster, newval; unsigned long fatsize; int clustersize; int invchar; @@ -255,7 +276,7 @@ int check_direntry(int dirstartclust, unsigned char*data, int*need_write, pp=&(data[24]); x=CHS(pp); - printf(" %02d.%02d.%02d",x&31,(x>>5)&15,(x>>9)+80); + printf(" %02d.%02d.%4d",x&31,(x>>5)&15,(x>>9)+1980); /* y2k compliant :) */ } pp=&(data[26]); @@ -378,21 +399,28 @@ int check_direntry(int dirstartclust, unsigned char*data, int*need_write, return 0; } + clustersize=dblsb->s_sectperclust*SECTOR_SIZE; + fatsize=0; + prevcluster=0; while(cluster>1&&cluster<=dblsb->s_max_cluster) - { cluster=dbl_fat_nextcluster(sb,cluster,NULL); - fatsize+=dblsb->s_sectperclust*SECTOR_SIZE; + { prevcluster=cluster; + cluster=dbl_fat_nextcluster(sb,cluster,NULL); + fatsize+=clustersize; } if(cluster==0) { printf("fat alloc ends with zero\n"); - return -1; + cluster=prevcluster; + fatsize-=clustersize; + if(repair("Correct this?")==0)return -1; + newval=FAT_EOF; + dbl_fat_nextcluster(sb,cluster,&newval); } - if(cluster==1&&cluster>dblsb->s_max_cluster) + if(cluster==1||cluster>dblsb->s_max_cluster) { printf("fat alloc invalid\n"); return -1; } - clustersize=dblsb->s_sectperclust*SECTOR_SIZE; if(size==fatsize) { lprintf("OK\n"); return 0; @@ -539,7 +567,7 @@ int main(int argc, char*argv[]) int i; char*filename=NULL; - fprintf(stderr, "dmsdosfsck 0.0.1 ALPHA TEST (be extremely careful with repairs)\n"); + fprintf(stderr, "dmsdosfsck 0.0.2 ALPHA TEST (be extremely careful with repairs)\n"); if(argc==1) { usage: diff --git a/src/dstacker_alloc.c b/src/dstacker_alloc.c index 8078b6b..a0b3762 100644 --- a/src/dstacker_alloc.c +++ b/src/dstacker_alloc.c @@ -55,7 +55,6 @@ See file COPYING for details. #include #endif - #ifdef DMSDOS_CONFIG_STAC /* initializes Stac_cwalk structure, which can be used for sequential diff --git a/src/dstacker_compr.c b/src/dstacker_compr.c index 51b5c0f..ae7d8b6 100644 --- a/src/dstacker_compr.c +++ b/src/dstacker_compr.c @@ -56,8 +56,6 @@ See file COPYING for details. #include #include #include -#include -#include #endif @@ -74,6 +72,13 @@ See file COPYING for details. int printk(const char * fmt, ...) __attribute__ ((format (printf, 1, 2))); #endif +#ifdef __GNUC__ +#define INLINE static inline +#else +/* non-gnu compilers may not like inline */ +#define INLINE static +#endif + #define MAX(a,b) (((a) > (b)) ? (a) : (b)) @@ -96,9 +101,9 @@ __asm__ /*__volatile__*/(\ :"0" (D),"1" (S),"2" (C) \ ) -static inline __u16 swap_bytes_in_word(__u16 x) +INLINE __u16 swap_bytes_in_word(__u16 x) { - __asm__("xchgb %b0,%h0" /* swap bytes */ + __asm__("xchgb %b0,%h0" /* swap bytes */ : "=q" (x) : "0" (x)); return x; @@ -106,12 +111,15 @@ static inline __u16 swap_bytes_in_word(__u16 x) #else +#ifdef __GNUC__ +/* non-gnu compilers may not like warning directive */ #warning USE_GNU_ASM_I386 not defined, using "C" equivalent +#endif #define M_FIRSTDIFF(D,S,C) for(;(*(__u8*)(D)==*(__u8*)(S))&&(C);\ - (__u8*)(D)++,(__u8*)(S)++,(C)--) + (__u8*)(D)++,(__u8*)(S)++,(C)--) -static inline __u16 swap_bytes_in_word(__u16 x) +INLINE __u16 swap_bytes_in_word(__u16 x) { return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8); } @@ -134,15 +142,13 @@ static inline __u16 swap_bytes_in_word(__u16 x) #define C_ST_u16(p,v) {put_unaligned(v,((__u16*)p)++);} #define C_LD_u16(p,v) {v=get_unaligned(((__u16*)p)++);} -#define INLINE static inline - /* for reading and writting from/to bitstream */ typedef struct { - __u32 buf; /* bit buffer */ - int pb; /* not read bits count in buffer */ - __u16 *pd; /* first not readed input data */ - __u16 *pe; /* after end of data */ + __u32 buf; /* bit buffer */ + int pb; /* not read bits count in buffer */ + __u16 *pd; /* first not readed input data */ + __u16 *pe; /* after end of data */ } bits_t; /*************************************************************************/ @@ -159,8 +165,8 @@ typedef typedef struct { - __u16 cod[0x180]; /* characters codes */ - __u8 ln[0x180]; /* characters lens */ + __u16 cod[0x180]; /* characters codes */ + __u8 ln[0x180]; /* characters lens */ }huf_wr_t; #ifdef MAX_COMP @@ -274,7 +280,7 @@ unsigned sd4_complz(void* pin,int lin,void* pout,int lout,int flg,count_t* ch_cn /* printk("There we are,work_mem=%X hash_hist=%X pin=%X lin=%X pend=%X pout=%X\n", - work_mem,hash_hist,pin,lin,pend,pout); + work_mem,hash_hist,pin,lin,pend,pout); */ if(lout<0x20) goto return_error; /* some minimal space for lz interform buffer */ @@ -320,7 +326,7 @@ unsigned sd4_complz(void* pin,int lin,void* pout,int lout,int flg,count_t* ch_cn { delay_best=0; while((delay_cn=0xAA0) break; /* longer offsets are not allowed */ if((hash_cur[0]==pi[0])&&(hash_cur[1]==pi[1])&& - /* pi[2]=hash_cur[2] from hash function */ - (hash_cur[max_match-1]==pi[max_match-1])&& - (hash_cur[max_match]==pi[max_match])&& - (hash_cur!=max_hash+delay_cn-delay_best)) + /* pi[2]=hash_cur[2] from hash function */ + (hash_cur[max_match-1]==pi[max_match-1])&& + (hash_cur[max_match]==pi[max_match])&& + (hash_cur!=max_hash+delay_cn-delay_best)) { /* do not test actual max match */ - match=pend-pi; /* length of rest of data */ - pd=pi+2; - pc=hash_cur+2; - M_FIRSTDIFF(pd,pc,match);/* compare */ - match=pd-pi; /* found match length */ - if((match>max_match+delay_cn)&&((match>=6)||(pi-hash_cur<0x800))) - { - max_hash=hash_cur;max_match=match; /* find maximal hash */ - delay_best=delay_cn; - if(pd>pend+1)break; /* match to end of block */ - }; + match=pend-pi; /* length of rest of data */ + pd=pi+2; + pc=hash_cur+2; + M_FIRSTDIFF(pd,pc,match);/* compare */ + match=pd-pi; /* found match length */ + if((match>max_match+delay_cn)&&((match>=6)||(pi-hash_cur<0x800))) + { + max_hash=hash_cur;max_match=match; /* find maximal hash */ + delay_best=delay_cn; + if(pd>pend+1)break; /* match to end of block */ + }; }; pc=hash_cur; }while(--try_cn&&((hash_cur=hash_hist[(unsigned)pc&hash_mask])s_full==0 && - /* well, this is estimated */ - dblsb->s_sectperclust*CCACHESIZE+100s_free_sectors + /* well, this is estimated */ + dblsb->s_sectperclust*CCACHESIZE+100s_free_sectors ) return 0; else return -ENOSPC; } @@ -1075,13 +1087,13 @@ int stac_write_cluster(struct super_block*sb, { /* raw compressed data from daemon */ length=-ucflag; method=UNCOMPRESSED^1; /* not uncompressed */ /* is this correct ??? */ - /* Hi Pavel, - Please check the code whether it works - correctly for daemon writes. I think this may - cause a FREE(data not to free) at the very - end. I added a ucflag>=0 test there to avoid - the problem. - */ + /* Hi Pavel, + Please check the code whether it works + correctly for daemon writes. I think this may + cause a FREE(data not to free) at the very + end. I added a ucflag>=0 test there to avoid + the problem. + */ clusterk=clusterd; } else if(method!=UNCOMPRESSED) @@ -1093,10 +1105,10 @@ int stac_write_cluster(struct super_block*sb, else { /* We test possible compression */ /* stacker needs length before compression to be - multiple of SECTOR_SIZE */ + multiple of SECTOR_SIZE */ if(((i=length%SECTOR_SIZE)!=0)||!length) { memset(clusterd+length,0,SECTOR_SIZE-i); - i=length+SECTOR_SIZE-i; + i=length+SECTOR_SIZE-i; } else i=length; cfaktor=dblsb->s_cfaktor; @@ -1104,25 +1116,25 @@ int stac_write_cluster(struct super_block*sb, if(method==SD_4) { LOG_CLUST("DMSDOS: stac_write_cluster: compressing sd4...\n"); - i=sd4_comp(clusterd,i,clusterk,max_clen,comp_rat_tab[cfaktor]); - LOG_CLUST("DMSDOS: stac_write_cluster: compressing finished\n"); + i=sd4_comp(clusterd,i,clusterk,max_clen,comp_rat_tab[cfaktor]); + LOG_CLUST("DMSDOS: stac_write_cluster: compressing finished\n"); } else if(method==SD_3) { LOG_CLUST("DMSDOS: stac_write_cluster: compressing sd3...\n"); - i=sd3_comp(clusterd,i,clusterk,max_clen,comp_rat_tab[cfaktor]); - LOG_CLUST("DMSDOS: stac_write_cluster: compressing finished\n"); + i=sd3_comp(clusterd,i,clusterk,max_clen,comp_rat_tab[cfaktor]); + LOG_CLUST("DMSDOS: stac_write_cluster: compressing finished\n"); } else if(method==DS_0_0) { LOG_CLUST("DMSDOS: stac_write_cluster: compressing ds00...\n"); - i=dbl_compress(clusterk,clusterd,(i+511)/512,method,cfaktor)*512; - LOG_CLUST("DMSDOS: stac_write_cluster: compressing finished\n"); + i=dbl_compress(clusterk,clusterd,(i+511)/512,method,cfaktor)*512; + LOG_CLUST("DMSDOS: stac_write_cluster: compressing finished\n"); } else i=0; LOG_CLUST("DMSDOS: Cluster %i compressed from %i to %i\n",clusternr,length,i); if((i<=0)||(i>=length)||(i>max_clen-SECTOR_SIZE)) { method=UNCOMPRESSED; - FREE(clusterk); + FREE(clusterk); } else length=i; } @@ -1133,7 +1145,7 @@ int stac_write_cluster(struct super_block*sb, val=stac_cwalk_init(&cw,sb,clusternr,3); if (val<0) { printk(KERN_ERR "DMSDOS: stac_write_cluster: alloc error in cluster %d\n", - clusternr); + clusternr); res=-EIO; goto error_return; }; @@ -1154,24 +1166,24 @@ int stac_write_cluster(struct super_block*sb, mde.size_hi_minus_1=size-1; if(method==UNCOMPRESSED) if(size==dblsb->s_sectperclust) - mde.flags=2; + mde.flags=2; else - mde.flags=0x23; + mde.flags=0x23; else mde.flags=2; LOG_CLUST("DMSDOS: stac_write_cluster: Replace size %2i flg 0x%02X cluster %i\n", - size,mde.flags,clusternr); + size,mde.flags,clusternr); sect=stac_replace_existing_cluster(sb,clusternr,near_sector,&mde); LOG_CLUST("DMSDOS: stac_write_cluster: stac_replace_existing_cluster returned %d\n", - sect); + sect); if(sect<0) {res=-ENOSPC;goto error_return;}; val=stac_cwalk_init(&cw,sb,clusternr,3); if ((val<0)||(length>cw.bytes_in_clust)) { printk(KERN_ERR "DMSDOS: stac_write_cluster: alloc error in cluster %d\n", - clusternr); + clusternr); res=-EIO; goto error_return; }; @@ -1184,23 +1196,23 @@ int stac_write_cluster(struct super_block*sb, if(bh==NULL)res=-EIO; else { if(count+cw.bytes>cw.bytes_in_clust) - { printk(KERN_ERR "DMSDOS: stac_write_cluster: internal cw error 1 cluster=%d\n", - clusternr); - raw_brelse(sb,bh); - stac_cwalk_done(&cw); - goto error_return; - }; - if(count+cw.bytes<=length) - memcpy(bh->b_data+cw.offset,clusterk+count,cw.bytes); - else - { if((i=length-count)>0) - { memcpy(bh->b_data+cw.offset,clusterk+count,i); - memset(bh->b_data+cw.offset+i,0,cw.bytes-i); - } else memset(bh->b_data+cw.offset,0,cw.bytes); - }; - raw_set_uptodate(sb,bh,1);/*getblk needs this*/ - raw_mark_buffer_dirty(sb,bh,1); - raw_brelse(sb,bh); + { printk(KERN_ERR "DMSDOS: stac_write_cluster: internal cw error 1 cluster=%d\n", + clusternr); + raw_brelse(sb,bh); + stac_cwalk_done(&cw); + goto error_return; + }; + if(count+cw.bytes<=length) + memcpy(bh->b_data+cw.offset,clusterk+count,cw.bytes); + else + { if((i=length-count)>0) + { memcpy(bh->b_data+cw.offset,clusterk+count,i); + memset(bh->b_data+cw.offset+i,0,cw.bytes-i); + } else memset(bh->b_data+cw.offset,0,cw.bytes); + }; + raw_set_uptodate(sb,bh,1);/*getblk needs this*/ + raw_mark_buffer_dirty(sb,bh,1); + raw_brelse(sb,bh); }; count+=cw.bytes; } @@ -1208,7 +1220,7 @@ int stac_write_cluster(struct super_block*sb, stac_cwalk_done(&cw); if((count=0)FREE(clusterk); diff --git a/src/dstacker_dec.c b/src/dstacker_dec.c index 03d5b9a..28ded1c 100644 --- a/src/dstacker_dec.c +++ b/src/dstacker_dec.c @@ -59,9 +59,14 @@ See file COPYING for details. #include #include #include -#include #endif +#ifdef __GNUC__ +#define INLINE static inline +#else +/* non-gnu compilers may not like inline */ +#define INLINE static +#endif #ifdef DMSDOS_CONFIG_STAC @@ -79,7 +84,7 @@ __asm__ /*__volatile__*/(\ :"0" (D),"1" (S),"2" (C) \ :"memory") -static inline __u16 swap_bytes_in_word(__u16 x) +INLINE __u16 swap_bytes_in_word(__u16 x) { __asm__("xchgb %b0,%h0" /* swap bytes */ : "=q" (x) @@ -90,11 +95,14 @@ static inline __u16 swap_bytes_in_word(__u16 x) #else +#ifdef __GNUC__ +/* non-gnu compilers may not like warning directive */ #warning USE_GNU_ASM_I386 not defined, using "C" equivalent +#endif #define M_MOVSB(D,S,C) for(;(C);(C)--) *((__u8*)(D)++)=*((__u8*)(S)++) -static inline __u16 swap_bytes_in_word(__u16 x) +INLINE __u16 swap_bytes_in_word(__u16 x) { return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8); } @@ -107,8 +115,6 @@ static inline __u16 swap_bytes_in_word(__u16 x) #define be16_to_cpu(v) (swap_bytes_in_word(v)) #endif -#define INLINE static inline - /***************************************************************************/ /***************************************************************************/ /********* begin code from sd3_bs0.c ***************************************/ diff --git a/src/dutil.c b/src/dutil.c index e8a7ea1..aa30db4 100644 --- a/src/dutil.c +++ b/src/dutil.c @@ -51,7 +51,7 @@ void error(void) exit(); } -void main(int argc, char*argv[]) +int main(int argc, char*argv[]) { Dblsb dblsb; int fd; int ret; @@ -89,13 +89,13 @@ void main(int argc, char*argv[]) printf(" %s (directory) checkfs [(repair)]\n",argv[0]); printf(" %s (directory) setloglevel (value)\n",argv[0]); printf(" %s (directory) setspeedup (value)\n",argv[0]); - return; + return 0; } fd=open(argv[1],O_RDONLY); if(fd<0) { perror(argv[1]); - return; + return 2; } /* this hack enables reverse version check */ @@ -107,7 +107,7 @@ void main(int argc, char*argv[]) if(ret<0) { printf("This is not a DMSDOS directory.\n"); close(fd); - return; + return 2; } printf("You are running DMSDOS driver version %d.%d.%d.\n",(ret&0xff0000)>>16, (ret&0x00ff00)>>8,ret&0xff); @@ -117,12 +117,12 @@ void main(int argc, char*argv[]) if(ret&0x0f000000) { printf("\nSorry, this utility is too old for the actual DMSDOS driver version.\n"); close(fd); - return; + return 2; } - if(ret<0x00000901) - { printf("\nSorry, this utility requires at least DMSDOS driver version 0.9.1.\n"); + if(ret<0x00000902) + { printf("\nSorry, this utility requires at least DMSDOS driver version 0.9.2.\n"); close(fd); - return; + return 2; } if(ret!=DMSDOS_VERSION)printf(" but should still work.\n\n"); else printf("\n"); @@ -150,13 +150,13 @@ void main(int argc, char*argv[]) { if(ioctl(fd,DMSDOS_DUMPCACHE,w)<0)error(); printf("Cache status written to syslog.\n"); close(fd); - return; + return 0; } if(strcmp(argv[2],"logstat")==0) { if(ioctl(fd,DMSDOS_LOG_STATISTICS,w)<0)error(); printf("Statistics written to syslog.\n"); close(fd); - return; + return 0; } if(strcmp(argv[2],"memory")==0) { if(ioctl(fd,DMSDOS_REPORT_MEMORY,w)<0)error(); @@ -165,7 +165,7 @@ void main(int argc, char*argv[]) if(w[1]>0)printf("%8ld (estimated)\n",w[1]); else printf(" -unknown- \n"); printf("Buffer cache: %8ld maximum: %8ld\n",w[2],w[3]); - return; + return 0; } } @@ -186,14 +186,14 @@ void main(int argc, char*argv[]) printf("The filesystem has been set to read-only mode.\n"); } close(fd); - return; + return 0; } if(strcmp(argv[2],"synccache")==0) { printf("Syncing cluster cache....be patient, this may take some time...\n"); if(ioctl(fd,DMSDOS_SYNC_CCACHE,(argc==4) ? scan(argv[3]) : 0)<0)error(); printf("Cluster cache synced.\n"); close(fd); - return; + return 0; } } @@ -415,5 +415,5 @@ void main(int argc, char*argv[]) else printf("??? syntax error in command line.\n"); close(fd); - + return 0; } diff --git a/src/lib_interface.c b/src/lib_interface.c index 855556c..3ff6796 100644 --- a/src/lib_interface.c +++ b/src/lib_interface.c @@ -29,13 +29,15 @@ See file COPYING for details. #include #include #include -#include -#include +#ifdef USE_FLOCK #include -#include #include -#include -#include +#endif +#ifdef USE_SOPEN +#include +#endif +#include +#include #define fat_boot_sector msdos_boot_sector @@ -54,10 +56,12 @@ See file COPYING for details. #include"dmsdos.h" -#define CF_LE_W(v) (v) -#define CF_LE_L(v) (v) -#define CT_LE_W(v) (v) -#define CT_LE_L(v) (v) +#ifndef cpu_to_le16 +/* works only for old kernels and little endian architecture */ +#define cpu_to_le16(v) (v) +#define cpu_to_le32(v) (v) +#endif + #define MSDOS_FAT12 4078 /* maximum number of clusters in a 12 bit FAT */ long int blk_size[1][1]; @@ -76,7 +80,7 @@ int printk(const char *fmt, ...) int i; va_start(ap, fmt); - i=vsnprintf(buf, 500, fmt, ap); + i=vsprintf(buf,fmt,ap); va_end(ap); if(p[0]=='<'&&p[1]>='0'&&p[1]<='7'&&p[2]=='>')p+=3; @@ -92,7 +96,7 @@ void panic(const char *fmt, ...) int i; va_start(ap, fmt); - i=vsnprintf(buf, 500, fmt, ap); + i=vsprintf(buf,fmt,ap); va_end(ap); fprintf(stderr,"libdmsdos panic: %s",buf); @@ -100,24 +104,61 @@ void panic(const char *fmt, ...) exit(1); } +int translate_direct(struct super_block*sb,int block) +{ int i; + + if(block>=sb->directsize) + { printk("DMSDOS: access beyond end of CVF in direct mode (wanted=%d limit=%d)\n", + block,sb->directsize-1); + return 0; + } + + /* calculate physical sector */ + i=0; + do + { block-=sb->directlen[i]; + ++i; + } + while(block>=0&&idirectlen[i]+sb->directlist[i]; + return block; +} + struct buffer_head* raw_bread(struct super_block*sb,int block) { struct buffer_head*bh; int fd=sb->s_dev; - if(lseek(fd,block*512,SEEK_SET)<0)return NULL; + if(sb->directlist) + { block=translate_direct(sb,block); + if(!block) + { printk("raw_bread: translate_direct failed\n"); + return NULL; + } + } + + if(lseek(fd,block*512,SEEK_SET)<0) + { printk("raw_bread: lseek block %d failed: %s\n",block,strerror(errno)); + return NULL; + } bh=malloc(sizeof(struct buffer_head)); - if(bh==NULL)return NULL; + if(bh==NULL) + { printk("raw_bread: malloc(%d) failed\n",sizeof(struct buffer_head)); + return NULL; + } bh->b_data=malloc(512); if(bh->b_data==NULL) { free(bh); + printk("raw_bread: malloc(512) failed\n"); return NULL; } bh->b_blocknr=block; - if(read(fd,bh->b_data,512)==512)return bh; - + if(read(fd,bh->b_data,512)>=0)return bh; + + printk("raw_bread: read failed: %s\n",strerror(errno)); free(bh->b_data); free(bh); @@ -128,7 +169,15 @@ struct buffer_head* raw_getblk(struct super_block*sb,int block) { struct buffer_head*bh; int fd=sb->s_dev; - if(lseek(fd,block*512,SEEK_SET)<0)return NULL; + if(sb->directlist) + { block=translate_direct(sb,block); + if(!block)return NULL; + } + + if(lseek(fd,block*512,SEEK_SET)<0) + { printk("raw_getblk: lseek block %d failed: %s\n",block,strerror(errno)); + return NULL; + } bh=malloc(sizeof(struct buffer_head)); if(bh==NULL)return NULL; @@ -157,17 +206,19 @@ void raw_mark_buffer_dirty(struct super_block*sb,struct buffer_head*bh,int dirty if(dirty_val==0)return; if(bh==NULL)return; - + +#ifdef DBL_WRITEACCESS + if(lseek(fd,bh->b_blocknr*512,SEEK_SET)<0) - { printf("can't seek block %ld\n",bh->b_blocknr); + { printk("can't seek block %ld: %s\n",bh->b_blocknr,strerror(errno)); return; } + + if(write(fd,bh->b_data,512)<0) + printk("writing block %ld failed: %s\n",bh->b_blocknr,strerror(errno)); -#ifdef DBL_WRITEACCESS - if(write(fd,bh->b_data,512)!=512) - printf("writing block %ld failed\n",bh->b_blocknr); #else - fprintf(stderr,"DMSDOS: write access not compiled in, ignored\n"); + printk("DMSDOS: write access not compiled in, ignored\n"); #endif } @@ -179,23 +230,201 @@ int try_daemon(struct super_block*sb,int clusternr, int length, int method) { return 0; } +int host_fat_lookup(struct super_block *sb,int nr) +{ + struct buffer_head *bh,*bh2; + unsigned char *p_first,*p_last; + int first,last,next,b; + + if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters) + return 0; + if (MSDOS_SB(sb)->fat_bits == 16) { + first = last = nr*2; + } else { + first = nr*3/2; + last = first+1; + } + b = MSDOS_SB(sb)->fat_start + (first >> SECTOR_BITS); + if (!(bh = raw_bread(sb, b))) { + printk("DMSDOS: bread in host_fat_access failed\n"); + return 0; + } + if ((first >> SECTOR_BITS) == (last >> SECTOR_BITS)) { + bh2 = bh; + } else { + if (!(bh2 = raw_bread(sb, b+1))) { + raw_brelse(sb, bh); + printk("DMSDOS: 2nd bread in host_fat_lookup failed\n"); return 0; + } + } + if (MSDOS_SB(sb)->fat_bits == 16) { + p_first = p_last = NULL; /* GCC needs that stuff */ + next = cpu_to_le16(((unsigned short *) bh->b_data)[(first & + (SECTOR_SIZE-1)) >> 1]); + if (next >= 0xfff7) next = -1; + } + else { + p_first = &((unsigned char *) bh->b_data)[first & (SECTOR_SIZE-1)]; + p_last = &((unsigned char *) bh2->b_data)[(first+1) & + (SECTOR_SIZE-1)]; + if (nr & 1) next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff; + else next = (*p_first+(*p_last << 8)) & 0xfff; + if (next >= 0xff7) next = -1; + } + + raw_brelse(sb, bh); + if (bh != bh2) + raw_brelse(sb, bh2); + return next; +} + +int dos_cluster2sector(struct super_block * sb,int clusternr) +{ return (clusternr-2)*MSDOS_SB(sb)->cluster_size+MSDOS_SB(sb)->data_start; +} + +int setup_fragment(struct super_block*sb, int startcluster) +{ int fragmentzaehler; + int clusterzaehler; + int akt_cluster; + int folge_cluster; + int i; + unsigned long* directlist; + unsigned long* directlen; + + LOG_REST("DMSDOS: setup_fragment\n"); + + directlist=malloc(sizeof(unsigned long)*(MAXFRAGMENT+1)); + if(directlist==NULL) + { printk("DMSDOS: out of memory (directlist)\n"); + return -1; + } + directlen=malloc(sizeof(unsigned long)*(MAXFRAGMENT+1)); + if(directlen==NULL) + { printk("DMSDOS: out of memory (directlen)\n"); + free(directlist); + return -1; + } + + fragmentzaehler=0; + + folge_cluster=startcluster; + + do + { + clusterzaehler=0; + directlist[fragmentzaehler]=folge_cluster; + do + { akt_cluster=folge_cluster; + folge_cluster=host_fat_lookup(sb,akt_cluster); + ++clusterzaehler; + } + while(folge_cluster==akt_cluster+1); + + directlen[fragmentzaehler]=clusterzaehler; + LOG_REST("DMSDOS: firstclust=%d anz=%d\n", + directlist[fragmentzaehler], + directlen[fragmentzaehler]); + + ++fragmentzaehler; + } + while(folge_cluster>0&&fragmentzaehler0) + { /* zu fragmentiert, raus */ + free(directlist); + free(directlen); + printk("DMSDOS: CVF too fragmented, not mounted.\n"); + printk("Increase MAXFRAGMENT in lib_interface.h and recompile.\n"); + return -1; + } + printk("DMSDOS: CVF has %d fragment(s)\n",fragmentzaehler); + + /* convert cluster-oriented numbers into sector-oriented ones */ + for(i=0;icluster_size; + /*printk("DMSDOS: umrechnen 3\n");*/ + } + + /* hang in */ + sb->directlist=directlist; + sb->directlen=directlen; + + return 0; +} + +int setup_translation(struct super_block*sb,char*ext) +{ int i,j,testvers; + struct buffer_head* bh; + struct msdos_dir_entry* data; + char cvfname[20]; + + /* scan the root directory for a CVF */ + + for(i=0;idir_entries/MSDOS_DPS;++i) + { bh=raw_bread(sb,MSDOS_SB(sb)->dir_start+i); + if(bh==NULL) + { printk("DMSDOS: unable to read msdos root directory\n"); + return -1; + } + data=(struct msdos_dir_entry*) bh->b_data; + + for(j=0;j='0'&&data[j].name[8]<='9' + &&data[j].name[9]>='0'&&data[j].name[9]<='9' + &&data[j].name[10]>='0'&&data[j].name[10]<='9' + ) | (testvers==2&&strncmp(data[j].name+8,"DSK",3)==0) + ) + { /* it is a CVF */ + strncpy(cvfname,data[j].name,9-testvers); + cvfname[9-testvers]='\0'; + strcat(cvfname,"."); + strncat(cvfname,data[j].ext,3); + printk("DMSDOS: CVF %s in root directory found.\n",cvfname); + if(ext) + { if(strncmp(ext,data[j].ext,3)!=0)continue; + } + if(setup_fragment(sb,data[j].start)==0) + { sb->directsize=data[j].size/SECTOR_SIZE; + blk_size[0][0]=(data[j].size%1024)?(data[j].size/1024)+1: + data[j].size/1024; + raw_brelse(sb,bh); + printk("DMSDOS: using CVF %s.\n",cvfname); + return 0; + } + } + } + } + raw_brelse(sb,bh); + } + return -1; +} + /*okay, first thing is setup super block*/ /* stolen from fatfs */ /* Read the super block of an MS-DOS FS. */ -struct super_block *read_super(struct super_block *sb) +struct super_block *read_super(struct super_block *sb,char*ext) { struct buffer_head *bh; struct fat_boot_sector *b; int data_sectors,logical_sector_size,sector_mult,fat_clusters=0; int debug=0,error,fat=0; int blksize = 512; - int i; + int i=-1; + int mt=0; char cvf_options[101]="bitfaterrs=nocheck"; MSDOS_SB(sb)->cvf_format=NULL; MSDOS_SB(sb)->private_data=NULL; + retry: blksize = 512; bh = raw_bread(sb, 0); @@ -225,22 +454,22 @@ struct super_block *read_super(struct super_block *sb) /* don't divide by zero */ logical_sector_size = - CF_LE_W(get_unaligned((unsigned short *) &b->sector_size)); + cpu_to_le16(get_unaligned((unsigned short *) &b->sector_size)); sector_mult = logical_sector_size >> SECTOR_BITS; MSDOS_SB(sb)->cluster_size = b->cluster_size*sector_mult; MSDOS_SB(sb)->fats = b->fats; - MSDOS_SB(sb)->fat_start = CF_LE_W(b->reserved)*sector_mult; - MSDOS_SB(sb)->fat_length = CF_LE_W(b->fat_length)*sector_mult; - MSDOS_SB(sb)->dir_start = (CF_LE_W(b->reserved)+b->fats*CF_LE_W( + MSDOS_SB(sb)->fat_start = cpu_to_le16(b->reserved)*sector_mult; + MSDOS_SB(sb)->fat_length = cpu_to_le16(b->fat_length)*sector_mult; + MSDOS_SB(sb)->dir_start = (cpu_to_le16(b->reserved)+b->fats*cpu_to_le16( b->fat_length))*sector_mult; MSDOS_SB(sb)->dir_entries = - CF_LE_W(get_unaligned((unsigned short *) &b->dir_entries)); + cpu_to_le16(get_unaligned((unsigned short *) &b->dir_entries)); MSDOS_SB(sb)->data_start = MSDOS_SB(sb)->dir_start+ROUND_TO_MULTIPLE(( MSDOS_SB(sb)->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS, sector_mult); - data_sectors = CF_LE_W(get_unaligned((unsigned short *) &b->sectors)); + data_sectors = cpu_to_le16(get_unaligned((unsigned short *) &b->sectors)); if (!data_sectors) { - data_sectors = CF_LE_L(b->total_sect); + data_sectors = cpu_to_le32(b->total_sect); } data_sectors = data_sectors * sector_mult - MSDOS_SB(sb)->data_start; error = !b->cluster_size || !sector_mult; @@ -259,6 +488,9 @@ struct super_block *read_super(struct super_block *sb) */ } raw_brelse(sb, bh); + + if(error)goto c_err; + /* This must be done after the brelse because the bh is a dummy allocated by fat_bread (see buffer.c) @@ -268,20 +500,29 @@ struct super_block *read_super(struct super_block *sb) /* because clusters (DOS) are often aligned */ /* on odd sectors. */ sb->s_blocksize_bits = blksize == 512 ? 9 : 10; - i=-1; + i=0; + #ifdef DMSDOS_CONFIG_DBL - if(i<0) + if(i==0) { i=detect_dblspace(sb); - if(i>=0)i=mount_dblspace(sb,cvf_options); + if(i>0){mt++;i=mount_dblspace(sb,cvf_options);} } #endif #ifdef DMSDOS_CONFIG_STAC - if(i<0) - { i=detect_stacker(sb); - if(i>=0)i=mount_stacker(sb,cvf_options); - } + if(i==0) + { i=detect_stacker(sb); + if(i>0){mt++;i=mount_stacker(sb,cvf_options);} + } #endif - error=i; + if(mt==0) + { /* looks like a real msdos filesystem */ + printk("DMSDOS: trying to find CVF inside host MSDOS filesystem...\n"); + i=setup_translation(sb,ext); + ++mt; + if(i==0)goto retry; + } + error=i; + c_err: if (error || debug) { /* The MSDOS_CAN_BMAP is obsolete, but left just to remember */ printk("MS-DOS FS Rel. 12 (hacked for libdmsdos), FAT %d\n", @@ -291,11 +532,11 @@ struct super_block *read_super(struct super_block *sb) MSDOS_SB(sb)->fats,MSDOS_SB(sb)->fat_start,MSDOS_SB(sb)->fat_length, MSDOS_SB(sb)->dir_start,MSDOS_SB(sb)->dir_entries, MSDOS_SB(sb)->data_start, - CF_LE_W(*(unsigned short *) &b->sectors), + cpu_to_le16(*(unsigned short *) &b->sectors), (unsigned long)b->total_sect,logical_sector_size); printk ("Transaction block size = %d\n",blksize); } - if(i<0) if (MSDOS_SB(sb)->clusters+2 > fat_clusters) + if(!error&&i<0) if (MSDOS_SB(sb)->clusters+2 > fat_clusters) MSDOS_SB(sb)->clusters = fat_clusters-2; if (error) { printk("Can't find a valid MSDOS CVF filesystem\n"); @@ -341,45 +582,27 @@ void do_lib_init(void) /* first call of DMSDOS library, initialising variables */ - fprintf(stderr,"DMSDOS library version %d.%d.%d" DMSDOS_VLT - " compiled " __DATE__ " " __TIME__ " with options:" + printk("DMSDOS library version %d.%d.%d" DMSDOS_VLT + " compiled " __DATE__ " " __TIME__ " with options:" #ifndef DBL_WRITEACCESS - " read-only" -#else - " read-write" -#endif -#ifdef USE_XMALLOC - ", xmalloc" -#else -#ifdef USE_VMALLOC - ", vmalloc" + " read-only" #else - ", kmalloc" -#endif -#endif -#ifdef DMSDOS_USE_READPAGE - ", readpage" -#endif -#ifdef USE_READA_LIST - ", reada list" -#endif -#ifdef INTERNAL_DAEMON - ", internal daemon" + " read-write" #endif #ifdef DMSDOS_CONFIG_DBLSP_DRVSP - ", doublespace/drivespace(<3)" + ", doublespace/drivespace(<3)" #endif #ifdef DMSDOS_CONFIG_DRVSP3 - ", drivespace 3" + ", drivespace 3" #endif #ifdef DMSDOS_CONFIG_STAC3 - ", stacker 3" + ", stacker 3" #endif #ifdef DMSDOS_CONFIG_STAC4 - ", stacker 4" + ", stacker 4" #endif - "\n", - DMSDOS_MAJOR,DMSDOS_MINOR,DMSDOS_ACT_REL); + "\n", + DMSDOS_MAJOR,DMSDOS_MINOR,DMSDOS_ACT_REL); for(i=0;imnt_fsname);*/ - if(stat(mn->mnt_fsname,&stat2))continue; /*this may happen e.g. for proc fs*/ - if(stat1.st_dev!=stat2.st_dev||stat1.st_ino!=stat2.st_ino)continue; - if(!hasmntopt(mn,"ro")) - { fprintf(stderr,"libdmsdos: CVF is currently mounted read-write, can't continue.\n"); - endmntent(mnt); - close(fd); - return NULL; - } - if(rwflag) - { fprintf(stderr,"libdmsdos: CVF is currently mounted, cannot open read-write.\n"); - fprintf(stderr,"libdmsdos: trying again in read-only mode\n"); - endmntent(mnt); - close(fd); - rwflag=0; - goto reopen; - } - fprintf(stderr,"libdmsdos: warning: CVF is currently mounted\n"); - } - endmntent(mnt); - } - +#ifdef USE_FLOCK if(rwflag) { if(flock(fd,LOCK_EX|LOCK_NB)) - { perror("libdmsdos: unable to lock CVF exclusively"); - fprintf(stderr,"libdmsdos: trying again in read-only mode\n"); + { printk("unable to lock CVF exclusively: %s",strerror(errno)); + printk("trying again in read-only mode\n"); rwflag=0; close(fd); goto reopen; @@ -456,29 +662,48 @@ struct super_block* open_cvf(char*filename,int rwflag) } else { if(flock(fd,LOCK_SH|LOCK_NB)) - { perror("libdmsdos: unable to lock CVF with shared flag"); - fprintf(stderr,"libdmsdos: probably some other process has opened the CVF read-write.\n"); + { printk("unable to lock CVF with shared flag: %s",strerror(errno)); + printk("probably some other process has opened the CVF read-write.\n"); close(fd); return NULL; } } +#endif /* USE_FLOCK */ +#else + /* open with win32 locking */ + fd=sopen(filename,rwflag?O_RDWR:O_RDONLY,rwflag?SH_DENYRW:SH_DENYWR); + if(fd<0) + { printk("unable to open CVF read-write: %s\n",strerror(errno)); + if(rwflag==0)return NULL; + printk("trying again in read-only mode\n"); + rwflag=0; + goto reopen; + } +#endif s=lseek(fd,0,SEEK_END); blk_size[0][0]=(s%1024)?(s/1024)+1:s/1024; sb=malloc(sizeof(struct super_block)); if(sb==NULL) - { fprintf(stderr,"malloc failed\n"); + { printk("malloc failed\n"); +#ifdef USE_FLOCK flock(fd,LOCK_UN); +#endif close(fd); return NULL; } + sb->s_dev=fd; sb->s_flags=0; if(rwflag==0)sb->s_flags|=MS_RDONLY; - sb->s_dev=fd; + sb->directlist=NULL; + sb->directlen=NULL; - if(read_super(sb)==NULL) - { flock(fd,LOCK_UN); + if(read_super(sb,ext)==NULL) + { +#ifdef USE_FLOCK + flock(fd,LOCK_UN); +#endif close(fd); free(sb); return NULL; @@ -491,7 +716,11 @@ void close_cvf(struct super_block*sb) { int fd=sb->s_dev; unmount_dblspace(sb); +#ifdef USE_FLOCK flock(fd,LOCK_UN); +#endif close(fd); + if(sb->directlist)free(sb->directlist); + if(sb->directlen)free(sb->directlen); free(sb); } diff --git a/src/lib_interface.h b/src/lib_interface.h index eaf01ef..551447b 100644 --- a/src/lib_interface.h +++ b/src/lib_interface.h @@ -32,8 +32,41 @@ See file COPYING for details. This has been done for libc6 support. */ +/* machine and system dependent hacks */ + +/* Linux section -- no problems here... :)) */ +#ifdef __linux__ /* this defines machine-dependent __u8, __s8 etc. types */ #include +/* this defines get_unaligned and put_unaligned */ +#include +/* this defines cpu_to_le16 etc. in 2.1 kernels - a kind of nop for 2.0 */ +#include + +/* Other systems usually do not have the asm include files */ +#else +/* emulate asm/types.h */ +typedef unsigned char __u8; +typedef signed char __s8; +typedef unsigned short int __u16; +typedef signed short int __s16; +typedef unsigned int __u32; +typedef signed int __s32; +/* emulate asm/unaligned.h */ +/* edit these lines if your system cannot do unaligned access */ +#define get_unaligned(ptr) (*(ptr)) +#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) )) +/* emulate asm/byteorder.h */ +/* edit these lines if your system is non-linux and big endian */ +/* the examples are commented out; they are valid for a little endian cpu */ +/* #define cpu_to_le16(v) (v) */ +/* #define cpu_to_be16(v) ( (((v)&0xff)<<8) | (((v)&0xff00)>>8) ) */ +/* #define cpu_to_le32(v) (v) */ +/* hack: sometimes NULL is missing */ +#ifndef NULL +#define NULL ((void*)0) +#endif +#endif int printk(const char *fmt, ...); void panic(const char * fmt, ...); @@ -71,6 +104,19 @@ struct buffer_head { #define MS_RDONLY 1 /* Mount read-only */ #define MSDOS_SB(s) (&((s)->u.msdos_sb)) +struct msdos_dir_entry { + __s8 name[8],ext[3]; /* name and extension */ + __u8 attr; /* attribute bits */ + __u8 lcase; /* Case for base and extension */ + __u8 ctime_ms; /* Creation time, milliseconds */ + __u16 ctime; /* Creation time */ + __u16 cdate; /* Creation date */ + __u16 adate; /* Last access date */ + __u16 starthi; /* High 16 bits of cluster in FAT32 */ + __u16 time,date,start;/* time, date and first cluster */ + __u32 size; /* file size (in bytes) */ +}; + struct msdos_sb_info { unsigned short cluster_size; /* sectors/cluster */ unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */ @@ -97,6 +143,9 @@ struct super_block { unsigned char s_blocksize_bits; unsigned long s_flags; unsigned long s_magic; + unsigned long* directlist; + unsigned long* directlen; + unsigned long directsize; union { struct msdos_sb_info msdos_sb; } u; @@ -136,3 +185,5 @@ struct fat_boot_sector { #define CURRENT_TIME time(NULL) #define vmalloc malloc #define vfree free + +#define MAXFRAGMENT 300 diff --git a/src/msdos.fsck-wrapper b/src/msdos.fsck-wrapper index 167e395..cedf1bd 100644 --- a/src/msdos.fsck-wrapper +++ b/src/msdos.fsck-wrapper @@ -3,6 +3,12 @@ # This is an example shell script that can be used as a wrapper for a # msdos.fsck (called by the generic fsck frontend). # +# WARNING: This script is an older implementation. See msdos.fsck-wrapper2 +# for a newer and cleaner one. +# +# WARNING: This script needs write access to /tmp which is probably not +# possible on bootup. Better use msdos.fsck-wrapper2 instead. +# # The script accepts a standard fsck command line and decides upon the # the raw filesystem data whether it is a CVF or not. If it is a CVF then # dmsdosfsck is invoked. diff --git a/src/prepare_dos_8.3 b/src/prepare_dos_8.3 old mode 100644 new mode 100755 diff --git a/src/win32_msc50.bat b/src/win32_msc50.bat old mode 100644 new mode 100755