1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
|
libtrash - a shared library to implement an intelligent, highly configurable
-------- "recycle bin" or "trash can" under GNU/Linux.
Written by Manuel Arriaga (m.arriaga@ip.pt).
Copyright (C) 2001, 2002 Manuel Arriaga
Licensed under the GNU General Public License version 2. See the file
COPYING for details.
Version: 0.8 (2002-02-03)
-------
See CHANGE.LOG for details.
DESCRIPTION:
-----------
libtrash is a shared library which, when preloaded, will intercept calls to
a series of GNU libc functions and make sure that, if an attempt to destroy
certain files is made, these won't be permanently destroyed but rather moved
to a "trash can". It also allows the user to mark certain directories as
"unremovable", which means that calls to functions which would result in the
loss of files under these directories will always fail, leaving those files
untouched in their original locations.
(This last feature is meant as a higher-level substitute for ext2fs'
"immutable" flag for use by those of us who rely on other file systems. An
important difference is that libtrash allows non-privileged users to take
advantage of this feature. Another important difference is that libtrash
only prevents the destruction of the file itself, not the editing /
modification of its contents.)
The GNU libc functions which can be overriden/"wrapped" are
- unlink();
- rename();
- fopen();
- freopen();
- open().
You can individually enable / disable each of these "protections"; by
default, only calls to the first two functions are intercepted.
----------------------------------------------------------------------------
IMPORTANT NOTE 1: The wrappers of the "open functions" (fopen, freopen and
open) behave differently from the real functions in an important way when
they are asked to open - in either write-mode or read-plus-write-mode - a
file considered "worthy" of having a copy of itself stored in the trash can
before being truncated: while the functions in GNU libc require
write-permission to that already existing file for the call to succeed,
these wrappers require write-permission to the DIRECTORY WHICH HOLDS THAT
FILE instead. This is so because, in fact, we are renaming the existing file
before opening it, and calls to rename() require write-permission to the
directory which holds the file for them to succeed. Usually, you only have
write-permission to files in directories to which you also have
write-permission, so this shouldn't be a huge problem in most cases.
IMPORTANT NOTE 2: When a file on a partition / filesystem other than the one
in which your trash can resides is destroyed, libtrash can't just use the
GNU libc function rename() to move it into your trash can: it must copy that
file byte-after-byte into your trash can and then delete the original. To
achieve that, read-permission to the destroyed file is required. Since in
most situations you don't have write-permission to a directory which holds
files you can't read, hopefully that won't prove a big problem, either.
However, be warned that copying a file (especially a large one) will take a
lot longer than simply renaming it.
IMPORTANT NOTE 3: At least on my system, 'su' doesn't pass the current
environment to the new shell (although the man page states "the current
environment is passed to the new shell"), so if you only type 'su root', the
environmental variable LD_PRELOAD won't be set (see below) and libtrash
won't work. The obvious solution is to always type 'su -' instead of just
'su', since this way the environment of the account you are su-ing to will
be set. But what if you forget the dash (after all, libtrash is supposed to
be a protection against mistakes of this kind... :))? The only work-around I
can think of is defining a shell alias 'su' -> 'su -', but, if you do that
and then mistakenly type 'su -', that will be translated to 'su - -'... If
you can think of (or actually know) a better work-around, please tell me
about it.
----------------------------------------------------------------------------
libtrash works with any GNU/Linux program, both at the console and under
XFree86, and operates independently of the programming language the program
was written in (unless, of course, it doesn't make use of GNU libc). It can
be extensively configured by each user through a personal, user-specific
configuration file.
Although libtrash itself was written in C, the installation procedure
requires Perl.
HOW libtrash WORKS / FEATURES:
-----------------------------
libtrash recreates the directory structure of your home directory under the
trash can, which means that, should you need to recover the mistakenly
deleted file /home/user/programming/test.c, it will be stored in
/home/user/Trash/programming/test.c. If you have instructed libtrash to also
store copies of files which you delete in directories outside of your home
dir (see libtrash.conf for details), they will be available under
Trash/SYSTEM_ROOT. E.g.: after deletion by the user joe, /common-dir/doc.txt
will be available at /home/joe/Trash/SYSTEM_ROOT/common-dir/doc.txt.
When you try to delete a file in a certain directory where you had
previously deleted another file with the same name, libtrash stores the new
file with a different name, in order to preserve both files. E.g.:
$ touch test
$ rm test
$ ls Trash/
test
$ touch test
$ rm test
$ ls Trash/
test test[1] <-- The file we deleted first wasn't lost.
libtrash keeps generating new names until no name collision occurs. The
deletion of a file never causes the permanent loss of a previously "deleted"
file.
Temporary files can be automatically "ignored" and really destroyed.
You can define whether you wish to allow the definitive removal of files
already in your trash can while libtrash is active. Allowing this has one
major disadvantage, which is explained in libtrash.conf. But, on the other
hand, if you don't allow the destruction of files already in your trash can,
when you need to recover HD space by permanently removing files currently
found in your trash can you will have to temporarily disable libtrash first
(instructions on how to achieve this can be found below).
To avoid the accumulation of useless files in your users' trash cans, it is
probably wise to run the script cleanTrash regularly (perhaps from a cron
job). This Perl script was kindly provided by Daniel Sadilek and works by
removing the oldest files from each trash can in your system whenever that
trash can grows beyond a certain disk size. It is meant to be run by root.
cleanTrash, together with the license according to which it can be
distributed and a short README file written by me, can be found under the
directory "cleanTrash".
You can also choose whether files outside of your home directory, hidden
files (and files under hidden directories), backup and temporary files used
by text editors and files on removable media should be handled normally or
"ignored" (i.e., you can decide if copies of such files should be created in
your trash can if the originals are about to be destroyed). It is also
possible to discriminate files based on their names' extensions: you can
instruct libtrash, e.g., to always ignore object files (files with the
extension ".o"), meaning that deleting files of this type won't result in
the creation of copies of these in your trash can. By default, besides
object files, TeX log and auxiliary files (".log" and ".aux", respectively)
are also ignored.
The user may also configure libtrash to print a warning message to stderr
after the execution of each program while libtrash is disabled. This feature
is meant to remind the user that libtrash is disabled and that, for that
reason, any deletions will be permanent. This feature is disabled by
default, so that libtrash remains "invisible" to the user.
Other options: name of trash can, name of TRASH_SYSTEM_ROOT under your trash
can, whether to allow the destruction of the configuration file used by
libtrash, and what to do in case of error.
To configure libtrash so that it better suits your purposes you should edit
the file libtrash.conf before compiling. Even if you won't be configuring
libtrash at compile-time, it is highly recommended that you at least read
config.txt so that you know how libtrash handles its configuration files.
CONFIGURING, COMPILING, INSTALLING AND ACTIVATING libtrash:
----------------------------------------------------------
To configure:
1 - Edit the file libtrash.conf. All options are verbosely explained there.
To compile:
2 - Run "make".
To install:
3- Edit the Makefile, possibly choosing alternative locations for the shared
library and the system-wide, uneditable configuration file (defaults:
/usr/local/lib and /etc/libtrash.conf, respectively).
4- Run, as root, "make install".
This installs libtrash-0.8 in the directory specified at the top of the
Makefile, runs ldconfig and puts a system-wide configuration file in
/etc/libtrash.conf reflecting the compile-time defaults used. NEVER EDIT
THIS FILE. USE A PERSONAL CONFIGURATION FILE INSTEAD.
5- Now go and read config.txt.
To activate libtrash:
5 - So that calls to the different GNU libc functions are intercepted, you
must "preload" this library. This is done by running the following command
whenever you log in:
export LD_PRELOAD=path_of_symlink_to_libtrash
where path_of_symlink_to_libtrash should be substituted with the real path
to that symbolic link (if you didn't modify the INSTLIBDIR variable in the
Makefile, that would be "/usr/local/lib/libtrash.so.0"). This can be
achieved in a painless way by appending that line to a file which gets
executed whenever you log in, such as ~/.profile or ~/.bash_login. If you
wish to activate libtrash for every user on the system, append that line to
/etc/profile instead. (Note: Your distribution might use different files for
this purpose. If you use a shell other than Bash, you probably know what to
do in your situation.)
TESTING libtrash:
----------------
libtrash should now be set up and ready to spare you a lot of headaches. You
can test drive it with the following commands (assuming that you didn't
change TRASH_CAN to a string other than "Trash"):
$ touch test_file
$ rm test_file
$ ls Trash/
test_file should now be stored in Trash/. But don't be fooled by this
example! libtrash isn't restricted to "saving" files which you explicitly
deleted with "rm": it also works with your (graphical) file manager, mail
user agent, etc...
SUSPENDING/RESUMING/CIRCUMVENTING libtrash:
------------------------------------------
Should you need to temporarily disable libtrash, you can do so by running
the command
$ export TRASH_OFF=YES
When you are done, libtrash can be reactivated by typing:
$ export TRASH_OFF=NO
You might make these operations simpler by appending the following two lines
to the init file you used in step 5) above (if you are using Bash as your
shell):
alias trash_on="export TRASH_OFF=NO"
alias trash_off="export TRASH_OFF=YES"
After doing so, you can enable/disable libtrash by typing
$ trash_on
or
$ trash_off
at the prompt.
If you often need to remove one or more files in a definitive way using
'rm', you might wish to define
alias hardrm="TRASH_OFF=YES rm"
After having done so,
hardrm file.txt
will achieve the same effect as
TRASH_OFF=YES rm file.txt
If you have set the option SHOULD_WARN (see libtrash.conf), running a
command while TRASH_OFF is set to "YES" will result in libtrash printing to
stderr (at least) one reminder that it is currently disabled after that
program exits.
CONTACT:
-------
This library was written by me, Manuel Arriaga. Feel free to contact me at
m.arriaga@ip.pt with questions, suggestions or bug reports.
CREDITS:
-------
- Avery Pennarun, whose "freestyle-concept" tarball showed me how to
intercept system calls and write a suitable Makefile.
- Phil Howard and wwp for pointing out problems with the (abandoned) hardrm
script. wwp also offered general advice.
- Karl Pitrich for letting me know about a bug in the calls to mkdir() and
chmod() in the code of dir_ok() which rendered the trash can (and all
subdirs) unbrowsable if you didn't manually correct their permissions with
'chmod'.
- Daniel Sadilek for letting me know that some people _did_ need inter-device
support :), the helpful cleanTrash Perl script and help testing libtrash-0.6.
- Ross Skaliotis for helping me pin down the cause of the incompatibility
between libtrash and Samba.
- Christoph Dworzak for reporting poor handling of special files, and
providing a patch.
|