The Loopback Root Filesystem HOWTO 作者: Andrew M. Bishop, [1]amb@gedanken.demon.co.uk 译者: Jing-Jong SHYUE, [2]shyue@sonoma.com.tw v1.1, 24 September 1999 _________________________________________________________________ 这份文件解释如何使用 Linux 的绕回设备来建立 Linux 的原生档案系统, 使得 Linux 可以安装在 DOS 分割区中, 并使用 Linux 原生档案系统. 同时也讨论此 种技巧的其他用途. _________________________________________________________________ 1. 简介 * 1.1 版权声明(此段不译) * 1.2 版本演变(此段不译) 2. 绕回设备与记忆体磁碟的原理 * 2.1 绕回设备 * 2.2 记忆体磁碟设备 * 2.3 起始记忆体磁碟 * 2.4 根目录档案系统 * 2.5 Linux 开机程序 3. 如何建立绕回根目录设备 * 3.1 需求 * 3.2 建立 Linux 核心 * 3.3 建立初始化记忆体磁碟装置 * 3.4 建立根目录装置 * 3.5 建立置换装置 * 3.6 建立 MSDOS 目录 * 3.7 建立开机软碟 4. 启动系统 * 4.1 可能发生的问题与解决方式 * 4.2 参考文件 5. 其他绕回根目录装置的可能用途 * 5.1 将 Linux 安装在仅有 DOS 分割区的硬碟上 * 5.2 利用 LILO 启动 * 5.3 将 Linux 安装在 VFAT / NTFS 档案系统上 * 5.4 安装 Linux 而不需重新格式化 * 5.5 从不可开机的设备上启动 Linux _________________________________________________________________ 1. 简介 1.1 版权声明(此段不译) The Loopback Root Filesystem HOWTO Copyright (C) 1998,99 Andrew M. Bishop (amb@gedanken.demon.co.uk). This documentation is free documentation; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. The GNU General Public License is available from [3]http://www.fsf.org/ or, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA 1.2 版本演变(此段不译) Version 1.0.0 Initial Version (June 1998) Version 1.0.1-1.0.3 Slight Modifications, kernel version changes, typos etc. (1998 - July 1999) Version 1.1 Added Copyright Information and Re-Submitted (September 1999) 2. 绕回设备与记忆体磁碟的原理 首先我将介绍用在将绕回档案系统设成根目录系统所需要的基本知识. 2.1 绕回设备 绕回设备 是 Linux 中的一种虚拟设备, 用法类似於其他储存媒体设备. 例如 /dev/hda1, /dev/hda2, /dev/sda1 或其他磁碟, 例如软碟机 /dev/fd0 等 等, 都属於储存设备. 这些设备都可以用来储存档案或是目录结构. 也都可以依 据使用需求而被格式化成各种不同的档案系统(例如 ext2fs, msdos, ntfs 等), 并且被挂载於目录树中. 绕回档案系统依存於一个储存在别的档案系统中的档案, 并将这个档案当作是一 个周边设备来操作. 这个虚拟的设备如同前面所列的真实设备一样, 可以被格式 化或挂载於目录树中. 绕回档案系统的设备档通常是 /dev/loop0 或是 /dev/loop1 等等, 这些设备再被指向所依存的档案, 如此这个档案便能被视为虚 拟设备而被挂载. 2.2 记忆体磁碟设备 在 Linux 中还有一种可以被当成档案系统操作的虚拟设备, 也就是记忆体磁碟设 备. 在这个状况中, 这个设备仅指向部分的实体记忆体, 并不参考其他硬体设备. 这 些记忆体绝不会被置换到硬碟中, 但会留存於磁碟快取中. 记忆体磁碟可以在任意时间经由写入记忆体磁碟设备档 /dev/ram0 或 /dev/ram1 等等, 而被产生. 记忆体磁碟同样可以被格式化或挂载於目录树中, 就像绕回设备一样. 记忆体磁碟通常被用於由软碟启动系统的时机, 例如 Linux 的安装磁碟或是救援 磁碟. 开机所需要的程式通常被存在一个磁碟映像档中, 而这个映像档通常被压 缩後存在软碟中. 系统核心将可以认知这个档案, 并且在开机程序中被解开後放 置於记忆体磁碟中, 再被挂载成开机所需的档案系统. 2.3 起始记忆体磁碟 在我们能将绕回设备当成根目录系统之前, 起始记忆体磁碟是一个非常重要的机 制. 因为记忆体磁碟需要复制一个档案系统的映像档到记忆体中, 所以这个映像档必 须是可以被存取的. 当记忆体磁碟的工作完成要正式将真实的根目录系统挂载之 前, 在这个记忆体磁碟中的 /linuxrc 会被执行. 而如果 /dev/initrd 存在且可 用的话, 记忆体磁碟则会被挂载在 /initrd之下. 对於一个正常的开机程序而言, 这是一个相当特殊的特性, 因为起始记忆体磁碟 仍继续执行. 而且在主要开机程序开始之前, 可以经由起始记忆体磁碟的参数来 变更根目录磁碟. 2.4 根目录档案系统 根目录磁碟是第一个被挂载的装置, 所以在开机後会成为根目录 "/". 由於根目录包含了所有的档案, 所以会有一些复杂. 在开机过程中 rc 命令稿会 被执行, 这些命令稿可能是 /etc/rc.d 或 /etc/rc?.d, 端视 /etc/init 程序的 设计. 在系统启动後, 根目录档案系统是不可能被卸载的, 因为所有的程式必须使用相 同的资讯. 这也就是为什麽起始记忆体磁碟是如此的重要, 因为只有这时的根目 录系统是不同的. 2.5 Linux 开机程序 为了了解在开机过程中起始记忆体磁碟的动作, 下列是开机的过程. 1. 核心被载入记忆体, 通常是由 LILO 或 LOADLIN 完成的. 你可以看到 Loading... 讯息, 表示正在载入核心. 2. 起始记忆体磁碟被载入, 通常也是由 LILO 或 LOADLIN 完成的. 你会再次的 看到 Loading... 讯息, 表示正在载入初始记忆体磁碟. 3. 核心被初始化, 所有给核心的参数都会被设定; 同时初始记忆体磁碟被挂载 为根目录. 4. 执行在初始记忆体磁碟上的 /linuxrc 程式. 5. 核心参数所指定的档案系统被挂载为根目录. 6. 执行 /etc/init 以完成使用者所设定的开机程序. 这只是一个简化的说明, 但足够解释核心的启动与初始记忆体磁碟的用途. 3. 如何建立绕回根目录设备 下面将介绍如何建立绕回设备 3.1 需求 要建立一个绕回根目录设备必须要有下列事项. * 一个可以运作的 Linux 系统 * 必须能够复制一个大档案到 DOS 分割区中 最重要的是必须能存取一个安装好可运作的 Linux 系统. 这是因为绕回设备只能 在 Linux 下建立. 也就是说你不可能从无中生有. 而且你必须要能在这个系统上 编译核心. 当绕回设备建立之後, 这将是一个很大的档案. 我使用了一个 80 MB 的档案, 如 此我才能建立一个 X 终端机; 但如果你希望能做更多事, 这可能也不够. 这个档 案必须被复制到 DOS 分割区中, 所以网路或是一堆软碟是必须的. 你所需要的软体包括: * LOADLIN 1.6版以上 * 任何一个支援绕回设备的 mount 程式 * 支援所需选项的核心 对现在的 Linux 而言, 应该都能符合以上需求. 3.2 建立 Linux 核心 我是用 2.0.31 版的核心来使用绕回装置, 其他版本的核心应该也可以用. 但他 们至少必须要有以下的功能. 你必须将核心的列功能启动 * 记忆体磁碟支援 (CONFIG_BLK_DEV_RAM). * 初始化记忆体 (initrd) 支援 (CONFIG_BLK_DEV_INITRD). * 绕回装置支援 (CONFIG_BLK_DEV_LOOP). * fat 档案系统支援 (CONFIG_FAT_FS). * msdos 档案系统支援 (CONFIG_MSDOS_FS). 前面二个是用来使用记忆体磁碟装置与初始化记忆体磁碟装置. 第三个是绕回档 案系统的支援, 最後二个则是用来挂载 DOS 分割区所必须的支援. 编译核心且不使用模组支援是最简单的选择. 但如果你希望使用模组化支援应该 也是可以, 虽然我没有试过. 如果你使用模组化支援, 你必须确定上列的选项是 直接编译在核心内而不是编译成模组. 依据核心版本的不同, 你可能需要使用一些修补. 下面是一些简单的修补用来让 核心可以将绕回装置作为根目录档案系统使用. * 2.0.0 版之前的核心: 我没有相关资讯. * 2.0.0 到 2.0.34 之间的核心版本: 你必须使用下列给 2.0.x 版的核心修 补. * 2.0.35 到 2.0.x 之间的核心不需要修补. * 2.1.x 版的核心必须依据您的确实版本而使用下列给 2.0.x 或 2.2.x 版的 核心修补. * 2.2.0 到 2.2.10 之间的核心版本: 你必须使用下列给 2.2.x 版的核心修 补. * 2.3.x 版的核心: 你必须使用下列给 2.2.x 版的核心修补. 对於 2.0.x 版的核心, 必须将 "loop", 0x0700 这一行加到 /init/main.c 的原 始码中而成为下面的样子. static void parse_root_dev(char * line) { int base = 0; static struct dev_name_struct { const char *name; const int num; } devices[] = { { "nfs", 0x00ff }, { "loop", 0x0700 }, { "hda", 0x0300 }, ... { "sonycd", 0x1800 }, { NULL, 0 } }; ... } 对於 2.2.x 版的核心, 必须将 "loop", 0x0700 与前後各一行(共三行)加到 /init/main.c 的原始码中而成为下面的样子 static struct dev_name_struct { const char *name; const int num; } root_dev_names[] __initdata = { #ifdef CONFIG_ROOT_NFS { "nfs", 0x00ff }, #endif #ifdef CONFIG_BLK_DEV_LOOP { "loop", 0x0700 }, #endif #ifdef CONFIG_BLK_DEV_IDE { "hda", 0x0300 }, ... { "ddv", DDV_MAJOR << 8}, #endif { NULL, 0 } }; 当核心组态设好後, 他必须被编译成 zImage 档 (make zImage). 编译好的档案 会被放在 arch/i386/boot/zImage. 3.3 建立初始化记忆体磁碟装置 建立初始化记忆体磁碟最简单的方式是将它当成绕回装置挂载. 你必须使用 root 的权限来做这件事. 建立程序如下所示, 这些指令是在 root 的家目录 (/root) 中执行的. mkdir /root/initrd dd if=/dev/zero of=initrd.img bs=1k count=1024 mke2fs -i 1024 -b 1024 -m 5 -F -v initrd.img mount initrd.img /root/initrd -t ext2 -o loop cd initrd [建立必须的档案] cd .. umount /root/initrd gzip -c -9 initrd.img > initrdgz.img 这些指令的作用如下所述. 1. 建立一个给初始化记忆体使用的挂载点 (一个空目录). 2. 建立一个指定大小的空档案, 此处我建立一个 1024kB 的档案, 你必须依据 你所要放置档案的量来决定这个档案的大小. (档案大小是最後一个参数) 3. 将这个档案格式化成 ext2 档案系统. 4. 将这个档案以绕回的方式挂载倒挂载点上. 5. 切换目录到绕回设备的挂载点中. 6. 建立必须的档案 (细节将在後面讨论). 7. 离开绕回档案所挂载的目录. 8. 将绕回设备卸载. 9. 建立一个压缩的版本以供後续使用. 初始化记忆体磁碟的内容 你必须至少有下列的档案放置於初始化记忆体磁碟中, 否则将不能使用任何指 令. * /linuxrc 挂载 DOS 档案系统的指令稿. (如下所示) * /lib/* 程式所需要的动态连结器与函式库. * /etc/* 动态连结所需的快取, 虽然静态连结程式不需要, 但可以避免警告讯 息. * /bin/* 使用者命令解译器 (此处我使用 ash, 因为它比 bash 小). 而 mount 与 losetup 程式是用於挂载 DOS 磁碟与设定绕回装置. * /dev/* 必须的装置控制档, 你至少需要 /dev/zero 以供 ld-linux.so 使 用, /dev/hda* 以挂载 DOS 磁碟, 以及 /dev/loop* 以挂载绕回装置. * /mnt 一个空的挂载点, 以供 DOS 磁碟挂载. 下面是我所用的起始化记忆体磁碟之内容, 所需空间约 800 kB. total 18 drwxr-xr-x 2 root root 1024 Jun 2 13:57 bin drwxr-xr-x 2 root root 1024 Jun 2 13:47 dev drwxr-xr-x 2 root root 1024 May 20 07:43 etc drwxr-xr-x 2 root root 1024 May 27 07:57 lib -rwxr-xr-x 1 root root 964 Jun 3 08:47 linuxrc drwxr-xr-x 2 root root 12288 May 27 08:08 lost+found drwxr-xr-x 2 root root 1024 Jun 2 14:16 mnt ./bin: total 168 -rwxr-xr-x 1 root root 60880 May 27 07:56 ash -rwxr-xr-x 1 root root 5484 May 27 07:56 losetup -rwsr-xr-x 1 root root 28216 May 27 07:56 mount lrwxrwxrwx 1 root root 3 May 27 08:08 sh -> ash ./dev: total 0 brw-r--r-- 1 root root 3, 0 May 20 07:43 hda brw-r--r-- 1 root root 3, 1 May 20 07:43 hda1 brw-r--r-- 1 root root 3, 2 Jun 2 13:46 hda2 brw-r--r-- 1 root root 3, 3 Jun 2 13:46 hda3 brw-r--r-- 1 root root 7, 0 May 20 07:43 loop0 brw-r--r-- 1 root root 7, 1 Jun 2 13:47 loop1 crw-r--r-- 1 root root 1, 3 May 20 07:42 null crw-r--r-- 1 root root 5, 0 May 20 07:43 tty crw-r--r-- 1 root root 4, 1 May 20 07:43 tty1 crw-r--r-- 1 root root 1, 5 May 20 07:42 zero ./etc: total 3 -rw-r--r-- 1 root root 2539 May 20 07:43 ld.so.cache ./lib: total 649 lrwxrwxrwx 1 root root 18 May 27 08:08 ld-linux.so.1 -> ld-linu x.so.1.7.14 -rwxr-xr-x 1 root root 21367 May 20 07:44 ld-linux.so.1.7.14 lrwxrwxrwx 1 root root 14 May 27 08:08 libc.so.5 -> libc.so.5.3 .12 -rwxr-xr-x 1 root root 583795 May 20 07:44 libc.so.5.3.12 ./lost+found: total 0 ./mnt: total 0 比较复杂的步骤是建立 dev 目录下面的装置控制档. 你可以用 /dev 下面现有的 装置控制档为□本, 并以 mknod 程式来建立他们. /linuxrc 指令档 起始化记忆磁碟中的 /linuxrc 指令稿是用来完成挂载绕回装置所需的前置准 备. 下面的□例是以 /dev/hda1 为 DOS 分割区, 并在成功挂载 DOS 分割区後, 将/linux/linuxdsk.img 设定为 /dev/loop0 ;并将 /linux/linuxswp.img 设定 为 /dev/loop1. #!/bin/sh echo INITRD: Trying to mount /dev/hda1 as msdos if /bin/mount -n -t msdos /dev/hda1 /mnt; then echo INITRD: Mounted OK /bin/losetup /dev/loop0 /mnt/linux/linuxdsk.img /bin/losetup /dev/loop1 /mnt/linux/linuxswp.img exit 0 else echo INITRD: Mount failed exit 1 fi 前面的 /dev/loop0 装置将被挂载为根目录, 後面的 /dev/loop1 则将被作为记 忆体置换区使用. 如果你希望 root 以外的使用者也能写入 DOS 分颗区, 你必须改成使用 mount -n -t msdos /dev/hda1 /mnt -o uid=0,gid=0,umask=000,quiet. 这会将所有对 DOS 分割区的存取对应成 root, 并且适当的设定权限. 3.4 建立根目录装置 你所使用的根目录装置将是 linuxdsk.img 这个档案. 你可以用与建立起始记忆 体磁碟相同的方法建立这个档案, 所不同处仅在於必须较大, 足以容纳你要安装 的程式. 最简单的办法是将现有的 Linux 系统复制到这个档案系统中. 当然你也可以重新 安装一套新的 Linux 系统. 假设你已经做过这些事, 你只要作一些小改变. /etc/fstab 档案必须将根目录磁碟与置换区对应到你在启示记忆体磁碟中的绕回 设备. /dev/loop0 / ext2 defaults 1 1 /dev/loop1 swap swap defaults 1 1 这将确保核心会使用正确的根目录装置. 也可以用相同的方法加入置换磁碟. 你 也必须移除其他根目录磁碟与置换区的对应. 如果你希望在 Linux 启动後能够读取 DOS 分割区, 你必须作下面这些额外的小 修改. 建立叫做 /initrd 的目录, 这是再绕回根目录系统挂载後, 初始记忆体磁碟挂载 的地方. 建立一个符号连接 /DOS 指向 /initrd/mnt, 也就是 DOS 分割区被挂载的地方. 在 rc 档中加入类似 mount -f -t msdos /dev/hda1 /initrd/mnt 的指令, 以建 立一个 "假的" 挂载, 如此例如 df 等程式才会知道这个挂载. 如果你在 /linuxrc 中用不同的设定, 请自行修正以符合设定. 由於核心在之前便会被载入, 所以你不需要在根目录装置中放置系统核心. 但如 果你使用了核心的模组, 你仍然必须将这些模组放在根目录装置中. 3.5 建立置换装置 你所使用的置换装置将是 linuxswap.img. 这个置换装置相当容易建立. 首先如 同之前的做法建立一个空档案, 然後执行 mkswap linuxswap.img 来格式化这个 置换档. 置换空间的大小依据个人的使用而不同, 但我建议将它设为大於 8MB, 但小於实 体记忆体量. 3.6 建立 MSDOS 目录 你所要使用的档案必须被搬移到 DOS 分割区中. 必须被放在 C:\LINUX 目录下的档案包括 * LINUXDSK.IMG 作为根目录装置的影像档. * LINUXSWP.IMG 置换装置. 3.7 建立开机软碟 开机软碟的制作与标准 DOS 开机软碟相同. 在 DOS 下使用 format a: /s 以建立开机软碟. 在这张软碟上, 你必须建立一个 AUTOEXEC.BAT 档, 如下所示. 并且复制 Linux 系统核心与压缩过的起始记忆体磁碟档案, 以及 LOADLIN 执行档. * AUTOEXEC.BAT - DOS 下的开机自动执行批次档. * LOADLIN.EXE - LOADLIN 执行档. * ZIMAGE - Linux 系统核心. * INITRDGZ.IMG - 压缩过的起始记忆体磁碟档. AUTOEXEC.BAT 仅需要下面这行. \loadlin \zImage initrd=\initrdgz.img root=/dev/loop0 ro 这会指定要用的系统核心与起始化记忆体磁碟档以及根目录磁碟的位置, 并将根 目录以唯读的方式挂载. 4. 启动系统 要用这个根目录装置启动必须将前面所做的开机软碟放於 PC 中, 并由这个软碟 开机. 你将会看到下列的程序 1. DOS 启动 2. AUTOEXEC.BAT 执行 3. LOADLIN 执行 4. Linux 核心被复制到记忆体中 5. 起始记忆体磁碟被复制到记忆体中 6. Linux 核心开始执行 7. 在起始记忆体磁碟中的 /linuxrc 命令稿被执行 8. DOS 分割区被挂载, 且根目录装置与置换装置被设定 9. 由绕回装置完成开机程序 开机完成後, 你可以取出开机软碟并使用这个 Linux 系统. 4.1 可能发生的问题与解决方式 开机程序可能在许多关卡上失败, 我将试著解释他们与该如何检查. DOS 的启动很容易辨别, 他应该会显示 MS-DOS Starting .... 如果没有显示, 则这个软碟可能是不可开机的, 或电脑不是由这台软碟机开机. 当 AUTOEXEC.BAT 被执行的时候, 所有被执行的指令预设会显示在萤幕上. 在此 处应该只有一行, 并以 LOADLIN 开头. 当 LOADLIN 执行时, 应该有二样很容易看的的事情发生. 首先是他会将核心载入 记忆体中. 接著会将起始记忆体磁碟载入记忆体. 这二个都可以由 Loading... 讯息确认. 核心将自己解压缩, 而且当核心档案损坏时, 将显示 crc 错误. 当核心开始执行 时, 会显示一堆初始化程序与检查讯息. 初始记忆体磁碟的载入也会在此阶段显 示. 当 /linuxrc 开始执行时, 不会有可供诊断的讯息产生, 但你可以自己加入辅助 讯息来检查. 在这个程序中, 如果在将绕回装置当成根目录装置时失败的话, 你 将会得到 "没有根目录装置" 的讯息, 且核心会放弃执行. 接下来定义在根目录装置中的正常开机程序会被启动. 你有可能得到根目录被挂 载成可读写的警告, 但在 LOADLIN 指令中的 'ro' 可以解决这个问题. 当开机程 序弄不清哪个是根目录装置时, 会产生一些问题, 这个问题多半来自 /etc/fstab 中的错误. 当开机程序完成後, 剩下的问题是程式搞不清楚 DOS 分割区被挂载在何处. 这也 是为何要执行一个"假"的挂载指令, 这将使你较容易存取 DOS 分割区. 4.2 参考文件 在我建立第一个入回根目录档案系统时, 我参考了下列文件: * Linux 核心原始码, 特别是 init/main.c * Linux 核心说明文件, 特别是 Documentation/initrd.txt 以及 Documentation/ramdisk.txt. * LILO 说明文件. * LOADLIN 说明文件. 5. 其他绕回根目录装置的可能用途 当由 DOS 分割区启动 Linux 的方法确立之後, 我们将可以用在下面的用途上. 5.1 将 Linux 安装在仅有 DOS 分割区的硬碟上 既然可以利用软碟与存在 DOS 磁碟中的一个档案来启动 Linux 系统, 那也可以 完全使用 DOS 磁碟来启动系统. 一个设定好的开机选单可以用来从 AUTOEXEC.BAT 中启动 LOADLIN, 这能使开机 速度较快, 但却会与其他部分相关. 5.2 利用 LILO 启动 使用 LOADLIN 只是其中一种启动 Linux 核心的放式. 另外可以使用 LILO 来启 动且不需要使用 DOS. 在这个状况下 DOS 格式的软碟被换成 ext2fs 格式的软碟. 其他细节都非常相 似, 必须将系统核心与初始记忆体磁碟放於该软碟上. 我选择使用 LOADLIN 的原因在於 LILO 需要较复杂的指令. 而且可以在 DOS 下 使用的软碟也较容易处理. 5.3 将 Linux 安装在 VFAT / NTFS 档案系统上 我曾经试过将 Linux 安装在 NTFS 之上, 而且没也任何问题. 但在标准的 2.0.x 版核心中, NTFS 并不被支援, 但你可以在 [4]http://www.informatik.hu-berlin.de/~loewis/ntfs/ 找到修补档. 在 2.2.x 版的核心中, NTFS 已被支援. 使用在 VFAT 或 NTFS 时与本文□例不同之处仅在於制作起始记忆体磁碟时, 编 写 /linuxrc 指令搞以挂载档案系统时, 必须以 vfat 或 ntfs 为参数而非 msdos. 据我所知没有理由不能用在 VFAT 分割区上. (译注: 弟是用在 VFAT 上面, 并以 100 MB ZIP 启动 Linux) 5.4 安装 Linux 而不需重新格式化 正常安装 Linux 套件时都必须由软碟机开机, 并重新格式化硬碟. 利用本文的方 法也可以建立绕回档案, 并继续正常的安装程序, 并将系统安装於绕回装置而不 是一个分割区中. 这可以作为安装在 UMSDOS 外的另一种选择, 这将会更有效率的使用磁碟空间, 因为在 ext2fs 中最小配置单位是 1kB, 而在 DOS 中则是 32kB. 同时也可以用 在 VFAT 或 NTFS 上而不会产生其他问题. 5.5 从不可开机的设备上启动 Linux 这个方法也可以用在正常不能用来开机的设备上启动 Linux 系统. * 光碟片 * Zip 磁碟片 * 平行埠磁碟装置 还有许多其他的装置可以使用, NFS 根目录系统已经被核心所支援, 所以本文的 方法应该也可以用. References 1. mailto:amb@gedanken.demon.co.uk 2. mailto:shyue@sonoma.com.tw 3. http://www.fsf.org/ 4. http://www.informatik.hu-berlin.de/~loewis/ntfs/