Miklos Szeredi | b5a3c9b | 2006-01-09 14:31:25 +0000 | [diff] [blame] | 1 | This was generated on 2006/01/09 from |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 2 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 3 | http://fuse.sourceforge.net/wiki/index.php/FAQ |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 4 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 5 | For an up to date version please see the above page. You can also add |
| 6 | new entries there. |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 7 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 8 | General |
| 9 | ======= |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 10 | |
Miklos Szeredi | b5a3c9b | 2006-01-09 14:31:25 +0000 | [diff] [blame] | 11 | How can I umount a filesystem? |
| 12 | ------------------------------ |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 13 | |
| 14 | Filesystems mounted without sysadmin privileges can be umounted with |
| 15 | the command |
| 16 | |
| 17 | fusermount -u mountpoint |
| 18 | |
| 19 | What's the difference between FUSE and LUFS? |
| 20 | -------------------------------------------- |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 21 | |
| 22 | The main difference between them is that in LUFS the filesystem is a |
| 23 | shared object (.so) which is loaded by lufsmount, and in FUSE the |
| 24 | filesystem is a separate executable, which uses the fuse library. The |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 25 | actual API is very similar, and there's a translator, that can load |
| 26 | LUFS modules and run them using the FUSE kernel module (see the lufis |
| 27 | package on the FUSE page). |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 28 | |
| 29 | Another difference is that LUFS does some caching of directories and |
| 30 | file attributes. FUSE does not do this, so it provides a 'thinner' |
| 31 | interface. |
| 32 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 33 | By now LUFS development seems to have completely ceased. |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 34 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 35 | Why is it called FUSE? There's a ZX Spectrum emulator called Fuse too. |
| 36 | ---------------------------------------------------------------------- |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 37 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 38 | At the time of christening it, the author of FUSE (the filesystem) |
| 39 | hadn't heard of Fuse (the Speccy emulator). Which is ironic, since he |
| 40 | knew Philip Kendall, the author of that other Fuse from earlier times. |
| 41 | Btw. the author of FUSE (the filesystem) also created a Speccy |
| 42 | emulator called Spectemu. |
Miklos Szeredi | e518374 | 2005-02-02 11:14:04 +0000 | [diff] [blame] | 43 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 44 | The name wanted to be a clever acronym for "Filesystem in USErspace", |
| 45 | but it turned out to be an unfortunate choice. The author has since |
| 46 | vowed never to name a project after a common term, not even anything |
| 47 | found more than a handful of times on Google. |
Miklos Szeredi | e518374 | 2005-02-02 11:14:04 +0000 | [diff] [blame] | 48 | |
Miklos Szeredi | b5a3c9b | 2006-01-09 14:31:25 +0000 | [diff] [blame] | 49 | Is it possible to mount a fuse filesystem from fstab? |
| 50 | ----------------------------------------------------- |
| 51 | |
| 52 | Yes, from version 2.4.0 this is possible. The filesystem must adhere |
| 53 | to some rules about command line options to be able to work this |
| 54 | way. Here's an example of mounting an sshfs filesystem: |
| 55 | |
| 56 | sshfs#user@host:/ /mnt/host fuse defaults 0 0 |
| 57 | |
| 58 | The mounting is performed by the /sbin/mount.fuse helper script. |
| 59 | |
| 60 | Licensing issues |
| 61 | ~~~~~~~~~~~~~~~~ |
| 62 | |
| 63 | Under what license is FUSE released? |
| 64 | ------------------------------------ |
| 65 | |
| 66 | The kernel part is released under the GNU GPL. |
| 67 | |
| 68 | Libfuse is released under the GNU LGPL. |
| 69 | |
| 70 | All other parts (examples, fusermount, etc) are released under the GNU GPL. |
| 71 | |
| 72 | Under what conditions may I modify or distribute FUSE? |
| 73 | ------------------------------------------------------ |
| 74 | |
| 75 | See the files COPYING and COPYING.LIB in the distribution. |
| 76 | |
| 77 | More information can be found at http://www.gnu.org/licenses/ |
| 78 | |
| 79 | Under what conditions may I distribute a filesystem which uses libfuse? |
| 80 | ----------------------------------------------------------------------- |
| 81 | |
| 82 | See COPYING.LIB in the distribution. |
| 83 | |
| 84 | In simple terms as long as you are linking dynamically (the default) |
| 85 | there are no limitations on linking with libfuse. For example you may |
| 86 | distribute the filesystem itself in binary form, without source code, |
| 87 | under any propriatery license. |
| 88 | |
| 89 | Under what conditions may I distribute a filesystem that uses the raw |
| 90 | --------------------------------------------------------------------- |
| 91 | kernel interface of FUSE? |
| 92 | ------------------------- |
| 93 | |
| 94 | There are no restrictions whatsoever for using the raw kernel interface. |
| 95 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 96 | API |
| 97 | === |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 98 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 99 | Which method is called on the close() system call? |
| 100 | -------------------------------------------------- |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 101 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 102 | flush() and possibly release(). For details see the documentation of |
| 103 | these methods in <fuse.h> |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 104 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 105 | Wouldn't it be simpler if there were a single close() method? |
| 106 | ------------------------------------------------------------- |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 107 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 108 | No, because the relationship between the close() system call and the |
| 109 | release of the file (the opposite of open) is not as simple as people |
| 110 | tend to imagine. UNIX allows open files to acquire multiple |
| 111 | references |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 112 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 113 | * after fork() two processes refer to the same open file |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 114 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 115 | * dup() and dup2() make another file descriptor refer to the same |
| 116 | file |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 117 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 118 | * mmap() makes a memory mapping refer to an open file |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 119 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 120 | This means, that for a single open() system call, there could be more |
| 121 | than one close() and possibly munmap() calls until the open file is |
| 122 | finally released. |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 123 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 124 | Can I return an error from release()? |
| 125 | ------------------------------------- |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 126 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 127 | No, it's not possible. |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 128 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 129 | If you need to return errors on close, you must do that from flush(). |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 130 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 131 | How do I know which is the last flush() before release()? |
| 132 | --------------------------------------------------------- |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 133 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 134 | You can't. All flush() calls should be treated equally. Anyway it |
| 135 | wouldn't be worth optimizing away non-final flushes, since it's fairly |
| 136 | rare to have multiple write-flush sequences on an open file. |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 137 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 138 | Why doesn't FUSE forward ioctl() calls to the filesystem? |
| 139 | --------------------------------------------------------- |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 140 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 141 | Because it's not possible: data passed to ioctl() doesn't have a well |
| 142 | defined length and structure like read() and write(). Consider using |
| 143 | getxattr() and setxattr() instead. |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 144 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 145 | Is there a way to know the uid, gid or pid of the process performing |
| 146 | -------------------------------------------------------------------- |
| 147 | the operation? |
| 148 | -------------- |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 149 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 150 | Yes: fuse_get_context()->uid, etc. |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 151 | |
Miklos Szeredi | b5a3c9b | 2006-01-09 14:31:25 +0000 | [diff] [blame] | 152 | How should threads be started? |
| 153 | ------------------------------ |
| 154 | |
| 155 | Miscellaneous threads should be started from the init() method. |
| 156 | Threads started before fuse_main() will exit when the process goes |
| 157 | into the background. |
| 158 | |
| 159 | Is it possible to store a pointer to private data in the |
| 160 | -------------------------------------------------------- |
| 161 | fuse_file_info structure? |
| 162 | ------------------------- |
| 163 | |
| 164 | Yes, the 'fh' filed is for this purpose. This filed may be set in the |
| 165 | open() and create() methods, and is available in all other methods |
| 166 | having a struct fuse_file_info parameter. Note, that changing the |
| 167 | value of 'fh' in any other method as open() or create() will have no |
| 168 | affect. |
| 169 | |
| 170 | Since the type of 'fh' is unsigned long, you need to use casts when |
| 171 | storing and retrieving a pointer. Under Linux (and most other |
| 172 | architectures) an unsigned long will be able to hold a pointer. |
| 173 | |
| 174 | This could have been done with a union of 'void *' and 'unsigned long' |
| 175 | but that would not have been any more type safe as having to use |
| 176 | explicit casts. The recommended type safe solution is to write a |
| 177 | small inline function that retrieves the pointer from the |
| 178 | fuse_file_info structure. |
| 179 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 180 | Problems |
| 181 | ======== |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 182 | |
Miklos Szeredi | b5a3c9b | 2006-01-09 14:31:25 +0000 | [diff] [blame] | 183 | Version problems |
| 184 | ~~~~~~~~~~~~~~~~ |
| 185 | |
| 186 | Why do I get Connection Refused after mounting? |
| 187 | ----------------------------------------------- |
| 188 | |
| 189 | Library is too old (< 2.3.0) |
| 190 | |
| 191 | You can check which version of the library is being used by foofs by |
| 192 | doing 'ldd path_to_foofs'. It will return something like this |
| 193 | |
| 194 | libfuse.so.2 => /usr/local/lib/libfuse.so.2 (0xb7fc9000) |
| 195 | libpthread.so.0 => /lib/tls/libpthread.so.0 (0xb7fb9000) |
| 196 | libglib-2.0.so.0 => /usr/lib/libglib-2.0.so.0 (0xb7f39000) |
| 197 | libc.so.6 => /lib/tls/libc.so.6 (0xb7e04000) |
| 198 | |
| 199 | Then do 'ls -l path_to_libfuse' |
| 200 | |
| 201 | > ls -l /usr/local/lib/libfuse.so.2 |
| 202 | lrwxrwxrwx 1 root root 16 Sep 26 13:41 /usr/local/lib/libfuse.so.2 -> libfuse.so.2.2.1 |
| 203 | |
| 204 | Why does fusermount fail with an Unknown option error? |
| 205 | ------------------------------------------------------ |
| 206 | |
| 207 | Errors like 'fusermount: Unknown option -o' or 'fusermount: Unknown |
| 208 | option --' mean, that an old version of fusermount is being used. You |
| 209 | can check by doing 'which fusermount'. |
| 210 | |
| 211 | If you installed FUSE from source, then this is probably because there |
| 212 | exists a binary package on your system which also contains a |
| 213 | fusermount program, and is found first in the path, e.g. in |
| 214 | /usr/bin/fusermount. |
| 215 | |
| 216 | The solution is to remove the binary package. |
| 217 | |
| 218 | Installation problems |
| 219 | ~~~~~~~~~~~~~~~~~~~~~ |
| 220 | |
| 221 | Why is there an error loading shared libraries? |
| 222 | ----------------------------------------------- |
| 223 | |
| 224 | If you get the following error when starting a FUSE-based filesystem: |
| 225 | |
| 226 | foofs: error while loading shared libraries: libfuse.so.2: |
| 227 | cannot open shared object file: No such file or directory |
| 228 | |
| 229 | check /etc/ld.so.conf for a line containing '/usr/local/lib'. If it's |
| 230 | missing, add it, and run ldconfig afterwards. |
| 231 | |
| 232 | Why doesn't mounting as user work if installing FUSE from a package? |
| 233 | -------------------------------------------------------------------- |
| 234 | |
| 235 | Distributions often package 'fusermount' without the suid bit, or only |
| 236 | executable to the 'fuse' group. |
| 237 | |
| 238 | This results in the following message, when trying to mount a |
| 239 | filesystem as an unprivileged user: |
| 240 | |
| 241 | fusermount: mount failed: Operation not permitted |
| 242 | |
| 243 | The simplest solution is to change the mode of 'fusermount': |
| 244 | |
| 245 | chmod 4755 /usr/bin/fusermount |
| 246 | |
| 247 | Note, you may have to do this after each upgrade. |
| 248 | |
| 249 | Other problems |
| 250 | ~~~~~~~~~~~~~~ |
| 251 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 252 | Why are some bytes zeroed when reading a file? |
| 253 | ---------------------------------------------- |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 254 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 255 | This happens if the filesystem returns a short count from the read() |
| 256 | method. If the file wasn't opened in direct I/O mode, the read() |
| 257 | method must return exactly the requested number of bytes, unless it's |
| 258 | the end of the file. |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 259 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 260 | If the file was opened in direct I/O mode (with direct_io mount |
| 261 | option, or by setting the direct_io field of fuse_file_info at open) |
| 262 | the read can return a smaller value than requested. In this case the |
| 263 | end of file can be signalled by returning zero. |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 264 | |
Miklos Szeredi | b5a3c9b | 2006-01-09 14:31:25 +0000 | [diff] [blame] | 265 | Why does cp return operation not permitted when copying a file with no |
| 266 | ---------------------------------------------------------------------- |
| 267 | write permissions for the owner? |
| 268 | -------------------------------- |
| 269 | |
| 270 | "cp" calls open(2) with read-only permissions and O_CREAT, the purpose |
| 271 | being to atomically obtain a read/write file handle and make the file |
| 272 | read-only. Unfortunately, this does not work very well in fuse, since |
| 273 | you first get a mknod, and then an open call. At the time of open, you |
| 274 | can't distinguish easily wether this is the first open issued by cp, |
| 275 | or another process trying to write a read-only file. |
| 276 | |
| 277 | Defining the 'create' method solves this problem, however this |
| 278 | requires a Linux kernel version of at least 2.6.15 and libfuse version |
| 279 | 2.5 or greater. |
| 280 | |
| 281 | There can be other workarounds, however the easy one is to use the |
| 282 | "default_permissions" mount option, and to avoid checking permissions |
| 283 | on open. If you store files on a filesystem, this can get tricky |
| 284 | because you will have to change the file mode to allow writing. Using |
| 285 | the stateful API (i.e. returning an handle on open) will simplify |
| 286 | things. In this case, and using "-o default_permissions", when |
| 287 | implementing the open call you have to: |
| 288 | |
| 289 | 1. check if the open is in write mode (i.e. mode has O_RDWR or O_WRONLY) |
| 290 | |
| 291 | 2. in that case (in mutual exclusion with other open, getattr |
| 292 | etc. calls on the same file) change the mode from "M" to "M OR |
| 293 | 0o200" |
| 294 | |
| 295 | 3. open the file, change back the mode even in case of errors, and |
| 296 | return the obtained handle |
| 297 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 298 | Why doesn't find work on my filesystem? |
| 299 | --------------------------------------- |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 300 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 301 | The st_nlink member must be set correctly for directories to make find |
| 302 | work. If it's not set correctly the -noleaf option of find can be |
| 303 | used to make it ignore the hard link count (see man find). |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 304 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 305 | The correct value of st_nlink for directories is NSUB + 2. Where NSUB |
| 306 | is the number of subdirectories. NOTE: regular-file/symlink/etc |
| 307 | entries do not count into NSUB, only directories. |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 308 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 309 | If calculating NSUB is hard, the filesystem can set st_nlink of |
| 310 | directories to 1, and find will still work. This is not documented |
Miklos Szeredi | 4322e17 | 2005-08-02 09:53:51 +0000 | [diff] [blame] | 311 | behavior of find, and it's not clear whether this is intended or just |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 312 | by accident. But for example the NTFS filesysem relies on this, so |
| 313 | it's unlikely that this "feature" will go away. |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 314 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 315 | What is the reason for IO errors? |
| 316 | --------------------------------- |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 317 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 318 | The kernel part of FUSE returns the EIO error value, whenever the |
| 319 | userspace filesystem sends a "bad" reply. Sometimes these are |
| 320 | unavoidable, and not necessarily a fault of the filesystem. Possible |
| 321 | causes of this are (non-exhaustive) |
| 322 | |
| 323 | * the filesystem returned a short count on write() |
| 324 | |
| 325 | * the type of the file has changed (e.g. a directory suddenly |
| 326 | became a symlink) |
| 327 | |
| 328 | * a directory entry contained a filename that was too long (no, |
| 329 | ENAMETOOLONG is not the right error here) |
| 330 | |
| 331 | * the same node ID value was used for two different directories |
| 332 | (i.e. hard-linked directories are not allowed) |
| 333 | |
| 334 | Misc |
| 335 | ==== |
| 336 | |
| 337 | Can the filesystem ask a question on the terminal of the user? |
| 338 | -------------------------------------------------------------- |
Miklos Szeredi | e518374 | 2005-02-02 11:14:04 +0000 | [diff] [blame] | 339 | |
Miklos Szeredi | a2c5e56 | 2004-10-19 22:01:21 +0000 | [diff] [blame] | 340 | It would not be possible generally speaking, since it might not be an |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 341 | interactive program but rather a daemon, or a GUI program doing the |
| 342 | operation. However you should be able to get the PID for the caller, |
| 343 | and by looking in /proc you should be able to find the process tty or |
| 344 | something similar. |
Miklos Szeredi | e518374 | 2005-02-02 11:14:04 +0000 | [diff] [blame] | 345 | |
Miklos Szeredi | 4cecc25 | 2005-09-27 15:42:22 +0000 | [diff] [blame] | 346 | But this is not recommended. You should rather think about solving |
| 347 | this another way. |