├── .gitignore ├── README.md ├── TODO ├── Vagrantfile ├── module ├── COPYING ├── Makefile ├── bitmap.c ├── bitmap.h ├── dir.c ├── file.c ├── inode.c ├── itree.c ├── namei.c └── xiafs.h └── programs ├── COPYING ├── Makefile ├── README.progs ├── bootsect.h ├── mkxfs.8 ├── mkxfs.c ├── originals ├── xfspgm-patch-2.diff └── xiafspgm-0.8.1 │ ├── Makefile │ ├── README.mkboot │ ├── README.upgrade │ ├── bootsect.h │ ├── converter.c │ ├── mkboot.8 │ ├── mkboot.c │ ├── mkxfs.8 │ ├── mkxfs.c │ ├── orgdump │ ├── primary.s │ ├── secondary.s │ ├── xfsck.8 │ └── xfsck.c ├── xfsck.8 ├── xfsck.c └── xiafs.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | 4 | # Libraries 5 | *.lib 6 | *.a 7 | 8 | # Shared objects (inc. Windows DLLs) 9 | *.dll 10 | *.so 11 | *.so.* 12 | *.dylib 13 | 14 | # Executables 15 | *.exe 16 | *.out 17 | *.app 18 | .*.sw? 19 | .*.o.d 20 | .*.cmd 21 | .DS_Store 22 | 23 | # vagranty bits 24 | .vagrant/ 25 | tmp/ 26 | 27 | # module building gunk 28 | .tmp_versions 29 | modules.order 30 | Module.symvers 31 | xiafs.ko 32 | xiafs.mod.c 33 | 34 | # built utilities 35 | mkxfs 36 | xfsck 37 | 38 | # patch mishaps 39 | *.rej 40 | *.orig 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | modern-xiafs 2 | ============ 3 | 4 | Kernel module for Xiafs for newish (2.6.32, 3.2.0, 3.10+) Linux kernels. 5 | 6 | ------------------------------------------------------------------------------- 7 | 8 | A port of the [Xiafs filesystem](https://en.wikipedia.org/wiki/Xiafs) from the 2.1.20 Linux kernel to the 2.6.32 Linux kernel using the Minix fs code in the 2.6.32 kernel. It is currently known to work with 2.6.32, 3.2.0, 3.10-3.19, and 4.x kernels. Lately this module is being tested against the major new stable kernel versions some time after their release, but it is not being tested against every minor point release. 9 | 10 | ------------------------------------------------------------------------------- 11 | 12 | **WARNING**: This module could cause kernel panics (see BUGS), set your computer on fire, explode in new and interesting ways, and is generally not recommended for production use. Use at your own risk, and remember that this port of an ancient filesytem to modern systems is meant as an intellectual exercise and not something you'd want to use for real work. 13 | 14 | ------------------------------------------------------------------------------- 15 | 16 | Xiafs is an ancient Linux filesystem that was an early competitor to ext2, but for various reasons, like its lack of extensibility, it fell from general use and was eventually removed from the kernel in version 2.1.21. As an intellectual exercise to learn more about how filesystems work, I decided to port xiafs from the last kernel it was still in to work with the kernel that shipped with Debian squeeze (2.6.32). Later, I also got it working with 3.2.0, 3.10.1, and at least one minor point release of each subsequent 3.x and 4.x series kernels. 17 | 18 | KERNELS 19 | ------- 20 | These are the kernels that the modern-xiafs module has been built and tested 21 | against: 22 | 23 | ``` 24 | 2.6.32 25 | 3.2.0 26 | 3.10.1 27 | 3.11.1 28 | 3.12.1 29 | 3.13.5 30 | 3.14.2 31 | 3.15.3 32 | 3.16.4 33 | 3.17.0 34 | 3.18.11 35 | 3.19.3 36 | 4.0.9 37 | 4.1.3 38 | 4.4.0 39 | 4.7.10 40 | 4.8.7 41 | 4.9.6 42 | 4.10.1 43 | 4.11.12 44 | 4.12.7 45 | 4.13.16 46 | 4.14.25 47 | 4.15.8 48 | 4.16.16 49 | 4.17.18 50 | 4.18.5 51 | ``` 52 | 53 | As noted below, some versions of the module are have been built and tested against other versions of the kernel. The module may work with other kernels, but that is uncertain. 54 | 55 | INSTALLATION 56 | ------------ 57 | 58 | Make sure your development packages are all installed. 59 | 60 | To build this module, you'll need to install the kernel sources. On Debian it will be something like `apt-get install linux-source-2.6.32`. The kernel source tarball will be in `/usr/src`. Untar it wherever you'd like to have the kernel sources, perhaps in your home directory or something. 61 | 62 | Then you'll need to prepare the kernel source tree for compiling the module. Copy the kernel's config file (which should be something like `/boot/config-2.6.32-5-amd64`) to `.config` in the kernel source directory. You'll also need to get `Module.symvers` out of `/usr/src/linux-headers` into the root of the kernel source directory. 63 | 64 | Once you've done that, run `make oldconfig && make prepare && make modules_prepare` to get the kernel source tree ready for compiling the module. If your distribution has another recommended way to build the kernel package, like `make deb-pkg`, follow those steps. Make sure the kernel source is owned by the user you're planning on compiling the module as. 65 | 66 | Along with the master branch, there are git branches for the kernels that this module is known to work with (currently linux-2.6.32, linux-3.2, linux-3.10.1, linux-3.11.1, linux-3.12.1, linux-3.13.5, linux-3.14.2, linux-3.15.3, linux-3.16.4 (which covers 3.17.0, 3.18.11, 3.19.3 and 4.0.9 as well), linux-4.1.3, linux-4.4.0, linux-4.7.10 (which covers 4.8.7), linux-4.9.6, linux-4.10.1, linux-4.11.12 (which also covers 4.12), and linux-4.13.16 (which also covers 4.14, 4.15, 4.165, 4.17, and 4.18). Just check out those branches to get the code for those versions of the kernel. Once the xiafs module is working with a particular version of the kernel, the code should remain pretty stable except for needed bugfixes that come along. If the kernel you're running isn't in one of the branches, try master, or the branch closest to your current kernel. 67 | 68 | After all that is done, go into the module subdirectory (checking out the appropriate version branch if needed) in this directory. Run: 69 | 70 | ``` 71 | $ make -C /path/to/linux-source-VERSION SUBDIRS=$PWD modules 72 | ``` 73 | 74 | After that runs, you'll have a shiny new xiafs.ko ready for loading. The easiest way to load it is run `insmod ./xiafs.ko` as root. If you're feeling brave, you could put it in `/lib/modules//kernel/fs/xiafs/xiafs.ko` and run `depmod`. Then `modprobe xiafs` will load xiafs up without having to specify the path. 75 | 76 | USAGE 77 | ----- 78 | 79 | Load the kernel module, most likely with `insmod /path/to/xiafs.ko`, unless you put it in your kernel's module tree properly, in which case you can run `modprobe xiafs`. 80 | 81 | If you don't have a xiafs filesystem, you'll need to make one. Using a small partition (< 2GB) and using sdc1 as our example partition, run: 82 | 83 | ``` 84 | # mkfs.xiafs /dev/sdc1 85 | ``` 86 | 87 | `mkfs.xiafs` does not figure out the number of blocks available on the device; you will need to calculate that yourself. Taking the number of 1024 blocks shown by fdisk and subtracting a few works, but you may need to experiment a little to see how many you can get on the filesystem. 88 | 89 | Once that's done, or if you have a xiafs disk image from some ancient computer, mount it: 90 | 91 | ``` 92 | # mount -t xiafs /dev/sdc1 /mnt 93 | ``` 94 | 95 | And your very own xiafs filesystem is there. Look around, copy stuff to it (assuming that the files aren't bigger than 64MB). Other than that, it's much like any other filesystem. 96 | 97 | To check or repair a xiafs filesystem, use `xfsck`. With no options it will tell you what's broken, -r gives interactive repair, -a gives automatic repair, and -s prints out the superblock info. 98 | 99 | LIMITATIONS 100 | ----------- 101 | 102 | * Maximum 64MB file size 103 | * Maximum 2GB volume size 104 | 105 | These limits are historical, and not bugs as such. 106 | 107 | BUGS 108 | ---- 109 | 110 | * Works and tested with the kernels mentioned above. Other 2.6, 3.x, and 4.x kernels are untested as of yet. 111 | * Has been tested with big-endian architectures (s390x, specifically) only with the linux-3.2 version. You can compile and load the module, and create and mount filesystems with the filesystem tools, but at this time you cannot mount a xiafs filesystem created on a big-endian machine on a little endian machine. I have not tested the reverse, but believe that to also be the case. 112 | 113 | TODO 114 | ---- 115 | 116 | See the TODO file. 117 | 118 | FURTHER READING 119 | --------------- 120 | 121 | * The previously mentioned [Xiafs article on Wikipedia](https://en.wikipedia.org/wiki/Xiafs). 122 | * The [annotated source of the Xiafs module for 3.12.1](http://time.to.pullthepl.ug/annotated-xiafs/). 123 | 124 | LICENSE, CREDITS 125 | ---------------- 126 | 127 | See COPYING in the subdirectories. 128 | 129 | The kernel module code is copyright (c) Linus Torvalds, Q. Frank Xia, and others as noted in the source files, with modifications by me to get it working on the 2.6.32 Linux kernel and is covered under the terms of version 2 of the GNU General Public License. 130 | 131 | The xiafs programs (xfsck, mkxfs) are copyright (c) Q. Frank Xia, with this notice: 132 | 133 | ``` 134 | (C) Copyright Q. Frank Xia, 1992. All rights reserved. 135 | 136 | Permission to use and redistribute this software is hereby granted 137 | provided that the following conditions are met: 138 | 1. Source code redistribution must retain this statement. 139 | 2. Binary redistribution must reproduce this statement in the 140 | documentation provided with the distribution. 141 | 3. This software is provided by author Q. Frank Xia "as is". There 142 | are absolutely no warranties at all. The author is not responsible 143 | for any possible damages caused by using this software. 144 | ``` 145 | 146 | The original version of these programs can be found in `programs/originals/xiafspgm-0.8.1`. 147 | 148 | The xiafs programs (xfsck, mkxfs) also have a patch, distributed under the terms of the GNU General Public License, copyright (c) 1996 by Thomas McWilliams. This patch is available in `programs/originals/xfspgm-patch-2.diff`. 149 | 150 | For more information on the xiafs programs, see `programs/README.progs`. 151 | 152 | The changes I made to get these programs compiling and working on a modern Linux are copyright 2013, Jeremy Bingham (), and are under the GPL as above. 153 | 154 | This software 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 license the software was originally released under for more details. 155 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | * Get this module tracking the very bleeding edge of kernel development. It's 2 | already at the latest stable (as of this writing) kernel, but is not yet 3 | known to work with the very latest latest kernels. 4 | 5 | * Get this module building against other distributions' default kernels, like 6 | whatever the various versions of Ubuntu ship with. 7 | 8 | * Make installation process smoother. 9 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | Vagrant.configure(2) do |config| 9 | # The most common configuration options are documented and commented below. 10 | # For a complete reference, please see the online documentation at 11 | # https://docs.vagrantup.com. 12 | 13 | # Every Vagrant development environment requires a box. You can search for 14 | # boxes at https://atlas.hashicorp.com/search. 15 | config.vm.box = "debian/bookworm64" 16 | 17 | config.vm.synced_folder '.', '/vagrant', :disabled => true 18 | 19 | # Disable automatic box update checking. If you disable this, then 20 | # boxes will only be checked for updates when the user runs 21 | # `vagrant box outdated`. This is not recommended. 22 | # config.vm.box_check_update = false 23 | 24 | # Create a forwarded port mapping which allows access to a specific port 25 | # within the machine from a port on the host machine. In the example below, 26 | # accessing "localhost:8080" will access port 80 on the guest machine. 27 | # config.vm.network "forwarded_port", guest: 80, host: 8080 28 | 29 | # Create a private network, which allows host-only access to the machine 30 | # using a specific IP. 31 | # config.vm.network "private_network", ip: "192.168.33.10" 32 | 33 | # Create a public network, which generally matched to bridged network. 34 | # Bridged networks make the machine appear as another physical device on 35 | # your network. 36 | # config.vm.network "public_network" 37 | 38 | # Share an additional folder to the guest VM. The first argument is 39 | # the path on the host to the actual folder. The second argument is 40 | # the path on the guest to mount the folder. And the optional third 41 | # argument is a set of non-required options. 42 | # config.vm.synced_folder "../data", "/vagrant_data" 43 | 44 | # Provider-specific configuration so you can fine-tune various 45 | # backing providers for Vagrant. These expose provider-specific options. 46 | # Example for VirtualBox: 47 | # 48 | file_to_disk = "./tmp/xiafs-disk.vdi" 49 | kern_disk = "./tmp/kern-src-disk.vdi" 50 | config.vm.provider "virtualbox" do |vb| 51 | # Customize the amount of memory on the VM: 52 | vb.memory = "1024" 53 | if !File.exist?(file_to_disk) 54 | vb.customize ['createhd', '--filename', file_to_disk, '--size', 4 * 1024] 55 | vb.customize ['createhd', '--filename', kern_disk, '--size', 30 * 1024] 56 | vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--type', 'hdd', '--medium', file_to_disk] 57 | vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 2, '--type', 'hdd', '--medium', kern_disk] 58 | end 59 | end 60 | # 61 | # View the documentation for the provider you are using for more 62 | # information on available options. 63 | 64 | # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies 65 | # such as FTP and Heroku are also available. See the documentation at 66 | # https://docs.vagrantup.com/v2/push/atlas.html for more information. 67 | # config.push.define "atlas" do |push| 68 | # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME" 69 | # end 70 | 71 | # Enable provisioning with a shell script. Additional provisioners such as 72 | # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the 73 | # documentation for more information about their specific syntax and use. 74 | config.vm.provision "shell", inline: <<-SHELL 75 | sudo apt-get update 76 | sudo DEBIAN_FRONTEND=noninteractive apt-get install git fakeroot kernel-package linux-headers-amd64 hexedit -y 77 | SHELL 78 | end 79 | -------------------------------------------------------------------------------- /module/COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 675 Mass Ave, Cambridge, MA 02139, USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | Appendix: How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 19yy 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) 19yy name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Library General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /module/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for the Linux xiafs filesystem routines. 3 | # 4 | 5 | obj-m += xiafs.o 6 | 7 | xiafs-objs := bitmap.o itree.o namei.o inode.o file.o dir.o 8 | -------------------------------------------------------------------------------- /module/bitmap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Porting work to modern kernels copyright (C) Jeremy Bingham, 2013. 3 | * Based on work by Linus Torvalds, Q. Frank Xia, and others as noted. 4 | * 5 | * This port of Q. Frank Xia's xiafs was done using the existing minix 6 | * filesystem code, but based on the original xiafs code in pre-2.1.21 or so 7 | * kernels. 8 | */ 9 | 10 | /* 11 | * linux/fs/xiafs/bitmap.c 12 | * 13 | * Copyright (C) 1991, 1992 Linus Torvalds 14 | */ 15 | 16 | /* 17 | * Modified for 680x0 by Hamish Macdonald 18 | * Fixed for 680x0 by Andreas Schwab 19 | */ 20 | 21 | /* bitmap.c contains the code that handles the inode and block bitmaps */ 22 | 23 | #include "xiafs.h" 24 | #include "bitmap.h" 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | static const int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 }; 31 | 32 | static DEFINE_SPINLOCK(bitmap_lock); 33 | 34 | static unsigned long count_used(struct buffer_head *map[], unsigned numblocks, __u32 numbits) 35 | { 36 | unsigned long i, j, sum = 0; 37 | struct buffer_head *bh; 38 | 39 | for (i=0; ib_size; j++) 43 | sum += nibblemap[bh->b_data[j] & 0xf] 44 | + nibblemap[(bh->b_data[j]>>4) & 0xf]; 45 | } 46 | 47 | if (numblocks==0 || !(bh=map[numblocks-1])) 48 | return(0); 49 | 50 | return(sum); 51 | } 52 | 53 | void xiafs_free_block(struct inode *inode, unsigned long block) 54 | { 55 | struct super_block *sb = inode->i_sb; 56 | struct xiafs_sb_info *sbi = xiafs_sb(sb); 57 | struct buffer_head *bh; 58 | int k = sb->s_blocksize_bits + 3; 59 | unsigned long bit, zone; 60 | 61 | if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) { 62 | printk("Trying to free block not in datazone\n"); 63 | return; 64 | } 65 | zone = block - sbi->s_firstdatazone + 1; 66 | bit = zone & ((1<>= k; 68 | if (zone >= sbi->s_zmap_zones) { 69 | printk("xiafs_free_block: nonexistent bitmap buffer\n"); 70 | return; 71 | } 72 | bh = sbi->s_zmap_buf[zone]; 73 | spin_lock(&bitmap_lock); 74 | if (!xiafs_test_and_clear_bit(bit, bh->b_data)) 75 | printk("xiafs_free_block (%s:%lu): bit already cleared\n", 76 | sb->s_id, block); 77 | inode->i_blocks -= 2 << XIAFS_ZSHIFT(sbi); 78 | spin_unlock(&bitmap_lock); 79 | mark_buffer_dirty(bh); 80 | return; 81 | } 82 | 83 | int xiafs_new_block(struct inode * inode) 84 | { 85 | struct xiafs_sb_info *sbi = xiafs_sb(inode->i_sb); 86 | int bits_per_zone = XIAFS_BITS_PER_Z(sbi); 87 | int i; 88 | 89 | for (i = 0; i < sbi->s_zmap_zones; i++) { 90 | struct buffer_head *bh = sbi->s_zmap_buf[i]; 91 | int j; 92 | 93 | spin_lock(&bitmap_lock); 94 | j = xiafs_find_first_zero_bit(bh->b_data, bits_per_zone); 95 | if (j < bits_per_zone) { 96 | xiafs_set_bit(j, bh->b_data); 97 | spin_unlock(&bitmap_lock); 98 | mark_buffer_dirty(bh); 99 | j += i * bits_per_zone + sbi->s_firstdatazone-1; 100 | if (j < sbi->s_firstdatazone || j >= sbi->s_nzones) 101 | break; 102 | inode->i_blocks += 2 << XIAFS_ZSHIFT(sbi); 103 | return j; 104 | } 105 | spin_unlock(&bitmap_lock); 106 | } 107 | return 0; 108 | } 109 | 110 | unsigned long xiafs_count_free_blocks(struct xiafs_sb_info *sbi) 111 | { 112 | return ((sbi->s_zmap_zones << XIAFS_BITS_PER_Z_BITS(sbi)) - count_used(sbi->s_zmap_buf, sbi->s_zmap_zones, 113 | sbi->s_nzones - sbi->s_firstdatazone + 1)); 114 | } 115 | 116 | struct xiafs_inode * 117 | xiafs_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh) 118 | { 119 | int block; 120 | struct xiafs_sb_info *sbi = xiafs_sb(sb); 121 | struct xiafs_inode *p; 122 | int xiafs_inodes_per_block = _XIAFS_INODES_PER_BLOCK; /* XIAFS_INODES_PER_Z(sbi); */ 123 | 124 | *bh = NULL; 125 | if (!ino || ino > sbi->s_ninodes) { 126 | printk("Bad inode number on dev %s: %ld is out of range\n", 127 | sb->s_id, (long)ino); 128 | return NULL; 129 | } 130 | ino--; 131 | block = 1 + sbi->s_imap_zones + sbi->s_zmap_zones + 132 | ino / xiafs_inodes_per_block; 133 | *bh = sb_bread(sb, block); 134 | if (!*bh) { 135 | printk("Unable to read inode block\n"); 136 | return NULL; 137 | } 138 | p = (void *)(*bh)->b_data; 139 | return p + ino % xiafs_inodes_per_block; 140 | } 141 | 142 | /* Clear the link count and mode of a deleted inode on disk. */ 143 | 144 | static void xiafs_clear_inode(struct inode *inode) 145 | { 146 | struct buffer_head *bh = NULL; 147 | 148 | struct xiafs_inode *raw_inode; 149 | raw_inode = xiafs_raw_inode(inode->i_sb, inode->i_ino, &bh); 150 | if (raw_inode) { 151 | raw_inode->i_nlinks = 0; 152 | raw_inode->i_mode = 0; 153 | } 154 | if (bh) { 155 | mark_buffer_dirty(bh); 156 | brelse (bh); 157 | } 158 | } 159 | 160 | void xiafs_free_inode(struct inode * inode) 161 | { 162 | struct super_block *sb = inode->i_sb; 163 | struct xiafs_sb_info *sbi = xiafs_sb(inode->i_sb); 164 | struct buffer_head *bh; 165 | int k = sb->s_blocksize_bits + 3; 166 | unsigned long ino, bit; 167 | 168 | ino = inode->i_ino; 169 | if (ino < 1 || ino > sbi->s_ninodes) { 170 | printk("xiafs_free_inode: inode 0 or nonexistent inode\n"); 171 | return; 172 | } 173 | bit = ino & ((1<>= k; 175 | if (ino >= sbi->s_imap_zones) { 176 | printk("xiafs_free_inode: nonexistent imap in superblock\n"); 177 | return; 178 | } 179 | 180 | xiafs_clear_inode(inode); /* clear on-disk copy */ 181 | 182 | bh = sbi->s_imap_buf[ino]; 183 | spin_lock(&bitmap_lock); 184 | if (!xiafs_test_and_clear_bit(bit, bh->b_data)) 185 | printk("xiafs_free_inode: bit %lu already cleared\n", bit); 186 | spin_unlock(&bitmap_lock); 187 | mark_buffer_dirty(bh); 188 | } 189 | 190 | struct inode * xiafs_new_inode(const struct inode * dir, umode_t mode, int * error) 191 | { 192 | struct super_block *sb = dir->i_sb; 193 | struct xiafs_sb_info *sbi = xiafs_sb(sb); 194 | struct inode *inode = new_inode(sb); 195 | struct buffer_head * bh; 196 | int bits_per_zone = 8 * sb->s_blocksize; 197 | unsigned long j; 198 | int i; 199 | 200 | if (!inode) { 201 | *error = -ENOMEM; 202 | return NULL; 203 | } 204 | j = bits_per_zone; 205 | bh = NULL; 206 | *error = -ENOSPC; 207 | spin_lock(&bitmap_lock); 208 | for (i = 0; i < sbi->s_imap_zones; i++) { 209 | bh = sbi->s_imap_buf[i]; 210 | j = xiafs_find_first_zero_bit(bh->b_data, bits_per_zone); 211 | if (j < bits_per_zone) 212 | break; 213 | } 214 | if (!bh || j >= bits_per_zone) { 215 | spin_unlock(&bitmap_lock); 216 | iput(inode); 217 | return NULL; 218 | } 219 | if (xiafs_test_and_set_bit(j, bh->b_data)) { /* shouldn't happen */ 220 | spin_unlock(&bitmap_lock); 221 | printk("xiafs_new_inode: bit already set\n"); 222 | iput(inode); 223 | return NULL; 224 | } 225 | spin_unlock(&bitmap_lock); 226 | mark_buffer_dirty(bh); 227 | j += i * bits_per_zone; 228 | if (!j || j > sbi->s_ninodes) { 229 | iput(inode); 230 | return NULL; 231 | } 232 | inode_init_owner(inode, dir, mode); 233 | inode->i_ino = j; 234 | inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); 235 | inode->i_blocks = 0; 236 | memset(&xiafs_i(inode)->i_zone, 0, sizeof(xiafs_i(inode)->i_zone)); 237 | insert_inode_hash(inode); 238 | mark_inode_dirty(inode); 239 | 240 | *error = 0; 241 | return inode; 242 | } 243 | 244 | unsigned long xiafs_count_free_inodes(struct xiafs_sb_info *sbi) 245 | { 246 | return (sbi->s_imap_zones << XIAFS_BITS_PER_Z_BITS(sbi)) - count_used(sbi->s_imap_buf, sbi->s_imap_zones, sbi->s_ninodes + 1); 247 | } 248 | -------------------------------------------------------------------------------- /module/bitmap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bitmap.h 3 | * 4 | * bit flipping definitions adapted from linux-3.8.8's fs/minix/minix.h to 5 | * replace functions that were available more generally in 2.6.32. 6 | * 7 | */ 8 | 9 | 10 | /* Taking a page from ext2, at least for now, use little endian bitmaps. Native 11 | * byte ordering may come later. */ 12 | 13 | #define xiafs_test_and_set_bit __test_and_set_bit_le 14 | #define xiafs_set_bit __set_bit_le 15 | #define xiafs_test_and_clear_bit __test_and_clear_bit_le 16 | #define xiafs_test_bit test_bit_le 17 | #define xiafs_find_first_zero_bit find_first_zero_bit_le 18 | -------------------------------------------------------------------------------- /module/dir.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Porting work to modern kernels copyright (C) Jeremy Bingham, 2013. 3 | * Based on work by Linus Torvalds, Q. Frank Xia, and others as noted. 4 | * 5 | * This port of Q. Frank Xia's xiafs was done using the existing minix 6 | * filesystem code, but based on the original xiafs code in pre-2.1.21 or so 7 | * kernels. 8 | */ 9 | 10 | /* 11 | * linux/fs/xiafs/dir.c 12 | * 13 | * Copyright (C) 1991, 1992 Linus Torvalds 14 | * 15 | * xiafs directory handling functions 16 | * 17 | * Updated to filesystem version 3 by Daniel Aragones 18 | */ 19 | 20 | #include "xiafs.h" 21 | #include 22 | #include 23 | #include 24 | 25 | typedef struct xiafs_direct xiafs_dirent; 26 | 27 | static int xiafs_readdir(struct file *, struct dir_context *); 28 | 29 | #define RNDUP4(x) ((3+(u_long)(x)) & ~3) 30 | 31 | const struct file_operations xiafs_dir_operations = { 32 | .llseek = generic_file_llseek, 33 | .read = generic_read_dir, 34 | .iterate = xiafs_readdir, 35 | .fsync = generic_file_fsync, 36 | }; 37 | 38 | static inline void dir_put_page(struct page *page) 39 | { 40 | kunmap(page); 41 | put_page(page); 42 | } 43 | 44 | /* 45 | * Return the offset into page `page_nr' of the last valid 46 | * byte in that page, plus one. 47 | */ 48 | static unsigned 49 | xiafs_last_byte(struct inode *inode, unsigned long page_nr) 50 | { 51 | unsigned last_byte = PAGE_SIZE; 52 | 53 | if (page_nr == (inode->i_size >> PAGE_SHIFT)) 54 | last_byte = inode->i_size & (PAGE_SIZE - 1); 55 | return last_byte; 56 | } 57 | 58 | static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len) 59 | { 60 | struct address_space *mapping = page->mapping; 61 | struct inode *dir = mapping->host; 62 | int err = 0; 63 | block_write_end(NULL, mapping, pos, len, len, page, NULL); 64 | 65 | if (pos+len > dir->i_size) { 66 | i_size_write(dir, pos+len); 67 | mark_inode_dirty(dir); 68 | } 69 | if (IS_DIRSYNC(dir)) 70 | err = write_one_page(page); 71 | else 72 | unlock_page(page); 73 | return err; 74 | } 75 | 76 | static struct page * dir_get_page(struct inode *dir, unsigned long n) 77 | { 78 | struct address_space *mapping = dir->i_mapping; 79 | struct page *page = read_mapping_page(mapping, n, NULL); 80 | if (!IS_ERR(page)) { 81 | kmap(page); 82 | if (!PageUptodate(page)) 83 | goto fail; 84 | } 85 | return page; 86 | 87 | fail: 88 | dir_put_page(page); 89 | return ERR_PTR(-EIO); 90 | } 91 | 92 | static inline void *xiafs_next_entry(void *de) 93 | { 94 | /* make this less gimpy */ 95 | xiafs_dirent *d = (xiafs_dirent *)de; /* not the most efficient way */ 96 | return (void*)((char*)de + d->d_rec_len); 97 | } 98 | 99 | static int xiafs_readdir(struct file * file, struct dir_context *ctx) 100 | { 101 | unsigned long pos = ctx->pos; 102 | struct inode *inode = file_inode(file); 103 | unsigned long npages = dir_pages(inode); 104 | unsigned chunk_size = _XIAFS_DIR_SIZE; /* 1st entry is always 12, it seems. */ 105 | char *name; 106 | unsigned char namelen; 107 | __u32 inumber; 108 | unsigned offset; 109 | unsigned long n; 110 | 111 | ctx->pos = pos = ALIGN(pos, chunk_size); /* (pos + chunk_size-1) & ~(chunk_size-1); */ 112 | if (pos >= inode->i_size) 113 | return 0; 114 | 115 | offset = pos & ~PAGE_MASK; 116 | n = pos >> PAGE_SHIFT; 117 | 118 | for ( ; n < npages; n++, offset = 0) { 119 | char *p, *kaddr, *limit; 120 | struct page *page = dir_get_page(inode, n); 121 | 122 | if (IS_ERR(page)) 123 | continue; 124 | kaddr = (char *)page_address(page); 125 | p = kaddr+offset; 126 | limit = kaddr + xiafs_last_byte(inode, n) - chunk_size; 127 | for ( ; p <= limit; p = xiafs_next_entry(p)) { 128 | xiafs_dirent *de = (xiafs_dirent *)p; 129 | if (de->d_rec_len == 0){ 130 | printk("XIAFS: Zero-length directory entry at (%s %d)\n", WHERE_ERR); 131 | dir_put_page(page); 132 | return -EIO; 133 | } 134 | name = de->d_name; 135 | inumber = de->d_ino; 136 | namelen = de->d_name_len; 137 | if (inumber) { 138 | if (!dir_emit(ctx, name, namelen, inumber, DT_UNKNOWN)){ 139 | dir_put_page(page); 140 | return 0; 141 | } 142 | } 143 | /* Minix has here: 144 | * ctx->pos += chunk_size; 145 | * xiafs has variable length directories, though, so we 146 | * want to increase the position by the length of the 147 | * directory entry rather than a fixed chunk size. */ 148 | ctx->pos += de->d_rec_len; 149 | } 150 | dir_put_page(page); 151 | } 152 | 153 | return 0; 154 | } 155 | 156 | static inline int namecompare(int len, int maxlen, 157 | const char * name, const char * buffer) 158 | { 159 | if (len < maxlen && buffer[len]) 160 | return 0; 161 | return !memcmp(name, buffer, len); 162 | } 163 | 164 | /* 165 | * xiafs_find_entry() 166 | * 167 | * finds an entry in the specified directory with the wanted name. It 168 | * returns the cache buffer in which the entry was found, and the entry 169 | * itself (as a parameter - res_dir). It does NOT read the inode of the 170 | * entry - you'll have to do that yourself if you want to. 171 | */ 172 | xiafs_dirent *xiafs_find_entry(struct dentry *dentry, struct page **res_page, struct xiafs_direct **old_de) 173 | { 174 | const char * name = dentry->d_name.name; 175 | int namelen = dentry->d_name.len; 176 | struct inode * dir = dentry->d_parent->d_inode; 177 | unsigned long n; 178 | unsigned long npages = dir_pages(dir); 179 | struct page *page = NULL; 180 | char *p; 181 | 182 | char *namx; 183 | __u32 inumber; 184 | *res_page = NULL; 185 | 186 | for (n = 0; n < npages; n++) { 187 | char *kaddr, *limit; 188 | unsigned short reclen; 189 | xiafs_dirent *de_pre; 190 | 191 | page = dir_get_page(dir, n); 192 | if (IS_ERR(page)) 193 | continue; 194 | 195 | kaddr = (char*)page_address(page); 196 | limit = kaddr + xiafs_last_byte(dir, n) - 12; 197 | de_pre = (xiafs_dirent *)kaddr; 198 | for (p = kaddr; p <= limit; p = xiafs_next_entry(p)) { 199 | xiafs_dirent *de = (xiafs_dirent *)p; 200 | if (de->d_rec_len == 0){ 201 | printk("XIAFS: Zero-length directory entry at (%s %d)\n", WHERE_ERR); 202 | dir_put_page(page); 203 | return ERR_PTR(-EIO); 204 | } 205 | namx = de->d_name; 206 | inumber = de->d_ino; 207 | if (!inumber) 208 | continue; 209 | reclen = de->d_rec_len; 210 | if(old_de) 211 | *old_de = de_pre; 212 | if (namecompare(namelen, _XIAFS_NAME_LEN, name, namx)) 213 | goto found; 214 | de_pre = de; 215 | } 216 | dir_put_page(page); 217 | } 218 | return NULL; 219 | 220 | found: 221 | *res_page = page; 222 | return (xiafs_dirent *)p; 223 | } 224 | 225 | int xiafs_add_link(struct dentry *dentry, struct inode *inode) 226 | { 227 | struct inode *dir = dentry->d_parent->d_inode; 228 | const char * name = dentry->d_name.name; 229 | int namelen = dentry->d_name.len; 230 | struct page *page = NULL; 231 | unsigned long npages = dir_pages(dir); 232 | unsigned long n; 233 | char *kaddr, *p; 234 | xiafs_dirent *de, *de_pre; 235 | loff_t pos; 236 | int err; 237 | int i; 238 | int rec_size; 239 | char *namx = NULL; 240 | __u32 inumber; 241 | 242 | /* 243 | * We take care of directory expansion in the same loop 244 | * This code plays outside i_size, so it locks the page 245 | * to protect that region. 246 | */ 247 | for (n = 0; n <= npages; n++) { 248 | char *limit, *dir_end; 249 | 250 | page = dir_get_page(dir, n); 251 | err = PTR_ERR(page); 252 | if (IS_ERR(page)) 253 | goto out; 254 | lock_page(page); 255 | kaddr = (char*)page_address(page); 256 | dir_end = kaddr + xiafs_last_byte(dir, n); 257 | limit = kaddr + PAGE_SIZE; 258 | de_pre = (xiafs_dirent *)kaddr; 259 | for (p = kaddr; p < limit; p = xiafs_next_entry(p)) { 260 | de = (xiafs_dirent *)p; 261 | if (de->d_rec_len == 0 && p != dir_end){ 262 | printk("XIAFS: Zero-length directory entry at (%s %d)\n", WHERE_ERR); 263 | dir_put_page(page); 264 | return -EIO; 265 | } 266 | rec_size = de->d_rec_len; 267 | if (de->d_ino && RNDUP4(de->d_name_len)+RNDUP4(namelen)+16 <= de->d_rec_len){ 268 | /* We have an entry we can get another one 269 | * inside of. */ 270 | i = RNDUP4(de->d_name_len)+8; 271 | de_pre = de; 272 | de = (xiafs_dirent *)(i+(u_char *)de_pre); 273 | de->d_ino = 0; 274 | de->d_rec_len = de_pre->d_rec_len-i; 275 | de_pre->d_rec_len=i; 276 | } 277 | namx = de->d_name; 278 | inumber = de->d_ino; 279 | if (p == dir_end) { 280 | /* We hit i_size */ 281 | de->d_ino = 0; 282 | /* NOTE: need to test what happens when dirsize 283 | * is equal to the page size, or when we go over 284 | * the initial XIAFS_ZSIZE. */ 285 | rec_size = de->d_rec_len = XIAFS_ZSIZE(xiafs_sb(dir->i_sb)); 286 | /* We're at the end of the directory, so we 287 | * need to make the new d_rec_len equal to 288 | * XIAFS_ZSIZE */ 289 | goto got_it; 290 | } 291 | if (!inumber && RNDUP4(namelen)+ 8 <= de->d_rec_len) 292 | goto got_it; 293 | err = -EEXIST; 294 | if (namecompare(namelen, _XIAFS_NAME_LEN, name, namx)) 295 | goto out_unlock; 296 | de_pre = de; 297 | } 298 | unlock_page(page); 299 | dir_put_page(page); 300 | } 301 | BUG(); 302 | return -EINVAL; 303 | 304 | got_it: 305 | pos = page_offset(page) + p - (char *)page_address(page); 306 | err = xiafs_prepare_chunk(page, pos, rec_size); 307 | if (err) 308 | goto out_unlock; 309 | memcpy (namx, name, namelen); 310 | /* memset (namx + namelen, 0, de->d_rec_len - namelen - 7); */ 311 | de->d_name[namelen] = 0; 312 | de->d_name_len=namelen; 313 | de->d_ino = inode->i_ino; 314 | err = dir_commit_chunk(page, pos, rec_size); 315 | dir->i_mtime = dir->i_ctime = current_time(dir); 316 | mark_inode_dirty(dir); 317 | out_put: 318 | dir_put_page(page); 319 | out: 320 | return err; 321 | out_unlock: 322 | unlock_page(page); 323 | goto out_put; 324 | } 325 | 326 | int xiafs_delete_entry(struct xiafs_direct *de, struct xiafs_direct *de_pre, struct page *page) 327 | { 328 | struct address_space *mapping = page->mapping; 329 | struct inode *inode = (struct inode*)mapping->host; 330 | char *kaddr = page_address(page); 331 | loff_t pos = page_offset(page) + (char*)de - kaddr; 332 | loff_t tmp_pos; 333 | unsigned len = de->d_rec_len; 334 | int err; 335 | 336 | lock_page(page); 337 | if (de == de_pre){ 338 | de->d_ino = 0; 339 | } else { 340 | /* Join the previous entry with this one. */ 341 | while (de_pre->d_rec_len + (u_char *)de_pre < (u_char *)de){ 342 | if (de_pre->d_rec_len < 12){ 343 | printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR); 344 | return -1; 345 | } 346 | de_pre=(struct xiafs_direct *)(de_pre->d_rec_len + (u_char *)de_pre); 347 | } 348 | if (de_pre->d_rec_len + (u_char *)de_pre > (u_char *)de){ 349 | printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR); 350 | return -1; 351 | } 352 | /* d_rec_len can only be XIAFS_ZSIZE at most. Don't join them 353 | * together if they'd go over */ 354 | tmp_pos = page_offset(page) + (char *)de_pre - kaddr; 355 | if (((tmp_pos & (XIAFS_ZSIZE(xiafs_sb(inode->i_sb)) - 1)) + de_pre->d_rec_len + de->d_rec_len) <= XIAFS_ZSIZE(xiafs_sb(inode->i_sb))){ 356 | de_pre->d_rec_len += de->d_rec_len; 357 | len = de_pre->d_rec_len; 358 | pos = tmp_pos; 359 | } else { 360 | /* If it would go over, just set d_ino to 0 */ 361 | de->d_ino = 0; 362 | } 363 | } 364 | 365 | err = xiafs_prepare_chunk(page, pos, len); 366 | 367 | if (err == 0) { 368 | err = dir_commit_chunk(page, pos, len); 369 | } else { 370 | unlock_page(page); 371 | } 372 | dir_put_page(page); 373 | inode->i_ctime = inode->i_mtime = current_time(inode); 374 | mark_inode_dirty(inode); 375 | return err; 376 | } 377 | 378 | int xiafs_make_empty(struct inode *inode, struct inode *dir) 379 | { 380 | struct address_space *mapping = inode->i_mapping; 381 | struct page *page = grab_cache_page(mapping, 0); 382 | char *kaddr; 383 | int err; 384 | unsigned int zsize = XIAFS_ZSIZE(xiafs_sb(dir->i_sb)); 385 | xiafs_dirent *de; 386 | 387 | if (!page) 388 | return -ENOMEM; 389 | err = xiafs_prepare_chunk(page, 0, zsize); 390 | if (err) { 391 | unlock_page(page); 392 | goto fail; 393 | } 394 | 395 | kaddr = kmap_atomic(page); 396 | memset(kaddr, 0, PAGE_SIZE); 397 | 398 | de = (xiafs_dirent *)kaddr; 399 | 400 | de->d_ino = inode->i_ino; 401 | strcpy(de->d_name, "."); 402 | de->d_name_len = 1; 403 | de->d_rec_len = 12; 404 | de = xiafs_next_entry(de); 405 | de->d_ino = dir->i_ino; 406 | strcpy(de->d_name, ".."); 407 | de->d_name_len = 2; 408 | de->d_rec_len = zsize - 12; 409 | kunmap_atomic(kaddr); 410 | 411 | err = dir_commit_chunk(page, 0, zsize); 412 | fail: 413 | put_page(page); 414 | return err; 415 | } 416 | 417 | /* 418 | * routine to check that the specified directory is empty (for rmdir) 419 | */ 420 | int xiafs_empty_dir(struct inode * inode) 421 | { 422 | struct page *page = NULL; 423 | unsigned long i, npages = dir_pages(inode); 424 | char *name; 425 | __u32 inumber; 426 | 427 | for (i = 0; i < npages; i++) { 428 | char *p, *kaddr, *limit; 429 | 430 | page = dir_get_page(inode, i); 431 | if (IS_ERR(page)) 432 | continue; 433 | 434 | kaddr = (char *)page_address(page); 435 | limit = kaddr + xiafs_last_byte(inode, i) - _XIAFS_DIR_SIZE; 436 | for (p = kaddr; p <= limit; p = xiafs_next_entry(p)) { 437 | xiafs_dirent *de = (xiafs_dirent *)p; 438 | if (de->d_rec_len == 0){ 439 | printk("XIAFS: Zero-length directory entry at (%s %d)\n", WHERE_ERR); 440 | dir_put_page(page); 441 | return -EIO; 442 | } 443 | name = de->d_name; 444 | inumber = de->d_ino; 445 | 446 | if (inumber != 0) { 447 | /* check for . and .. */ 448 | if (name[0] != '.') 449 | goto not_empty; 450 | if (!name[1]) { 451 | if (inumber != inode->i_ino) 452 | goto not_empty; 453 | } else if (name[1] != '.') 454 | goto not_empty; 455 | else if (name[2]) 456 | goto not_empty; 457 | } 458 | } 459 | dir_put_page(page); 460 | } 461 | return 1; 462 | 463 | not_empty: 464 | dir_put_page(page); 465 | return 0; 466 | } 467 | 468 | /* Releases the page */ 469 | void xiafs_set_link(struct xiafs_direct *de, struct page *page, 470 | struct inode *inode) 471 | { 472 | struct address_space *mapping = page->mapping; 473 | struct inode *dir = mapping->host; 474 | loff_t pos = page_offset(page) + 475 | (char *)de-(char*)page_address(page); 476 | int err; 477 | 478 | lock_page(page); 479 | 480 | err = xiafs_prepare_chunk(page, pos, de->d_rec_len); 481 | if (err == 0) { 482 | de->d_ino = inode->i_ino; 483 | err = dir_commit_chunk(page, pos, de->d_rec_len); 484 | } else { 485 | unlock_page(page); 486 | } 487 | dir_put_page(page); 488 | dir->i_mtime = dir->i_ctime = current_time(inode); 489 | mark_inode_dirty(dir); 490 | } 491 | 492 | struct xiafs_direct * xiafs_dotdot (struct inode *dir, struct page **p) 493 | { 494 | struct page *page = dir_get_page(dir, 0); 495 | struct xiafs_direct *de = NULL; 496 | 497 | if (!IS_ERR(page)) { 498 | de = xiafs_next_entry(page_address(page)); 499 | *p = page; 500 | } 501 | return de; 502 | } 503 | 504 | ino_t xiafs_inode_by_name(struct dentry *dentry) 505 | { 506 | struct page *page; 507 | struct xiafs_direct *de = xiafs_find_entry(dentry, &page, NULL); 508 | ino_t res = 0; 509 | 510 | if (de) { 511 | res = de->d_ino; 512 | dir_put_page(page); 513 | } 514 | return res; 515 | } 516 | -------------------------------------------------------------------------------- /module/file.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Porting work to modern kernels copyright (C) Jeremy Bingham, 2013. 3 | * Based on work by Linus Torvalds, Q. Frank Xia, and others as noted. 4 | * 5 | * This port of Q. Frank Xia's xiafs was done using the existing minix 6 | * filesystem code, but based on the original xiafs code in pre-2.1.21 or so 7 | * kernels. 8 | */ 9 | 10 | /* 11 | * linux/fs/xiafs/file.c 12 | * 13 | * Copyright (C) 1991, 1992 Linus Torvalds 14 | * 15 | * xiafs regular file handling primitives 16 | */ 17 | 18 | #include "xiafs.h" 19 | #include 20 | 21 | /* 22 | * We have mostly NULLs here: the current defaults are OK for 23 | * the xiafs filesystem. 24 | */ 25 | const struct file_operations xiafs_file_operations = { 26 | .llseek = generic_file_llseek, 27 | .read_iter = generic_file_read_iter, 28 | .write_iter = generic_file_write_iter, 29 | .mmap = generic_file_mmap, 30 | .fsync = generic_file_fsync, 31 | .splice_read = generic_file_splice_read, 32 | }; 33 | 34 | /* a new setattr function is in the minix source tree. Trying to bring that in 35 | * and see how it works. */ 36 | 37 | static int xiafs_setattr(struct dentry *dentry, struct iattr *attr) 38 | { 39 | struct inode *inode = dentry->d_inode; 40 | int error; 41 | 42 | error = setattr_prepare(dentry, attr); 43 | if (error) 44 | return error; 45 | 46 | if ((attr->ia_valid & ATTR_SIZE) && 47 | attr->ia_size != i_size_read(inode)) { 48 | error = inode_newsize_ok(inode, attr->ia_size); 49 | if (error) 50 | return error; 51 | truncate_setsize(inode, attr->ia_size); 52 | xiafs_truncate(inode); 53 | } 54 | 55 | setattr_copy(inode, attr); 56 | mark_inode_dirty(inode); 57 | return 0; 58 | } 59 | 60 | const struct inode_operations xiafs_file_inode_operations = { 61 | .setattr = xiafs_setattr, 62 | .getattr = xiafs_getattr, 63 | }; 64 | -------------------------------------------------------------------------------- /module/inode.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Porting work to modern kernels copyright (C) Jeremy Bingham, 2013. 3 | * Based on work by Linus Torvalds, Q. Frank Xia, and others as noted. 4 | * 5 | * This port of Q. Frank Xia's xiafs was done using the existing minix 6 | * filesystem code, but based on the original xiafs code in pre-2.1.21 or so 7 | * kernels. 8 | */ 9 | 10 | /* 11 | * linux/fs/xiafs/inode.c 12 | * 13 | * Copyright (C) 1991, 1992 Linus Torvalds 14 | * 15 | * Copyright (C) 1996 Gertjan van Wingerde 16 | * Minix V2 fs support. 17 | * 18 | * Modified for 680x0 by Andreas Schwab 19 | * Updated to filesystem version 3 by Daniel Aragones 20 | */ 21 | 22 | #include 23 | #include "xiafs.h" 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static int xiafs_write_inode(struct inode * inode, struct writeback_control *wbc); 32 | static int xiafs_statfs(struct dentry *dentry, struct kstatfs *buf); 33 | /* static int xiafs_remount (struct super_block * sb, int * flags, char * data);*/ 34 | 35 | static void xiafs_evict_inode(struct inode *inode) 36 | { 37 | truncate_inode_pages(&inode->i_data, 0); 38 | if (!inode->i_nlink){ 39 | inode->i_size = 0; 40 | xiafs_truncate(inode); 41 | } 42 | invalidate_inode_buffers(inode); 43 | clear_inode(inode); 44 | if (!inode->i_nlink) 45 | xiafs_free_inode(inode); 46 | } 47 | 48 | static void xiafs_put_super(struct super_block *sb) 49 | { 50 | int i; 51 | struct xiafs_sb_info *sbi = xiafs_sb(sb); 52 | 53 | for (i = 0; i < sbi->s_imap_zones; i++) 54 | brelse(sbi->s_imap_buf[i]); 55 | for (i = 0; i < sbi->s_zmap_zones; i++) 56 | brelse(sbi->s_zmap_buf[i]); 57 | kfree(sbi->s_imap_buf); 58 | sb->s_fs_info = NULL; 59 | kfree(sbi); 60 | } 61 | 62 | static struct kmem_cache * xiafs_inode_cachep; 63 | 64 | static struct inode *xiafs_alloc_inode(struct super_block *sb) 65 | { 66 | struct xiafs_inode_info *ei; 67 | ei = (struct xiafs_inode_info *)kmem_cache_alloc(xiafs_inode_cachep, GFP_KERNEL); 68 | if (!ei) 69 | return NULL; 70 | return &ei->vfs_inode; 71 | } 72 | 73 | static void xiafs_destroy_inode(struct inode *inode) 74 | { 75 | kmem_cache_free(xiafs_inode_cachep, xiafs_i(inode)); 76 | } 77 | 78 | static void init_once(void *foo) 79 | { 80 | struct xiafs_inode_info *ei = (struct xiafs_inode_info *) foo; 81 | 82 | inode_init_once(&ei->vfs_inode); 83 | } 84 | 85 | static int init_inodecache(void) 86 | { 87 | xiafs_inode_cachep = kmem_cache_create("xiafs_inode_cache", 88 | sizeof(struct xiafs_inode_info), 89 | 0, (SLAB_RECLAIM_ACCOUNT| 90 | SLAB_MEM_SPREAD), 91 | init_once); 92 | if (xiafs_inode_cachep == NULL) 93 | return -ENOMEM; 94 | return 0; 95 | } 96 | 97 | static void destroy_inodecache(void) 98 | { 99 | kmem_cache_destroy(xiafs_inode_cachep); 100 | } 101 | 102 | static const struct super_operations xiafs_sops = { 103 | .alloc_inode = xiafs_alloc_inode, 104 | .destroy_inode = xiafs_destroy_inode, 105 | .write_inode = xiafs_write_inode, 106 | .evict_inode = xiafs_evict_inode, 107 | .put_super = xiafs_put_super, 108 | .statfs = xiafs_statfs 109 | }; 110 | 111 | static int xiafs_fill_super(struct super_block *s, void *data, int silent) 112 | { 113 | struct buffer_head *bh; 114 | struct buffer_head **map; 115 | struct xiafs_super_block *xs; 116 | unsigned long i, block; 117 | struct inode *root_inode; 118 | struct xiafs_sb_info *sbi; 119 | int ret = -EINVAL; 120 | 121 | sbi = kzalloc(sizeof(struct xiafs_sb_info), GFP_KERNEL); 122 | if (!sbi) 123 | return -ENOMEM; 124 | s->s_fs_info = sbi; 125 | 126 | BUILD_BUG_ON(64 != sizeof(struct xiafs_inode)); 127 | 128 | if (!sb_set_blocksize(s, BLOCK_SIZE)) 129 | goto out_bad_hblock; 130 | 131 | /* Interesting. Minix had this as 1, but xiafs seems to want 0 for 132 | * some reason. */ 133 | if (!(bh = sb_bread(s, 0))) 134 | goto out_bad_sb; 135 | 136 | xs = (struct xiafs_super_block *) bh->b_data; 137 | s->s_magic = xs->s_magic; 138 | if (s->s_magic != _XIAFS_SUPER_MAGIC) { 139 | s->s_dev = 0; 140 | ret = -EINVAL; 141 | goto out_no_fs; 142 | } 143 | sbi->s_ninodes = xs->s_ninodes; 144 | sbi->s_nzones = xs->s_nzones; 145 | sbi->s_ndatazones = xs->s_ndatazones; 146 | sbi->s_imap_zones = xs->s_imap_zones; 147 | sbi->s_zmap_zones = xs->s_zmap_zones; 148 | sbi->s_firstdatazone = xs->s_firstdatazone; 149 | sbi->s_zone_shift = xs->s_zone_shift; 150 | sbi->s_max_size = xs->s_max_size; 151 | 152 | 153 | /* 154 | * Allocate the buffer map to keep the superblock small. 155 | */ 156 | if (sbi->s_imap_zones == 0 || sbi->s_zmap_zones == 0) 157 | goto out_illegal_sb; 158 | i = (sbi->s_imap_zones + sbi->s_zmap_zones) * sizeof(bh); 159 | map = kzalloc(i, GFP_KERNEL); 160 | if (!map) 161 | goto out_no_map; 162 | sbi->s_imap_buf = &map[0]; 163 | sbi->s_zmap_buf = &map[sbi->s_imap_zones]; 164 | 165 | block=1; 166 | for (i=0 ; i < sbi->s_imap_zones ; i++) { 167 | if (!(sbi->s_imap_buf[i]=sb_bread(s, block))) 168 | goto out_no_bitmap; 169 | block++; 170 | } 171 | for (i=0 ; i < sbi->s_zmap_zones ; i++) { 172 | if (!(sbi->s_zmap_buf[i]=sb_bread(s, block))) 173 | goto out_no_bitmap; 174 | block++; 175 | } 176 | 177 | /* set up enough so that it can read an inode */ 178 | s->s_op = &xiafs_sops; 179 | root_inode = xiafs_iget(s, _XIAFS_ROOT_INO); 180 | if (IS_ERR(root_inode)) { 181 | printk("XIAFS: error getting root inode\n"); 182 | ret = PTR_ERR(root_inode); 183 | goto out_no_root; 184 | } 185 | 186 | ret = -ENOMEM; 187 | s->s_root = d_make_root(root_inode); 188 | if (!s->s_root) 189 | goto out_iput; 190 | 191 | if (!(s->s_flags & MS_RDONLY)) { 192 | mark_buffer_dirty(bh); 193 | } 194 | return 0; 195 | 196 | out_iput: 197 | iput(root_inode); 198 | goto out_freemap; 199 | 200 | out_no_root: 201 | if (!silent) 202 | printk("XIAFS-fs: get root inode failed\n"); 203 | goto out_freemap; 204 | 205 | out_no_bitmap: 206 | printk("XIAFS-fs: bad superblock or unable to read bitmaps\n"); 207 | out_freemap: 208 | for (i = 0; i < sbi->s_imap_zones; i++) 209 | brelse(sbi->s_imap_buf[i]); 210 | for (i = 0; i < sbi->s_zmap_zones; i++) 211 | brelse(sbi->s_zmap_buf[i]); 212 | kfree(sbi->s_imap_buf); 213 | goto out_release; 214 | 215 | out_no_map: 216 | ret = -ENOMEM; 217 | if (!silent) 218 | printk("XIAFS-fs: can't allocate map\n"); 219 | goto out_release; 220 | 221 | out_illegal_sb: 222 | if (!silent) 223 | printk("XIAFS-fs: bad superblock\n"); 224 | goto out_release; 225 | 226 | out_no_fs: 227 | if (!silent) 228 | printk("VFS: Can't find a Xiafs filesystem " 229 | "on device %s.\n", s->s_id); 230 | out_release: 231 | brelse(bh); 232 | goto out; 233 | 234 | out_bad_hblock: 235 | printk("XIAFS-fs: blocksize too small for device\n"); 236 | goto out; 237 | 238 | out_bad_sb: 239 | printk("XIAFS-fs: unable to read superblock\n"); 240 | out: 241 | s->s_fs_info = NULL; 242 | kfree(sbi); 243 | return ret; 244 | } 245 | 246 | static int xiafs_statfs(struct dentry *dentry, struct kstatfs *buf) 247 | { 248 | struct super_block *sb = dentry->d_sb; 249 | struct xiafs_sb_info *sbi = xiafs_sb(sb); 250 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); 251 | buf->f_type = sb->s_magic; 252 | buf->f_bsize = sb->s_blocksize; 253 | buf->f_blocks = sbi->s_ndatazones; 254 | buf->f_bfree = xiafs_count_free_blocks(sbi); 255 | buf->f_bavail = buf->f_bfree; 256 | buf->f_files = sbi->s_ninodes; 257 | buf->f_ffree = xiafs_count_free_inodes(sbi); 258 | buf->f_namelen = _XIAFS_NAME_LEN; 259 | buf->f_fsid.val[0] = (u32)id; 260 | buf->f_fsid.val[1] = (u32)(id >> 32); 261 | 262 | return 0; 263 | } 264 | 265 | static int xiafs_writepage(struct page *page, struct writeback_control *wbc) 266 | { 267 | return block_write_full_page(page, xiafs_get_block, wbc); 268 | } 269 | 270 | static int xiafs_readpage(struct file *file, struct page *page) 271 | { 272 | return block_read_full_page(page,xiafs_get_block); 273 | } 274 | 275 | int xiafs_prepare_chunk(struct page *page, loff_t pos, unsigned len) 276 | { 277 | return __block_write_begin(page, pos, len, xiafs_get_block); 278 | } 279 | 280 | static int xiafs_write_begin(struct file *file, struct address_space *mapping, 281 | loff_t pos, unsigned len, unsigned flags, 282 | struct page **pagep, void **fsdata) 283 | { 284 | /* *pagep = NULL; */ 285 | int ret; 286 | ret = block_write_begin(mapping, pos, len, flags, pagep, 287 | xiafs_get_block); 288 | 289 | if (unlikely(ret)){ 290 | loff_t isize = mapping->host->i_size; 291 | if (pos + len > isize){ 292 | truncate_pagecache_range(mapping->host, pos + len, isize); 293 | xiafs_truncate(mapping->host); 294 | } 295 | } 296 | return ret; 297 | } 298 | 299 | static sector_t xiafs_bmap(struct address_space *mapping, sector_t block) 300 | { 301 | return generic_block_bmap(mapping,block,xiafs_get_block); 302 | } 303 | 304 | static const struct address_space_operations xiafs_aops = { 305 | .readpage = xiafs_readpage, 306 | .writepage = xiafs_writepage, 307 | .write_begin = xiafs_write_begin, 308 | .write_end = generic_write_end, 309 | .bmap = xiafs_bmap 310 | }; 311 | 312 | static const struct inode_operations xiafs_symlink_inode_operations = { 313 | .get_link = page_get_link, 314 | .getattr = xiafs_getattr, 315 | }; 316 | 317 | void xiafs_set_inode(struct inode *inode, dev_t rdev) 318 | { 319 | if (S_ISREG(inode->i_mode)) { 320 | inode->i_op = &xiafs_file_inode_operations; 321 | inode->i_fop = &xiafs_file_operations; 322 | inode->i_mapping->a_ops = &xiafs_aops; 323 | } else if (S_ISDIR(inode->i_mode)) { 324 | inode->i_op = &xiafs_dir_inode_operations; 325 | inode->i_fop = &xiafs_dir_operations; 326 | inode->i_mapping->a_ops = &xiafs_aops; 327 | } else if (S_ISLNK(inode->i_mode)) { 328 | inode->i_op = &xiafs_symlink_inode_operations; 329 | inode_nohighmem(inode); 330 | inode->i_mapping->a_ops = &xiafs_aops; 331 | } else 332 | init_special_inode(inode, inode->i_mode, rdev); 333 | } 334 | 335 | struct inode *xiafs_iget(struct super_block *sb, unsigned long ino) 336 | { 337 | struct inode *inode; 338 | struct buffer_head * bh; 339 | struct xiafs_inode * raw_inode; 340 | struct xiafs_inode_info *xiafs_inode; 341 | int zone; 342 | inode = iget_locked(sb, ino); 343 | 344 | if (!inode) 345 | return ERR_PTR(-ENOMEM); 346 | if (!(inode->i_state & I_NEW)) 347 | return inode; 348 | xiafs_inode = xiafs_i(inode); 349 | 350 | raw_inode = xiafs_raw_inode(inode->i_sb, inode->i_ino, &bh); 351 | if (!raw_inode) { 352 | iget_failed(inode); 353 | return ERR_PTR(-EIO); 354 | } 355 | inode->i_mode = raw_inode->i_mode; 356 | i_uid_write(inode, raw_inode->i_uid); 357 | i_gid_write(inode, raw_inode->i_gid); 358 | set_nlink(inode, raw_inode->i_nlinks); 359 | inode->i_size = raw_inode->i_size; 360 | inode->i_mtime.tv_sec = raw_inode->i_mtime; 361 | inode->i_atime.tv_sec = raw_inode->i_atime; 362 | inode->i_ctime.tv_sec = raw_inode->i_ctime; 363 | inode->i_mtime.tv_nsec = 0; 364 | inode->i_atime.tv_nsec = 0; 365 | inode->i_ctime.tv_nsec = 0; 366 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { 367 | inode->i_blocks=0; 368 | inode->i_rdev = old_decode_dev(raw_inode->i_zone[0]); 369 | } else { 370 | XIAFS_GET_BLOCKS(raw_inode, inode->i_blocks); 371 | /* Changing this to put the former i_ind and i_dind_zone inode 372 | * elements into the same array as the direct blocks, per the 373 | * way it works with minix and ext2. Hopefully it will simplify 374 | * using the block allocation code lifted from the minix code. 375 | */ 376 | for (zone = 0; zone < _XIAFS_NUM_BLOCK_POINTERS; zone++) 377 | xiafs_inode->i_zone[zone] = raw_inode->i_zone[zone] & 0xffffff; 378 | } 379 | xiafs_set_inode(inode, old_decode_dev(raw_inode->i_zone[0])); 380 | brelse(bh); 381 | unlock_new_inode(inode); 382 | return inode; 383 | } 384 | 385 | /* 386 | * The xiafs function to synchronize an inode. 387 | */ 388 | static struct buffer_head * xiafs_update_inode(struct inode * inode) 389 | { 390 | struct buffer_head * bh; 391 | struct xiafs_inode * raw_inode; 392 | struct xiafs_inode_info *xiafs_inode = xiafs_i(inode); 393 | int i; 394 | 395 | raw_inode = xiafs_raw_inode(inode->i_sb, inode->i_ino, &bh); 396 | if (!raw_inode) 397 | return NULL; 398 | raw_inode->i_mode = inode->i_mode; 399 | raw_inode->i_uid = fs_high2lowuid(i_uid_read(inode)); 400 | raw_inode->i_gid = fs_high2lowgid(i_gid_read(inode)); 401 | raw_inode->i_nlinks = inode->i_nlink; 402 | raw_inode->i_size = inode->i_size; 403 | raw_inode->i_mtime = inode->i_mtime.tv_sec; 404 | raw_inode->i_atime = inode->i_atime.tv_sec; 405 | raw_inode->i_ctime = inode->i_ctime.tv_sec; 406 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) 407 | raw_inode->i_zone[0] = old_encode_dev(inode->i_rdev); 408 | else { 409 | XIAFS_PUT_BLOCKS(raw_inode, inode->i_blocks); 410 | /* Changing this to put the former i_ind and i_dind_zone inode 411 | * elements into the same array as the direct blocks, per the 412 | * way it works with minix and ext2. Hopefully it will simplify 413 | * using the block allocation code lifted from the minix code. 414 | */ 415 | for (i = 0; i < _XIAFS_NUM_BLOCK_POINTERS; i++) 416 | raw_inode->i_zone[i] = (raw_inode->i_zone[i] & 0xff000000) | (xiafs_inode->i_zone[i] & 0xffffff); 417 | } 418 | mark_buffer_dirty(bh); 419 | return bh; 420 | } 421 | 422 | static int xiafs_write_inode(struct inode *inode, struct writeback_control *wbc) 423 | { 424 | int err = 0; 425 | struct buffer_head *bh; 426 | 427 | bh = xiafs_update_inode(inode); 428 | if (!bh) 429 | return -EIO; 430 | if (wbc->sync_mode == WB_SYNC_ALL && buffer_dirty(bh)) { 431 | sync_dirty_buffer(bh); 432 | if (buffer_req(bh) && !buffer_uptodate(bh)) { 433 | printk("IO error syncing xiafs inode [%s:%08lx]\n", 434 | inode->i_sb->s_id, inode->i_ino); 435 | err = -EIO; 436 | } 437 | } 438 | brelse (bh); 439 | return err; 440 | } 441 | 442 | int xiafs_getattr(const struct path *path, struct kstat *stat, u32 request_mask, unsigned int flags) 443 | { 444 | struct super_block *sb = path->dentry->d_sb; 445 | struct inode *inode = d_inode(path->dentry); 446 | generic_fillattr(inode, stat); 447 | stat->blocks = (sb->s_blocksize / 512) * xiafs_blocks(stat->size, sb); 448 | stat->blksize = sb->s_blocksize; 449 | return 0; 450 | } 451 | 452 | static struct dentry *xiafs_mount(struct file_system_type *fs_type, 453 | int flags, const char *dev_name, void *data) 454 | { 455 | return mount_bdev(fs_type, flags, dev_name, data, xiafs_fill_super); 456 | } 457 | 458 | static struct file_system_type xiafs_fs_type = { 459 | .owner = THIS_MODULE, 460 | .name = "xiafs", 461 | .mount = xiafs_mount, 462 | .kill_sb = kill_block_super, 463 | .fs_flags = FS_REQUIRES_DEV, 464 | }; 465 | 466 | static int __init init_xiafs_fs(void) 467 | { 468 | int err = init_inodecache(); 469 | if (err) 470 | goto out1; 471 | err = register_filesystem(&xiafs_fs_type); 472 | if (err) 473 | goto out; 474 | return 0; 475 | out: 476 | destroy_inodecache(); 477 | out1: 478 | return err; 479 | } 480 | 481 | static void __exit exit_xiafs_fs(void) 482 | { 483 | unregister_filesystem(&xiafs_fs_type); 484 | destroy_inodecache(); 485 | } 486 | 487 | module_init(init_xiafs_fs) 488 | module_exit(exit_xiafs_fs) 489 | MODULE_LICENSE("GPL"); 490 | 491 | -------------------------------------------------------------------------------- /module/itree.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Porting work to modern kernels copyright (C) Jeremy Bingham, 2013. 3 | * Based on work by Linus Torvalds, Q. Frank Xia, and others as noted. 4 | * 5 | * This port of Q. Frank Xia's xiafs was done using the existing minix 6 | * filesystem code, but based on the original xiafs code in pre-2.1.21 or so 7 | * kernels. 8 | */ 9 | 10 | #include 11 | #include "xiafs.h" 12 | 13 | enum {DIRECT = 8, DEPTH = 3}; 14 | 15 | typedef u32 block_t; /* 32 bit, host order */ 16 | 17 | static inline unsigned long block_to_cpu(block_t n) 18 | { 19 | return n; 20 | } 21 | 22 | static inline block_t cpu_to_block(unsigned long n) 23 | { 24 | return n; 25 | } 26 | 27 | static inline block_t *i_data(struct inode *inode) 28 | { 29 | return (block_t *)xiafs_i(inode)->i_zone; 30 | } 31 | 32 | static int block_to_path(struct inode * inode, long block, int offsets[DEPTH]) 33 | { 34 | int n = 0; 35 | char b[BDEVNAME_SIZE]; 36 | struct super_block *sb = inode->i_sb; 37 | struct xiafs_sb_info *sbi = xiafs_sb(sb); 38 | 39 | if (block < 0) { 40 | printk("XIAFS-fs: block_to_path: block %ld < 0 on dev %s\n", 41 | block, bdevname(sb->s_bdev, b)); 42 | } else if (block >= (xiafs_sb(inode->i_sb)->s_max_size/sb->s_blocksize)) { 43 | if (printk_ratelimit()) 44 | printk("XIAFS-fs: block_to_path: " 45 | "block %ld too big on dev %s\n", 46 | block, bdevname(sb->s_bdev, b)); 47 | } else if (block < 8) { 48 | offsets[n++] = block; 49 | } else if ((block -= 8) < XIAFS_ADDRS_PER_Z(sbi)) { 50 | offsets[n++] = 8; 51 | offsets[n++] = block; 52 | } else { 53 | block -= XIAFS_ADDRS_PER_Z(sbi); 54 | offsets[n++] = 9; 55 | offsets[n++] = block>>XIAFS_ADDRS_PER_Z_BITS(sbi); 56 | offsets[n++] = block & (XIAFS_ADDRS_PER_Z(sbi)-1); 57 | } 58 | return n; 59 | } 60 | 61 | /* 62 | * Porting work to modern kernels copyright (C) Jeremy Bingham, 2013. 63 | * Based on work by Linus Torvalds, Q. Frank Xia, and others as noted. 64 | * 65 | * This port of Q. Frank Xia's xiafs was done using the existing minix 66 | * filesystem code, but based on the original xiafs code in pre-2.1.21 or so 67 | * kernels. 68 | * 69 | * This code was formerly in itree_common.c 70 | */ 71 | 72 | /* Generic part */ 73 | 74 | typedef struct { 75 | block_t *p; 76 | block_t key; 77 | struct buffer_head *bh; 78 | } Indirect; 79 | 80 | static DEFINE_RWLOCK(pointers_lock); 81 | 82 | static inline void add_chain(Indirect *p, struct buffer_head *bh, block_t *v) 83 | { 84 | p->key = *(p->p = v); 85 | p->bh = bh; 86 | } 87 | 88 | static inline int verify_chain(Indirect *from, Indirect *to) 89 | { 90 | while (from <= to && from->key == *from->p) 91 | from++; 92 | return (from > to); 93 | } 94 | 95 | static inline block_t *block_end(struct buffer_head *bh) 96 | { 97 | return (block_t *)((char*)bh->b_data + bh->b_size); 98 | } 99 | 100 | static inline Indirect *get_branch(struct inode *inode, 101 | int depth, 102 | int *offsets, 103 | Indirect chain[DEPTH], 104 | int *err) 105 | { 106 | struct super_block *sb = inode->i_sb; 107 | Indirect *p = chain; 108 | struct buffer_head *bh; 109 | 110 | *err = 0; 111 | /* i_data is not going away, no lock needed */ 112 | add_chain (chain, NULL, i_data(inode) + *offsets); 113 | if (!p->key) 114 | goto no_block; 115 | while (--depth) { 116 | bh = sb_bread(sb, block_to_cpu(p->key)); 117 | if (!bh) 118 | goto failure; 119 | read_lock(&pointers_lock); 120 | if (!verify_chain(chain, p)) 121 | goto changed; 122 | add_chain(++p, bh, (block_t *)bh->b_data + *++offsets); 123 | read_unlock(&pointers_lock); 124 | if (!p->key) 125 | goto no_block; 126 | } 127 | return NULL; 128 | 129 | changed: 130 | read_unlock(&pointers_lock); 131 | brelse(bh); 132 | *err = -EAGAIN; 133 | goto no_block; 134 | failure: 135 | *err = -EIO; 136 | no_block: 137 | return p; 138 | } 139 | 140 | static int alloc_branch(struct inode *inode, 141 | int num, 142 | int *offsets, 143 | Indirect *branch) 144 | { 145 | int n = 0; 146 | int i; 147 | int parent = xiafs_new_block(inode); 148 | 149 | branch[0].key = cpu_to_block(parent); 150 | if (parent) for (n = 1; n < num; n++) { 151 | struct buffer_head *bh; 152 | /* Allocate the next block */ 153 | int nr = xiafs_new_block(inode); 154 | if (!nr) 155 | break; 156 | branch[n].key = cpu_to_block(nr); 157 | bh = sb_getblk(inode->i_sb, parent); 158 | lock_buffer(bh); 159 | memset(bh->b_data, 0, bh->b_size); 160 | branch[n].bh = bh; 161 | branch[n].p = (block_t*) bh->b_data + offsets[n]; 162 | *branch[n].p = branch[n].key; 163 | set_buffer_uptodate(bh); 164 | unlock_buffer(bh); 165 | mark_buffer_dirty_inode(bh, inode); 166 | parent = nr; 167 | } 168 | if (n == num) 169 | return 0; 170 | 171 | /* Allocation failed, free what we already allocated */ 172 | for (i = 1; i < n; i++) 173 | bforget(branch[i].bh); 174 | for (i = 0; i < n; i++) 175 | xiafs_free_block(inode, block_to_cpu(branch[i].key)); 176 | return -ENOSPC; 177 | } 178 | 179 | static inline int splice_branch(struct inode *inode, 180 | Indirect chain[DEPTH], 181 | Indirect *where, 182 | int num) 183 | { 184 | int i; 185 | 186 | write_lock(&pointers_lock); 187 | 188 | /* Verify that place we are splicing to is still there and vacant */ 189 | if (!verify_chain(chain, where-1) || *where->p) 190 | goto changed; 191 | 192 | *where->p = where->key; 193 | 194 | write_unlock(&pointers_lock); 195 | 196 | /* We are done with atomic stuff, now do the rest of housekeeping */ 197 | 198 | inode->i_ctime = current_time(inode); 199 | 200 | /* had we spliced it onto indirect block? */ 201 | if (where->bh) 202 | mark_buffer_dirty_inode(where->bh, inode); 203 | 204 | mark_inode_dirty(inode); 205 | return 0; 206 | 207 | changed: 208 | write_unlock(&pointers_lock); 209 | for (i = 1; i < num; i++) 210 | bforget(where[i].bh); 211 | for (i = 0; i < num; i++) 212 | xiafs_free_block(inode, block_to_cpu(where[i].key)); 213 | return -EAGAIN; 214 | } 215 | 216 | static inline int get_block(struct inode * inode, sector_t block, 217 | struct buffer_head *bh, int create) 218 | { 219 | int err = -EIO; 220 | int offsets[DEPTH]; 221 | Indirect chain[DEPTH]; 222 | Indirect *partial; 223 | int left; 224 | int depth = block_to_path(inode, block, offsets); 225 | 226 | if (depth == 0) 227 | goto out; 228 | 229 | reread: 230 | partial = get_branch(inode, depth, offsets, chain, &err); 231 | 232 | /* Simplest case - block found, no allocation needed */ 233 | if (!partial) { 234 | got_it: 235 | map_bh(bh, inode->i_sb, block_to_cpu(chain[depth-1].key)); 236 | /* Clean up and exit */ 237 | partial = chain+depth-1; /* the whole chain */ 238 | goto cleanup; 239 | } 240 | 241 | /* Next simple case - plain lookup or failed read of indirect block */ 242 | if (!create || err == -EIO) { 243 | cleanup: 244 | while (partial > chain) { 245 | brelse(partial->bh); 246 | partial--; 247 | } 248 | out: 249 | return err; 250 | } 251 | 252 | /* 253 | * Indirect block might be removed by truncate while we were 254 | * reading it. Handling of that case (forget what we've got and 255 | * reread) is taken out of the main path. 256 | */ 257 | if (err == -EAGAIN) 258 | goto changed; 259 | 260 | left = (chain + depth) - partial; 261 | err = alloc_branch(inode, left, offsets+(partial-chain), partial); 262 | if (err) 263 | goto cleanup; 264 | 265 | if (splice_branch(inode, chain, partial, left) < 0) 266 | goto changed; 267 | 268 | set_buffer_new(bh); 269 | goto got_it; 270 | 271 | changed: 272 | while (partial > chain) { 273 | brelse(partial->bh); 274 | partial--; 275 | } 276 | goto reread; 277 | } 278 | 279 | static inline int all_zeroes(block_t *p, block_t *q) 280 | { 281 | while (p < q) 282 | if (*p++) 283 | return 0; 284 | return 1; 285 | } 286 | 287 | static Indirect *find_shared(struct inode *inode, 288 | int depth, 289 | int offsets[DEPTH], 290 | Indirect chain[DEPTH], 291 | block_t *top) 292 | { 293 | Indirect *partial, *p; 294 | int k, err; 295 | 296 | *top = 0; 297 | for (k = depth; k > 1 && !offsets[k-1]; k--) 298 | ; 299 | partial = get_branch(inode, k, offsets, chain, &err); 300 | 301 | write_lock(&pointers_lock); 302 | if (!partial) 303 | partial = chain + k-1; 304 | if (!partial->key && *partial->p) { 305 | write_unlock(&pointers_lock); 306 | goto no_top; 307 | } 308 | for (p=partial;p>chain && all_zeroes((block_t*)p->bh->b_data,p->p);p--) 309 | ; 310 | if (p == chain + k - 1 && p > chain) { 311 | p->p--; 312 | } else { 313 | *top = *p->p; 314 | *p->p = 0; 315 | } 316 | write_unlock(&pointers_lock); 317 | 318 | while(partial > p) 319 | { 320 | brelse(partial->bh); 321 | partial--; 322 | } 323 | no_top: 324 | return partial; 325 | } 326 | 327 | static inline void free_data(struct inode *inode, block_t *p, block_t *q) 328 | { 329 | unsigned long nr; 330 | 331 | for ( ; p < q ; p++) { 332 | nr = block_to_cpu(*p); 333 | if (nr) { 334 | *p = 0; 335 | xiafs_free_block(inode, nr); 336 | } 337 | } 338 | } 339 | 340 | static void free_branches(struct inode *inode, block_t *p, block_t *q, int depth) 341 | { 342 | struct buffer_head * bh; 343 | unsigned long nr; 344 | 345 | if (depth--) { 346 | for ( ; p < q ; p++) { 347 | nr = block_to_cpu(*p); 348 | if (!nr) 349 | continue; 350 | *p = 0; 351 | bh = sb_bread(inode->i_sb, nr); 352 | if (!bh) 353 | continue; 354 | free_branches(inode, (block_t*)bh->b_data, 355 | block_end(bh), depth); 356 | bforget(bh); 357 | xiafs_free_block(inode, nr); 358 | mark_inode_dirty(inode); 359 | } 360 | } else 361 | free_data(inode, p, q); 362 | } 363 | 364 | static inline void truncate (struct inode * inode) 365 | { 366 | struct super_block *sb = inode->i_sb; 367 | block_t *idata = i_data(inode); 368 | int offsets[DEPTH]; 369 | Indirect chain[DEPTH]; 370 | Indirect *partial; 371 | block_t nr = 0; 372 | int n; 373 | int first_whole; 374 | long iblock; 375 | 376 | iblock = (inode->i_size + sb->s_blocksize -1) >> sb->s_blocksize_bits; 377 | block_truncate_page(inode->i_mapping, inode->i_size, get_block); 378 | 379 | n = block_to_path(inode, iblock, offsets); 380 | if (!n) 381 | return; 382 | 383 | if (n == 1) { 384 | free_data(inode, idata+offsets[0], idata + DIRECT); 385 | first_whole = 0; 386 | goto do_indirects; 387 | } 388 | 389 | first_whole = offsets[0] + 1 - DIRECT; 390 | partial = find_shared(inode, n, offsets, chain, &nr); 391 | if (nr) { 392 | if (partial == chain) 393 | mark_inode_dirty(inode); 394 | else 395 | mark_buffer_dirty_inode(partial->bh, inode); 396 | free_branches(inode, &nr, &nr+1, (chain+n-1) - partial); 397 | } 398 | /* Clear the ends of indirect blocks on the shared branch */ 399 | while (partial > chain) { 400 | free_branches(inode, partial->p + 1, block_end(partial->bh), 401 | (chain+n-1) - partial); 402 | mark_buffer_dirty_inode(partial->bh, inode); 403 | brelse (partial->bh); 404 | partial--; 405 | } 406 | do_indirects: 407 | /* Kill the remaining (whole) subtrees */ 408 | while (first_whole < DEPTH-1) { 409 | nr = idata[DIRECT+first_whole]; 410 | if (nr) { 411 | idata[DIRECT+first_whole] = 0; 412 | mark_inode_dirty(inode); 413 | free_branches(inode, &nr, &nr+1, first_whole+1); 414 | } 415 | first_whole++; 416 | } 417 | inode->i_mtime = inode->i_ctime = current_time(inode); 418 | mark_inode_dirty(inode); 419 | } 420 | 421 | static inline unsigned nblocks(loff_t size, struct super_block *sb) 422 | { 423 | int k = sb->s_blocksize_bits - 10; 424 | unsigned blocks, res, direct = DIRECT, i = DEPTH; 425 | blocks = (size + sb->s_blocksize - 1) >> (BLOCK_SIZE_BITS + k); 426 | res = blocks; 427 | while (--i && blocks > direct) { 428 | blocks -= direct; 429 | blocks += sb->s_blocksize/sizeof(block_t) - 1; 430 | blocks /= sb->s_blocksize/sizeof(block_t); 431 | res += blocks; 432 | direct = 1; 433 | } 434 | return res; 435 | } 436 | 437 | /* end former itree_common.c */ 438 | 439 | int xiafs_get_block(struct inode * inode, sector_t block, 440 | struct buffer_head *bh_result, int create) 441 | { 442 | return get_block(inode, block, bh_result, create); 443 | } 444 | 445 | void xiafs_truncate(struct inode * inode) 446 | { 447 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) 448 | return; 449 | truncate(inode); 450 | } 451 | 452 | unsigned xiafs_blocks(loff_t size, struct super_block *sb) 453 | { 454 | return nblocks(size, sb); 455 | } 456 | -------------------------------------------------------------------------------- /module/namei.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Porting work to modern kernels copyright (C) Jeremy Bingham, 2013. 3 | * Based on work by Linus Torvalds, Q. Frank Xia, and others as noted. 4 | * 5 | * This port of Q. Frank Xia's xiafs was done using the existing minix 6 | * filesystem code, but based on the original xiafs code in pre-2.1.21 or so 7 | * kernels. 8 | */ 9 | 10 | /* 11 | * linux/fs/xiafs/namei.c 12 | * 13 | * Copyright (C) 1991, 1992 Linus Torvalds 14 | */ 15 | 16 | #include "xiafs.h" 17 | #include 18 | #include 19 | 20 | static int add_nondir(struct dentry *dentry, struct inode *inode) 21 | { 22 | int err = xiafs_add_link(dentry, inode); 23 | if (!err) { 24 | d_instantiate(dentry, inode); 25 | return 0; 26 | } 27 | inode_dec_link_count(inode); 28 | iput(inode); 29 | return err; 30 | } 31 | 32 | static struct dentry *xiafs_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags) 33 | { 34 | struct inode * inode = NULL; 35 | ino_t ino; 36 | 37 | dentry->d_op = dir->i_sb->s_root->d_op; 38 | 39 | if (dentry->d_name.len > _XIAFS_NAME_LEN) 40 | return ERR_PTR(-ENAMETOOLONG); 41 | 42 | ino = xiafs_inode_by_name(dentry); 43 | if (ino) { 44 | inode = xiafs_iget(dir->i_sb, ino); 45 | if (IS_ERR(inode)) 46 | return ERR_CAST(inode); 47 | } 48 | d_add(dentry, inode); 49 | return NULL; 50 | } 51 | 52 | static int xiafs_mknod(struct inode * dir, struct dentry *dentry, umode_t mode, dev_t rdev) 53 | { 54 | int error; 55 | struct inode *inode; 56 | 57 | if (!old_valid_dev(rdev)) 58 | return -EINVAL; 59 | 60 | inode = xiafs_new_inode(dir, mode, &error); 61 | 62 | if (inode) { 63 | inode->i_mode = mode; 64 | xiafs_set_inode(inode, rdev); 65 | mark_inode_dirty(inode); 66 | error = add_nondir(dentry, inode); 67 | } 68 | return error; 69 | } 70 | 71 | static int xiafs_create(struct inode * dir, struct dentry *dentry, umode_t mode, 72 | bool excl) 73 | { 74 | return xiafs_mknod(dir, dentry, mode, 0); 75 | } 76 | 77 | static int xiafs_symlink(struct inode * dir, struct dentry *dentry, 78 | const char * symname) 79 | { 80 | int err = -ENAMETOOLONG; 81 | int i = strlen(symname)+1; 82 | struct inode * inode; 83 | umode_t mode; 84 | 85 | if (i > dir->i_sb->s_blocksize) 86 | goto out; 87 | 88 | mode = S_IFLNK | 0777; 89 | inode = xiafs_new_inode(dir, mode, &err); 90 | if (!inode) 91 | goto out; 92 | 93 | xiafs_set_inode(inode, 0); 94 | err = page_symlink(inode, symname, i); 95 | if (err) 96 | goto out_fail; 97 | 98 | err = add_nondir(dentry, inode); 99 | out: 100 | return err; 101 | 102 | out_fail: 103 | inode_dec_link_count(inode); 104 | iput(inode); 105 | goto out; 106 | } 107 | 108 | static int xiafs_link(struct dentry * old_dentry, struct inode * dir, 109 | struct dentry *dentry) 110 | { 111 | struct inode *inode = old_dentry->d_inode; 112 | 113 | if (inode->i_nlink >= _XIAFS_MAX_LINK) 114 | return -EMLINK; 115 | 116 | inode->i_ctime = current_time(inode); 117 | inode_inc_link_count(inode); 118 | atomic_inc(&inode->i_count); 119 | return add_nondir(dentry, inode); 120 | } 121 | 122 | static int xiafs_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode) 123 | { 124 | struct inode * inode; 125 | int err = -EMLINK; 126 | 127 | if (dir->i_nlink >= _XIAFS_MAX_LINK) 128 | goto out; 129 | 130 | inode_inc_link_count(dir); 131 | 132 | inode = xiafs_new_inode(dir, mode, &err); 133 | if (!inode) 134 | goto out_dir; 135 | 136 | inode->i_mode = S_IFDIR | mode; 137 | if (dir->i_mode & S_ISGID) 138 | inode->i_mode |= S_ISGID; 139 | xiafs_set_inode(inode, 0); 140 | 141 | inode_inc_link_count(inode); 142 | 143 | err = xiafs_make_empty(inode, dir); 144 | if (err) 145 | goto out_fail; 146 | 147 | err = xiafs_add_link(dentry, inode); 148 | if (err) 149 | goto out_fail; 150 | 151 | d_instantiate(dentry, inode); 152 | out: 153 | return err; 154 | 155 | out_fail: 156 | inode_dec_link_count(inode); 157 | inode_dec_link_count(inode); 158 | iput(inode); 159 | out_dir: 160 | inode_dec_link_count(dir); 161 | goto out; 162 | } 163 | 164 | static int xiafs_unlink(struct inode * dir, struct dentry *dentry) 165 | { 166 | int err = -ENOENT; 167 | struct inode * inode = dentry->d_inode; 168 | struct page * page; 169 | struct xiafs_direct * de; 170 | struct xiafs_direct * de_pre; 171 | 172 | de = xiafs_find_entry(dentry, &page, &de_pre); 173 | if (!de) 174 | goto end_unlink; 175 | 176 | err = xiafs_delete_entry(de, de_pre, page); 177 | if (err) 178 | goto end_unlink; 179 | 180 | inode->i_ctime = dir->i_ctime; 181 | inode_dec_link_count(inode); 182 | end_unlink: 183 | return err; 184 | } 185 | 186 | static int xiafs_rmdir(struct inode * dir, struct dentry *dentry) 187 | { 188 | struct inode * inode = dentry->d_inode; 189 | int err = -ENOTEMPTY; 190 | 191 | if (xiafs_empty_dir(inode)) { 192 | err = xiafs_unlink(dir, dentry); 193 | if (!err) { 194 | inode_dec_link_count(dir); 195 | inode_dec_link_count(inode); 196 | } 197 | } 198 | return err; 199 | } 200 | 201 | static int xiafs_rename(struct inode * old_dir, struct dentry *old_dentry, 202 | struct inode * new_dir, struct dentry *new_dentry, 203 | unsigned int flags) 204 | { 205 | struct inode * old_inode = old_dentry->d_inode; 206 | struct inode * new_inode = new_dentry->d_inode; 207 | struct page * dir_page = NULL; 208 | struct xiafs_direct * dir_de = NULL; 209 | struct page * old_page; 210 | struct xiafs_direct * old_de; 211 | struct xiafs_direct * old_de_pre; 212 | int err = -ENOENT; 213 | 214 | old_de = xiafs_find_entry(old_dentry, &old_page, &old_de_pre); 215 | if (!old_de) 216 | goto out; 217 | 218 | if (S_ISDIR(old_inode->i_mode)) { 219 | err = -EIO; 220 | dir_de = xiafs_dotdot(old_inode, &dir_page); 221 | if (!dir_de) 222 | goto out_old; 223 | } 224 | 225 | if (new_inode) { 226 | struct page * new_page; 227 | struct xiafs_direct * new_de; 228 | 229 | err = -ENOTEMPTY; 230 | if (dir_de && !xiafs_empty_dir(new_inode)) 231 | goto out_dir; 232 | 233 | err = -ENOENT; 234 | new_de = xiafs_find_entry(new_dentry, &new_page, NULL); 235 | if (!new_de) 236 | goto out_dir; 237 | inode_inc_link_count(old_inode); 238 | xiafs_set_link(new_de, new_page, old_inode); 239 | new_inode->i_ctime = current_time(new_inode); 240 | if (dir_de) 241 | drop_nlink(new_inode); 242 | inode_dec_link_count(new_inode); 243 | } else { 244 | if (dir_de) { 245 | err = -EMLINK; 246 | if (new_dir->i_nlink >= _XIAFS_MAX_LINK) 247 | goto out_dir; 248 | } 249 | inode_inc_link_count(old_inode); 250 | err = xiafs_add_link(new_dentry, old_inode); 251 | if (err) { 252 | inode_dec_link_count(old_inode); 253 | goto out_dir; 254 | } 255 | if (dir_de) 256 | inode_inc_link_count(new_dir); 257 | } 258 | 259 | xiafs_delete_entry(old_de, old_de_pre, old_page); 260 | inode_dec_link_count(old_inode); 261 | 262 | if (dir_de) { 263 | xiafs_set_link(dir_de, dir_page, new_dir); 264 | inode_dec_link_count(old_dir); 265 | } 266 | return 0; 267 | 268 | out_dir: 269 | if (dir_de) { 270 | kunmap(dir_page); 271 | put_page(dir_page); 272 | } 273 | out_old: 274 | kunmap(old_page); 275 | put_page(old_page); 276 | out: 277 | return err; 278 | } 279 | 280 | /* 281 | * directories can handle most operations... 282 | */ 283 | const struct inode_operations xiafs_dir_inode_operations = { 284 | .create = xiafs_create, 285 | .lookup = xiafs_lookup, 286 | .link = xiafs_link, 287 | .unlink = xiafs_unlink, 288 | .symlink = xiafs_symlink, 289 | .mkdir = xiafs_mkdir, 290 | .rmdir = xiafs_rmdir, 291 | .mknod = xiafs_mknod, 292 | .rename = xiafs_rename, 293 | .getattr = xiafs_getattr, 294 | }; 295 | -------------------------------------------------------------------------------- /module/xiafs.h: -------------------------------------------------------------------------------- 1 | #ifndef _XIAFS_H 2 | #define _XIAFS_H 3 | 4 | /* 5 | * Porting work to modern kernels copyright (C) Jeremy Bingham, 2013. 6 | * Based on work by Linus Torvalds, Q. Frank Xia, and others as noted. 7 | * 8 | * This port of Q. Frank Xia's xiafs was done using the existing minix 9 | * filesystem code, but based on the original xiafs code in pre-2.1.21 or so 10 | * kernels. 11 | */ 12 | 13 | /* 14 | * Adapted from: 15 | * include/linux/xia_fs.h 16 | * 17 | * Copyright (C) Q. Frank Xia, 1993. 18 | * 19 | * Based on Linus' minix_fs.h. 20 | * Copyright (C) Linus Torvalds, 1991, 1992. 21 | */ 22 | 23 | #include 24 | 25 | #define _XIAFS_SUPER_MAGIC 0x012FD16D 26 | #define _XIAFS_ROOT_INO 1 27 | #define _XIAFS_BAD_INO 2 28 | #define _XIAFS_MAX_LINK 64000 29 | /* I think this is the equivalent of s_dirsize in the minix stuff */ 30 | #define _XIAFS_DIR_SIZE 12 31 | #define _XIAFS_NUM_BLOCK_POINTERS 10 32 | 33 | #define _XIAFS_NAME_LEN 248 34 | 35 | #define _XIAFS_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof(struct xiafs_inode))) 36 | 37 | struct xiafs_inode { /* 64 bytes */ 38 | __u16 i_mode; 39 | __u16 i_nlinks; 40 | __u16 i_uid; 41 | __u16 i_gid; 42 | __u32 i_size; /* 8 */ 43 | __u32 i_ctime; 44 | __u32 i_atime; 45 | __u32 i_mtime; 46 | __u32 i_zone[_XIAFS_NUM_BLOCK_POINTERS]; 47 | }; 48 | 49 | /* 50 | * linux super-block data on disk 51 | */ 52 | struct xiafs_super_block { 53 | u_char s_boot_segment[512]; /* 1st sector reserved for boot */ 54 | __u32 s_zone_size; /* 0: the name says it */ 55 | __u32 s_nzones; /* 1: volume size, zone aligned */ 56 | __u32 s_ninodes; /* 2: # of inodes */ 57 | __u32 s_ndatazones; /* 3: # of data zones */ 58 | __u32 s_imap_zones; /* 4: # of imap zones */ 59 | __u32 s_zmap_zones; /* 5: # of zmap zones */ 60 | __u32 s_firstdatazone; /* 6: first data zone */ 61 | __u32 s_zone_shift; /* 7: z size = 1KB << z shift */ 62 | __u32 s_max_size; /* 8: max size of a single file */ 63 | __u32 s_reserved0; /* 9: reserved */ 64 | __u32 s_reserved1; /* 10: */ 65 | __u32 s_reserved2; /* 11: */ 66 | __u32 s_reserved3; /* 12: */ 67 | __u32 s_firstkernzone; /* 13: first kernel zone */ 68 | __u32 s_kernzones; /* 14: kernel size in zones */ 69 | __u32 s_magic; /* 15: magic number for xiafs */ 70 | }; 71 | 72 | struct xiafs_direct { 73 | __u32 d_ino; 74 | u_short d_rec_len; 75 | u_char d_name_len; 76 | char d_name[_XIAFS_NAME_LEN+1]; 77 | }; 78 | 79 | /* 80 | * Adapted from: 81 | * include/linux/xia_fs_i.h 82 | * 83 | * Copyright (C) Q. Frank Xia, 1993. 84 | * 85 | * Based on Linus' minix_fs_i.h. 86 | * Copyright (C) Linus Torvalds, 1991, 1992. 87 | */ 88 | 89 | struct xiafs_inode_info { /* for data zone pointers */ 90 | __u32 i_zone[_XIAFS_NUM_BLOCK_POINTERS]; 91 | struct inode vfs_inode; 92 | }; 93 | 94 | /* 95 | * Adapted from: 96 | * include/linux/xia_fs_sb.h 97 | * 98 | * Copyright (C) Q. Frank Xia, 1993. 99 | * 100 | * Based on Linus' minix_fs_sb.h. 101 | * Copyright (C) Linus Torvalds, 1991, 1992. 102 | */ 103 | 104 | #define _XIAFS_IMAP_SLOTS 8 105 | #define _XIAFS_ZMAP_SLOTS 32 106 | 107 | struct xiafs_sb_info { 108 | u_long s_nzones; 109 | u_long s_ninodes; 110 | u_long s_ndatazones; 111 | u_long s_imap_zones; 112 | u_long s_zmap_zones; 113 | u_long s_firstdatazone; 114 | u_long s_zone_shift; 115 | u_long s_max_size; /* 32 bytes */ 116 | struct buffer_head ** s_imap_buf; /* 32 bytes */ 117 | struct buffer_head ** s_zmap_buf; /* 128 bytes */ 118 | u_char s_imap_cached; /* flag for cached imap */ 119 | u_char s_zmap_cached; /* flag for cached imap */ 120 | }; 121 | 122 | /* 123 | * Adapted from: 124 | * linux/fs/xiafs/xiafs_mac.h 125 | * 126 | * Copyright (C) Q. Frank Xia, 1993. 127 | */ 128 | 129 | extern char internal_error_message[]; 130 | #define INTERN_ERR internal_error_message, __FILE__, __LINE__ 131 | #define WHERE_ERR __FILE__, __LINE__ 132 | 133 | #define XIAFS_ZSHIFT(sp) ((sp)->s_zone_shift) 134 | #define XIAFS_ZSIZE(sp) (BLOCK_SIZE << XIAFS_ZSHIFT(sp)) 135 | #define XIAFS_ZSIZE_BITS(sp) (BLOCK_SIZE_BITS + XIAFS_ZSHIFT(sp)) 136 | #define XIAFS_ADDRS_PER_Z(sp) (BLOCK_SIZE >> (2 - XIAFS_ZSHIFT(sp))) 137 | #define XIAFS_ADDRS_PER_Z_BITS(sp) (BLOCK_SIZE_BITS - 2 + XIAFS_ZSHIFT(sp)) 138 | #define XIAFS_BITS_PER_Z(sp) (BLOCK_SIZE << (3 + XIAFS_ZSHIFT(sp))) 139 | #define XIAFS_BITS_PER_Z_BITS(sp) (BLOCK_SIZE_BITS + 3 + XIAFS_ZSHIFT(sp)) 140 | #define XIAFS_INODES_PER_Z(sp) (_XIAFS_INODES_PER_BLOCK << XIAFS_ZSHIFT(sp)) 141 | 142 | /* Use the most significant bytes of zone pointers to store block counter. */ 143 | /* This is ugly, but it works. Note, We have another 7 bytes for "expansion". */ 144 | 145 | #define XIAFS_GET_BLOCKS(row_ip, blocks) \ 146 | blocks=((((row_ip)->i_zone[0] >> 24) & 0xff )|\ 147 | (((row_ip)->i_zone[1] >> 16) & 0xff00 )|\ 148 | (((row_ip)->i_zone[2] >> 8) & 0xff0000 ) ) 149 | 150 | /* XIAFS_PUT_BLOCKS should be called before saving zone pointers */ 151 | #define XIAFS_PUT_BLOCKS(row_ip, blocks) \ 152 | (row_ip)->i_zone[2]=((blocks)<< 8) & 0xff000000;\ 153 | (row_ip)->i_zone[1]=((blocks)<<16) & 0xff000000;\ 154 | (row_ip)->i_zone[0]=((blocks)<<24) & 0xff000000 155 | 156 | /* sb_info taken from 2.6.32 minix */ 157 | 158 | static inline struct xiafs_sb_info *xiafs_sb(struct super_block *sb) 159 | { 160 | return sb->s_fs_info; 161 | } 162 | 163 | static inline struct xiafs_inode_info *xiafs_i(struct inode *inode) 164 | { 165 | return list_entry(inode, struct xiafs_inode_info, vfs_inode); 166 | } 167 | 168 | /* be able to dump out data */ 169 | #define PRINT_OPAQUE_DATA(p) print_mem((p), sizeof(*(p))) 170 | static inline void print_mem(void const *vp, size_t n){ 171 | unsigned char const *p = vp; 172 | size_t i; 173 | for (i = 0; i < n; i++) 174 | printk("%02x ", p[i]); 175 | printk("\n"); 176 | } 177 | 178 | #ifdef __KERNEL__ 179 | 180 | extern struct inode * xiafs_new_inode(const struct inode * dir, umode_t mode, int * error); 181 | extern void xiafs_free_inode(struct inode * inode); 182 | extern unsigned long xiafs_count_free_inodes(struct xiafs_sb_info *sbi); 183 | extern int xiafs_prepare_chunk(struct page *page, loff_t pos, unsigned len); 184 | 185 | extern void xiafs_set_inode(struct inode *, dev_t); 186 | extern int xiafs_add_link(struct dentry*, struct inode*); 187 | extern ino_t xiafs_inode_by_name(struct dentry*); 188 | extern int xiafs_make_empty(struct inode*, struct inode*); 189 | extern struct xiafs_direct *xiafs_find_entry(struct dentry*, struct page**, struct xiafs_direct**); 190 | extern int xiafs_delete_entry(struct xiafs_direct*, struct xiafs_direct*, struct page*); 191 | extern struct xiafs_direct *xiafs_dotdot(struct inode*, struct page**); 192 | extern void xiafs_set_link(struct xiafs_direct*, struct page*, struct inode*); 193 | extern int xiafs_empty_dir(struct inode*); 194 | 195 | extern void xiafs_truncate(struct inode *); 196 | extern struct inode * xiafs_iget(struct super_block *, unsigned long); 197 | extern int xiafs_getattr(const struct path *path, struct kstat *stat, u32 request_mask, unsigned int flags); 198 | 199 | extern const struct inode_operations xiafs_file_inode_operations; 200 | extern const struct inode_operations xiafs_dir_inode_operations; 201 | extern const struct file_operations xiafs_file_operations; 202 | extern const struct file_operations xiafs_dir_operations; 203 | 204 | extern int xiafs_new_block(struct inode * inode); 205 | extern unsigned long xiafs_count_free_blocks(struct xiafs_sb_info * sbi); 206 | extern void xiafs_free_block(struct inode * inode, unsigned long block); 207 | extern int xiafs_get_block(struct inode * inode, sector_t block, struct buffer_head *bh_result, int create); 208 | extern struct xiafs_inode * xiafs_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh); 209 | extern unsigned xiafs_blocks(loff_t size, struct super_block *sb); 210 | 211 | #endif /* __KERNEL__ */ 212 | 213 | #endif /* _XIAFS_H */ 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /programs/COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 675 Mass Ave, Cambridge, MA 02139, USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | Appendix: How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 19yy 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) 19yy name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Library General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /programs/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 1996 Thomas G. McWilliams 2 | # Free Software under terms of FSF GNU GENERAL PUBLIC LICENSE Version 2 3 | 4 | SHELL = /bin/sh 5 | WARN := $(WARN) -Wall 6 | CFLAGS := $(CFLAGS) $(WARN) -O2 -fomit-frame-pointer -fno-strength-reduce 7 | 8 | AS86 = as86 -0 -a 9 | LD86 = ld86 -0 10 | 11 | CC = gcc 12 | #MAKE = 13 | CPP = $(CC) -E 14 | STRIP = strip 15 | INSTALL = install -c 16 | NROFF = groff -mandoc -Tascii 17 | 18 | # set ownership and group for executable programs 19 | binowner = root 20 | bingroup = root 21 | 22 | # set ownership and group for manpages 23 | manowner = root 24 | mangroup = man 25 | 26 | PROGS = xfsck mkxfs 27 | .PHONY : all clean dep distclean spotless uninstall veryclean 28 | 29 | .c.s: 30 | $(CC) $(CFLAGS) -S -o $*.s $< 31 | .s.o: 32 | $(AS) -c -o $*.o $< 33 | .c.o: 34 | $(CC) $(CFLAGS) -c -o $*.o $< 35 | 36 | all: xiafspgm 37 | # @cat README.upgrade 38 | 39 | xiafspgm: mkxfs xfsck 40 | 41 | mkxfs: mkxfs.c 42 | $(CC) $(CFLAGS) -o mkxfs mkxfs.c 43 | 44 | xfsck: xfsck.c bootsect.h 45 | $(CC) $(CFLAGS) -o xfsck xfsck.c 46 | 47 | install: uninstall install-pgm install-man 48 | 49 | install-pgm: mkxfs xfsck 50 | $(INSTALL) -g $(bingroup) -o $(binowner) -s -m 555 xfsck /sbin 51 | $(INSTALL) -g $(bingroup) -o $(binowner) -s -m 555 mkxfs /sbin 52 | cd /sbin ; ln -sf mkxfs mkfs.xiafs ; ln -sf xfsck fsck.xiafs 53 | chown $(binowner):$(bingroup) /sbin/fsck.xiafs 54 | chown $(binowner):$(bingroup) /sbin/mkfs.xiafs 55 | 56 | install-man: xfsck.8 mkxfs.8 57 | $(INSTALL) -g $(mangroup) -o $(manowner) -m 644 xfsck.8 /usr/share/man/man8 58 | $(INSTALL) -g $(mangroup) -o $(manowner) -m 644 mkxfs.8 /usr/share/man/man8 59 | cd /usr/share/man/man8 ; \ 60 | ln -sf mkxfs.8 mkfs.xiafs.8 ; ln -sf xfsck.8 fsck.xiafs.8 61 | chown $(manowner):$(mangroup) /usr/share/man/man8/mkfs.xiafs.8 62 | chown $(manowner):$(mangroup) /usr/share/man/man8/fsck.xiafs.8 63 | 64 | man: xfsck.8 mkxfs.8 65 | $(NROFF) xfsck.8 > xfsck.man 66 | $(NROFF) mkxfs.8 > mkxfs.man 67 | 68 | uninstall: 69 | rm -f /sbin/mkxfs /sbin/xfsck 70 | rm -f /sbin/mkfs.xiafs /sbin/fsck.xiafs 71 | rm -f /usr/share/man/man8/mkxfs.8 /usr/share/man/man8/mkfs.xiafs.8 72 | rm -f /usr/share/man/man8/xfsck.8 /usr/share/man/man8/fsck.xiafs.8 73 | 74 | clean veryclean distclean spotless: 75 | rm -f core *~ *.o *.man $(PROGS) tmp_make erro* *orig 76 | 77 | tz: veryclean 78 | THISDIR=`pwd`; cd .. && \ 79 | tar cvf - `basename $$THISDIR` | gzip - > xiafspgm-0.8.2.tar.gz 80 | 81 | dep: 82 | sed '/\#\#\# Dependencies/q' tmp_make 83 | $(CPP) $(CFLAGS) -MM *.c >>tmp_make 84 | mv tmp_make Makefile 85 | 86 | ### Dependencies 87 | mkxfs.o: mkxfs.c 88 | xfsck.o: xfsck.c bootsect.h 89 | -------------------------------------------------------------------------------- /programs/README.progs: -------------------------------------------------------------------------------- 1 | This directory contains xfsck and mkxfs (NOT to be confused with the programs 2 | used for maintaining the completly different XFS). They were adapted from the 3 | xiafspgm-0.8.1.tar.gz and xfspgm-patch-2.diff.gz files grabbed from Slackware 4 | 3.5 off the Internet, and ported to a modern Linux. These programs were old 5 | when they were included in Slackware 3.5, and that came out 15 years ago. Some 6 | work had to be done to port them to a modern system. 7 | 8 | Links are also installed for these programs as fsck.xiafs and mkfs.xiafs, along 9 | with man pages under all of their names. This is good, because their command 10 | line help isn't very helpful.. 11 | 12 | NB: xiafspgm-0.8.1 also included a program called "mkboot" that would make a 13 | simple bootloader. I have not included it here since it was unnecessary and 14 | there wasn't much reason to port it. You could say that about this entire 15 | project to get Xiafs working on a modern Linux system, of course. 16 | 17 | The original xfsck and mkxfs programs are copyright 1992 Q. Frank Xia, and bear 18 | this notice: 19 | 20 | /************************************************************************** 21 | * (C) Copyright Q. Frank Xia, 1992. All rights reserved. * 22 | * * 23 | * Permission to use and redistribute this software is hereby granted * 24 | * provided that the following conditions are met: * 25 | * 1. Source code redistribution must retain this statement. * 26 | * 2. Binary redistribution must reproduce this statement in the * 27 | * documentation provided with the distribution. * 28 | * 3. This software is provided by author Q. Frank Xia "as is". There * 29 | * are absolutely no warranties at all. The author is not responsible * 30 | * for any possible damages caused by using this software. * 31 | **************************************************************************/ 32 | 33 | The original xia.README attached to the original xfspgm-patch-2.diff file is below. 34 | 35 | ---- 36 | PATCH FOR XIA UTILITIES 37 | Copyright (c) 1996 Thomas McWilliams 38 | Distributed under terms of GNU GENERAL PUBLIC LICENSE Version 2 39 | 40 | This patch is to bring the building and installation of the Xia 41 | filesystem utilities into compliance with current Linux filesystem 42 | standards. There are no functional changes to the utilities other 43 | than fixing some mismatched printf() arguments in xfsck.c. 44 | 45 | To patch the original source code, place the files "xfspgm-patch-2" and 46 | "apply-patch.sh" in the same directory with "xiafspgm-0.8.1.z". 47 | Then you can either run the shell script "apply-patch.sh" to automatically 48 | invoke patch, OR you can run patch manually: 49 | tar zxvf xiafspgm-0.8.1.z 50 | patch -p0 < xfspgm-patch-2 2>&1 | tee patch-2.log. 51 | 52 | The author of these utilities and of the Xia filesystem is Frank Xia. 53 | He seems to have dropped out of sight, but his e-mail address was (is?) 54 | qx@math.columbia.edu. 55 | 56 | I am not actively maintaining any of the Xia code. This patch was only 57 | motivated by my converting some older Linux systems to ELF. 58 | 59 | Thomas McWilliams 60 | July 14, 1996 61 | ---- 62 | 63 | This patch is already applied here. For reference and to satisfy any needed 64 | licensing obligation, the originals of both xiafspgm-0.8.1 and 65 | xfspgm-patch-2.diff are located in the "originals" directory under this one. 66 | 67 | As of the writing of this README file, the files I used to build these tools can 68 | also be found at this Slackware mirror site: 69 | 70 | http://slackware.mirror.ac.za/slackware-3.5/source/a/bin/xfspgm-patch-2.diff.gz 71 | http://slackware.mirror.ac.za/slackware-3.5/source/a/bin/xia.README 72 | http://slackware.mirror.ac.za/slackware-3.5/source/a/bin/xiafspgm-0.8.1.tar.gz 73 | 74 | If they are unavailable, you should be able to find them at another old 75 | Slackware mirror. 76 | 77 | The changes I made to get these programs compiling and working on a modern Linux 78 | are copyright 2013, Jeremy Bingham , and are under the GPL 79 | as above. 80 | -------------------------------------------------------------------------------- /programs/bootsect.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------* 2 | * bootsect.h * 3 | * * 4 | * Copyright (C) Q. Frank Xia, 1993. All rights reserved. * 5 | * * 6 | * This software may be redistributed as per Linux copyright * 7 | * * 8 | -----------------------------------------------------------------------*/ 9 | 10 | /* Get new int size definitions; old code was (as it happens) not 64 bit clean 11 | */ 12 | 13 | #include 14 | #define SECTEXTSIZE 496 15 | #define PRITEXTSIZE 382 16 | #define ORGTEXTSIZE 446 17 | 18 | struct mast_text { 19 | u_char mast_code[PRITEXTSIZE]; 20 | struct { 21 | char os_name[15]; 22 | char part_nr; 23 | } os[4]; 24 | }; 25 | 26 | struct boot_text { 27 | u_char boot_code[SECTEXTSIZE]; 28 | uint32_t Istart_sect; 29 | uint16_t end_seg; 30 | uint16_t swap_dev; 31 | uint16_t ram_size; 32 | uint16_t video_mode; 33 | uint16_t root_dev; 34 | uint16_t boot_flag; 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /programs/mkxfs.8: -------------------------------------------------------------------------------- 1 | .TH MKXFS 8 "20 February 1993" 2 | .SH NAME 3 | mkxfs - make a xiafs file system 4 | .SH SYNOPSIS 5 | .B mkxfs 6 | .B [-c | -l file] [-k blocks] [-z blocks] device blocks 7 | .SH DESCRIPTION 8 | The command 9 | .I mkxfs 10 | makes a xiafs file system on a low level formatted block device 11 | .I device. 12 | The numeric argument 13 | .I blocks 14 | specifies the number of blocks in the file system. In this context, a 15 | block is a 1024-byte piece of disk storage, usually occupying 2 16 | physical disk sectors. Blocks are grouped into zones. A zone is 17 | the smallest amount of device space that can be allocated to a file. 18 | The default zone size is 1024 bytes, i.e., a single block. 19 | .I mkxfs 20 | builds a xiafs file system with a root directory. i-node 2 is reserved 21 | for bad blocks. The number of inodes is calculated as a function of 22 | the file system size. Currently one i-node is allocated for every four 23 | zones. 24 | 25 | This command can only be used by the super-user. 26 | 27 | .SH OPTIONS 28 | .I mkxfs 29 | has the following options: 30 | .TP 31 | .B -c 32 | .I mkxfs 33 | checks bad blocks and links them to i-node 2. 34 | a file 35 | .I badblocks.log 36 | is created in the current directory by 37 | .I mkxfs 38 | for recording. 39 | .TP 40 | .B -l file 41 | .I mkxfs 42 | reads bad block numbers from the file 43 | .I file 44 | and links them to i-node 2. 45 | .I file 46 | is an ASCII file and each line contains a single bad block number. 47 | .TP 48 | .B -k blocks 49 | reserves 50 | .I blocks 51 | block for kernel image. This reserved space could be used by a simple 52 | booter. However, the reserved space is not initialized by 53 | .I mkxfs. 54 | Mkboot(8) may be used to install a kernel image in the reserved space. 55 | .TP 56 | .B -z blocks 57 | This option specifies the zone size. The default is one block (1024 58 | bytes). 59 | The numeric argument 60 | .I blocks 61 | may be 2 or 4. Currently only the default value is supported by the kernel. 62 | 63 | .SH EXAMPLE 64 | .nf 65 | # mkxfs /dev/fd0 1440 % make a xiafs file system 66 | # mkxfs -c /dev/hda3 150000 % check bad blocks and make 67 | % a xiafs file system on hda3 68 | # mkxfs -k 512 /dev/hda1 20000 % make a xiafs file system 69 | % with 512 KB reserved. 70 | .fi 71 | .SH AUTHOR 72 | Q. Frank Xia (qx@math.columbia.edu) 73 | .SH SEE ALSO 74 | mkboot(8), xfsck(8). 75 | .SH BUGS 76 | Currently, the Linux kernel only supports xiafs with one-block 77 | zone size. 78 | The ratio of blocks-per-inode (currently 4) should be selectable 79 | through a commandline argument. 80 | -------------------------------------------------------------------------------- /programs/mkxfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mkxiafs.c - make a xiafs file system 3 | */ 4 | /************************************************************************** 5 | * (C) Copyright Q. Frank Xia, 1992. All rights reserved. * 6 | * * 7 | * Permission to use and redistribute this software is hereby granted * 8 | * provided that the following conditions are met: * 9 | * 1. Source code redistribution must retain this statement. * 10 | * 2. Binary redistribution must reproduce this statement in the * 11 | * documentation provided with the distribution. * 12 | * 3. This software is provided by author Q. Frank Xia "as is". There * 13 | * are absolutely no warranties at all. The author is not responsible * 14 | * for any possible damages caused by using this software. * 15 | **************************************************************************/ 16 | 17 | /* 18 | * Usage: mkxiafs [-c | -l path] [-k size] [-z size] device size 19 | * 20 | * size is in KB. 21 | * 22 | * -c readablility checking. 23 | * -k reserve 'size' KB for kernel image. 24 | * -l getting a list of bad blocks from a file. 25 | * -z 'size' KB in a zone, 1 KB is default. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "xiafs.h" 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #if BLOCK_SIZE != 1024 44 | #error "only block size 1024 supported" 45 | #endif 46 | 47 | #define ZONE_SIZE (BLOCK_SIZE << zone_shift) 48 | #define BITS_PER_ZONE (BLOCK_SIZE << (3 + zone_shift)) 49 | #define BITS_PER_ZONE_BITS (BLOCK_SIZE_BITS + 3 + zone_shift) 50 | #define ADDR_PER_ZONE (BLOCK_SIZE >> (2 - zone_shift)) 51 | 52 | #define NR_INODES (INODE_ZONES * _XIAFS_INODES_PER_BLOCK << zone_shift) 53 | #define INODE_ZONES (((zones - kern_zones) >> (2 + zone_shift)) \ 54 | / _XIAFS_INODES_PER_BLOCK + 1) 55 | #define IMAP_ZONES (NR_INODES / BITS_PER_ZONE + 1) 56 | #define ZMAP_ZONES ((zones - kern_zones) / BITS_PER_ZONE + 1) 57 | #define FIRST_KERN_ZONE (1 + IMAP_ZONES + ZMAP_ZONES + INODE_ZONES) 58 | #define FIRST_DATA_ZONE (FIRST_KERN_ZONE + kern_zones) 59 | #define NR_DATA_ZONES (zones - FIRST_DATA_ZONE) 60 | #define MAX_SIZE (zone_shift == 2 ? 0xffffffff : \ 61 | (((ADDR_PER_ZONE+1)*ADDR_PER_ZONE)+8) * ZONE_SIZE) 62 | 63 | char *pgm; /* program name */ 64 | u_char *zone_buf; /* main buffer */ 65 | uint32_t *indz_buf; /* inderect zone buffer */ 66 | uint32_t *dindz_buf; /* double inderect zone buffer */ 67 | int zones; /* size of the file system in zones */ 68 | int kern_zones=0; /* nr of reserved zones for kernal image */ 69 | int zone_shift=0; /* ZONE_SIZE = BLOCK_SIZE << zone_shfit */ 70 | int bad_zones=0; /* # of bad zones */ 71 | int *bad_zlist=(int *) 0; 72 | int dev; 73 | 74 | /*----------------------------------------------------------------------- 75 | * error process rutines 76 | */ 77 | void usage() 78 | { 79 | fprintf(stderr, 80 | "usage: mkxiafs [-c | -l path] [-k size] [-z size] device size\n"); 81 | exit(1); 82 | } 83 | 84 | void die(char *cp) 85 | { 86 | fprintf(stderr, "%s: %s\n", pgm, cp); 87 | exit(1); 88 | } 89 | 90 | /*------------------------------------------------------------------------ 91 | * error free read/write rutines 92 | */ 93 | void rd_zone(int zone_nr, void *buffer) 94 | { 95 | if (lseek(dev, zone_nr * ZONE_SIZE, SEEK_SET) < 0) 96 | die("seek device failed"); 97 | if (read(dev, buffer, ZONE_SIZE) < 0) 98 | die("read device failed"); 99 | } 100 | 101 | void wt_zone(int zone_nr, void *buffer) 102 | { 103 | if (lseek(dev, zone_nr * ZONE_SIZE, SEEK_SET) < 0) 104 | die("seek device failed"); 105 | if (write(dev, buffer, ZONE_SIZE) < 0) 106 | die("write device failed"); 107 | } 108 | 109 | /*---------------------------------------------------------------------- 110 | * bad block check / read bad block from a file 111 | */ 112 | static int zones_done=0; 113 | 114 | void save_bad_num(int num) 115 | { 116 | static int bad_zlist_size=0; 117 | 118 | if (bad_zones >= bad_zlist_size) { 119 | bad_zlist_size += BLOCK_SIZE; 120 | if (!(bad_zlist=realloc(bad_zlist, bad_zlist_size >> 2))) 121 | die("allocate memory failed"); 122 | } 123 | 124 | bad_zlist[bad_zones++]=num; 125 | } 126 | 127 | void alarm_intr() 128 | { 129 | if (zones_done >= zones) 130 | return; 131 | signal(SIGALRM, alarm_intr); /* set for next alarm */ 132 | alarm(2); /* alarm in 2 seconds */ 133 | printf("%d... ", zones_done); /* report how many blocks checked */ 134 | fflush(stdout); 135 | } 136 | 137 | void do_bad_ck() 138 | { 139 | FILE *bf; 140 | int i; 141 | 142 | signal(SIGALRM, alarm_intr); /* set alarm */ 143 | alarm(2); 144 | 145 | if (lseek(dev, 0, SEEK_SET) < 0) /* ready to start */ 146 | die("seek device failed"); 147 | 148 | while (zones_done++ < zones) { /* try twice */ 149 | if (read(dev, zone_buf, BLOCK_SIZE) < 0 ) { 150 | if (lseek(dev, (zones_done-1) * BLOCK_SIZE, SEEK_SET) < 0) 151 | die("seek device failed"); 152 | if (read(dev, zone_buf, BLOCK_SIZE) < 0) { 153 | if (lseek(dev, zones_done * BLOCK_SIZE, SEEK_SET) < 0) 154 | die("seek device fail"); 155 | save_bad_num(zones_done-1); /* record bad blk, 0 based */ 156 | } 157 | } 158 | } 159 | printf("\n"); 160 | bf=fopen("badblocks.log", "w"); 161 | if (!bf) { 162 | fprintf(stderr, "open file \'badblocks.log\' failed\n"); 163 | return; 164 | } 165 | for (i=0; i < bad_zones; i++) 166 | fprintf(bf, "%d\n", bad_zlist[i]); 167 | fclose(bf); 168 | } 169 | 170 | void rd_bad_num(char *bad_nr_file) 171 | { 172 | int tmp, notdone=1; /* read bad block # from a file */ 173 | char *cp; /* each line contains a single # */ 174 | FILE *fp; 175 | 176 | if (!(fp=fopen(bad_nr_file, "r"))) 177 | die("open bad block number file failed"); 178 | 179 | while ( notdone ) { 180 | if (!fgets((char *)zone_buf, 128, fp)) { 181 | if (!feof(fp)) 182 | die("read bad block number file fail"); 183 | notdone=0; 184 | } else { 185 | tmp=strtol((char *)zone_buf, &cp, 0); 186 | if ( !isspace(*cp) && *cp) 187 | die("invalid bad block number file"); 188 | save_bad_num(tmp); 189 | } 190 | } 191 | 192 | for (tmp=1; tmp < bad_zones; tmp++) { /* recycle temp */ 193 | if (bad_zlist[tmp-1] >= bad_zlist[tmp]) 194 | die("invalid bad block number file"); 195 | } 196 | if (bad_zlist[bad_zones] >= zones) 197 | die("bad block number > volume"); 198 | } 199 | 200 | void fatal_bad_ck() 201 | { 202 | int i; 203 | 204 | if (!bad_zones || (bad_zlist[0] >> zone_shift) > FIRST_DATA_ZONE) 205 | return; 206 | fprintf(stderr, "bad zone%s:", (bad_zones==1) ? "": "s"); 207 | for (i=0; i < 20 && i < bad_zones; i++) 208 | fprintf(stderr, " %d", bad_zlist[i]); 209 | if (i != bad_zones) 210 | fprintf(stderr, " ..."); 211 | fprintf(stderr, "\nfirst data block: %lu\n",(FIRST_DATA_ZONE+1)<>= zone_shift; 221 | ip1=bad_zlist; 222 | ip2=bad_zlist; 223 | endp=bad_zlist+bad_zones; 224 | while (ip2 < endp) { 225 | *ip1=*ip2++; 226 | while (ip2 < endp && *ip1==*ip2) ip2++; 227 | ip1++; 228 | } 229 | bad_zones=ip1-bad_zlist; 230 | } 231 | 232 | /*---------------------------------------------------------------------- 233 | * make super block 234 | */ 235 | void do_sup_zone() 236 | { 237 | struct xiafs_super_block * sp; 238 | 239 | memset(zone_buf, 0, ZONE_SIZE); 240 | sp=(struct xiafs_super_block *)zone_buf; 241 | sp->s_zone_size=ZONE_SIZE; 242 | sp->s_nzones=zones; 243 | sp->s_ninodes=NR_INODES; 244 | sp->s_ndatazones=NR_DATA_ZONES; 245 | sp->s_imap_zones=IMAP_ZONES; 246 | sp->s_zmap_zones=ZMAP_ZONES; 247 | sp->s_firstdatazone=FIRST_DATA_ZONE; 248 | sp->s_zone_shift=zone_shift; 249 | sp->s_max_size=MAX_SIZE; 250 | sp->s_firstkernzone=kern_zones ? FIRST_KERN_ZONE : 0; 251 | sp->s_magic=_XIAFS_SUPER_MAGIC; 252 | 253 | wt_zone(0, zone_buf); 254 | } 255 | 256 | /*------------------------------------------------------------------------- 257 | * make imap and zmap 258 | */ 259 | void do_map_zones(int start_zone, int nr_zones, int nr_bits, int first_byte) 260 | { 261 | int i; 262 | int bits, bytes; 263 | 264 | bits=nr_bits & 7; 265 | bytes=nr_bits >> 3; 266 | 267 | for (i=0; i < nr_zones; i++) { 268 | if (!bytes && !bits) { 269 | memset(zone_buf, 0xff, ZONE_SIZE); 270 | } else if (bytes < ZONE_SIZE) { 271 | memset(zone_buf, 0, bytes); 272 | zone_buf[bytes]=255 << bits; 273 | memset(zone_buf+bytes+1, 0xff, ZONE_SIZE-bytes-1); 274 | bytes=0; 275 | bits=0; 276 | } else { 277 | memset(zone_buf, 0, ZONE_SIZE); 278 | bytes-=ZONE_SIZE; 279 | } 280 | if (!i) 281 | zone_buf[0]=first_byte; 282 | wt_zone(start_zone+i, zone_buf); 283 | } 284 | } 285 | 286 | #define do_imap() do_map_zones(1, IMAP_ZONES, NR_INODES+1, 7) 287 | 288 | #define do_zmap() do_map_zones(1+IMAP_ZONES, ZMAP_ZONES, NR_DATA_ZONES+1, 3) 289 | 290 | /*------------------------------------------------------------------------ 291 | * make a file for bad blocks. All bad blocks link to ino 2. 292 | */ 293 | #define set_bit(bit_nr) (zone_buf[(bit_nr) >> 3] |= 1 << ((bit_nr) & 7)) 294 | 295 | #define z_to_bnr(zone_nr) ((zone_nr)-FIRST_DATA_ZONE+1) 296 | #define bnr_to_z(bit_nr) ((bit_nr)-1+FIRST_DATA_ZONE) 297 | 298 | void do_bad_bits() 299 | { 300 | int i, znr, cur_znr=-1; 301 | 302 | for (i=0; i < bad_zones; i++) { 303 | if ((znr = z_to_bnr(bad_zlist[i]) >> BITS_PER_ZONE_BITS) != cur_znr) { 304 | if (cur_znr >= 0) 305 | wt_zone(1+IMAP_ZONES+cur_znr, zone_buf); 306 | rd_zone(1+IMAP_ZONES+znr, zone_buf); 307 | cur_znr=znr; 308 | } 309 | set_bit(z_to_bnr(bad_zlist[i]) & (BITS_PER_ZONE -1)); 310 | } 311 | if (cur_znr >= 0) 312 | wt_zone(1+IMAP_ZONES+cur_znr, zone_buf); 313 | } 314 | 315 | static int last_used=1; 316 | static int next_bad_ind=0; 317 | 318 | uint32_t get_free_zone() 319 | { 320 | int i; 321 | uint32_t tmp; 322 | 323 | for (i=last_used+1; i < NR_DATA_ZONES; i++) { 324 | tmp=bnr_to_z(i); 325 | if (tmp != bad_zlist[next_bad_ind]) { 326 | last_used=i; /* good zone find */ 327 | rd_zone(1+IMAP_ZONES+(i>>BITS_PER_ZONE_BITS), zone_buf); 328 | set_bit(i & (BITS_PER_ZONE-1)); /* read in zmap, set z-bit */ 329 | wt_zone(1+IMAP_ZONES+(i>>BITS_PER_ZONE_BITS), zone_buf); 330 | return tmp; /* write back zmap */ 331 | } 332 | next_bad_ind++; /* bad zone, skip this zone */ 333 | } 334 | die("too many bad zones"); /* no good zone */ 335 | return 0; 336 | } 337 | 338 | void mk_bad_file(struct xiafs_inode *inode_pt) 339 | { 340 | int i, di, bad_zs, good_z=0; 341 | 342 | bad_zs=bad_zones; /* keep bad_zones */ 343 | if (bad_zs <= 8) { /* only direct zones */ 344 | for (i=0; i < bad_zs; i++) 345 | inode_pt->i_zone[i]=bad_zlist[i]; /* fill and done */ 346 | } else { 347 | for (i=0; i < 8; i++) /* have indirect zones */ 348 | inode_pt->i_zone[i]=bad_zlist[i]; /* fill direct zones */ 349 | inode_pt->i_zone[8]=get_free_zone(); /* get indirect ptr zone */ 350 | good_z++; 351 | if (bad_zs > 8 + ADDR_PER_ZONE) { /* have dindirect zones */ 352 | inode_pt->i_zone[9]=get_free_zone(); /* get dindirect ptr zone */ 353 | good_z++; 354 | } 355 | } 356 | 357 | bad_zs -= 8; /* bad zone left */ 358 | if (bad_zs > 0) { /* have indirect zones */ 359 | if (bad_zs > ADDR_PER_ZONE) { 360 | for (i=0; i < ADDR_PER_ZONE; i++) /* fill indirect ptr zone */ 361 | indz_buf[i]=bad_zlist[i+8]; 362 | } else { 363 | for (i=0; i < bad_zs; i++) 364 | indz_buf[i]=bad_zlist[i+8]; 365 | for (; i < ADDR_PER_ZONE; i++) 366 | indz_buf[i]=0; 367 | } 368 | wt_zone(inode_pt->i_zone[8], indz_buf); /* save it */ 369 | bad_zs -= ADDR_PER_ZONE; /* bad zone left */ 370 | } 371 | if (bad_zs > 0) { /* have dindirect zones */ 372 | for (di=0; di < ADDR_PER_ZONE; di++) { /* do 2nd */ 373 | if (bad_zs > 0) { 374 | dindz_buf[di]=get_free_zone(); /* get 2nd level ptr zone */ 375 | good_z++; 376 | if (bad_zs > ADDR_PER_ZONE) { 377 | for (i=0; i < ADDR_PER_ZONE; i++) /* fill 2nd level ptr zone */ 378 | indz_buf[i]=bad_zlist[8+(1+di)*ADDR_PER_ZONE+i]; 379 | } else { 380 | for (i=0; i < bad_zs; i++) 381 | indz_buf[i]=bad_zlist[8+(1+di)*ADDR_PER_ZONE+i]; 382 | for (; i < ADDR_PER_ZONE; i++) 383 | indz_buf[i]=0; 384 | } 385 | wt_zone(dindz_buf[di], indz_buf); /* write back */ 386 | bad_zs -= ADDR_PER_ZONE; /* bad zones left */ 387 | } else 388 | dindz_buf[di]=0; /* no bad zones any more */ 389 | wt_zone(inode_pt->i_zone[9], dindz_buf); 390 | } 391 | } 392 | good_z = (good_z + bad_zones) << (zone_shift + 1); 393 | inode_pt->i_zone[0] |= (good_z << 24) & 0xff000000; 394 | inode_pt->i_zone[1] |= (good_z << 16) & 0xff000000; 395 | inode_pt->i_zone[2] |= (good_z << 8) & 0xff000000; 396 | } 397 | 398 | /*------------------------------------------------------------------------ 399 | * make inodes 400 | */ 401 | void do_inode_zones() 402 | { 403 | int i, cp; 404 | struct xiafs_inode ti, *ip; 405 | 406 | memset(&ti, 0, sizeof(struct xiafs_inode)); 407 | ti.i_mode=S_IFREG; 408 | ti.i_uid=getuid(); 409 | ti.i_gid=getgid(); 410 | ti.i_nlinks=1; 411 | ti.i_size=bad_zones * ZONE_SIZE; 412 | ti.i_mtime=time(NULL); 413 | ti.i_atime=time(NULL); 414 | ti.i_atime=time(NULL); 415 | mk_bad_file(&ti); 416 | 417 | if (!(cp=umask(0))) 418 | i=0777; 419 | else 420 | i= ~cp & 0777; 421 | memset(zone_buf, 0, ZONE_SIZE); 422 | ip=(struct xiafs_inode *)zone_buf; 423 | ip->i_mode=S_IFDIR | i; 424 | ip->i_uid=ti.i_uid; 425 | ip->i_gid=ti.i_gid; 426 | ip->i_nlinks=2; 427 | ip->i_size=ZONE_SIZE; 428 | ip->i_mtime=ip->i_ctime=ip->i_atime=ti.i_mtime; 429 | ip->i_zone[0]=FIRST_DATA_ZONE | (2 << 24); 430 | ip++; 431 | *ip=ti; 432 | 433 | wt_zone(1+IMAP_ZONES+ZMAP_ZONES, zone_buf); 434 | memset(zone_buf, 0, ZONE_SIZE); 435 | for (i=1; i < INODE_ZONES; i++) 436 | wt_zone(1+IMAP_ZONES+ZMAP_ZONES+i, zone_buf); 437 | } 438 | 439 | /*----------------------------------------------------------------------- 440 | * fill kernel image zones with 0 441 | */ 442 | void do_kern_image() 443 | { 444 | int i; 445 | 446 | memset(zone_buf, 0, ZONE_SIZE); 447 | for (i=FIRST_KERN_ZONE; i < FIRST_DATA_ZONE; i++) 448 | wt_zone(i, zone_buf); 449 | } 450 | 451 | /*----------------------------------------------------------------------- 452 | * 453 | */ 454 | void do_root_dir() 455 | { 456 | struct xiafs_direct * dir_entry_pt; 457 | 458 | memset(zone_buf, 0, ZONE_SIZE); 459 | dir_entry_pt=(struct xiafs_direct *)zone_buf; 460 | dir_entry_pt->d_ino=1; 461 | dir_entry_pt->d_rec_len=12; 462 | dir_entry_pt->d_name_len=1; 463 | dir_entry_pt->d_name[0]='.'; 464 | dir_entry_pt=(struct xiafs_direct *)((u_char *)dir_entry_pt+12); 465 | dir_entry_pt->d_ino=1; 466 | dir_entry_pt->d_rec_len=ZONE_SIZE-12; 467 | dir_entry_pt->d_name_len=2; 468 | dir_entry_pt->d_name[0]='.'; 469 | dir_entry_pt->d_name[1]='.'; 470 | 471 | wt_zone(FIRST_DATA_ZONE, zone_buf); 472 | } 473 | 474 | /*------------------------------------------------------------------------ 475 | * test physical size 476 | */ 477 | void last_zone_test() 478 | { 479 | if (FIRST_DATA_ZONE >= zones) 480 | die("device too small"); 481 | *(uint32_t *)(zone_buf+ZONE_SIZE-4)=_XIAFS_SUPER_MAGIC; 482 | wt_zone(zones-1, zone_buf); 483 | sync(); 484 | memset(zone_buf, 0, ZONE_SIZE); 485 | rd_zone(zones-1, zone_buf); 486 | if (*(uint32_t *)(zone_buf+ZONE_SIZE-4)!=_XIAFS_SUPER_MAGIC) { 487 | sprintf((char *)zone_buf, "device < %d zones", zones); 488 | die((char *)zone_buf); 489 | } 490 | } 491 | 492 | /*--------------------------------------------------------------------- 493 | * report 494 | */ 495 | void report() 496 | { 497 | printf(" zone size: %d KB\n", 1<> 20); 503 | if (bad_zlist) 504 | printf(" bad zones: %d ( %lu%% )\n", bad_zones, 505 | (bad_zones*100+NR_DATA_ZONES/2)/NR_DATA_ZONES); 506 | } 507 | 508 | /*--------------------------------------------------------------------- 509 | * main rutine 510 | */ 511 | int main(int argc, char * argv[]) 512 | { 513 | int bad_ck=0; 514 | char *bad_nr_file=(char *) 0; 515 | char *dev_name; 516 | char *endp; 517 | int opt; 518 | 519 | extern int optind; 520 | extern char *optarg; 521 | 522 | pgm=argv[0]; 523 | if (getuid()) 524 | die("this program can only be run by root"); 525 | while ((opt=getopt(argc, argv, "ck:l:z:")) != EOF) { 526 | switch (opt) { 527 | case 'c': 528 | bad_ck=1; 529 | break; 530 | case 'k': 531 | kern_zones=strtol(optarg, &endp, 0); 532 | if (!isspace(*endp) && *endp) 533 | usage(); 534 | if (kern_zones < 0) 535 | usage(); 536 | break; 537 | case 'l': 538 | bad_nr_file=optarg; 539 | break; 540 | case 'z': 541 | zone_shift=strtol(optarg, &endp, 0); 542 | if (!isspace(*endp) && *endp) 543 | usage(); 544 | if (zone_shift != 1 && zone_shift != 2 && zone_shift != 4) 545 | usage(); 546 | zone_shift >>= 1; 547 | break; 548 | default: 549 | usage(); 550 | } 551 | } 552 | if (bad_ck && bad_nr_file) 553 | usage(); 554 | if (argc != optind+2) 555 | usage(); 556 | dev_name=argv[optind]; 557 | zones=strtol(argv[optind+1], &endp, 0) & ~((1 << zone_shift) - 1); 558 | if ( !isspace(*endp) && *endp) 559 | usage(); 560 | if (zones < 0 || zones > 0x400000) 561 | die("invalid volume size"); 562 | if ((dev=open(dev_name, O_RDWR)) < 0) 563 | die("open device failed"); 564 | if (!(zone_buf=(u_char *)malloc(3 * ZONE_SIZE))) 565 | die("allocate memory failed"); 566 | indz_buf=(uint32_t *)(zone_buf+ZONE_SIZE); 567 | dindz_buf=(uint32_t *)(zone_buf+ZONE_SIZE*2); 568 | 569 | zones >>= zone_shift; 570 | kern_zones = (kern_zones + (1 << zone_shift) - 1 )>> zone_shift; 571 | 572 | last_zone_test(); 573 | 574 | if (bad_ck) 575 | do_bad_ck(); 576 | if (bad_nr_file) 577 | rd_bad_num(bad_nr_file); 578 | 579 | fatal_bad_ck(); 580 | bad_blk_to_zone(); 581 | 582 | do_sup_zone(); 583 | do_imap(); 584 | do_zmap(); 585 | do_bad_bits(); 586 | do_inode_zones(); 587 | do_kern_image(); 588 | do_root_dir(); 589 | report(); 590 | 591 | exit(0); 592 | } 593 | 594 | -------------------------------------------------------------------------------- /programs/originals/xiafspgm-0.8.1/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -Wall -O6 -fomit-frame-pointer #-g 2 | 3 | AS86 =as86 -0 -a 4 | LD86 =ld86 -0 5 | 6 | CC =gcc 7 | MAKE =make 8 | CPP =$(CC) -E 9 | STRIP =strip 10 | INSTALL =install 11 | NROFF =groff -mandoc -Tascii 12 | 13 | PROGS = xfsck mkxfs mkboot 14 | 15 | .c.s: 16 | $(CC) $(CFLAGS) -S -o $*.s $< 17 | .s.o: 18 | $(AS) -c -o $*.o $< 19 | .c.o: 20 | $(CC) $(CFLAGS) -c -o $*.o $< 21 | 22 | all: 23 | @cat README.upgrade 24 | 25 | xiafspgm: mkxfs xfsck mkboot 26 | 27 | mkxfs: mkxfs.c 28 | $(CC) $(CFLAGS) -o mkxfs mkxfs.c 29 | 30 | xfsck: xfsck.c bootsect.h 31 | $(CC) $(CFLAGS) -o xfsck xfsck.c 32 | 33 | mkboot: mkboot.o image0.o image1.o image2.o 34 | $(CC) $(CFLAGS) -o mkboot mkboot.o image0.o image1.o image2.o 35 | 36 | mkboot.o : mkboot.c bootsect.h 37 | 38 | image0.c: orgdump converter 39 | ./converter orgtext < orgdump > image0.c 40 | 41 | image1.c: primary converter 42 | ./converter pritext < primary > image1.c 43 | 44 | image2.c: secondary converter 45 | ./converter sectext < secondary > image2.c 46 | 47 | converter: converter.o 48 | gcc -o converter converter.o 49 | 50 | primary: primary.s 51 | $(AS86) -o primary.o primary.s 52 | $(LD86) -s -o primary primary.o 53 | 54 | secondary: secondary.s 55 | $(AS86) -o secondary.o secondary.s 56 | $(LD86) -s -o secondary secondary.o 57 | 58 | install: install-pgm install-man 59 | 60 | install-pgm: mkxfs xfsck mkboot 61 | $(INSTALL) -g bin -o root -s -m 755 xfsck /bin 62 | $(INSTALL) -g bin -o root -s -m 755 mkxfs /bin 63 | $(INSTALL) -g bin -o root -s -m 755 mkboot /bin 64 | 65 | install-man: xfsck.8 mkxfs.8 mkboot.8 66 | $(INSTALL) -g bin -o root -m 644 xfsck.8 /usr/man/man8 67 | $(INSTALL) -g bin -o root -m 644 mkxfs.8 /usr/man/man8 68 | $(INSTALL) -g bin -o root -m 644 mkboot.8 /usr/man/man8 69 | 70 | man: xfsck.8 mkxfs.8 mkboot.8 71 | $(NROFF) xfsck.8 > xfsck.man 72 | $(NROFF) mkxfs.8 > mkxfs.man 73 | $(NROFF) mkboot.8 > mkboot.man 74 | 75 | uninstall: 76 | rm -f /bin/mkxfs /bin/xfsck /bin/mkboot 77 | rm -f /usr/man/man8/mkxfs.8 /usr/man/man8/xfsck.8 /usr/man/man8/mkboot.8 78 | 79 | clean veryclean: 80 | rm -f core *~ *.o *.man $(PROGS) 81 | rm -f converter image0.c image1.c primary image2.c secondary 82 | 83 | tz: veryclean 84 | cd .. && tar cvf - xiafspgm | compress - > xiafspgm.tar.Z 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /programs/originals/xiafspgm-0.8.1/README.mkboot: -------------------------------------------------------------------------------- 1 | README 2 | 3 | for mkboot 4 | 5 | Q. Frank Xia 6 | qx@math.columbia.edu 7 | March 20, 1993 8 | 9 | 10 | Mkboot is a small, easy to install and easy to use Linux booter. 11 | It is filesystem independent (not really). The binary distribution 12 | contains nothing but a 13KB mkboot. 13 | 14 | 15 | The procedure of booting: 16 | A PC based system is usually booted as following. When 17 | power is turned on, the BIOS load the master boot sector 18 | which is the first sector of the first hard disk. The first 19 | 446 bytes of the master boot sector usually contains a small 20 | program and the last 66 bytes contains a partition table and 21 | a boot sector signature. The program looks for an "active" 22 | partition. Once found, it load the first sector, the secondary 23 | booter, of the active partition. Then it gives the control 24 | to the secondary booter. It is the secondary booter who 25 | take case the rest of the booting. 26 | 27 | What mkboot provide ? 28 | Mkboot provides both a master booter and a secondary booter. 29 | In addition, it also provides a traditional master boot 30 | sector, so one can uninstall mkboot. The master booter and 31 | the secondary booter mkboot provide are independent. i.e., 32 | the master booter can work with other secondary booter and 33 | the secondary booter can work with other master booter. 34 | 35 | How to install the master booter ? 36 | The syntex for installing master booter is like this. 37 | 38 | # mkboot -M /dev/hda -2 "Linux 0.99.7" -4 "OLD Linux" -1 MS-DOS 39 | 40 | Where, switch "-M" means dealing with master boot sector. 41 | "/dev/hda" specifies which special deivce is the first disk. 42 | One can fool mkboot by using other block device, so that 43 | one can practise on floppy until one is convinced that it is 44 | safe to use mkboot with hard disk and that you like it. 45 | The switch "-2" "-4" and "-1" specify which partitions are 46 | bootable. The partition number ranges from 1 to 4 for the 47 | four primary partitions. "Linux 0.99.7", "OLD Linus" and MS-DOS 48 | are the names one gives to bootable systems respectively. They 49 | will be showed on the menu the master booter displays during 50 | booting. 51 | 52 | To uninstall mkboot do 53 | 54 | # mkboot -M /dev/hda 55 | 56 | 57 | How the master booter works ? 58 | After the BIOS loads the master booter, the booter diskplays 59 | a menu. The entries in the memu is specified by the command 60 | line options of mkboot as above. For instance, the booter 61 | installed above will show a menu looks like this. 62 | 63 | Frank Xia's Linux Booter v0.8 64 | 65 | [1] Linux 0.99.7 66 | [2] OLD Linux 67 | [3] MS-DOS 68 | 69 | Boot: 70 | 71 | The order of the entries is the same as specified in the command 72 | line options. The numbers in the menu has nothing to do with 73 | the partition numbers. The first system is the default one. 74 | One can choose one of them to boot. If one hit the key other than 75 | all the numbers showed on the menu or no key is hit after 15 seconds, 76 | the master booter will boot the default partiton. 77 | 78 | How to install the secondary booter ? 79 | If you want install the secondary booter and the kernel image 80 | in xiafs filesystem on /dev/hda2, do 81 | 82 | # mkboot /dev/hda2 < zImage 83 | 84 | The xiafs filesystem should reserve at least as much as zImage 85 | needed for kernel image. For hard disk, 512KB reserved space 86 | is recommanded for future upgrade. For floppy, one just 87 | need to reserve as much as zImage need. The default root device 88 | is the device you installs secondary booter and the kernel image. 89 | If you want use other device as root device you can use seitch "-f". 90 | For example, If you want install the booter and the kernel image 91 | on /dev/hda2 and use /dev/hdb6 as root device, do 92 | 93 | # mkboot -f /dev/hdb6 /dev/hda2 < zImage 94 | 95 | If you do not have xiafs, you have to use one partition for 96 | the secondary booter and the kernel image (there are better 97 | approach, see "Things to do" section). You may make a small 98 | partition, 512KB is recommanded, for this purpose. For an 99 | example, If you want install booter and kernel image on 100 | /dev/hda4 and use /dev/hdb1 as root device, do 101 | 102 | # mkboot -r /dev/hdb1 /dev/hda4 < zImage 103 | 104 | Note, if you use "-r" switch, the contants of /dev/hda4 is 105 | over written by the booter and the kernel. 106 | 107 | How to use mkboot to make a bootable root diskette ? 108 | Suppose the size of zImage you made is 180KB, do 109 | 110 | # mkxfs -k 180 /dev/fd0 1440 111 | # mkboot /dev/fd0 < zImage 112 | 113 | Where 1440 is the size of filesystem. If your "disk A:" is 1.2MB 114 | use 1200. Then you may mount the floppy, make directories and 115 | copy necessary file to the floppy. 116 | To install Linux on a hard disk from the bootable root diskette, 117 | do 118 | 119 | # xfsck -k /dev/fd0 | mkboot 120 | 121 | where "xfsck -k " reads the kernel from the reserved 122 | space on the diskette and feed it into mkboot. 123 | 124 | What caution one should take ? 125 | mkboot, as any booter installation program, will write something 126 | into the "reserved area" in the filesystem. If mkboot get wrong 127 | information, it may trash the filesystem. If you use mkboot 128 | without using switch "-M", it at most trash the partition you 129 | specified. So make a backup of that partition before installing 130 | secondary booter and the kernel image. With switch "-M", it is 131 | more dangerous because mkboot will write the master booter to 132 | the first sector of the first disk, which contains the partition 133 | table. You may do following to avoid the possible damage. 134 | 135 | 136 | 1. Copy the first sector to a file 137 | 138 | # dd if=/dev/hda of=master.bak bz=512 count=1 139 | 140 | and save master.bak in a bootable root diskette. In case the 141 | partition table get trashed, you can restore it by booting the 142 | root diskette and do 143 | 144 | # dd if=master.bak of=/dev/hda bz=512 count=1 145 | 146 | 2. Copy the first sector to a floppy 147 | 148 | # dd if=/dev/hda of=/dev/fd0 bz=512 count=1 149 | 150 | 3. Install the master booter on the floppy 151 | 152 | # mkboot -M 153 | 154 | 4. Leave the floppy in the "disk A:", reboot the system. 155 | 156 | If it works, you may install the master booter on your hard disk. 157 | 158 | Things to do. 159 | There are two approaches to the booter. One approaches is to use a 160 | sophiscated booter and put the kernel image in a file under root 161 | directory or some other directory. The booter has to know more or 162 | less the filesystem and/or the geometry of the disk. LILO and 163 | Shoelace use this approach. The other approach is to use a simple 164 | booter and put the kernel image in a contiguous sectors. This is 165 | the approach mkboot use. Since all Linux filesystem except xiafs as 166 | I know does not reserve space for kernel image, there are 167 | difficulties to put kernel image in contiguous sectors. We can get 168 | around this difficulty in two ways. The first one is to use a 169 | raw partition as above. 170 | 171 | # mkboot -r /dev/hdb6 /dev/hda4 < zImage 172 | 173 | where /dev/hda4 is used as a raw device. Another way to get around 174 | is like this: Make a filesystem, say e2fs, smaller than the partition. 175 | The space which is not used by the filesystem is "reserved" for 176 | the kernel image. One can put kernel image there. 177 | 178 | The mkboot support the first mathod, namely the raw device. It is 179 | not difficult to support the second method. Because I have other 180 | higher prioraty things to do, I leave it open. If there are 181 | someone like to hack mkboot to support second method, I will 182 | happy to put it into the mkboot. 183 | 184 | Limitation. 185 | The master booter only support four primary partitions. 186 | 187 | --- END of README --- 188 | 189 | 190 | -------------------------------------------------------------------------------- /programs/originals/xiafspgm-0.8.1/README.upgrade: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Which version of xiafspgm works with which kernel version ? 5 | xiafspgm 0.8, 0.8.1 work with Linux/xiafs-0.7.3, Linux-0.99.7A. 6 | xiafspgm 0.7.1 works with xiafs-0.7.3 and/or earlier version. 7 | 8 | !!! DO NOT USE xiafspgm-0.7.1 OR EARLIER VERSION AFTER YOU HAVE RUN 9 | (0.8/0.8.1) xfsck. 10 | 11 | To upgrade to Linux-0.99.7A/xiafspgm-0.8.1, do 12 | 13 | 1). Compile 0.99.7A kernel and xiafspgm-0.8.1 under any version. 14 | 15 | 2). Install the kernel (one may use mkboot included in xiafspgm-0.8.1). 16 | 17 | 3). Boot the new kernel, and make sure the new kernel works for you. 18 | 19 | 4). Run (0.8.1) "xfsck -a /dev/xxx", xfsck will report many "bad i_blocks". 20 | You can safely ignore this error message when you run xfsck first 21 | time. 22 | 23 | 5). replace old xiafs and xfsck with new ones. 24 | 25 | 26 | 27 | If you want to check filesystem during booting, put "xfsck -r " 28 | in "/etc/rc". In any case, do not use "xfsck -a" unless you know what 29 | you are doing. 30 | 31 | 32 | 33 | *********** type "make xiafspgm" to compile ****************** 34 | -------------------------------------------------------------------------------- /programs/originals/xiafspgm-0.8.1/bootsect.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------* 2 | * bootsect.h * 3 | * * 4 | * Copyright (C) Q. Frank Xia, 1993. All rights reserved. * 5 | * * 6 | * This software may be redistributed as per Linux copyright * 7 | * * 8 | -----------------------------------------------------------------------*/ 9 | 10 | #define SECTEXTSIZE 496 11 | #define PRITEXTSIZE 382 12 | #define ORGTEXTSIZE 446 13 | 14 | struct mast_text { 15 | u_char mast_code[PRITEXTSIZE]; 16 | struct { 17 | char os_name[15]; 18 | char part_nr; 19 | } os[4]; 20 | }; 21 | 22 | struct boot_text { 23 | u_char boot_code[SECTEXTSIZE]; 24 | u_long Istart_sect; 25 | u_short end_seg; 26 | u_short swap_dev; 27 | u_short ram_size; 28 | u_short video_mode; 29 | u_short root_dev; 30 | u_short boot_flag; 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /programs/originals/xiafspgm-0.8.1/converter.c: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------* 2 | * converter.c * 3 | * * 4 | * Copyright (C) Q. Frank Xia, 1993. All rights reserved. * 5 | * * 6 | * This software may be redistributed as per Linux copyright * 7 | * * 8 | -----------------------------------------------------------------------*/ 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #define MINIX_HEADER 32 16 | 17 | void die(char * str) 18 | { 19 | fprintf(stderr,"convert: %s\n", str); 20 | exit(1); 21 | } 22 | 23 | int main(int argc, char ** argv) 24 | { 25 | int i; 26 | unsigned char buf[1024]; 27 | 28 | if ( *(argv[1]) != 'o' ) { 29 | for (i=0; i < 1024; i++) buf[i]=0; 30 | if (read(0, buf, MINIX_HEADER) != MINIX_HEADER 31 | || ((long *) buf)[0] != 0x04100301 32 | || ((long *) buf)[1] != MINIX_HEADER 33 | || ((long *) buf)[3] != 0 34 | || ((long *) buf)[4] != 0 35 | || ((long *) buf)[5] != 0 36 | || ((long *) buf)[7] != 0 ) 37 | die("bad file format"); 38 | } 39 | if ( read(0, buf, 1024) != 512 40 | || (*(unsigned short *)(buf+510)) != 0xAA55 ) 41 | die("bad file format"); 42 | 43 | fprintf(stdout, "unsigned char %s[512]={\n", argv[1]); 44 | for (i=0; i < 512; i++) { 45 | if ( !(i & 7) ) 46 | fprintf(stdout, " "); 47 | fprintf(stdout, " 0x%02X", buf[i]); 48 | if ( i != 511 ) 49 | fprintf(stdout, ","); 50 | if ( !((i+1) & 7) ) 51 | fprintf(stdout, "\n"); 52 | } 53 | fprintf(stdout, "};\n"); 54 | exit(0); 55 | } 56 | -------------------------------------------------------------------------------- /programs/originals/xiafspgm-0.8.1/mkboot.8: -------------------------------------------------------------------------------- 1 | .TH MKBOOT 8 "14 March 1993" 2 | .SH NAME 3 | mkboot - install kernel image and make a system bootable 4 | .SH SYNOPSIS 5 | .B mkboot [-fr root-dev] block-dev 6 | 7 | .B mkboot -M disk-dev [-partition-number OS-name] 8 | .SH DESCRIPTION 9 | The command 10 | .I mkboot 11 | can only be used by the super-user. 12 | 13 | .I mkboot, 14 | by default, puts a secondary booter at the first sector of a partition with 15 | xiafs file system specified by 16 | .I block-dev 17 | and installs a kernel image in the space reserved for it in the xiafs. 18 | The reserved space should be at least as big as the kernel image. 19 | For future kernel upgrade, 512KB reserved space for kernel image is 20 | recommanded for bootable hard disk partitions. 21 | .I mkboot, 22 | by default, changes the root device to 23 | .I block-dev. 24 | .I mkboot 25 | provides the secondary booter. The kernel image is read from the 26 | stardard input. 27 | The default can be changed by using following options. 28 | 29 | .SH OPTIONS 30 | .I mkboot 31 | has the following options: 32 | .TP 33 | .B -f root-dev 34 | Force 35 | .I root-dev 36 | as root device 37 | .TP 38 | .B -r root-dev 39 | Install secondary booter and the kernel image on the raw device 40 | .I block-dev 41 | and use 42 | .I root-dev 43 | as root device. This option make the booter work with any file system. 44 | One may make a small partition for this purpose. 512KB is recommanded. 45 | .TP 46 | .B -M disk-dev 47 | If there are at least one 48 | .I -partition-number OS-name 49 | option, the 50 | .I mkboot 51 | installs the master booter, otherwise a traditional master booter 52 | is restored in the first sector 53 | of the first disk specified by 54 | .I disk-dev. 55 | The master booter is provided by mkboot. 56 | For the reason which will become clear soon, 57 | .I mkboot 58 | does not check if 59 | .I disk-dev 60 | is the first hard disk. 61 | .TP 62 | .B -partition-number OS-name 63 | Where, 64 | .I partition-number 65 | ranges from 1 to 4. 66 | This option is used with option 67 | .I -M disk-dev. 68 | This option specifies the bootable partition and its name one want to 69 | see in the menu displayed by the master booter during booting. 70 | One can specifies at most four bootable partitions. The name of the 71 | OS' can be as long as 15 charactors. 72 | 73 | .SH EXAMPLE 74 | This example installs the secondary booter and the kernel image 75 | on the hda2, making /dev/hda2 as the root device. 76 | 77 | .nf 78 | # mkxfs -k 512 /dev/hda2 16000 79 | # mkboot /dev/hda2 < zImage 80 | .fi 81 | 82 | This example installs the secondary booter and the kernel image 83 | on the raw hda2, making /dev/hdb1 as the root device. Note that 84 | contants of hda2 is over wrotten by the booter and the image 85 | since this is installing on the raw device. 86 | 87 | .nf 88 | # mkboot -r /dev/hdb1 /dev/hda2 < zImage 89 | .fi 90 | 91 | To install the master booter, additional care may be taken to avoid 92 | the possible disaster. First make a floppy to simulate the installation. 93 | 94 | .nf 95 | # dd if=/dev/hda of=/dev/fd0 bs=512 count=1 96 | # mkboot -M /dev/fd0 -2 "LINUX 0.99.7" -3 "LINUX 0.99.6" -1 MS-DOS 97 | .fi 98 | 99 | Then reboot the machine with the floppy in "drive A:". 100 | If it works, do it on hard drive. 101 | 102 | .nf 103 | # mkboot -M /dev/hda -2 "LINUX 0.99.7" -3 "OLD LINUX" -1 MS-DOS 104 | .fi 105 | 106 | .SH AUTHOR 107 | Q. Frank Xia (qx@math.columbia.edu) 108 | .SH SEE ALSO 109 | mkxfs(8). 110 | 111 | -------------------------------------------------------------------------------- /programs/originals/xiafspgm-0.8.1/mkboot.c: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------* 2 | * mkboot.c * 3 | * * 4 | * Copyright (C) Q. Frank Xia, 1993. All rights reserved. * 5 | * * 6 | * This software may be redistributed as per Linux copyright * 7 | * * 8 | -----------------------------------------------------------------------*/ 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "bootsect.h" 25 | 26 | #define VERSION "0.8" 27 | 28 | #define FLOPPY 2 29 | #define IDE 3 30 | #define SCSI 8 31 | 32 | struct partition_table { 33 | u_char who_care[8]; 34 | u_long start_sect; 35 | u_long len_in_sect; 36 | }; 37 | 38 | union { 39 | struct mast_text mastsect; 40 | struct boot_text bootsect; 41 | struct xiafs_super_block supblock; 42 | char dummy[1024]; 43 | } super_buf; 44 | 45 | #define supb super_buf.supblock 46 | #define master super_buf.mastsect 47 | #define bsect super_buf.bootsect 48 | 49 | char *pgm_name; /* program name */ 50 | 51 | #define INST_SEC_BOOT 0 52 | #define INST_PRI_BOOT 1 53 | #define REST_PRI_BOOT 2 54 | 55 | int action; 56 | int raw_boot; 57 | char *os_name[4]; 58 | int os_part[4]; 59 | int os_nr; 60 | int blk_dev; 61 | char *blk_dev_name; 62 | char *root_dev_name; 63 | int part_dev; 64 | struct partition_table part_tab[4]; 65 | 66 | u_char buf[512]; 67 | 68 | extern u_char orgtext[]; 69 | extern u_char pritext[]; 70 | extern u_char sectext[]; 71 | 72 | void die(char * format, ...) 73 | { 74 | va_list ap; 75 | 76 | va_start(ap, format); 77 | 78 | fprintf(stderr, "%s: ", pgm_name); 79 | vfprintf(stderr, format, ap); 80 | fprintf(stderr, "\n"); 81 | 82 | va_end(ap); 83 | exit(1); 84 | } 85 | 86 | void usage() 87 | { 88 | fprintf(stderr, "usage: %s -M disk_dev [-partition OS_name]\n", pgm_name); 89 | fprintf(stderr, " %s [-fr root_dev] block_dev\n", pgm_name); 90 | exit(1); 91 | } 92 | 93 | int confirm() 94 | { 95 | char c; 96 | 97 | fprintf(stderr, "Is this what you want to do ? [y/n] "); 98 | fflush(stderr); 99 | c=getchar(); 100 | if (c != 'y' && c != 'Y') 101 | return 0; 102 | getchar(); 103 | fprintf(stderr, "\nAre you sure ? [y/n] "); 104 | fflush(stderr); 105 | c=getchar(); 106 | fprintf(stderr, "\n"); 107 | if (c != 'y' && c != 'Y') 108 | return 0; 109 | return 1; 110 | } 111 | 112 | void parse_pri(int argc, char *argv[]) 113 | { 114 | extern char * optarg; 115 | int c; 116 | 117 | os_nr=0; 118 | while ((c = getopt(argc, argv, "1:2:3:4:M:")) != EOF) 119 | switch (c) { 120 | case '1': 121 | case '2': 122 | case '3': 123 | case '4': 124 | if (os_nr > 3) 125 | die("Only 4 partitions are supported."); 126 | os_name[os_nr] = optarg; 127 | os_part[os_nr] = c - '0'; 128 | os_nr++; 129 | break; 130 | case 'M': 131 | if (os_nr > 0) 132 | usage(); 133 | blk_dev_name = optarg; 134 | break; 135 | default : usage(); 136 | } 137 | if ( os_nr == 0) 138 | action = REST_PRI_BOOT; 139 | else 140 | action = INST_PRI_BOOT; 141 | } 142 | 143 | void parse_sec(int argc, char *argv[]) 144 | { 145 | extern char * optarg; 146 | extern int optind; 147 | int c; 148 | 149 | raw_boot = 0; 150 | root_dev_name = NULL; 151 | while ((c = getopt(argc, argv, "f:r:")) != EOF) 152 | switch(c) { 153 | case 'f': 154 | case 'r': 155 | if (c == 'r') 156 | raw_boot = 1; 157 | root_dev_name = optarg; 158 | break; 159 | default: usage(); 160 | } 161 | blk_dev_name = argv[optind]; 162 | if (!root_dev_name) 163 | root_dev_name = blk_dev_name; 164 | if (optind+1 < argc) 165 | usage(); 166 | } 167 | 168 | void parse_arg(int argc, char *argv[]) 169 | { 170 | char *cp; 171 | 172 | if (argc < 2) 173 | usage(); 174 | action = INST_SEC_BOOT; 175 | cp = argv[1]; 176 | if (cp[0] == '-' && cp[1] == 'V' && !cp[2]) { 177 | printf("mkboot, Version %s\n", VERSION); 178 | exit(0); 179 | } 180 | if (cp[0] == '-' && cp[1] == 'M' && !cp[2]) 181 | parse_pri(argc, argv); 182 | else 183 | parse_sec(argc, argv); 184 | } 185 | 186 | void get_part_tab(char * blk_dev_name) 187 | { 188 | char * cp, * cp2; 189 | char tmp; 190 | int fd; 191 | u_short signature; 192 | 193 | cp2 = cp = blk_dev_name + strlen(blk_dev_name) - 1; 194 | while (*cp >= '0' && *cp <= '9') cp--; 195 | if (cp == cp2) 196 | die("bad block device name `%s'", blk_dev_name); 197 | cp++; 198 | tmp = *cp; 199 | *cp = 0; 200 | if ((fd = open(blk_dev_name, O_RDONLY)) < 0) 201 | die("open device `%s' failed", blk_dev_name); 202 | if (lseek(fd, 0x1be, SEEK_SET) != 0x1be || read(fd, part_tab, 64) != 64 203 | || read(fd, &signature, 2) != 2) 204 | die("read device `%s' failed", blk_dev_name); 205 | if (signature != 0xAA55) 206 | die("bad partition table"); 207 | close(fd); 208 | *cp = tmp; 209 | } 210 | 211 | 212 | int get_rdev(char * device) 213 | { 214 | struct stat ds; 215 | int major; 216 | 217 | stat(device, &ds); 218 | if ( S_ISBLK(ds.st_mode) ) { 219 | major = MAJOR(ds.st_rdev); 220 | if (major == FLOPPY || major == IDE || major == SCSI) 221 | return ds.st_rdev; 222 | } 223 | return 0; 224 | } 225 | 226 | 227 | void get_super_block() 228 | { 229 | if (!raw_boot) { /* read in super block */ 230 | if (read(blk_dev, (void *)&super_buf, 1024) != 1024) 231 | die("read device `%s' failed", blk_dev_name); 232 | if (supb.s_magic != _XIAFS_SUPER_MAGIC) 233 | die("super magic mismatch"); 234 | } 235 | 236 | /* read in bootsect from Image */ 237 | if (read(0, (void *)&super_buf, 512) != 512 || bsect.boot_flag != 0xAA55) 238 | die("bad kernel image"); 239 | 240 | memcpy((void *)&super_buf, sectext, SECTEXTSIZE); 241 | } 242 | 243 | 244 | int put_image(u_long start_sect, int sectors) 245 | { 246 | int tmp, i, count = 0; 247 | u_char *cp; 248 | 249 | if (lseek(blk_dev, start_sect * 512, SEEK_SET) != start_sect * 512) 250 | die("seek device `%s' failed", blk_dev_name); 251 | while ((tmp = read(0, buf, 512)) > 0) { 252 | count ++; 253 | if (count > sectors) 254 | die("not enought space"); 255 | if (tmp != 512) { 256 | cp = tmp + (u_char *) buf; 257 | for (i = tmp; i < 512; i++) 258 | *cp++ = 0; 259 | } 260 | if (write(blk_dev, buf, 512) != 512) 261 | die("write to device `%s' failed", blk_dev_name); 262 | if (tmp != 512) { 263 | count--; 264 | goto put_image_done; 265 | } 266 | } 267 | 268 | put_image_done: 269 | 270 | printf("kernel image size %d bytes\n", (count+1) * 512 + tmp); 271 | return count + (tmp ? 1 : 0); 272 | } 273 | 274 | 275 | void put_super_block(u_long Istart_sector, int kern_sectors) 276 | { 277 | u_long tmp; 278 | 279 | bsect.root_dev = get_rdev(root_dev_name); 280 | bsect.Istart_sect = Istart_sector; 281 | 282 | tmp = (kern_sectors + 127) / 128 + 1; /* rundup to 64KB + sys_seg */ 283 | tmp *= 0x1000; 284 | bsect.end_seg = tmp; 285 | 286 | if (!raw_boot) { 287 | tmp = 1 << (1 + supb.s_zone_shift); 288 | supb.s_kernzones = (kern_sectors + tmp - 1) / tmp; 289 | } 290 | 291 | tmp = raw_boot ? 512 : 1024; 292 | if (lseek(blk_dev, 0, SEEK_SET) != 0 || write(blk_dev, &super_buf, tmp) != tmp) 293 | die("write device `%s' failed", blk_dev_name); /* put super block */ 294 | } 295 | 296 | 297 | void inst_sec_boot() 298 | { 299 | int rdev, is_floppy; 300 | u_long sect_reserved, sect_aligned, start_sect; 301 | 302 | if (!(rdev = get_rdev(blk_dev_name))) 303 | die("bad block device name"); 304 | if ( MAJOR(rdev) == FLOPPY ) 305 | is_floppy = 1; 306 | else 307 | is_floppy = 0; 308 | rdev &= 0xf; 309 | rdev--; 310 | if (!is_floppy && ( rdev < 0 || rdev > 3) ) 311 | die("partition number not supported"); 312 | 313 | if (!is_floppy) 314 | get_part_tab(blk_dev_name); 315 | if ( (blk_dev = open(blk_dev_name, O_RDWR)) < 0 ) 316 | die("open `%s' failed", blk_dev_name); 317 | get_super_block(); 318 | if (raw_boot) { 319 | if (is_floppy) 320 | sect_reserved = 2400; 321 | else { 322 | sect_reserved = part_tab[rdev].len_in_sect; 323 | sect_reserved -= 5; 324 | sect_reserved &= ~127; 325 | } 326 | start_sect = 1; 327 | } else { 328 | if ( !supb.s_firstkernzone ) 329 | die("no space reserved for kernel image"); 330 | sect_aligned = (supb.s_nzones - supb.s_firstkernzone) << (1 + supb.s_zone_shift); 331 | sect_aligned -= 4; 332 | sect_aligned &= ~127; 333 | sect_reserved = (supb.s_firstdatazone - supb.s_firstkernzone) << (1 + supb.s_zone_shift); 334 | if (sect_aligned < sect_reserved) 335 | sect_reserved = sect_aligned; 336 | start_sect =supb.s_firstkernzone << (1 + supb.s_zone_shift); 337 | } 338 | sect_aligned = put_image(start_sect, sect_reserved); 339 | if (!is_floppy) 340 | start_sect += part_tab[rdev].start_sect; 341 | put_super_block(start_sect, sect_aligned); 342 | } 343 | 344 | 345 | void inst_pri_boot() 346 | { 347 | int dev_fd; 348 | int i, j; 349 | char * cp; 350 | 351 | fprintf(stderr, 352 | "\nThe master booter will be installed \n" 353 | "in the first sector of %s.\n\n", 354 | blk_dev_name); 355 | if ( !confirm() ) 356 | die("installing master booter aborted\n\n"); 357 | 358 | if ((dev_fd = open(blk_dev_name, O_RDWR)) < 0) 359 | die("open disk device `%s' failed", blk_dev_name); 360 | if ( read(dev_fd, &super_buf, 512) != 512 ) 361 | die("read `%s' failed", blk_dev_name); 362 | 363 | memcpy(&super_buf, pritext, PRITEXTSIZE); 364 | for (i=0; i < os_nr; i++) { 365 | cp = os_name[i]; 366 | for (j=0; cp[j] && j < 15; j++) 367 | master.os[i].os_name[j] = cp[j]; 368 | for (; j < 15; j++) 369 | master.os[i].os_name[j] = ' '; 370 | master.os[i].part_nr = os_part[i]; 371 | } 372 | for (; i < 4; i++) { 373 | for (j=0; j < 15; j++) 374 | master.os[i].os_name[j] = ' '; 375 | master.os[i].part_nr = 0; 376 | } 377 | 378 | if ( lseek(dev_fd, 0, SEEK_SET) != 0 ) 379 | die("seek `%s' failed", blk_dev_name); 380 | if ( write(dev_fd, &super_buf, 512) != 512) 381 | die("write `%s' failed", blk_dev_name); 382 | 383 | close(dev_fd); 384 | } 385 | 386 | 387 | void rest_pri_boot() 388 | { 389 | int fd; 390 | int i; 391 | 392 | if ((fd = open(blk_dev_name, O_RDWR)) < 0) 393 | die("open `%s' failed", blk_dev_name); 394 | if (read(fd, buf, 512) != 512) 395 | die("read `%s' failed", blk_dev_name); 396 | for (i=0; i < ORGTEXTSIZE; i++) 397 | buf[i]=orgtext[i]; 398 | if (lseek(fd, 0, SEEK_SET) != 0) 399 | die("seek `%s' failed", blk_dev_name); 400 | if (write(fd, buf, 512) != 512) 401 | die("write `%s' failed", blk_dev_name); 402 | close(fd); 403 | } 404 | 405 | void main(int argc, char *argv[]) 406 | { 407 | 408 | pgm_name=argv[0]; 409 | 410 | if (getuid()) 411 | die("this program can only be run by the super-user"); 412 | 413 | parse_arg(argc, argv); 414 | 415 | switch(action) { 416 | case INST_SEC_BOOT: inst_sec_boot(); break; 417 | case INST_PRI_BOOT: inst_pri_boot(); break; 418 | case REST_PRI_BOOT: rest_pri_boot(); break; 419 | } 420 | 421 | exit(0); 422 | } 423 | -------------------------------------------------------------------------------- /programs/originals/xiafspgm-0.8.1/mkxfs.8: -------------------------------------------------------------------------------- 1 | .TH MKXFS 8 "20 February 1993" 2 | .SH NAME 3 | mkxfs - make a xiafs file system 4 | .SH SYNOPSIS 5 | .B mkxfs 6 | .B [-c | -l file] [-k blocks] [-z blocks] device blocks 7 | .SH DESCRIPTION 8 | The command 9 | .I mkxfs 10 | makes a xiafs file system on a low level formatted block device 11 | .I device. 12 | The numeric argument 13 | .I blocks 14 | specifies the number of blocks in the file system. In this context, a 15 | block is a 1024-byte piece of disk storage, usually occupying 2 16 | physical disk sectors. Blocks are grouped into zones. A zone is 17 | the smallest amount of device space that can be allocated to a file. 18 | The default zone size is 1024 bytes, i.e., a single block. 19 | .I mkxfs 20 | builds a xiafs file system with a root directory. i-node 2 is reserved 21 | for bad blocks. The number of inodes is calculated as a function of 22 | the file system size. Currently one i-node is allocated for every four 23 | zones. 24 | 25 | This command can only be used by the super-user. 26 | 27 | .SH OPTIONS 28 | .I mkxfs 29 | has the following options: 30 | .TP 31 | .B -c 32 | .I mkxfs 33 | checks bad blocks and links them to i-node 2. 34 | a file 35 | .I badblocks.log 36 | is created in the current directory by 37 | .I mkxfs 38 | for recording. 39 | .TP 40 | .B -l file 41 | .I mkxfs 42 | reads bad block numbers from the file 43 | .I file 44 | and links them to i-node 2. 45 | .I file 46 | is an ASCII file and each line contains a single bad block number. 47 | .TP 48 | .B -k blocks 49 | reserves 50 | .I blocks 51 | block for kernel image. This reserved space could be used by a simple 52 | booter. However, the reserved space is not initialized by 53 | .I mkxfs. 54 | Mkboot(8) may be used to install a kernel image in the reserved space. 55 | .TP 56 | .B -z blocks 57 | This option specifies the zone size. The default is one block (1024 58 | bytes). 59 | The numeric argument 60 | .I blocks 61 | may be 2 or 4. Currently only the default value is supported by the kernel. 62 | 63 | .SH EXAMPLE 64 | .nf 65 | # mkxfs /dev/fd0 1440 % make a xiafs file system 66 | # mkxfs -c /dev/hda3 150000 % check bad blocks and make 67 | % a xiafs file system on hda3 68 | # mkxfs -k 512 /dev/hda1 20000 % make a xiafs file system 69 | % with 512 KB reserved. 70 | .fi 71 | .SH AUTHOR 72 | Q. Frank Xia (qx@math.columbia.edu) 73 | .SH SEE ALSO 74 | mkboot(8), xfsck(8). 75 | .SH BUGS 76 | Currently, the Linux kernel only supports xiafs with one-block 77 | zone size. 78 | The ratio of blocks-per-inode (currently 4) should be selectable 79 | through a commandline argument. 80 | -------------------------------------------------------------------------------- /programs/originals/xiafspgm-0.8.1/mkxfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mkxiafs.c - make a xiafs file system 3 | */ 4 | /************************************************************************** 5 | * (C) Copyright Q. Frank Xia, 1992. All rights reserved. * 6 | * * 7 | * Permission to use and redistribute this software is hereby granted * 8 | * provided that the following conditions are met: * 9 | * 1. Source code redistribution must retain this statement. * 10 | * 2. Binary redistribution must reproduce this statement in the * 11 | * documentation provided with the distribution. * 12 | * 3. This software is provided by author Q. Frank Xia "as is". There * 13 | * are absolutely no warranties at all. The author is not responsible * 14 | * for any possible damages caused by using this software. * 15 | **************************************************************************/ 16 | 17 | /* 18 | * Usage: mkxiafs [-c | -l path] [-k size] [-z size] device size 19 | * 20 | * size is in KB. 21 | * 22 | * -c readablility checking. 23 | * -k reserve 'size' KB for kernel image. 24 | * -l getting a list of bad blocks from a file. 25 | * -z 'size' KB in a zone, 1 KB is default. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #if BLOCK_SIZE != 1024 43 | #error "only block size 1024 supported" 44 | #endif 45 | 46 | #define ZONE_SIZE (BLOCK_SIZE << zone_shift) 47 | #define BITS_PER_ZONE (BLOCK_SIZE << (3 + zone_shift)) 48 | #define BITS_PER_ZONE_BITS (BLOCK_SIZE_BITS + 3 + zone_shift) 49 | #define ADDR_PER_ZONE (BLOCK_SIZE >> (2 - zone_shift)) 50 | 51 | #define NR_INODES (INODE_ZONES * _XIAFS_INODES_PER_BLOCK << zone_shift) 52 | #define INODE_ZONES (((zones - kern_zones) >> (2 + zone_shift)) \ 53 | / _XIAFS_INODES_PER_BLOCK + 1) 54 | #define IMAP_ZONES (NR_INODES / BITS_PER_ZONE + 1) 55 | #define ZMAP_ZONES ((zones - kern_zones) / BITS_PER_ZONE + 1) 56 | #define FIRST_KERN_ZONE (1 + IMAP_ZONES + ZMAP_ZONES + INODE_ZONES) 57 | #define FIRST_DATA_ZONE (FIRST_KERN_ZONE + kern_zones) 58 | #define NR_DATA_ZONES (zones - FIRST_DATA_ZONE) 59 | #define MAX_SIZE (zone_shift == 2 ? 0xffffffff : \ 60 | (((ADDR_PER_ZONE+1)*ADDR_PER_ZONE)+8) * ZONE_SIZE) 61 | 62 | char *pgm; /* program name */ 63 | u_char *zone_buf; /* main buffer */ 64 | u_long *indz_buf; /* inderect zone buffer */ 65 | u_long *dindz_buf; /* double inderect zone buffer */ 66 | int zones; /* size of the file system in zones */ 67 | int kern_zones=0; /* nr of reserved zones for kernal image */ 68 | int zone_shift=0; /* ZONE_SIZE = BLOCK_SIZE << zone_shfit */ 69 | int bad_zones=0; /* # of bad zones */ 70 | int *bad_zlist=(int *) 0; 71 | int dev; 72 | 73 | /*----------------------------------------------------------------------- 74 | * error process rutines 75 | */ 76 | void usage() 77 | { 78 | fprintf(stderr, 79 | "usage: mkxiafs [-c | -l path] [-k size] [-z size] device size\n"); 80 | exit(1); 81 | } 82 | 83 | void die(char *cp) 84 | { 85 | fprintf(stderr, "%s: %s\n", pgm, cp); 86 | exit(1); 87 | } 88 | 89 | /*------------------------------------------------------------------------ 90 | * error free read/write rutines 91 | */ 92 | void rd_zone(int zone_nr, void *buffer) 93 | { 94 | if (lseek(dev, zone_nr * ZONE_SIZE, SEEK_SET) < 0) 95 | die("seek device failed"); 96 | if (read(dev, buffer, ZONE_SIZE) < 0) 97 | die("read device failed"); 98 | } 99 | 100 | void wt_zone(int zone_nr, void *buffer) 101 | { 102 | if (lseek(dev, zone_nr * ZONE_SIZE, SEEK_SET) < 0) 103 | die("seek device failed"); 104 | if (write(dev, buffer, ZONE_SIZE) < 0) 105 | die("write device failed"); 106 | } 107 | 108 | /*---------------------------------------------------------------------- 109 | * bad block check / read bad block from a file 110 | */ 111 | static int zones_done=0; 112 | 113 | void save_bad_num(int num) 114 | { 115 | static int bad_zlist_size=0; 116 | 117 | if (bad_zones >= bad_zlist_size) { 118 | bad_zlist_size += BLOCK_SIZE; 119 | if (!(bad_zlist=realloc(bad_zlist, bad_zlist_size >> 2))) 120 | die("allocate memory failed"); 121 | } 122 | 123 | bad_zlist[bad_zones++]=num; 124 | } 125 | 126 | void alarm_intr() 127 | { 128 | if (zones_done >= zones) 129 | return; 130 | signal(SIGALRM, alarm_intr); /* set for next alarm */ 131 | alarm(2); /* alarm in 2 seconds */ 132 | printf("%d... ", zones_done); /* report how many blocks checked */ 133 | fflush(stdout); 134 | } 135 | 136 | void do_bad_ck() 137 | { 138 | FILE *bf; 139 | int i; 140 | 141 | signal(SIGALRM, alarm_intr); /* set alarm */ 142 | alarm(2); 143 | 144 | if (lseek(dev, 0, SEEK_SET) < 0) /* ready to start */ 145 | die("seek device failed"); 146 | 147 | while (zones_done++ < zones) { /* try twice */ 148 | if (read(dev, zone_buf, BLOCK_SIZE) < 0 ) { 149 | if (lseek(dev, (zones_done-1) * BLOCK_SIZE, SEEK_SET) < 0) 150 | die("seek device failed"); 151 | if (read(dev, zone_buf, BLOCK_SIZE) < 0) { 152 | if (lseek(dev, zones_done * BLOCK_SIZE, SEEK_SET) < 0) 153 | die("seek device fail"); 154 | save_bad_num(zones_done-1); /* record bad blk, 0 based */ 155 | } 156 | } 157 | } 158 | printf("\n"); 159 | bf=fopen("badblocks.log", "w"); 160 | if (!bf) { 161 | fprintf(stderr, "open file \'badblocks.log\' failed\n"); 162 | return; 163 | } 164 | for (i=0; i < bad_zones; i++) 165 | fprintf(bf, "%d\n", bad_zlist[i]); 166 | fclose(bf); 167 | } 168 | 169 | void rd_bad_num(char *bad_nr_file) 170 | { 171 | int tmp, notdone=1; /* read bad block # from a file */ 172 | char *cp; /* each line contains a single # */ 173 | FILE *fp; 174 | 175 | if (!(fp=fopen(bad_nr_file, "r"))) 176 | die("open bad block number file failed"); 177 | 178 | while ( notdone ) { 179 | if (!fgets(zone_buf, 128, fp)) { 180 | if (!feof(fp)) 181 | die("read bad block number file fail"); 182 | notdone=0; 183 | } else { 184 | tmp=strtol(zone_buf, &cp, 0); 185 | if ( !isspace(*cp) && *cp) 186 | die("invalid bad block number file"); 187 | save_bad_num(tmp); 188 | } 189 | } 190 | 191 | for (tmp=1; tmp < bad_zones; tmp++) { /* recycle temp */ 192 | if (bad_zlist[tmp-1] >= bad_zlist[tmp]) 193 | die("invalid bad block number file"); 194 | } 195 | if (bad_zlist[bad_zones] >= zones) 196 | die("bad block number > volume"); 197 | } 198 | 199 | void fatal_bad_ck() 200 | { 201 | int i; 202 | 203 | if (!bad_zones || (bad_zlist[0] >> zone_shift) > FIRST_DATA_ZONE) 204 | return; 205 | fprintf(stderr, "bad zone%s:", (bad_zones==1) ? "": "s"); 206 | for (i=0; i < 20 && i < bad_zones; i++) 207 | fprintf(stderr, " %d", bad_zlist[i]); 208 | if (i != bad_zones) 209 | fprintf(stderr, " ..."); 210 | fprintf(stderr, "\nfirst data block: %d\n",(FIRST_DATA_ZONE+1)<>= zone_shift; 220 | ip1=bad_zlist; 221 | ip2=bad_zlist; 222 | endp=bad_zlist+bad_zones; 223 | while (ip2 < endp) { 224 | *ip1=*ip2++; 225 | while (ip2 < endp && *ip1==*ip2) ip2++; 226 | ip1++; 227 | } 228 | bad_zones=ip1-bad_zlist; 229 | } 230 | 231 | /*---------------------------------------------------------------------- 232 | * make super block 233 | */ 234 | void do_sup_zone() 235 | { 236 | struct xiafs_super_block * sp; 237 | 238 | memset(zone_buf, 0, ZONE_SIZE); 239 | sp=(struct xiafs_super_block *)zone_buf; 240 | sp->s_zone_size=ZONE_SIZE; 241 | sp->s_nzones=zones; 242 | sp->s_ninodes=NR_INODES; 243 | sp->s_ndatazones=NR_DATA_ZONES; 244 | sp->s_imap_zones=IMAP_ZONES; 245 | sp->s_zmap_zones=ZMAP_ZONES; 246 | sp->s_firstdatazone=FIRST_DATA_ZONE; 247 | sp->s_zone_shift=zone_shift; 248 | sp->s_max_size=MAX_SIZE; 249 | sp->s_firstkernzone=kern_zones ? FIRST_KERN_ZONE : 0; 250 | sp->s_magic=_XIAFS_SUPER_MAGIC; 251 | 252 | wt_zone(0, zone_buf); 253 | } 254 | 255 | /*------------------------------------------------------------------------- 256 | * make imap and zmap 257 | */ 258 | void do_map_zones(int start_zone, int nr_zones, int nr_bits, int first_byte) 259 | { 260 | int i; 261 | int bits, bytes; 262 | 263 | bits=nr_bits & 7; 264 | bytes=nr_bits >> 3; 265 | 266 | for (i=0; i < nr_zones; i++) { 267 | if (!bytes && !bits) { 268 | memset(zone_buf, 0xff, ZONE_SIZE); 269 | } else if (bytes < ZONE_SIZE) { 270 | memset(zone_buf, 0, bytes); 271 | zone_buf[bytes]=255 << bits; 272 | memset(zone_buf+bytes+1, 0xff, ZONE_SIZE-bytes-1); 273 | bytes=0; 274 | bits=0; 275 | } else { 276 | memset(zone_buf, 0, ZONE_SIZE); 277 | bytes-=ZONE_SIZE; 278 | } 279 | if (!i) 280 | zone_buf[0]=first_byte; 281 | wt_zone(start_zone+i, zone_buf); 282 | } 283 | } 284 | 285 | #define do_imap() do_map_zones(1, IMAP_ZONES, NR_INODES+1, 7) 286 | 287 | #define do_zmap() do_map_zones(1+IMAP_ZONES, ZMAP_ZONES, NR_DATA_ZONES+1, 3) 288 | 289 | /*------------------------------------------------------------------------ 290 | * make a file for bad blocks. All bad blocks link to ino 2. 291 | */ 292 | #define set_bit(bit_nr) (zone_buf[(bit_nr) >> 3] |= 1 << ((bit_nr) & 7)) 293 | 294 | #define z_to_bnr(zone_nr) ((zone_nr)-FIRST_DATA_ZONE+1) 295 | #define bnr_to_z(bit_nr) ((bit_nr)-1+FIRST_DATA_ZONE) 296 | 297 | void do_bad_bits() 298 | { 299 | int i, znr, cur_znr=-1; 300 | 301 | for (i=0; i < bad_zones; i++) { 302 | if ((znr = z_to_bnr(bad_zlist[i]) >> BITS_PER_ZONE_BITS) != cur_znr) { 303 | if (cur_znr >= 0) 304 | wt_zone(1+IMAP_ZONES+cur_znr, zone_buf); 305 | rd_zone(1+IMAP_ZONES+znr, zone_buf); 306 | cur_znr=znr; 307 | } 308 | set_bit(z_to_bnr(bad_zlist[i]) & (BITS_PER_ZONE -1)); 309 | } 310 | if (cur_znr >= 0) 311 | wt_zone(1+IMAP_ZONES+cur_znr, zone_buf); 312 | } 313 | 314 | static int last_used=1; 315 | static int next_bad_ind=0; 316 | 317 | u_long get_free_zone() 318 | { 319 | int i; 320 | u_long tmp; 321 | 322 | for (i=last_used+1; i < NR_DATA_ZONES; i++) { 323 | tmp=bnr_to_z(i); 324 | if (tmp != bad_zlist[next_bad_ind]) { 325 | last_used=i; /* good zone find */ 326 | rd_zone(1+IMAP_ZONES+(i>>BITS_PER_ZONE_BITS), zone_buf); 327 | set_bit(i & (BITS_PER_ZONE-1)); /* read in zmap, set z-bit */ 328 | wt_zone(1+IMAP_ZONES+(i>>BITS_PER_ZONE_BITS), zone_buf); 329 | return tmp; /* write back zmap */ 330 | } 331 | next_bad_ind++; /* bad zone, skip this zone */ 332 | } 333 | die("too many bad zones"); /* no good zone */ 334 | return 0; 335 | } 336 | 337 | void mk_bad_file(struct xiafs_inode *inode_pt) 338 | { 339 | int i, di, bad_zs, good_z=0; 340 | 341 | bad_zs=bad_zones; /* keep bad_zones */ 342 | if (bad_zs <= 8) { /* only direct zones */ 343 | for (i=0; i < bad_zs; i++) 344 | inode_pt->i_zone[i]=bad_zlist[i]; /* fill and done */ 345 | } else { 346 | for (i=0; i < 8; i++) /* have indirect zones */ 347 | inode_pt->i_zone[i]=bad_zlist[i]; /* fill direct zones */ 348 | inode_pt->i_ind_zone=get_free_zone(); /* get indirect ptr zone */ 349 | good_z++; 350 | if (bad_zs > 8 + ADDR_PER_ZONE) { /* have dindirect zones */ 351 | inode_pt->i_dind_zone=get_free_zone(); /* get dindirect ptr zone */ 352 | good_z++; 353 | } 354 | } 355 | 356 | bad_zs -= 8; /* bad zone left */ 357 | if (bad_zs > 0) { /* have indirect zones */ 358 | if (bad_zs > ADDR_PER_ZONE) { 359 | for (i=0; i < ADDR_PER_ZONE; i++) /* fill indirect ptr zone */ 360 | indz_buf[i]=bad_zlist[i+8]; 361 | } else { 362 | for (i=0; i < bad_zs; i++) 363 | indz_buf[i]=bad_zlist[i+8]; 364 | for (; i < ADDR_PER_ZONE; i++) 365 | indz_buf[i]=0; 366 | } 367 | wt_zone(inode_pt->i_ind_zone, indz_buf); /* save it */ 368 | bad_zs -= ADDR_PER_ZONE; /* bad zone left */ 369 | } 370 | if (bad_zs > 0) { /* have dindirect zones */ 371 | for (di=0; di < ADDR_PER_ZONE; di++) { /* do 2nd */ 372 | if (bad_zs > 0) { 373 | dindz_buf[di]=get_free_zone(); /* get 2nd level ptr zone */ 374 | good_z++; 375 | if (bad_zs > ADDR_PER_ZONE) { 376 | for (i=0; i < ADDR_PER_ZONE; i++) /* fill 2nd level ptr zone */ 377 | indz_buf[i]=bad_zlist[8+(1+di)*ADDR_PER_ZONE+i]; 378 | } else { 379 | for (i=0; i < bad_zs; i++) 380 | indz_buf[i]=bad_zlist[8+(1+di)*ADDR_PER_ZONE+i]; 381 | for (; i < ADDR_PER_ZONE; i++) 382 | indz_buf[i]=0; 383 | } 384 | wt_zone(dindz_buf[di], indz_buf); /* write back */ 385 | bad_zs -= ADDR_PER_ZONE; /* bad zones left */ 386 | } else 387 | dindz_buf[di]=0; /* no bad zones any more */ 388 | wt_zone(inode_pt->i_dind_zone, dindz_buf); 389 | } 390 | } 391 | good_z = (good_z + bad_zones) << (zone_shift + 1); 392 | inode_pt->i_zone[0] |= (good_z << 24) & 0xff000000; 393 | inode_pt->i_zone[1] |= (good_z << 16) & 0xff000000; 394 | inode_pt->i_zone[2] |= (good_z << 8) & 0xff000000; 395 | } 396 | 397 | /*------------------------------------------------------------------------ 398 | * make inodes 399 | */ 400 | void do_inode_zones() 401 | { 402 | int i; 403 | char *cp; 404 | struct xiafs_inode ti, *ip; 405 | 406 | memset(&ti, 0, sizeof(struct xiafs_inode)); 407 | ti.i_mode=S_IFREG; 408 | ti.i_uid=getuid(); 409 | ti.i_gid=getgid(); 410 | ti.i_nlinks=1; 411 | ti.i_size=bad_zones * ZONE_SIZE; 412 | ti.i_mtime=ti.i_atime=ti.i_atime=time(NULL); 413 | mk_bad_file(&ti); 414 | 415 | if (!(cp=getenv("umark"))) 416 | i=0777; 417 | else 418 | i= (~atoi(cp)) & 0777; 419 | memset(zone_buf, 0, ZONE_SIZE); 420 | ip=(struct xiafs_inode *)zone_buf; 421 | ip->i_mode=S_IFDIR | i; 422 | ip->i_uid=ti.i_uid; 423 | ip->i_gid=ti.i_gid; 424 | ip->i_nlinks=2; 425 | ip->i_size=ZONE_SIZE; 426 | ip->i_mtime=ip->i_ctime=ip->i_atime=ti.i_mtime; 427 | ip->i_zone[0]=FIRST_DATA_ZONE | (2 << 24); 428 | ip++; 429 | *ip=ti; 430 | 431 | wt_zone(1+IMAP_ZONES+ZMAP_ZONES, zone_buf); 432 | memset(zone_buf, 0, ZONE_SIZE); 433 | for (i=1; i < INODE_ZONES; i++) 434 | wt_zone(1+IMAP_ZONES+ZMAP_ZONES+i, zone_buf); 435 | } 436 | 437 | /*----------------------------------------------------------------------- 438 | * fill kernel image zones with 0 439 | */ 440 | void do_kern_image() 441 | { 442 | int i; 443 | 444 | memset(zone_buf, 0, ZONE_SIZE); 445 | for (i=FIRST_KERN_ZONE; i < FIRST_DATA_ZONE; i++) 446 | wt_zone(i, zone_buf); 447 | } 448 | 449 | /*----------------------------------------------------------------------- 450 | * 451 | */ 452 | void do_root_dir() 453 | { 454 | struct xiafs_direct * dir_entry_pt; 455 | 456 | memset(zone_buf, 0, ZONE_SIZE); 457 | dir_entry_pt=(struct xiafs_direct *)zone_buf; 458 | dir_entry_pt->d_ino=1; 459 | dir_entry_pt->d_rec_len=12; 460 | dir_entry_pt->d_name_len=1; 461 | dir_entry_pt->d_name[0]='.'; 462 | dir_entry_pt=(struct xiafs_direct *)((u_char *)dir_entry_pt+12); 463 | dir_entry_pt->d_ino=1; 464 | dir_entry_pt->d_rec_len=ZONE_SIZE-12; 465 | dir_entry_pt->d_name_len=2; 466 | dir_entry_pt->d_name[0]='.'; 467 | dir_entry_pt->d_name[1]='.'; 468 | 469 | wt_zone(FIRST_DATA_ZONE, zone_buf); 470 | } 471 | 472 | /*------------------------------------------------------------------------ 473 | * test physical size 474 | */ 475 | void last_zone_test() 476 | { 477 | if (FIRST_DATA_ZONE >= zones) 478 | die("device too small"); 479 | *(u_long *)(zone_buf+ZONE_SIZE-4)=_XIAFS_SUPER_MAGIC; 480 | wt_zone(zones-1, zone_buf); 481 | sync(); 482 | memset(zone_buf, 0, ZONE_SIZE); 483 | rd_zone(zones-1, zone_buf); 484 | if (*(u_long *)(zone_buf+ZONE_SIZE-4)!=_XIAFS_SUPER_MAGIC) { 485 | sprintf(zone_buf, "device < %d zones", zones); 486 | die(zone_buf); 487 | } 488 | } 489 | 490 | /*--------------------------------------------------------------------- 491 | * report 492 | */ 493 | void report() 494 | { 495 | printf(" zone size: %d KB\n", 1<> 20); 501 | if (bad_zlist) 502 | printf(" bad zones: %d ( %d%% )\n", bad_zones, 503 | (bad_zones*100+NR_DATA_ZONES/2)/NR_DATA_ZONES); 504 | } 505 | 506 | /*--------------------------------------------------------------------- 507 | * main rutine 508 | */ 509 | void main(int argc, char * argv[]) 510 | { 511 | int bad_ck=0; 512 | char *bad_nr_file=(char *) 0; 513 | char *dev_name; 514 | char *endp; 515 | int opt; 516 | 517 | extern int optind; 518 | extern char *optarg; 519 | 520 | pgm=argv[0]; 521 | if (getuid()) 522 | die("this program can only be run by root"); 523 | while ((opt=getopt(argc, argv, "ck:l:z:")) != EOF) { 524 | switch (opt) { 525 | case 'c': 526 | bad_ck=1; 527 | break; 528 | case 'k': 529 | kern_zones=strtol(optarg, &endp, 0); 530 | if (!isspace(*endp) && *endp) 531 | usage(); 532 | if (kern_zones < 0) 533 | usage(); 534 | break; 535 | case 'l': 536 | bad_nr_file=optarg; 537 | break; 538 | case 'z': 539 | zone_shift=strtol(optarg, &endp, 0); 540 | if (!isspace(*endp) && *endp) 541 | usage(); 542 | if (zone_shift != 1 && zone_shift != 2 && zone_shift != 4) 543 | usage(); 544 | zone_shift >>= 1; 545 | break; 546 | default: 547 | usage(); 548 | } 549 | } 550 | if (bad_ck && bad_nr_file) 551 | usage(); 552 | if (argc != optind+2) 553 | usage(); 554 | dev_name=argv[optind]; 555 | zones=strtol(argv[optind+1], &endp, 0) & ~((1 << zone_shift) - 1); 556 | if ( !isspace(*endp) && *endp) 557 | usage(); 558 | if (zones < 0 || zones > 0x400000) 559 | die("invalid volume size"); 560 | if ((dev=open(dev_name, O_RDWR)) < 0) 561 | die("open device failed"); 562 | if (!(zone_buf=(u_char *)malloc(3 * ZONE_SIZE))) 563 | die("allocate memory failed"); 564 | indz_buf=(u_long *)(zone_buf+ZONE_SIZE); 565 | dindz_buf=(u_long *)(zone_buf+ZONE_SIZE*2); 566 | 567 | zones >>= zone_shift; 568 | kern_zones = (kern_zones + (1 << zone_shift) - 1 )>> zone_shift; 569 | 570 | last_zone_test(); 571 | 572 | if (bad_ck) 573 | do_bad_ck(); 574 | if (bad_nr_file) 575 | rd_bad_num(bad_nr_file); 576 | 577 | fatal_bad_ck(); 578 | bad_blk_to_zone(); 579 | 580 | do_sup_zone(); 581 | do_imap(); 582 | do_zmap(); 583 | do_bad_bits(); 584 | do_inode_zones(); 585 | do_kern_image(); 586 | do_root_dir(); 587 | report(); 588 | 589 | exit(0); 590 | } 591 | 592 | -------------------------------------------------------------------------------- /programs/originals/xiafspgm-0.8.1/orgdump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ctdk/modern-xiafs/681afcc7e6b58ca026529d4b8bfc4cb08c2cc254/programs/originals/xiafspgm-0.8.1/orgdump -------------------------------------------------------------------------------- /programs/originals/xiafspgm-0.8.1/primary.s: -------------------------------------------------------------------------------- 1 | !-----------------------------------------------------------------------! 2 | ! primary.s ! 3 | ! ! 4 | ! Copyright (C) Q. Frank Xia, 1993. All rights reserved. ! 5 | ! ! 6 | ! This software may be redistributed as per Linux copyright ! 7 | ! ! 8 | !-----------------------------------------------------------------------! 9 | 10 | 11 | BOOTSEG = 0x07C0 ! original address of boot seg 12 | INITSEG = 0x3000 ! we move boot here 13 | PARTTABOFF = 0x01be ! partition table offset 14 | OSTABOFF = 0x017e ! bootable OS table 15 | BOOTOFF = 0x7c00 ! boot code offset 16 | 17 | TIMEOUT = 15*18 ! timeout for keyhit 18 | TIMELO = 0x46c ! timer count low 19 | 20 | ZERO = 0x30 ! ascii '0' 21 | FIVE = 0x35 ! ascii '5' 22 | 23 | !------------------------------------------------------------- 24 | 25 | .text 26 | .globl _main 27 | _main: 28 | 29 | 30 | ! move this 512 byte to INITSEG:0x0000 31 | 32 | mov ax, #BOOTSEG 33 | mov ds, ax 34 | mov ax, #INITSEG 35 | mov es, ax 36 | mov cx, #256 37 | sub si, si 38 | sub di, di 39 | cld 40 | rep 41 | movsw 42 | jmpi start, INITSEG 43 | 44 | start: 45 | mov ax, cs 46 | mov ds, ax 47 | mov es, ax 48 | mov ss, ax 49 | mov sp, #0x4000 50 | 51 | call clr_screen 52 | mov bp, #msg_name 53 | mov cx, #32 54 | call print_string 55 | mov bp, #msg_crlf 56 | mov cx, #2 57 | call print_string 58 | 59 | call print_OS 60 | 61 | mov bp, #msg_boot 62 | mov cx, #7 63 | call print_string 64 | 65 | call get_key 66 | 67 | boot: 68 | mov bx, #16 69 | mul bx 70 | add ax, #boot_tab 71 | mov bp, ax 72 | mov cx, #15 73 | call print_string 74 | mov bp, #msg_crlf 75 | mov cx, #2 76 | call print_string 77 | 78 | add ax, #15 79 | mov si, ax 80 | movb al, (si) ! get partition number 81 | xor ah, ah 82 | dec ax 83 | 84 | mul bx 85 | add ax, #part_tab 86 | mov si, ax 87 | 88 | push si 89 | push cs 90 | 91 | xor ax, ax 92 | mov es, ax 93 | mov bx, #BOOTOFF 94 | 95 | mov ax, #0x201 ! read one sector 96 | movb dh, 1(si) ! head 97 | movb cl, 2(si) ! sector 98 | movb ch, 3(si) ! cylinder 99 | movb dl, #0x80 ! disk 100 | int 0x13 101 | 102 | pop es 103 | pop si 104 | jmpi BOOTOFF, 0 ! read boot 105 | 106 | !------------------------------------------------------------------ 107 | ! print a string 108 | ! bp = address of the string to print 109 | ! cx = length of the string 110 | 111 | print_string: 112 | pusha 113 | push bp 114 | push cx 115 | mov ah, #0x03 ! read cursor pos 116 | xor bh, bh 117 | int 0x10 118 | 119 | pop cx 120 | pop bp 121 | mov bx, #0x0007 ! page 0, attribute 7 (normal) 122 | mov ax, #0x1301 ! write string, move cursor 123 | int 0x10 124 | popa 125 | ret 126 | 127 | !------------------------------------------------------------------ 128 | ! print all bootable OS 129 | 130 | print_OS: 131 | pusha 132 | mov cx, #4 133 | mov ax, #boot_tab 134 | rept_OS: 135 | mov si, ax 136 | add si, #15 137 | movb dl, (si) 138 | testb dl, dl 139 | jnz more_OS 140 | popa 141 | ret 142 | more_OS: 143 | mov dx, #FIVE 144 | sub dx, cx 145 | mov msg_nr, dl 146 | push cx 147 | mov bp, #msg_head 148 | mov cx, #11 149 | call print_string 150 | 151 | mov bp, ax 152 | mov cx, #15 153 | call print_string 154 | mov bp, #msg_crlf 155 | mov cx, #2 156 | call print_string 157 | 158 | pop cx 159 | add ax, #16 160 | dec cx 161 | jnz rept_OS 162 | popa 163 | ret 164 | 165 | !------------------------------------------------------------------ 166 | ! Wait for indication of partition to boot 167 | ! return ax = ascii code of the key hit. 168 | 169 | get_key: 170 | xor bx, bx 171 | mov fs, bx 172 | mov bx, #TIMEOUT ! timeout 173 | 174 | loadtime: 175 | seg fs 176 | mov cx,TIMELO ! load the current time 177 | 178 | waitkey: 179 | movb ah,#1 ! check for keystroke 180 | int 0x16 181 | jnz keyhit ! key was struck 182 | 183 | seg fs 184 | cmp cx,TIMELO ! check for new time 185 | je waitkey 186 | dec bx ! wait for timeout to elapse 187 | jnz loadtime 188 | 189 | timedout: 190 | xor ax, ax ! get default boot partition 191 | ret 192 | 193 | keyhit: 194 | xorb ah, ah ! read key 195 | int 0x16 196 | xor ah, ah 197 | sub ax, #ZERO+1 ! convert partition number 198 | jc def 199 | cmp ax, #4 200 | jnc def 201 | push ax 202 | mov bx, #16 203 | mul bx 204 | add ax, #boot_tab+15 205 | mov si, ax 206 | movb al, (si) 207 | testb al, al 208 | pop ax 209 | jz def 210 | ret 211 | 212 | def: 213 | xor ax, ax 214 | ret 215 | 216 | !-------------------------------------------------------------------- 217 | ! clean screen 218 | 219 | clr_screen: 220 | pusha 221 | 222 | mov ax, #0x0700 223 | mov bh, #0x07 224 | mov cx, #0 225 | mov dh, #24 226 | mov dl, #79 227 | int 0x10 228 | 229 | mov ah, #2 230 | mov bh, #0 231 | mov dx, #0 232 | int 0x10 233 | 234 | popa 235 | ret 236 | 237 | !-------------------------------------------------------------------- 238 | ! Misc message. 239 | 240 | msg_head: 241 | .byte 0x20, 0x20, 0x20, 0x20, 0x5b 242 | msg_nr: 243 | .byte 0x30 244 | .ascii "] " 245 | 246 | msg_boot: 247 | .byte 0x0a 248 | .ascii "Boot: " 249 | 250 | msg_name: 251 | .byte 0x0a 252 | .ascii "Frank Xia's Linux Booter v0.8" 253 | 254 | msg_crlf: 255 | .byte 0x0d,0x0a 256 | 257 | !-------------------------------------------------------------- 258 | ! Bootable partitions. These fields filled by mkboot. 259 | 260 | .org 0x17e 261 | boot_tab: 262 | .ascii "Linux " ! string. OS name, etc. 263 | .byte 2 ! partition 264 | .ascii "MS-DOS " ! string. OS name, etc. 265 | .byte 1 ! partition 266 | .ascii "123456789012345" ! string. OS name, etc. 267 | .byte 0 ! partition 268 | .ascii "123456789012345" ! string. OS name, etc. 269 | .byte 0 ! partition 270 | 271 | !-------------------------------------------------------------- 272 | ! Partition table. These fields copied from old master bootsect. 273 | 274 | .org 0x1be 275 | part_tab: 276 | .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 277 | .long 0x00000000,0x00000000 278 | .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 279 | .long 0x00000000,0x00000000 280 | .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 281 | .long 0x00000000,0x00000000 282 | .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 283 | .long 0x00000000,0x00000000 284 | .byte 0x55,0xAA 285 | 286 | 287 | -------------------------------------------------------------------------------- /programs/originals/xiafspgm-0.8.1/secondary.s: -------------------------------------------------------------------------------- 1 | !-----------------------------------------------------------------------! 2 | ! secondary.s ! 3 | ! ! 4 | ! Copyright (C) Q. Frank Xia, 1993. All rights reserved. ! 5 | ! ! 6 | ! This software may be redistributed as per Linux copyright ! 7 | ! ! 8 | !-----------------------------------------------------------------------! 9 | 10 | 11 | SETUPSECTS = 4 ! nr of setup sectors 12 | BOOTSEG = 0x07C0 ! original address of boot sector 13 | INITSEG = 0x9000 ! we move boot here - out of the way 14 | SETUPSEG = 0x9020 ! setup starts here 15 | SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). 16 | IMAGESEG = 0 ! setup loaded at 0:0xf8000 first 17 | IMAGEOFF = 0xf800 ! then moved to SETUPSEG:0x0000 18 | 19 | .text 20 | .globl _main 21 | _main: 22 | 23 | 24 | ! move this 512 byte to INITSEG:0x0000 25 | 26 | mov ax, #BOOTSEG 27 | mov ds, ax 28 | mov ax, #INITSEG 29 | mov es, ax 30 | mov cx, #256 31 | sub si, si 32 | sub di, di 33 | cld 34 | rep 35 | movsw 36 | jmpi start, INITSEG 37 | 38 | 39 | ! set up the segment registers and the stack 40 | 41 | start: 42 | mov ax, cs ! setup seg registers 43 | mov ds, ax ! put stack at INITSEG:0x4000-12. 44 | mov es, ax 45 | mov ss, ax 46 | mov ax, #0x4000-12 47 | mov sp, ax 48 | 49 | 50 | ! get disk drive parameters 51 | 52 | movb boot_disk, dl ! save root disk code 53 | 54 | testb dl, #0x80 ! hd or floppy ? 55 | jz floppy 56 | 57 | 58 | ! get hard disk drive parameters 59 | 60 | mov di, sp ! hard disk boot 61 | movb ah, #0x08 ! find out the parameters of the hard disk 62 | int 0x13 63 | die1: jc die1 64 | andb cl, #0x3f 65 | movb nr_sects, cl 66 | incb dh 67 | movb nr_heads, dh 68 | jmp load_all 69 | 70 | 71 | ! get diskette drive parameters 72 | 73 | floppy: 74 | xor ax, ax 75 | mov fs, ax 76 | mov bx, #0x78 ! fs:bx is parameter table address 77 | seg fs 78 | lgs si, (bx) ! gs:si is source 79 | mov di, dx ! es:di is destination 80 | mov cx, #6 ! copy 12 bytes 81 | cld 82 | rep 83 | seg gs 84 | movsw 85 | 86 | mov di, dx 87 | movb 4(di), *18 ! patch sector count 88 | seg fs 89 | mov (bx), di 90 | seg fs 91 | mov 2(bx), es 92 | mov ax, cs 93 | mov fs, ax 94 | mov gs, ax 95 | xor ah, ah ! reset FDC 96 | xor dl, dl 97 | int 0x13 98 | 99 | 100 | ! get parameters 101 | 102 | xor dx, dx ! drive 0, head 0 103 | mov cx, #0x0012 ! sector 18, track 0 104 | mov bx, #0x0200 ! address after setup (es = cs) 105 | mov ax, #0x0201 ! service 2, 1 sector 106 | int 0x13 107 | jnc params_got 108 | movb cl, #0x0f ! sector 15 109 | mov ax, #0x0201 ! service 2, 1 sector 110 | int 0x13 111 | jnc params_got 112 | die2: jmp die2 113 | 114 | params_got: 115 | movb nr_sects, cl 116 | movb nr_heads, #2 117 | 118 | 119 | ! load the kernel image 120 | 121 | load_all: 122 | 123 | movb al, nr_sects ! calculate start cylinder, 124 | mulb nr_heads ! head, secot_read 125 | mov cx, ax 126 | mov ax, Istart_lo 127 | mov dx, Istart_hi 128 | div cx 129 | mov cylinder, ax 130 | mov ax, dx 131 | divb nr_sects 132 | movb head, al 133 | movb sect_read, ah 134 | 135 | mov bp, #msg_load ! Print "loading" 136 | call print_string 137 | 138 | mov ax, #IMAGESEG ! load Image to 0:IMAGEOFF 139 | mov es, ax 140 | mov bx, #IMAGEOFF 141 | call do_load 142 | call move_setup 143 | call kill_motor 144 | mov bp, #msg_crlf 145 | call print_string 146 | 147 | mov ax, root_dev ! get root_dev device number 148 | or ax, ax ! major and minor. 149 | jne root_defined 150 | mov bx, nr_sects 151 | mov ax, #0x0208 ! /dev/ps0 - 1.2Mb (2,8) 152 | cmp bx, #15 153 | je root_defined 154 | mov ax, #0x021c ! /dev/PS0 - 1.44Mb (2,28) 155 | cmp bx, #18 156 | je root_defined 157 | mov ax, #0x0200 ! /dev/fd0 - autodetect 158 | 159 | root_defined: 160 | mov root_dev, ax 161 | 162 | jmpi 0, SETUPSEG ! load done, jump to setup seg 163 | 164 | do_load: 165 | mov ax, es 166 | test ax, #0x0fff 167 | die3: jne die3 ! es must be at 64kB boundary 168 | 169 | repeat_load: 170 | mov ax, es 171 | cmp ax, end_seg ! have we loaded all yet? 172 | jb do_load_1 173 | ret 174 | do_load_1: 175 | movb al, nr_sects 176 | subb al, sect_read 177 | mov cx, ax 178 | shl cx, #9 179 | add cx, bx 180 | jnc do_load_2 181 | je do_load_2 182 | xor ax, ax 183 | sub ax, bx 184 | shr ax, #9 185 | do_load_2: 186 | call read_track 187 | movb cl, al 188 | addb al, sect_read 189 | cmpb al, nr_sects 190 | jne do_load_3 191 | mov ax, #0 192 | incb head 193 | movb dl, head 194 | cmpb dl, nr_heads 195 | jne do_load_3 196 | movb head, #0 197 | incb cylinder 198 | do_load_3: 199 | movb sect_read, al 200 | shl cx, #9 201 | add bx, cx 202 | jnc repeat_load 203 | mov ax, es 204 | add ah, #0x10 205 | mov es, ax 206 | xor bx, bx 207 | jmp repeat_load 208 | 209 | read_track: 210 | pusha 211 | pusha 212 | mov ax, #0xe2e ! print `.' 213 | mov bx, #7 214 | int 0x10 215 | popa 216 | 217 | mov dx, cylinder ! al = # of sectors already loaded 218 | movb cl, sect_read 219 | incb cl ! cl = sector, 1 related 220 | movb ch, dl ! ch = sylinder 221 | shlb dh, #6 ! bit 6-7 of cl contains up 2 bits 222 | orb cl, dh ! of cylinder 223 | movb dh, head ! dh = head 224 | movb dl, boot_disk ! dl = disk code 225 | movb ah, #2 226 | 227 | int 0x13 228 | jc read_err 229 | popa 230 | ret 231 | 232 | read_err: 233 | mov bp, #msg_err 234 | call print_string ! ah = error, al = read 235 | 236 | xor ah, ah 237 | xor dl, dl 238 | int 0x13 239 | 240 | popa 241 | jmp read_track 242 | 243 | move_setup: 244 | pusha 245 | mov ax, #IMAGESEG 246 | mov ds, ax 247 | mov si, #IMAGEOFF 248 | mov ax, #SETUPSEG 249 | mov es, ax 250 | xor di, di 251 | mov cx, #0x800 252 | cld 253 | rep 254 | movsw 255 | mov ax, cx 256 | mov ds, ax 257 | mov es, ax 258 | popa 259 | ret 260 | 261 | 262 | ! print a string 263 | ! bp = address of the string to print 264 | 265 | print_string: 266 | pusha 267 | push bp 268 | mov ah, #0x03 ! read cursor pos 269 | xor bh, bh 270 | int 0x10 271 | pop bp 272 | mov cx, #9 273 | mov bx, #0x0007 ! page 0, attribute 7 (normal) 274 | mov ax, #0x1301 ! write string, move cursor 275 | int 0x10 276 | popa 277 | ret 278 | 279 | ! kill the floppy motor 280 | 281 | kill_motor: 282 | push dx 283 | mov dx, #0x3f2 284 | xor al, al 285 | outb 286 | pop dx 287 | ret 288 | 289 | msg_load: 290 | .byte 13, 10 291 | .ascii "loading" 292 | msg_err: 293 | .byte 13, 10 294 | .ascii "retry" 295 | msg_crlf: 296 | .byte 13, 10, 0 297 | 298 | nr_sects: 299 | .byte 9 300 | nr_heads: 301 | .byte 2 302 | 303 | sect_read: 304 | .byte 0 ! sectors read of current track 305 | 306 | .org 496 307 | head: 308 | Istart_lo: ! Istart_lo, Istart_hi and end_seg 309 | .word 1 ! are filled by mkboot. 310 | cylinder: 311 | Istart_hi: 312 | .word 0 313 | end_seg: 314 | .word 0x4000 315 | 316 | swap_dev: ! root_dev may changed by mkboot. 317 | .word 0 ! other feilds are copied from 318 | ram_size: ! kernel image. 319 | .word 0 320 | vid_mode: 321 | .word 1 322 | root_dev: 323 | .word 0 324 | boot_disk: 325 | boot_flag: 326 | .word 0xAA55 327 | -------------------------------------------------------------------------------- /programs/originals/xiafspgm-0.8.1/xfsck.8: -------------------------------------------------------------------------------- 1 | .TH XFSCK 8 "20 February 1993" 2 | .SH NAME 3 | xfsck - xiafs file system consistency check and repair 4 | .SH SYNOPSIS 5 | .B xfsck 6 | .B [-a|-k|-r|-s] device 7 | .SH DESCRIPTION 8 | The command 9 | .I xfsck 10 | checks the consistency of xiafs file systems. Inconsistencies of xiafs 11 | file systems may be caused by an improper shutdown of the system. 12 | 13 | To do a repair in case inconsistencies are found, the file system 14 | should be unmounted if it is not the root device. If it is the root 15 | device, the system should be in single-user mode and the file system 16 | should be synchronized. Run xfsck until it stops reporting errors. 17 | If it is the root device, reboot or shutdown the system right after 18 | the repair. 19 | 20 | Repairing can only be done by the super-user. 21 | 22 | Inconsistencies checked in order are as follows: 23 | .TP 24 | - 25 | Bad directory size and bad directory entry. 26 | .TP 27 | - 28 | Blocks claimed by an inode outside the range of the file system. 29 | .TP 30 | - 31 | Blocks claimed by more than one inode or the free list, or blocks claimed 32 | by no inode and free list. 33 | .TP 34 | - 35 | Incorrect link counts. 36 | 37 | .SH OPTIONS 38 | .I xfsck 39 | has the following options: 40 | .TP 41 | .B -a 42 | This option makes 43 | .I xfsck 44 | repair the damage automatically. 45 | .TP 46 | .B -k 47 | This option checks the super block, read the kernel image installed by 48 | mkboot(8) and write it to the standard output. The output can be fed 49 | into mkboot(8) to make a new installation. 50 | .TP 51 | .B -r 52 | .I xfsck 53 | prompts for repair. One may answer 54 | .I y 55 | for repair 56 | .I n 57 | for no repair, or 58 | .I a 59 | for automatic repair. 60 | .TP 61 | .B -s 62 | Check super block and display the super block information and bad blocks 63 | on standard output. 64 | .SH EXAMPLE 65 | 66 | .nf 67 | # umount /dev/hda3 % hda3 is not a root device 68 | # xfsck /dev/hda3 69 | 70 | # sync /dev/hda1 % hda1 is a root device 71 | # xfsck /dev/hda1 72 | # shutdown now % if the file system is modified. 73 | .fi 74 | 75 | .SH AUTHOR 76 | Q. Frank Xia (qx@math.columbia.edu) 77 | .SH SEE ALSO 78 | mkboot(8), mkxfs(8), umount(8), shutdown(8), sync(1). 79 | -------------------------------------------------------------------------------- /programs/xfsck.8: -------------------------------------------------------------------------------- 1 | .TH XFSCK 8 "20 February 1993" 2 | .SH NAME 3 | xfsck - xiafs file system consistency check and repair 4 | .SH SYNOPSIS 5 | .B xfsck 6 | .B [-a|-k|-r|-s] device 7 | .SH DESCRIPTION 8 | The command 9 | .I xfsck 10 | checks the consistency of xiafs file systems. Inconsistencies of xiafs 11 | file systems may be caused by an improper shutdown of the system. 12 | 13 | To do a repair in case inconsistencies are found, the file system 14 | should be unmounted if it is not the root device. If it is the root 15 | device, the system should be in single-user mode and the file system 16 | should be synchronized. Run xfsck until it stops reporting errors. 17 | If it is the root device, reboot or shutdown the system right after 18 | the repair. 19 | 20 | Repairing can only be done by the super-user. 21 | 22 | Inconsistencies checked in order are as follows: 23 | .TP 24 | - 25 | Bad directory size and bad directory entry. 26 | .TP 27 | - 28 | Blocks claimed by an inode outside the range of the file system. 29 | .TP 30 | - 31 | Blocks claimed by more than one inode or the free list, or blocks claimed 32 | by no inode and free list. 33 | .TP 34 | - 35 | Incorrect link counts. 36 | 37 | .SH OPTIONS 38 | .I xfsck 39 | has the following options: 40 | .TP 41 | .B -a 42 | This option makes 43 | .I xfsck 44 | repair the damage automatically. 45 | .TP 46 | .B -k 47 | This option checks the super block, read the kernel image installed by 48 | mkboot(8) and write it to the standard output. The output can be fed 49 | into mkboot(8) to make a new installation. 50 | .TP 51 | .B -r 52 | .I xfsck 53 | prompts for repair. One may answer 54 | .I y 55 | for repair 56 | .I n 57 | for no repair, or 58 | .I a 59 | for automatic repair. 60 | .TP 61 | .B -s 62 | Check super block and display the super block information and bad blocks 63 | on standard output. 64 | .SH EXAMPLE 65 | 66 | .nf 67 | # umount /dev/hda3 % hda3 is not a root device 68 | # xfsck /dev/hda3 69 | 70 | # sync /dev/hda1 % hda1 is a root device 71 | # xfsck /dev/hda1 72 | # shutdown now % if the file system is modified. 73 | .fi 74 | 75 | .SH AUTHOR 76 | Q. Frank Xia (qx@math.columbia.edu) 77 | .SH SEE ALSO 78 | mkboot(8), mkxfs(8), umount(8), shutdown(8), sync(1). 79 | -------------------------------------------------------------------------------- /programs/xiafs.h: -------------------------------------------------------------------------------- 1 | #ifndef _XIAFS_H 2 | #define _XIAFS_H 3 | 4 | /* 5 | * Adapted from: 6 | * include/linux/xia_fs.h 7 | * 8 | * Copyright (C) Q. Frank Xia, 1993. 9 | * 10 | * Based on Linus' minix_fs.h. 11 | * Copyright (C) Linus Torvalds, 1991, 1992. 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | #define _XIAFS_SUPER_MAGIC 0x012FD16D 18 | #define _XIAFS_ROOT_INO 1 19 | #define _XIAFS_BAD_INO 2 20 | #define _XIAFS_MAX_LINK 64000 21 | /* I think this is the equivalent of s_dirsize in the minix stuff */ 22 | #define _XIAFS_DIR_SIZE 12 23 | 24 | #define _XIAFS_NAME_LEN 248 25 | 26 | #define _XIAFS_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof(struct xiafs_inode))) 27 | 28 | struct xiafs_inode { /* 64 bytes */ 29 | uint16_t i_mode; 30 | uint16_t i_nlinks; 31 | uint16_t i_uid; 32 | uint16_t i_gid; 33 | uint32_t i_size; /* 8 */ 34 | uint32_t i_ctime; 35 | uint32_t i_atime; 36 | uint32_t i_mtime; 37 | uint32_t i_zone[10]; 38 | }; 39 | 40 | /* 41 | * linux super-block data on disk 42 | */ 43 | struct xiafs_super_block { 44 | u_char s_boot_segment[512]; /* 1st sector reserved for boot */ 45 | uint32_t s_zone_size; /* 0: the name says it */ 46 | uint32_t s_nzones; /* 1: volume size, zone aligned */ 47 | uint32_t s_ninodes; /* 2: # of inodes */ 48 | uint32_t s_ndatazones; /* 3: # of data zones */ 49 | uint32_t s_imap_zones; /* 4: # of imap zones */ 50 | uint32_t s_zmap_zones; /* 5: # of zmap zones */ 51 | uint32_t s_firstdatazone; /* 6: first data zone */ 52 | uint32_t s_zone_shift; /* 7: z size = 1KB << z shift */ 53 | uint32_t s_max_size; /* 8: max size of a single file */ 54 | uint32_t s_reserved0; /* 9: reserved */ 55 | uint32_t s_reserved1; /* 10: */ 56 | uint32_t s_reserved2; /* 11: */ 57 | uint32_t s_reserved3; /* 12: */ 58 | uint32_t s_firstkernzone; /* 13: first kernel zone */ 59 | uint32_t s_kernzones; /* 14: kernel size in zones */ 60 | uint32_t s_magic; /* 15: magic number for xiafs */ 61 | }; 62 | 63 | struct xiafs_direct { 64 | uint32_t d_ino; 65 | uint16_t d_rec_len; 66 | u_char d_name_len; 67 | char d_name[_XIAFS_NAME_LEN+1]; 68 | }; 69 | 70 | #endif /* _XIAFS_H */ 71 | 72 | --------------------------------------------------------------------------------