├── AUTHORS ├── COPYING ├── INSTALL ├── LICENSE ├── Makefile.am ├── NEWS ├── README ├── TODO ├── configure.ac ├── m4 ├── ax_boost_base.m4 ├── ax_boost_filesystem.m4 ├── ax_boost_iostreams.m4 ├── ax_boost_program_options.m4 ├── ax_boost_serialization.m4 └── ax_boost_system.m4 └── src ├── Block.cpp ├── Block.hpp ├── Compress.cpp ├── Compress.hpp ├── CompressedMagic.cpp ├── CompressedMagic.hpp ├── CompressionType.cpp ├── CompressionType.hpp ├── File.cpp ├── File.hpp ├── FileHeader.cpp ├── FileHeader.hpp ├── FileManager.cpp ├── FileManager.hpp ├── FileRememberTimes.cpp ├── FileRememberTimes.hpp ├── FileRememberXattrs.cpp ├── FileRememberXattrs.hpp ├── FileUtils.cpp ├── FileUtils.hpp ├── FuseCompress.cpp ├── FuseCompress.hpp ├── LayerMap.cpp ├── LayerMap.hpp ├── LinearMap.cpp ├── LinearMap.hpp ├── Lock.hpp ├── Makefile.am ├── Memory.cpp ├── Memory.hpp ├── Mutex.hpp ├── assert.h ├── boost ├── archive │ ├── polymorphic_portable_archive.hpp │ ├── portable_archive.hpp │ ├── portable_archive_exception.hpp │ ├── portable_iarchive.hpp │ └── portable_oarchive.hpp ├── integer │ ├── cover_operators.hpp │ └── endian.hpp ├── iostreams │ ├── device │ │ └── nonclosable_file_descriptor.hpp │ └── filter │ │ ├── bytescounter.hpp │ │ ├── lzma.cpp │ │ ├── lzma.hpp │ │ ├── lzo.hpp │ │ └── xor.hpp └── math │ ├── detail │ └── fp_traits.hpp │ ├── fpclassify.hpp │ ├── nonfinite_num_facets.hpp │ └── signbit.hpp ├── fusecompress.1 ├── fusecompress_offline.1 ├── main.cpp ├── main_offline.cpp ├── rlog └── rlog.h └── tests ├── Makefile.am ├── TLayerMap.cpp ├── print_compress.cpp └── xattrs.cpp /AUTHORS: -------------------------------------------------------------------------------- 1 | Milan Svoboda 2 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free 5 | Software Foundation, Inc. 6 | 7 | This file is free documentation; the Free Software Foundation gives 8 | unlimited permission to copy, distribute and modify it. 9 | 10 | Basic Installation 11 | ================== 12 | 13 | These are generic installation instructions. 14 | 15 | The `configure' shell script attempts to guess correct values for 16 | various system-dependent variables used during compilation. It uses 17 | those values to create a `Makefile' in each directory of the package. 18 | It may also create one or more `.h' files containing system-dependent 19 | definitions. Finally, it creates a shell script `config.status' that 20 | you can run in the future to recreate the current configuration, and a 21 | file `config.log' containing compiler output (useful mainly for 22 | debugging `configure'). 23 | 24 | It can also use an optional file (typically called `config.cache' 25 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 26 | the results of its tests to speed up reconfiguring. (Caching is 27 | disabled by default to prevent problems with accidental use of stale 28 | cache files.) 29 | 30 | If you need to do unusual things to compile the package, please try 31 | to figure out how `configure' could check whether to do them, and mail 32 | diffs or instructions to the address given in the `README' so they can 33 | be considered for the next release. If you are using the cache, and at 34 | some point `config.cache' contains results you don't want to keep, you 35 | may remove or edit it. 36 | 37 | The file `configure.ac' (or `configure.in') is used to create 38 | `configure' by a program called `autoconf'. You only need 39 | `configure.ac' if you want to change it or regenerate `configure' using 40 | a newer version of `autoconf'. 41 | 42 | The simplest way to compile this package is: 43 | 44 | 1. `cd' to the directory containing the package's source code and type 45 | `./configure' to configure the package for your system. If you're 46 | using `csh' on an old version of System V, you might need to type 47 | `sh ./configure' instead to prevent `csh' from trying to execute 48 | `configure' itself. 49 | 50 | Running `configure' takes awhile. While running, it prints some 51 | messages telling which features it is checking for. 52 | 53 | 2. Type `make' to compile the package. 54 | 55 | 3. Optionally, type `make check' to run any self-tests that come with 56 | the package. 57 | 58 | 4. Type `make install' to install the programs and any data files and 59 | documentation. 60 | 61 | 5. You can remove the program binaries and object files from the 62 | source code directory by typing `make clean'. To also remove the 63 | files that `configure' created (so you can compile the package for 64 | a different kind of computer), type `make distclean'. There is 65 | also a `make maintainer-clean' target, but that is intended mainly 66 | for the package's developers. If you use it, you may have to get 67 | all sorts of other programs in order to regenerate files that came 68 | with the distribution. 69 | 70 | Compilers and Options 71 | ===================== 72 | 73 | Some systems require unusual options for compilation or linking that the 74 | `configure' script does not know about. Run `./configure --help' for 75 | details on some of the pertinent environment variables. 76 | 77 | You can give `configure' initial values for configuration parameters 78 | by setting variables in the command line or in the environment. Here 79 | is an example: 80 | 81 | ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix 82 | 83 | *Note Defining Variables::, for more details. 84 | 85 | Compiling For Multiple Architectures 86 | ==================================== 87 | 88 | You can compile the package for more than one kind of computer at the 89 | same time, by placing the object files for each architecture in their 90 | own directory. To do this, you must use a version of `make' that 91 | supports the `VPATH' variable, such as GNU `make'. `cd' to the 92 | directory where you want the object files and executables to go and run 93 | the `configure' script. `configure' automatically checks for the 94 | source code in the directory that `configure' is in and in `..'. 95 | 96 | If you have to use a `make' that does not support the `VPATH' 97 | variable, you have to compile the package for one architecture at a 98 | time in the source code directory. After you have installed the 99 | package for one architecture, use `make distclean' before reconfiguring 100 | for another architecture. 101 | 102 | Installation Names 103 | ================== 104 | 105 | By default, `make install' installs the package's commands under 106 | `/usr/local/bin', include files under `/usr/local/include', etc. You 107 | can specify an installation prefix other than `/usr/local' by giving 108 | `configure' the option `--prefix=PREFIX'. 109 | 110 | You can specify separate installation prefixes for 111 | architecture-specific files and architecture-independent files. If you 112 | pass the option `--exec-prefix=PREFIX' to `configure', the package uses 113 | PREFIX as the prefix for installing programs and libraries. 114 | Documentation and other data files still use the regular prefix. 115 | 116 | In addition, if you use an unusual directory layout you can give 117 | options like `--bindir=DIR' to specify different values for particular 118 | kinds of files. Run `configure --help' for a list of the directories 119 | you can set and what kinds of files go in them. 120 | 121 | If the package supports it, you can cause programs to be installed 122 | with an extra prefix or suffix on their names by giving `configure' the 123 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 124 | 125 | Optional Features 126 | ================= 127 | 128 | Some packages pay attention to `--enable-FEATURE' options to 129 | `configure', where FEATURE indicates an optional part of the package. 130 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 131 | is something like `gnu-as' or `x' (for the X Window System). The 132 | `README' should mention any `--enable-' and `--with-' options that the 133 | package recognizes. 134 | 135 | For packages that use the X Window System, `configure' can usually 136 | find the X include and library files automatically, but if it doesn't, 137 | you can use the `configure' options `--x-includes=DIR' and 138 | `--x-libraries=DIR' to specify their locations. 139 | 140 | Specifying the System Type 141 | ========================== 142 | 143 | There may be some features `configure' cannot figure out automatically, 144 | but needs to determine by the type of machine the package will run on. 145 | Usually, assuming the package is built to be run on the _same_ 146 | architectures, `configure' can figure that out, but if it prints a 147 | message saying it cannot guess the machine type, give it the 148 | `--build=TYPE' option. TYPE can either be a short name for the system 149 | type, such as `sun4', or a canonical name which has the form: 150 | 151 | CPU-COMPANY-SYSTEM 152 | 153 | where SYSTEM can have one of these forms: 154 | 155 | OS KERNEL-OS 156 | 157 | See the file `config.sub' for the possible values of each field. If 158 | `config.sub' isn't included in this package, then this package doesn't 159 | need to know the machine type. 160 | 161 | If you are _building_ compiler tools for cross-compiling, you should 162 | use the option `--target=TYPE' to select the type of system they will 163 | produce code for. 164 | 165 | If you want to _use_ a cross compiler, that generates code for a 166 | platform different from the build platform, you should specify the 167 | "host" platform (i.e., that on which the generated programs will 168 | eventually be run) with `--host=TYPE'. 169 | 170 | Sharing Defaults 171 | ================ 172 | 173 | If you want to set default values for `configure' scripts to share, you 174 | can create a site shell script called `config.site' that gives default 175 | values for variables like `CC', `cache_file', and `prefix'. 176 | `configure' looks for `PREFIX/share/config.site' if it exists, then 177 | `PREFIX/etc/config.site' if it exists. Or, you can set the 178 | `CONFIG_SITE' environment variable to the location of the site script. 179 | A warning: not all `configure' scripts look for a site script. 180 | 181 | Defining Variables 182 | ================== 183 | 184 | Variables not defined in a site shell script can be set in the 185 | environment passed to `configure'. However, some packages may run 186 | configure again during the build, and the customized values of these 187 | variables may be lost. In order to avoid this problem, you should set 188 | them in the `configure' command line, using `VAR=value'. For example: 189 | 190 | ./configure CC=/usr/local2/bin/gcc 191 | 192 | causes the specified `gcc' to be used as the C compiler (unless it is 193 | overridden in the site shell script). Here is a another example: 194 | 195 | /bin/bash ./configure CONFIG_SHELL=/bin/bash 196 | 197 | Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent 198 | configuration-related scripts to be executed by `/bin/bash'. 199 | 200 | `configure' Invocation 201 | ====================== 202 | 203 | `configure' recognizes the following options to control how it operates. 204 | 205 | `--help' 206 | `-h' 207 | Print a summary of the options to `configure', and exit. 208 | 209 | `--version' 210 | `-V' 211 | Print the version of Autoconf used to generate the `configure' 212 | script, and exit. 213 | 214 | `--cache-file=FILE' 215 | Enable the cache: use and save the results of the tests in FILE, 216 | traditionally `config.cache'. FILE defaults to `/dev/null' to 217 | disable caching. 218 | 219 | `--config-cache' 220 | `-C' 221 | Alias for `--cache-file=config.cache'. 222 | 223 | `--quiet' 224 | `--silent' 225 | `-q' 226 | Do not print messages saying which checks are being made. To 227 | suppress all normal output, redirect it to `/dev/null' (any error 228 | messages will still be shown). 229 | 230 | `--srcdir=DIR' 231 | Look for the package's source code in directory DIR. Usually 232 | `configure' can determine that directory automatically. 233 | 234 | `configure' also accepts some other, not widely useful, options. Run 235 | `configure --help' for more details. 236 | 237 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This program is distributed under GNU/GPLv2 and later. 2 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | 3 | SUBDIRS = @subdirs@ 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | See GIT's log. 2 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | FuseCompress (compressed filesystem in userspace) 2 | 3 | We are not responsible for any badness that may happen to you during using 4 | this software. 5 | 6 | Todo: 7 | 8 | Bugs: 9 | File becames unreadable when it hits a not enough space condition. So 10 | be careful to really have enough free space on the disk to store all the data. 11 | 12 | This is more a feature than a bug: 13 | 14 | In CFile *FileManager::GetUnlocked(const char *name, bool create) FuseCompress 15 | uses the underlying filesystem inode number. This is a problem when you have 16 | multiple partitions underneath. 17 | 18 | For example 19 | 20 | /backups/.max (partition 1) 21 | /backups/.max/alex (partition 2) 22 | /backups/.max -> /backup/max (fusecompress) 23 | 24 | This would spoil the inode pool and potentially lead to conflicts, especially 25 | with hard links. 26 | 27 | Problems: 28 | Do NOT compile FuseCompress with g++-4.3.3! Strange threading problems 29 | (broken locking) were detected (thank you Steve!) when using this version of 30 | g++. 31 | 32 | There is a memory leak (not too big, user detects it after milions of 33 | copyied files) in 'file' package, more exactly in it's magic library, see: 34 | 35 | http://mx.gw.com/pipermail/file/2009/000306.html 36 | 37 | ==13747== 1,356 bytes in 135 blocks are definitely lost in loss record 9 of 12 38 | ==13747== at 0x4C256AE: malloc (in /usr/lib64/valgrind/amd64-linux/vgpreload_memcheck.so) 39 | ==13747== by 0x725503F: __vasprintf_chk (in /lib64/libc-2.9.so) 40 | ==13747== by 0x7254ED2: __asprintf_chk (in /lib64/libc-2.9.so) 41 | ==13747== by 0x63C2993: file_printf (in /usr/lib64/libmagic.so.1.0.0) 42 | ==13747== by 0x63BBDC5: (within /usr/lib64/libmagic.so.1.0.0) 43 | ==13747== by 0x63BC6A7: file_softmagic (in /usr/lib64/libmagic.so.1.0.0) 44 | ==13747== by 0x63C2B8A: file_buffer (in /usr/lib64/libmagic.so.1.0.0) 45 | ==13747== by 0x63B6104: magic_buffer (in /usr/lib64/libmagic.so.1.0.0) 46 | ==13747== by 0x41F9CF: CompressedMagic::isNativelyCompressed(char const*, int) (CompressedMagic.cpp:140) 47 | ==13747== by 0x42A44F: Compress::write(char const*, unsigned long, long) (Compress.cpp:361) 48 | ==13747== by 0x43B99E: Memory::write(bool) (Memory.cpp:203) 49 | ==13747== by 0x43BC77: Memory::merge(char const*) (Memory.cpp:53) 50 | ==13747== 51 | 52 | This leak should be fixed with the newer 'file' package. 53 | 54 | Requires: 55 | boost >= 1.33.1 56 | 57 | libz 58 | libbz2 59 | xz-4.999.9beta (lzma library from http://tukaani.org/xz/xz-4.999.9beta.tar.gz) 60 | liblzo2 61 | 62 | Example (with apt-get): 63 | 64 | $ sudo apt-get install libboost-dev libz-dev liblzo2-dev libmagic-dev libfuse-dev -y 65 | (also install the xz-beta manually, above) 66 | Note that 32-bit users may need to recompile boost by hand for long file support (see below). 67 | 68 | Compile: 69 | 70 | Typically you only need to run autoreconf -fiv && ./configure && make && sudo make install 71 | 72 | Boost's libraries may be stored in /usr/lib64 on 64bit systems, 73 | configure script needs to be called with: 74 | 75 | ./configure --with-boost-libdir=/usr/lib64/ 76 | 77 | Don't use --enable-debug flag. Build fails during linking with boost 78 | libraries. 79 | 80 | If you don't have pkg-tool installed, try following: 81 | 82 | FUSE_CFLAGS="-D_GNU_SOURCE -D_REENTRANT -D_POSIX_C_SOURCE=200112L -D_POSIX_SOURCE -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=500 -pedantic -Wno-long-long -Wall -fpermissive -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26" FUSE_LIBS="-lfuse" ./configure --with-boost=/usr/include/ --with-boost-libdir=/usr/lib64 83 | 84 | If your boost library was compiled for 32bit system without support for long files (bigger than 2GiB) 85 | configure script prints this error message: 86 | Boost library compiled for 32bit architecture without long file support! 87 | 88 | It means that any program using this library is limited to work with files smaller than 2GiB. 89 | You can either ignore this problem by passing --enable-crippled_boost to FuseCompress' configure script 90 | or compile boost with long file support. In both cases, try to report this problem to authors of your 91 | Linux distribution. 92 | 93 | There are switches you can use to build boost library with long file support: 94 | 95 | ./bjam "define=_FILE_OFFSET_BITS=64" release --toolset=gcc --build-type=minimal --layout=system --libdir=/usr/lib/ --prefix=/usr 96 | sudo ./bjam "define=_FILE_OFFSET_BITS=64" release --toolset=gcc --build-type=minimal --layout=system --libdir=/usr/lib/ --includedir=/usr/include/boost --prefix=/usr install 97 | 98 | Usage: 99 | 100 | See man pages for fusecompress and fusecompress_offline. 101 | 102 | Author: 103 | 104 | Milan Svoboda (author and project maintainer) 105 | 106 | Feel free to contact me with suggestions and bug reports. 107 | 108 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tex/fusecompress/08d824520a3fa06431502e7f9c42fa9ef93824ca/TODO -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ(2.59) 5 | AC_INIT(FuseCompress, 2.0, milan.svoboda@centrum.cz) 6 | AM_INIT_AUTOMAKE([foreign]) 7 | AC_CONFIG_HEADER([config.h]) 8 | AC_CONFIG_SRCDIR([.]) 9 | 10 | AC_LANG_CPLUSPLUS 11 | AC_PREFIX_DEFAULT([/usr/local]) 12 | 13 | # Checks for programs. 14 | AC_PROG_LIBTOOL 15 | AC_PROG_CXX 16 | AC_PROG_CC 17 | AC_PROG_CPP 18 | AC_PROG_LN_S 19 | 20 | # Need to include any user specified flags in the tests below, as they might 21 | # specify required include directories.. 22 | FUSEFLAGS="-D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26" 23 | CPPFLAGS="$CPPFLAGS $USER_INCLUDES $FUSEFLAGS" 24 | CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS $USER_INCLUDES" 25 | LDFLAGS="$LDFLAGS $PTHREAD_LIBS $USER_LDFLAGS" 26 | 27 | AX_BOOST_BASE([1.33.1]) 28 | AX_BOOST_SYSTEM 29 | AX_BOOST_SERIALIZATION 30 | AX_BOOST_IOSTREAMS 31 | AX_BOOST_PROGRAM_OPTIONS 32 | AX_BOOST_FILESYSTEM 33 | 34 | # Test the boost library whether it was compiled for 64bit system / 32bit 35 | # system with long file support or not. 36 | # 37 | # If not, there is a little help with intructions to get boost library compiled: 38 | # ./bjam "define=_FILE_OFFSET_BITS=64" release --toolset=gcc --build-type=minimal --layout=system --libdir=/usr/lib/ --prefix=/usr 39 | # sudo ./bjam "define=_FILE_OFFSET_BITS=64" release --toolset=gcc --build-type=minimal --layout=system --libdir=/usr/lib/ --includedir=/usr/include/boost --prefix=/usr install 40 | # 41 | AC_ARG_ENABLE(crippled_boost, 42 | AC_HELP_STRING([--enable-crippled_boost], 43 | [enables use of boost without long file support. don't report bugs or ask for help if working with files bigger than 1.5GiB]), 44 | USE_CRIPPLED_BOOST="yes",USE_CRIPPLED_BOOST="no") 45 | 46 | if test "x$USE_CRIPPLED_BOOST" = "xno"; then 47 | old_LIBS=$LIBS 48 | LIBS="$LIBS $BOOST_IOSTREAMS_LIB" 49 | AC_LANG_PUSH([C++]) 50 | AC_RUN_IFELSE([ 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include "src/boost/iostreams/device/nonclosable_file_descriptor.hpp" 59 | int main(int argc, char **argv) { 60 | int fd = open("bigfs.tmp", O_RDWR|O_CREAT, 0666); 61 | boost::iostreams::nonclosable_file_descriptor file(fd); 62 | long long ret = file.seek(3*1024*1024*1024LL, std::ios_base::beg); 63 | return ret == 3*1024*1024*1024LL ? 0 : 1; 64 | }], 65 | [], 66 | [AC_MSG_ERROR([Boost library compiled for 32bit architecture without long file support!])]) 67 | AC_LANG_POP([C++]) 68 | LIBS=$old_LIBS 69 | fi 70 | 71 | # Checks for libraries. 72 | AC_CHECK_LIB([pthread], [pthread_mutex_lock],, 73 | [AC_MSG_ERROR([Can't find pthread.a])],) 74 | AC_CHECK_LIB([magic], [magic_open],, 75 | [AC_MSG_ERROR([FuseCompress depends on libmagic.])],) 76 | 77 | # This function helps with configuring optional libraries. 78 | AC_DEFUN([AX_CHECK_OPTIONAL_LIB], 79 | [ 80 | AC_ARG_WITH([$1], 81 | AS_HELP_STRING([--with-$1@<:@=DIR@:>@], 82 | [use the $1 library - it is possible to specify a path for the library]), 83 | [ 84 | if test "$withval" = "no"; then 85 | want_lib="no" 86 | elif test "$withval" = "yes"; then 87 | want_lib="yes" 88 | ax_user_lib_path="" 89 | else 90 | want_lib="yes" 91 | ax_user_lib_path="$withval" 92 | fi 93 | ], 94 | [want_lib="yes"] 95 | ) 96 | 97 | if test "x$want_lib" = "xyes"; then 98 | if test "$ax_user_lib_path" != ""; then 99 | LDFLAGS="$LDFLAGS -L$ax_user_lib_path" 100 | export LDFLAGS 101 | fi 102 | AC_CHECK_LIB([$1], [$2],,,) 103 | fi 104 | ] 105 | ) 106 | 107 | # Check optional compression libraries. 108 | AX_CHECK_OPTIONAL_LIB([lzma], [lzma_code]) 109 | AX_CHECK_OPTIONAL_LIB([z], [uncompress]) 110 | AX_CHECK_OPTIONAL_LIB([bz2], [BZ2_bzBuffToBuffCompress]) 111 | AX_CHECK_OPTIONAL_LIB([lzo2], [lzo1x_1_compress]) 112 | 113 | AC_CHECK_HEADER(attr/xattr.h, 114 | [AC_DEFINE([HAVE_ATTR_XATTR_H], [], ["Have xattr.h header in attr/"])], 115 | [AC_CHECK_HEADER(sys/xattr.h, 116 | [AC_DEFINE([HAVE_SYS_XATTR_H], [], ["Have xattr.h header in sys/"])], 117 | [AC_MSG_ERROR([Can't find xattr.h in attr/ or /sys])])]) 118 | 119 | PKG_CHECK_MODULES([FUSE], [fuse]) 120 | 121 | # Check for a supported FUSE_MAJOR_VERSION. 122 | AC_MSG_CHECKING([For supported FUSE API version]) 123 | AC_RUN_IFELSE([ 124 | AC_LANG_PROGRAM([[#include ]], 125 | [[ 126 | if(FUSE_MAJOR_VERSION == 2 && FUSE_MINOR_VERSION >= 6) 127 | return 0; 128 | else 129 | return -1; 130 | ]])], 131 | [AC_MSG_RESULT([yes])], 132 | [AC_MSG_RESULT([no]) 133 | AC_MSG_FAILURE([FuseCompress requires FUSE 2.6 or newer.]) 134 | ] 135 | ) 136 | 137 | AC_ARG_ENABLE(profile, 138 | AC_HELP_STRING([--enable-profile], 139 | [collects profile for gprof]), 140 | CPPFLAGS="$CPPFLAGS -pg" LDFLAGS="$LDFLAGS -pg",) 141 | 142 | AC_ARG_ENABLE(debug, 143 | AC_HELP_STRING([--enable-debug], 144 | [creates debug build]), 145 | CPPFLAGS="$CPPFLAGS -D_GLIBCXX_DEBUG", CPPFLAGS="$CPPFLAGS -DNDEBUG") 146 | 147 | # Checks for header files. 148 | AC_HEADER_DIRENT 149 | AC_HEADER_STDC 150 | AC_CHECK_HEADERS([fcntl.h limits.h stddef.h stdlib.h string.h unistd.h utime.h]) 151 | 152 | # Checks for typedefs, structures, and compiler characteristics. 153 | AC_HEADER_STDBOOL 154 | AC_C_CONST 155 | AC_TYPE_UID_T 156 | AC_C_INLINE 157 | AC_TYPE_MODE_T 158 | AC_TYPE_OFF_T 159 | AC_C_RESTRICT 160 | AC_TYPE_SIZE_T 161 | AC_CHECK_TYPES([ptrdiff_t]) 162 | 163 | # Checks for library functions. 164 | AC_FUNC_CHOWN 165 | AC_FUNC_CLOSEDIR_VOID 166 | AC_FUNC_LSTAT 167 | AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK 168 | AC_FUNC_MALLOC 169 | AC_FUNC_MEMCMP 170 | AC_FUNC_REALLOC 171 | AC_FUNC_STAT 172 | AC_FUNC_UTIME_NULL 173 | AC_CHECK_FUNCS([fchdir fdatasync ftruncate lchown memmove memset mkdir rmdir strchr strerror utime]) 174 | 175 | # Tell Makefile.am to process following subdirectories 176 | subdirs="src src/tests" 177 | AC_SUBST(subdirs) 178 | 179 | AC_CONFIG_FILES([Makefile] [src/Makefile] [src/tests/Makefile]) 180 | AC_OUTPUT 181 | -------------------------------------------------------------------------------- /m4/ax_boost_base.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://autoconf-archive.cryp.to/ax_boost_base.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_BASE([MINIMUM-VERSION]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for the Boost C++ libraries of a particular version (or newer) 12 | # 13 | # If no path to the installed boost library is given the macro searchs 14 | # under /usr, /usr/local, /opt and /opt/local and evaluates the 15 | # $BOOST_ROOT environment variable. Further documentation is available at 16 | # . 17 | # 18 | # This macro calls: 19 | # 20 | # AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS) 21 | # 22 | # And sets: 23 | # 24 | # HAVE_BOOST 25 | # 26 | # LAST MODIFICATION 27 | # 28 | # 2008-04-12 29 | # 30 | # COPYLEFT 31 | # 32 | # Copyright (c) 2008 Thomas Porschberg 33 | # 34 | # Copying and distribution of this file, with or without modification, are 35 | # permitted in any medium without royalty provided the copyright notice 36 | # and this notice are preserved. 37 | 38 | AC_DEFUN([AX_BOOST_BASE], 39 | [ 40 | AC_ARG_WITH([boost], 41 | AS_HELP_STRING([--with-boost@<:@=DIR@:>@], [use boost (default is yes) - it is possible to specify the root directory for boost (optional)]), 42 | [ 43 | if test "$withval" = "no"; then 44 | want_boost="no" 45 | elif test "$withval" = "yes"; then 46 | want_boost="yes" 47 | ac_boost_path="" 48 | else 49 | want_boost="yes" 50 | ac_boost_path="$withval" 51 | fi 52 | ], 53 | [want_boost="yes"]) 54 | 55 | 56 | AC_ARG_WITH([boost-libdir], 57 | AS_HELP_STRING([--with-boost-libdir=LIB_DIR], 58 | [Force given directory for boost libraries. Note that this will overwrite library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]), 59 | [ 60 | if test -d $withval 61 | then 62 | ac_boost_lib_path="$withval" 63 | else 64 | AC_MSG_ERROR(--with-boost-libdir expected directory name) 65 | fi 66 | ], 67 | [ac_boost_lib_path=""] 68 | ) 69 | 70 | if test "x$want_boost" = "xyes"; then 71 | boost_lib_version_req=ifelse([$1], ,1.20.0,$1) 72 | boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'` 73 | boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'` 74 | boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'` 75 | boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` 76 | if test "x$boost_lib_version_req_sub_minor" = "x" ; then 77 | boost_lib_version_req_sub_minor="0" 78 | fi 79 | WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor` 80 | AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req) 81 | succeeded=no 82 | 83 | dnl first we check the system location for boost libraries 84 | dnl this location ist chosen if boost libraries are installed with the --layout=system option 85 | dnl or if you install boost with RPM 86 | if test "$ac_boost_path" != ""; then 87 | BOOST_LDFLAGS="-L$ac_boost_path/lib" 88 | BOOST_CPPFLAGS="-I$ac_boost_path/include" 89 | else 90 | for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do 91 | if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then 92 | BOOST_LDFLAGS="-L$ac_boost_path_tmp/lib" 93 | BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include" 94 | break; 95 | fi 96 | done 97 | fi 98 | 99 | dnl overwrite ld flags if we have required special directory with 100 | dnl --with-boost-libdir parameter 101 | if test "$ac_boost_lib_path" != ""; then 102 | BOOST_LDFLAGS="-L$ac_boost_lib_path" 103 | fi 104 | 105 | CPPFLAGS_SAVED="$CPPFLAGS" 106 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 107 | export CPPFLAGS 108 | 109 | LDFLAGS_SAVED="$LDFLAGS" 110 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 111 | export LDFLAGS 112 | 113 | AC_LANG_PUSH(C++) 114 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 115 | @%:@include 116 | ]], [[ 117 | #if BOOST_VERSION >= $WANT_BOOST_VERSION 118 | // Everything is okay 119 | #else 120 | # error Boost version is too old 121 | #endif 122 | ]])],[ 123 | AC_MSG_RESULT(yes) 124 | succeeded=yes 125 | found_system=yes 126 | ],[ 127 | ]) 128 | AC_LANG_POP([C++]) 129 | 130 | 131 | 132 | dnl if we found no boost with system layout we search for boost libraries 133 | dnl built and installed without the --layout=system option or for a staged(not installed) version 134 | if test "x$succeeded" != "xyes"; then 135 | _version=0 136 | if test "$ac_boost_path" != ""; then 137 | if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then 138 | for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do 139 | _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` 140 | V_CHECK=`expr $_version_tmp \> $_version` 141 | if test "$V_CHECK" = "1" ; then 142 | _version=$_version_tmp 143 | fi 144 | VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` 145 | BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" 146 | done 147 | fi 148 | else 149 | for ac_boost_path in /usr /usr/local /opt /opt/local ; do 150 | if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then 151 | for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do 152 | _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` 153 | V_CHECK=`expr $_version_tmp \> $_version` 154 | if test "$V_CHECK" = "1" ; then 155 | _version=$_version_tmp 156 | best_path=$ac_boost_path 157 | fi 158 | done 159 | fi 160 | done 161 | 162 | VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` 163 | BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" 164 | if test "$ac_boost_lib_path" = "" 165 | then 166 | BOOST_LDFLAGS="-L$best_path/lib" 167 | fi 168 | 169 | if test "x$BOOST_ROOT" != "x"; then 170 | if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/lib" && test -r "$BOOST_ROOT/stage/lib"; then 171 | version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'` 172 | stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` 173 | stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'` 174 | V_CHECK=`expr $stage_version_shorten \>\= $_version` 175 | if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then 176 | AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT) 177 | BOOST_CPPFLAGS="-I$BOOST_ROOT" 178 | BOOST_LDFLAGS="-L$BOOST_ROOT/stage/lib" 179 | fi 180 | fi 181 | fi 182 | fi 183 | 184 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 185 | export CPPFLAGS 186 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 187 | export LDFLAGS 188 | 189 | AC_LANG_PUSH(C++) 190 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 191 | @%:@include 192 | ]], [[ 193 | #if BOOST_VERSION >= $WANT_BOOST_VERSION 194 | // Everything is okay 195 | #else 196 | # error Boost version is too old 197 | #endif 198 | ]])],[ 199 | AC_MSG_RESULT(yes) 200 | succeeded=yes 201 | found_system=yes 202 | ],[ 203 | ]) 204 | AC_LANG_POP([C++]) 205 | fi 206 | 207 | if test "$succeeded" != "yes" ; then 208 | if test "$_version" = "0" ; then 209 | AC_MSG_ERROR([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation.]]) 210 | else 211 | AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).]) 212 | fi 213 | else 214 | AC_SUBST(BOOST_CPPFLAGS) 215 | AC_SUBST(BOOST_LDFLAGS) 216 | AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available]) 217 | fi 218 | 219 | CPPFLAGS="$CPPFLAGS_SAVED" 220 | LDFLAGS="$LDFLAGS_SAVED" 221 | fi 222 | 223 | ]) 224 | -------------------------------------------------------------------------------- /m4/ax_boost_filesystem.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://autoconf-archive.cryp.to/ax_boost_filesystem.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_FILESYSTEM 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for Filesystem library from the Boost C++ libraries. The macro 12 | # requires a preceding call to AX_BOOST_BASE. Further documentation is 13 | # available at . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_FILESYSTEM_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_FILESYSTEM 22 | # 23 | # LAST MODIFICATION 24 | # 25 | # 2008-04-12 26 | # 27 | # COPYLEFT 28 | # 29 | # Copyright (c) 2008 Thomas Porschberg 30 | # Copyright (c) 2008 Michael Tindal 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. 35 | 36 | AC_DEFUN([AX_BOOST_FILESYSTEM], 37 | [ 38 | AC_ARG_WITH([boost-filesystem], 39 | AS_HELP_STRING([--with-boost-filesystem@<:@=special-lib@:>@], 40 | [use the Filesystem library from boost - it is possible to specify a certain library for the linker 41 | e.g. --with-boost-filesystem=boost_filesystem-gcc-mt ]), 42 | [ 43 | if test "$withval" = "no"; then 44 | want_boost="no" 45 | elif test "$withval" = "yes"; then 46 | want_boost="yes" 47 | ax_boost_user_filesystem_lib="" 48 | else 49 | want_boost="yes" 50 | ax_boost_user_filesystem_lib="$withval" 51 | fi 52 | ], 53 | [want_boost="yes"] 54 | ) 55 | 56 | if test "x$want_boost" = "xyes"; then 57 | AC_REQUIRE([AC_PROG_CC]) 58 | CPPFLAGS_SAVED="$CPPFLAGS" 59 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 60 | export CPPFLAGS 61 | 62 | LDFLAGS_SAVED="$LDFLAGS" 63 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 64 | export LDFLAGS 65 | 66 | AC_CACHE_CHECK(whether the Boost::Filesystem library is available, 67 | ax_cv_boost_filesystem, 68 | [AC_LANG_PUSH([C++]) 69 | AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[@%:@include ]], 70 | [[using namespace boost::filesystem; 71 | path my_path( "foo/bar/data.txt" ); 72 | return 0;]]), 73 | ax_cv_boost_filesystem=yes, ax_cv_boost_filesystem=no) 74 | AC_LANG_POP([C++]) 75 | ]) 76 | if test "x$ax_cv_boost_filesystem" = "xyes"; then 77 | AC_DEFINE(HAVE_BOOST_FILESYSTEM,,[define if the Boost::Filesystem library is available]) 78 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 79 | if test "x$ax_boost_user_filesystem_lib" = "x"; then 80 | for libextension in `ls $BOOSTLIBDIR/libboost_filesystem*.{so,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_filesystem.*\)\.so.*$;\1;' -e 's;^lib\(boost_filesystem.*\)\.a*$;\1;'` ; do 81 | ax_lib=${libextension} 82 | AC_CHECK_LIB($ax_lib, exit, 83 | [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], 84 | [link_filesystem="no"]) 85 | done 86 | if test "x$link_program_options" != "xyes"; then 87 | for libextension in `ls $BOOSTLIBDIR/boost_filesystem*.{dll,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_filesystem.*\)\.dll.*$;\1;' -e 's;^\(boost_filesystem.*\)\.a*$;\1;'` ; do 88 | ax_lib=${libextension} 89 | AC_CHECK_LIB($ax_lib, exit, 90 | [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], 91 | [link_filesystem="no"]) 92 | done 93 | fi 94 | else 95 | for ax_lib in $ax_boost_user_filesystem_lib boost_filesystem-$ax_boost_user_filesystem_lib; do 96 | AC_CHECK_LIB($ax_lib, exit, 97 | [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], 98 | [link_filesystem="no"]) 99 | done 100 | 101 | fi 102 | if test "x$link_filesystem" != "xyes"; then 103 | AC_MSG_ERROR(Could not link against $ax_lib !) 104 | fi 105 | fi 106 | 107 | CPPFLAGS="$CPPFLAGS_SAVED" 108 | LDFLAGS="$LDFLAGS_SAVED" 109 | fi 110 | ]) 111 | -------------------------------------------------------------------------------- /m4/ax_boost_iostreams.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://autoconf-archive.cryp.to/ax_boost_iostreams.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_IOSTREAMS 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for IOStreams library from the Boost C++ libraries. The macro 12 | # requires a preceding call to AX_BOOST_BASE. Further documentation is 13 | # available at . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_IOSTREAMS_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_IOSTREAMS 22 | # 23 | # LAST MODIFICATION 24 | # 25 | # 2008-04-12 26 | # 27 | # COPYLEFT 28 | # 29 | # Copyright (c) 2008 Thomas Porschberg 30 | # 31 | # Copying and distribution of this file, with or without modification, are 32 | # permitted in any medium without royalty provided the copyright notice 33 | # and this notice are preserved. 34 | 35 | AC_DEFUN([AX_BOOST_IOSTREAMS], 36 | [ 37 | AC_ARG_WITH([boost-iostreams], 38 | AS_HELP_STRING([--with-boost-iostreams@<:@=special-lib@:>@], 39 | [use the IOStreams library from boost - it is possible to specify a certain library for the linker 40 | e.g. --with-boost-iostreams=boost_iostreams-gcc-mt-d-1_33_1 ]), 41 | [ 42 | if test "$withval" = "no"; then 43 | want_boost="no" 44 | elif test "$withval" = "yes"; then 45 | want_boost="yes" 46 | ax_boost_user_iostreams_lib="" 47 | else 48 | want_boost="yes" 49 | ax_boost_user_iostreams_lib="$withval" 50 | fi 51 | ], 52 | [want_boost="yes"] 53 | ) 54 | 55 | if test "x$want_boost" = "xyes"; then 56 | AC_REQUIRE([AC_PROG_CC]) 57 | CPPFLAGS_SAVED="$CPPFLAGS" 58 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 59 | export CPPFLAGS 60 | 61 | LDFLAGS_SAVED="$LDFLAGS" 62 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 63 | export LDFLAGS 64 | 65 | AC_CACHE_CHECK(whether the Boost::IOStreams library is available, 66 | ax_cv_boost_iostreams, 67 | [AC_LANG_PUSH([C++]) 68 | AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[@%:@include 69 | @%:@include 70 | ]], 71 | [[std::string input = "Hello World!"; 72 | namespace io = boost::iostreams; 73 | io::filtering_istream in(boost::make_iterator_range(input)); 74 | return 0; 75 | ]]), 76 | ax_cv_boost_iostreams=yes, ax_cv_boost_iostreams=no) 77 | AC_LANG_POP([C++]) 78 | ]) 79 | if test "x$ax_cv_boost_iostreams" = "xyes"; then 80 | AC_DEFINE(HAVE_BOOST_IOSTREAMS,,[define if the Boost::IOStreams library is available]) 81 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 82 | if test "x$ax_boost_user_iostreams_lib" = "x"; then 83 | for libextension in `ls $BOOSTLIBDIR/libboost_iostreams*.{so,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_iostreams.*\)\.so.*$;\1;' -e 's;^lib\(boost_iostreams.*\)\.a*$;\1;'` ; do 84 | ax_lib=${libextension} 85 | AC_CHECK_LIB($ax_lib, exit, 86 | [BOOST_IOSTREAMS_LIB="-l$ax_lib"; AC_SUBST(BOOST_IOSTREAMS_LIB) link_iostreams="yes"; break], 87 | [link_iostreams="no"]) 88 | done 89 | if test "x$link_iostreams" != "xyes"; then 90 | for libextension in `ls $BOOSTLIBDIR/boost_iostreams*.{dll,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_iostreams.*\)\.dll.*$;\1;' -e 's;^\(boost_iostreams.*\)\.a*$;\1;'` ; do 91 | ax_lib=${libextension} 92 | AC_CHECK_LIB($ax_lib, exit, 93 | [BOOST_IOSTREAMS_LIB="-l$ax_lib"; AC_SUBST(BOOST_IOSTREAMS_LIB) link_iostreams="yes"; break], 94 | [link_iostreams="no"]) 95 | done 96 | fi 97 | 98 | else 99 | for ax_lib in $ax_boost_user_iostreams_lib boost_iostreams-$ax_boost_user_iostreams_lib; do 100 | AC_CHECK_LIB($ax_lib, main, 101 | [BOOST_IOSTREAMS_LIB="-l$ax_lib"; AC_SUBST(BOOST_IOSTREAMS_LIB) link_iostreams="yes"; break], 102 | [link_iostreams="no"]) 103 | done 104 | 105 | fi 106 | if test "x$link_iostreams" != "xyes"; then 107 | AC_MSG_ERROR(Could not link against $ax_lib !) 108 | fi 109 | fi 110 | 111 | CPPFLAGS="$CPPFLAGS_SAVED" 112 | LDFLAGS="$LDFLAGS_SAVED" 113 | fi 114 | ]) 115 | -------------------------------------------------------------------------------- /m4/ax_boost_program_options.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://autoconf-archive.cryp.to/ax_boost_program_options.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_PROGRAM_OPTIONS 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for program options library from the Boost C++ libraries. The macro 12 | # requires a preceding call to AX_BOOST_BASE. Further documentation is 13 | # available at . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_PROGRAM_OPTIONS 22 | # 23 | # LAST MODIFICATION 24 | # 25 | # 2008-04-12 26 | # 27 | # COPYLEFT 28 | # 29 | # Copyright (c) 2008 Thomas Porschberg 30 | # 31 | # Copying and distribution of this file, with or without modification, are 32 | # permitted in any medium without royalty provided the copyright notice 33 | # and this notice are preserved. 34 | 35 | AC_DEFUN([AX_BOOST_PROGRAM_OPTIONS], 36 | [ 37 | AC_ARG_WITH([boost-program-options], 38 | AS_HELP_STRING([--with-boost-program-options@<:@=special-lib@:>@], 39 | [use the program options library from boost - it is possible to specify a certain library for the linker 40 | e.g. --with-boost-program-options=boost_program_options-gcc-mt-1_33_1 ]), 41 | [ 42 | if test "$withval" = "no"; then 43 | want_boost="no" 44 | elif test "$withval" = "yes"; then 45 | want_boost="yes" 46 | ax_boost_user_program_options_lib="" 47 | else 48 | want_boost="yes" 49 | ax_boost_user_program_options_lib="$withval" 50 | fi 51 | ], 52 | [want_boost="yes"] 53 | ) 54 | 55 | if test "x$want_boost" = "xyes"; then 56 | AC_REQUIRE([AC_PROG_CC]) 57 | export want_boost 58 | CPPFLAGS_SAVED="$CPPFLAGS" 59 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 60 | export CPPFLAGS 61 | LDFLAGS_SAVED="$LDFLAGS" 62 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 63 | export LDFLAGS 64 | AC_CACHE_CHECK([whether the Boost::Program_Options library is available], 65 | ax_cv_boost_program_options, 66 | [AC_LANG_PUSH(C++) 67 | AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[@%:@include 68 | ]], 69 | [[boost::program_options::options_description generic("Generic options"); 70 | return 0;]]), 71 | ax_cv_boost_program_options=yes, ax_cv_boost_program_options=no) 72 | AC_LANG_POP([C++]) 73 | ]) 74 | if test "$ax_cv_boost_program_options" = yes; then 75 | AC_DEFINE(HAVE_BOOST_PROGRAM_OPTIONS,,[define if the Boost::PROGRAM_OPTIONS library is available]) 76 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 77 | if test "x$ax_boost_user_program_options_lib" = "x"; then 78 | for libextension in `ls $BOOSTLIBDIR/libboost_program_options*.{so,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.so.*$;\1;' -e 's;^lib\(boost_program_options.*\)\.a*$;\1;'` ; do 79 | ax_lib=${libextension} 80 | AC_CHECK_LIB($ax_lib, exit, 81 | [BOOST_PROGRAM_OPTIONS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) link_program_options="yes"; break], 82 | [link_program_options="no"]) 83 | done 84 | if test "x$link_program_options" != "xyes"; then 85 | for libextension in `ls $BOOSTLIBDIR/boost_program_options*.{dll,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_program_options.*\)\.dll.*$;\1;' -e 's;^\(boost_program_options.*\)\.a*$;\1;'` ; do 86 | ax_lib=${libextension} 87 | AC_CHECK_LIB($ax_lib, exit, 88 | [BOOST_PROGRAM_OPTIONS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) link_program_options="yes"; break], 89 | [link_program_options="no"]) 90 | done 91 | fi 92 | else 93 | for ax_lib in $ax_boost_user_program_options_lib boost_program_options-$ax_boost_user_program_options_lib; do 94 | AC_CHECK_LIB($ax_lib, main, 95 | [BOOST_PROGRAM_OPTIONS_LIB="-l$ax_lib"; AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) link_program_options="yes"; break], 96 | [link_program_options="no"]) 97 | done 98 | fi 99 | if test "x$link_program_options" != "xyes"; then 100 | AC_MSG_ERROR([Could not link against [$ax_lib] !]) 101 | fi 102 | fi 103 | CPPFLAGS="$CPPFLAGS_SAVED" 104 | LDFLAGS="$LDFLAGS_SAVED" 105 | fi 106 | ]) 107 | -------------------------------------------------------------------------------- /m4/ax_boost_serialization.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://autoconf-archive.cryp.to/ax_boost_serialization.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_SERIALIZATION 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for Serialization library from the Boost C++ libraries. The macro 12 | # requires a preceding call to AX_BOOST_BASE. Further documentation is 13 | # available at . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_SERIALIZATION_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_SERIALIZATION 22 | # 23 | # LAST MODIFICATION 24 | # 25 | # 2008-04-12 26 | # 27 | # COPYLEFT 28 | # 29 | # Copyright (c) 2008 Thomas Porschberg 30 | # 31 | # Copying and distribution of this file, with or without modification, are 32 | # permitted in any medium without royalty provided the copyright notice 33 | # and this notice are preserved. 34 | 35 | AC_DEFUN([AX_BOOST_SERIALIZATION], 36 | [ 37 | AC_ARG_WITH([boost-serialization], 38 | AS_HELP_STRING([--with-boost-serialization@<:@=special-lib@:>@], 39 | [use the Serialization library from boost - it is possible to specify a certain library for the linker 40 | e.g. --with-boost-serialization=boost_serialization-gcc-mt-d-1_33_1 ]), 41 | [ 42 | if test "$withval" = "no"; then 43 | want_boost="no" 44 | elif test "$withval" = "yes"; then 45 | want_boost="yes" 46 | ax_boost_user_serialization_lib="" 47 | else 48 | want_boost="yes" 49 | ax_boost_user_serialization_lib="$withval" 50 | fi 51 | ], 52 | [want_boost="yes"] 53 | ) 54 | 55 | if test "x$want_boost" = "xyes"; then 56 | AC_REQUIRE([AC_PROG_CC]) 57 | CPPFLAGS_SAVED="$CPPFLAGS" 58 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 59 | AC_MSG_WARN(BOOST_CPPFLAGS $BOOST_CPPFLAGS) 60 | export CPPFLAGS 61 | 62 | LDFLAGS_SAVED="$LDFLAGS" 63 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 64 | export LDFLAGS 65 | 66 | AC_CACHE_CHECK(whether the Boost::Serialization library is available, 67 | ax_cv_boost_serialization, 68 | [AC_LANG_PUSH([C++]) 69 | AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[@%:@include 70 | @%:@include 71 | @%:@include 72 | ]], 73 | [[std::ofstream ofs("filename"); 74 | boost::archive::text_oarchive oa(ofs); 75 | return 0; 76 | ]]), 77 | ax_cv_boost_serialization=yes, ax_cv_boost_serialization=no) 78 | AC_LANG_POP([C++]) 79 | ]) 80 | if test "x$ax_cv_boost_serialization" = "xyes"; then 81 | AC_DEFINE(HAVE_BOOST_SERIALIZATION,,[define if the Boost::Serialization library is available]) 82 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 83 | if test "x$ax_boost_user_serialization_lib" = "x"; then 84 | for libextension in `ls $BOOSTLIBDIR/libboost_serialization*.{so,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_serialization.*\)\.so.*$;\1;' -e 's;^lib\(boost_serialization.*\)\.a*$;\1;'` ; do 85 | ax_lib=${libextension} 86 | AC_CHECK_LIB($ax_lib, exit, 87 | [BOOST_SERIALIZATION_LIB="-l$ax_lib"; AC_SUBST(BOOST_SERIALIZATION_LIB) link_serialization="yes"; break], 88 | [link_serialization="no"]) 89 | done 90 | if test "x$link_serialization" != "xyes"; then 91 | for libextension in `ls $BOOSTLIBDIR/boost_serialization*.{dll,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_serialization.*\)\.dll.*$;\1;' -e 's;^\(boost_serialization.*\)\.a*$;\1;'` ; do 92 | ax_lib=${libextension} 93 | AC_CHECK_LIB($ax_lib, exit, 94 | [BOOST_SERIALIZATION_LIB="-l$ax_lib"; AC_SUBST(BOOST_SERIALIZATION_LIB) link_serialization="yes"; break], 95 | [link_serialization="no"]) 96 | done 97 | fi 98 | 99 | else 100 | for ax_lib in $ax_boost_user_serialization_lib boost_serialization-$ax_boost_user_serialization_lib; do 101 | AC_CHECK_LIB($ax_lib, main, 102 | [BOOST_SERIALIZATION_LIB="-l$ax_lib"; AC_SUBST(BOOST_SERIALIZATION_LIB) link_serialization="yes"; break], 103 | [link_serialization="no"]) 104 | done 105 | 106 | fi 107 | if test "x$link_serialization" != "xyes"; then 108 | AC_MSG_ERROR(Could not link against $ax_lib !) 109 | fi 110 | fi 111 | 112 | CPPFLAGS="$CPPFLAGS_SAVED" 113 | LDFLAGS="$LDFLAGS_SAVED" 114 | fi 115 | ]) 116 | -------------------------------------------------------------------------------- /m4/ax_boost_system.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://autoconf-archive.cryp.to/ax_boost_system.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_SYSTEM 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for System library from the Boost C++ libraries. The macro requires 12 | # a preceding call to AX_BOOST_BASE. Further documentation is available at 13 | # . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_SYSTEM_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_SYSTEM 22 | # 23 | # LAST MODIFICATION 24 | # 25 | # 2008-04-12 26 | # 27 | # COPYLEFT 28 | # 29 | # Copyright (c) 2008 Thomas Porschberg 30 | # Copyright (c) 2008 Michael Tindal 31 | # Copyright (c) 2008 Daniel Casimiro 32 | # 33 | # Copying and distribution of this file, with or without modification, are 34 | # permitted in any medium without royalty provided the copyright notice 35 | # and this notice are preserved. 36 | 37 | AC_DEFUN([AX_BOOST_SYSTEM], 38 | [ 39 | AC_ARG_WITH([boost-system], 40 | AS_HELP_STRING([--with-boost-system@<:@=special-lib@:>@], 41 | [use the System library from boost - it is possible to specify a certain library for the linker 42 | e.g. --with-boost-system=boost_system-gcc-mt ]), 43 | [ 44 | if test "$withval" = "no"; then 45 | want_boost="no" 46 | elif test "$withval" = "yes"; then 47 | want_boost="yes" 48 | ax_boost_user_system_lib="" 49 | else 50 | want_boost="yes" 51 | ax_boost_user_system_lib="$withval" 52 | fi 53 | ], 54 | [want_boost="yes"] 55 | ) 56 | 57 | if test "x$want_boost" = "xyes"; then 58 | AC_REQUIRE([AC_PROG_CC]) 59 | AC_REQUIRE([AC_CANONICAL_BUILD]) 60 | CPPFLAGS_SAVED="$CPPFLAGS" 61 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 62 | export CPPFLAGS 63 | 64 | LDFLAGS_SAVED="$LDFLAGS" 65 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 66 | export LDFLAGS 67 | 68 | AC_CACHE_CHECK(whether the Boost::System library is available, 69 | ax_cv_boost_system, 70 | [AC_LANG_PUSH([C++]) 71 | CXXFLAGS_SAVE=$CXXFLAGS 72 | 73 | AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[@%:@include ]], 74 | [[boost::system::system_category]]), 75 | ax_cv_boost_system=yes, ax_cv_boost_system=no) 76 | CXXFLAGS=$CXXFLAGS_SAVE 77 | AC_LANG_POP([C++]) 78 | ]) 79 | if test "x$ax_cv_boost_system" = "xyes"; then 80 | AC_SUBST(BOOST_CPPFLAGS) 81 | 82 | AC_DEFINE(HAVE_BOOST_SYSTEM,,[define if the Boost::System library is available]) 83 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 84 | 85 | LDFLAGS_SAVE=$LDFLAGS 86 | if test "x$ax_boost_user_system_lib" = "x"; then 87 | for libextension in `ls $BOOSTLIBDIR/libboost_system*.{so,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_system.*\)\.so.*$;\1;' -e 's;^lib\(boost_system.*\)\.a*$;\1;'` ; do 88 | ax_lib=${libextension} 89 | AC_CHECK_LIB($ax_lib, exit, 90 | [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], 91 | [link_system="no"]) 92 | done 93 | if test "x$link_system" != "xyes"; then 94 | for libextension in `ls $BOOSTLIBDIR/boost_system*.{dll,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_system.*\)\.dll.*$;\1;' -e 's;^\(boost_system.*\)\.a*$;\1;'` ; do 95 | ax_lib=${libextension} 96 | AC_CHECK_LIB($ax_lib, exit, 97 | [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], 98 | [link_system="no"]) 99 | done 100 | fi 101 | 102 | else 103 | for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do 104 | AC_CHECK_LIB($ax_lib, exit, 105 | [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], 106 | [link_system="no"]) 107 | done 108 | 109 | fi 110 | if test "x$link_system" = "xno"; then 111 | AC_MSG_ERROR(Could not link against $ax_lib !) 112 | fi 113 | fi 114 | 115 | CPPFLAGS="$CPPFLAGS_SAVED" 116 | LDFLAGS="$LDFLAGS_SAVED" 117 | fi 118 | ]) 119 | -------------------------------------------------------------------------------- /src/Block.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include "Block.hpp" 23 | 24 | std::ostream &operator<< (std::ostream& os, const Block& rBl) 25 | { 26 | boost::io::ios_flags_saver ifs(os); 27 | 28 | os << std::hex << "offset: 0x" << rBl.offset 29 | << ", length: 0x" << rBl.length 30 | << ", olength: 0x" << rBl.olength 31 | << ", level: 0x" << rBl.level 32 | << ", coffset: 0x" << rBl.coffset 33 | << ", clength: 0x" << rBl.clength; 34 | return os; 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/Block.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #ifndef BLOCKHPP 21 | #define BLOCKHPP 22 | 23 | #include 24 | 25 | #include 26 | 27 | #include "CompressionType.hpp" 28 | 29 | class Block 30 | { 31 | friend class boost::serialization::access; 32 | 33 | template 34 | void serialize(Archive& ar, const unsigned int version) 35 | { 36 | ar & offset & coffset; 37 | ar & length & olength; 38 | ar & clength; 39 | ar & level; 40 | ar & type; 41 | } 42 | public: 43 | Block(const Block &src) : 44 | offset (src.offset), coffset (src.coffset), length (src.length), 45 | olength (src.olength), clength(src.clength), level (src.level), type (src.type) 46 | { } 47 | 48 | Block(off_t offset, size_t length, off_t coffset, size_t olength, size_t clength, unsigned int level, unsigned char type) : 49 | offset (offset), coffset (coffset), length (length), 50 | olength (olength), clength(clength), level (level), type (type) 51 | { } 52 | 53 | Block() 54 | : offset (0), coffset (0), length (0), 55 | olength (0), clength (0), level (0), type (CompressionType::NONE) 56 | { } 57 | 58 | Block(off_t offset, size_t length) 59 | : offset (offset), coffset (0), length (length), 60 | olength (length), clength (0), level (0), type(CompressionType::NONE) 61 | { } 62 | 63 | Block(off_t offset, size_t length, unsigned int level) 64 | : offset (offset), coffset (0), length (length), 65 | olength (length), clength (0), level (level), type(CompressionType::NONE) 66 | { } 67 | 68 | Block(CompressionType type) 69 | : offset (0), coffset (0), length (0), 70 | olength (0), clength (0), level (0), type (type) 71 | { } 72 | 73 | ~Block() {}; 74 | 75 | friend std::ostream &operator<< (std::ostream& os, const Block& rBl); 76 | 77 | off_t offset, coffset; 78 | size_t length, olength; 79 | size_t clength; 80 | 81 | unsigned int level; 82 | 83 | CompressionType type; 84 | }; 85 | 86 | BOOST_CLASS_VERSION(Block, 0) 87 | 88 | #endif 89 | 90 | -------------------------------------------------------------------------------- /src/Compress.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of FuseCompress. 3 | 4 | FuseCompress is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | FuseCompress is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with FuseCompress. If not, see . 16 | */ 17 | 18 | #ifndef COMPRESS_HPP 19 | #define COMPRESS_HPP 20 | 21 | #include "File.hpp" 22 | #include "FileHeader.hpp" 23 | #include "LayerMap.hpp" 24 | #include "CompressionType.hpp" 25 | 26 | #include 27 | 28 | typedef File PARENT_COMPRESS; 29 | 30 | /** 31 | */ 32 | class Compress : public PARENT_COMPRESS 33 | { 34 | private: 35 | typedef PARENT_COMPRESS Parent; 36 | 37 | void restoreFileHeader(const char *name); 38 | void restoreLayerMap(); 39 | 40 | /** 41 | * Store (save) the layer map and the file header. 42 | * 43 | * @returns 0 on success, -1 otherwise and errno set to -EIO. 44 | */ 45 | int store(); 46 | 47 | /** 48 | * Store (save) the file header m_fh. 49 | * 50 | * @throws boost::iostreams exception on error. 51 | */ 52 | void storeFileHeader() const; 53 | 54 | /** 55 | * Store (save) the layer map m_lm (to offset m_RawFileSize) using 56 | * compression as requested by 'm_fh.type'. 57 | * 58 | * @throws boost::iostreams exception on error. 59 | */ 60 | void storeLayerMap(); 61 | 62 | off_t writeCompressed(LayerMap& lm, off_t offset, off_t coffset, const char *buf, size_t size, int fd, off_t rawFileSize); 63 | off_t readBlock(int fd, const Block& block, off_t size, off_t len, off_t offset, char *buf) const; 64 | ssize_t readCompressed(char *buf, size_t size, off_t offset, int fd) const; 65 | off_t copy(int readFd, off_t writeOffset, int writeFd, LayerMap& writeLm); 66 | off_t cleverCopy(int readFd, off_t writeOffset, int writeFd, LayerMap& writeLm); 67 | 68 | void DefragmentFast(); 69 | 70 | // Length of the lower file 71 | // (not as seen by the user via fuse mount point). 72 | // 73 | off_t m_RawFileSize; 74 | 75 | bool m_IsCompressed; 76 | 77 | // Items used when a file is compressed. 78 | // 79 | FileHeader m_fh; 80 | LayerMap m_lm; 81 | 82 | Compress(const Compress &); // No copy constructor 83 | Compress(); // No default constructor 84 | Compress& operator=(const Compress &); // No assign operator 85 | public: 86 | 87 | friend ostream &operator<<(ostream &os, const Compress &rCompress); 88 | 89 | Compress(const struct stat *st, const char *name); 90 | ~Compress(); 91 | 92 | int open(const char *name, int flags); 93 | 94 | int release(const char *name); 95 | 96 | int unlink(const char *name); 97 | 98 | int truncate(const char *name, off_t size); 99 | 100 | int getattr(const char *name, struct stat *st); 101 | 102 | ssize_t read(char *buf, size_t size, off_t offset) const; 103 | 104 | ssize_t write(const char *buf, size_t size, off_t offset); 105 | 106 | bool isCompressed() { return m_IsCompressed; } 107 | void setCompressed(bool compressed) { m_IsCompressed = compressed; if (!compressed) m_RawFileSize = 0; } 108 | bool isCompressedOnlyWith(CompressionType& type); 109 | }; 110 | 111 | #endif 112 | 113 | -------------------------------------------------------------------------------- /src/CompressedMagic.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "rlog/rlog.h" 33 | 34 | using namespace std; 35 | 36 | #include "Lock.hpp" 37 | #include "CompressedMagic.hpp" 38 | 39 | void CompressedMagic::PopulateTable() 40 | { 41 | m_table.insert("audio/mp4"); 42 | m_table.insert("audio/mpeg"); 43 | m_table.insert("audio/x-pn-realaudio"); 44 | m_table.insert("audio/x-mod"); 45 | m_table.insert("audio/x-flac"); 46 | m_table.insert("audio/x-musepack"); 47 | m_table.insert("audio/x-ape"); 48 | m_table.insert("audio/x-wavpack"); 49 | m_table.insert("audio/x-wavpack-correction"); 50 | m_table.insert("application/x-7z-compressed"); 51 | m_table.insert("application/ogg"); 52 | m_table.insert("application/pdf"); 53 | m_table.insert("application/vnd.rn-realmedia"); 54 | m_table.insert("application/x-arc"); 55 | m_table.insert("application/x-arj"); 56 | m_table.insert("application/x-bzip2"); 57 | m_table.insert("application/x-bzip"); 58 | m_table.insert("application/x-bzip-compressed-tar"); 59 | m_table.insert("application/x-compress"); 60 | m_table.insert("application/x-compress-tar"); 61 | m_table.insert("application/x-cpio"); 62 | m_table.insert("application/x-debian-package"); 63 | m_table.insert("application/x-deb"); 64 | m_table.insert("application/x-gzip"); 65 | m_table.insert("application/x-lharc"); 66 | m_table.insert("application/x-lzma"); 67 | m_table.insert("application/x-lzma-compressed-tar"); 68 | m_table.insert("application/x-quicktime"); 69 | m_table.insert("application/x-rar"); 70 | m_table.insert("application/x-rpm"); 71 | m_table.insert("application/x-shockwave-flash"); 72 | m_table.insert("application/x-xz"); 73 | m_table.insert("application/x-zip"); 74 | m_table.insert("application/x-zoo"); 75 | m_table.insert("image/gif"); 76 | m_table.insert("image/jpeg"); 77 | m_table.insert("image/jp2"); 78 | m_table.insert("image/png"); 79 | m_table.insert("image/x-quicktime"); 80 | m_table.insert("video/3gpp"); 81 | m_table.insert("video/mp4"); 82 | m_table.insert("video/mp4v-es"); 83 | m_table.insert("video/mpeg"); 84 | m_table.insert("video/mp2t"); 85 | m_table.insert("video/mpv"); 86 | m_table.insert("video/quicktime"); 87 | m_table.insert("video/x-msvideo"); 88 | m_table.insert("video/x-ms-asf"); 89 | m_table.insert("video/x-ms-wmv"); 90 | m_table.insert("video/x-matroska"); 91 | m_table.insert("video/x-flv"); 92 | } 93 | 94 | CompressedMagic::CompressedMagic() 95 | { 96 | // In newer versions of libmagic MAGIC_MIME is declared as MAGIC_MIME_TYPE | MAGIC_MIME_ENCODING. 97 | // Older versions don't know MAGIC_MIME_TYPE, though -- the old MAGIC_MIME is the new MAGIC_MIME_TYPE, 98 | // and the new MAGIC_MIME has been redefined. 99 | // However, I recommend you to upgrade to the newest version of libmagic because at least 100 | // one bug (memory leak) is fixed there. 101 | 102 | #ifdef MAGIC_MIME_TYPE 103 | m_magic = magic_open(MAGIC_MIME_TYPE | MAGIC_PRESERVE_ATIME); 104 | #else 105 | m_magic = magic_open(MAGIC_MIME | MAGIC_PRESERVE_ATIME); 106 | #endif 107 | if (!m_magic) 108 | { 109 | rError("CompressedMagic::CompressedMagic magic_open failed with: %s", 110 | magic_error(m_magic)); 111 | abort(); 112 | } 113 | magic_load(m_magic, NULL); 114 | 115 | PopulateTable(); 116 | } 117 | 118 | CompressedMagic::~CompressedMagic() 119 | { 120 | m_table.clear(); 121 | 122 | magic_close(m_magic); 123 | } 124 | 125 | std::ostream &operator<<(std::ostream &os, const CompressedMagic &rObj) 126 | { 127 | CompressedMagic::con_t::const_iterator it; 128 | unsigned int len = 0; 129 | 130 | // Get length of the longest name. 131 | // 132 | for (it = rObj.m_table.begin(); it != rObj.m_table.end(); ++it) 133 | { 134 | if (len < (*it).length()) 135 | len = (*it).length(); 136 | } 137 | 138 | // Compute how many colums fit to a terminal. 139 | // 140 | struct winsize w; 141 | ioctl(0, TIOCGWINSZ, &w); 142 | 143 | unsigned int cols = (w.ws_col - 2) / (len + 5); 144 | cols = cols > 0 ? cols : 1; 145 | 146 | unsigned int col; 147 | 148 | os << " "; 149 | 150 | for (it = rObj.m_table.begin(), col = 1; it != rObj.m_table.end(); ++it, col++) 151 | { 152 | os << std::setw(len + 5) << std::left << *it; 153 | if ((col % cols)== 0) 154 | os << std::endl << " "; 155 | } 156 | return os; 157 | } 158 | 159 | void CompressedMagic::Add(const std::string &rMimes) 160 | { 161 | typedef boost::tokenizer > tokenizer; 162 | boost::char_separator sep(";"); 163 | tokenizer tokens(rMimes, sep); 164 | for (tokenizer::iterator tok_it = tokens.begin(); tok_it != tokens.end(); ++tok_it) 165 | { 166 | m_table.insert(boost::algorithm::to_lower_copy(*tok_it)); 167 | } 168 | } 169 | 170 | void CompressedMagic::Remove(const std::string &rMimes) 171 | { 172 | typedef boost::tokenizer > tokenizer; 173 | boost::char_separator sep(";"); 174 | tokenizer tokens(rMimes, sep); 175 | for (tokenizer::iterator tok_it = tokens.begin(); tok_it != tokens.end(); ++tok_it) 176 | { 177 | con_t::iterator it = m_table.find(boost::algorithm::to_lower_copy(*tok_it)); 178 | if (it != m_table.end()) 179 | m_table.erase(it); 180 | } 181 | } 182 | 183 | bool CompressedMagic::isNativelyCompressed(const char *buf, int len) 184 | { 185 | const char *mime; 186 | 187 | Lock lock(m_Mutex); 188 | 189 | mime = magic_buffer(m_magic, buf, len); 190 | 191 | if (mime != NULL) 192 | { 193 | if (m_table.find(mime) != m_table.end()) 194 | { 195 | rDebug("Data identified as already compressed (%s)", mime); 196 | return true; 197 | } 198 | } 199 | rDebug("Data identified as not compressed (%s)", mime); 200 | return false; 201 | } 202 | 203 | bool CompressedMagic::isNativelyCompressed(const char *name) 204 | { 205 | const char *mime; 206 | 207 | Lock lock(m_Mutex); 208 | 209 | mime = magic_file(m_magic, name); 210 | 211 | if (mime != NULL) 212 | { 213 | if (m_table.find(mime) != m_table.end()) 214 | { 215 | rDebug("Data identified as already compressed (%s)", mime); 216 | return true; 217 | } 218 | } 219 | rDebug("Data identified as not compressed (%s)", mime); 220 | return false; 221 | } 222 | 223 | -------------------------------------------------------------------------------- /src/CompressedMagic.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #ifndef __COMPRESSED_MAGIC__ 21 | #define __COMPRESSED_MAGIC__ 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "Mutex.hpp" 31 | 32 | class CompressedMagic 33 | { 34 | typedef std::set con_t; 35 | con_t m_table; 36 | magic_t m_magic; 37 | Mutex m_Mutex; 38 | 39 | void PopulateTable(); 40 | public: 41 | CompressedMagic(); 42 | ~CompressedMagic(); 43 | 44 | bool isNativelyCompressed(const char *buf, int len); 45 | bool isNativelyCompressed(const char *name); 46 | 47 | void Remove(const std::string &rMime); 48 | void Add(const std::string &rMime); 49 | 50 | friend std::ostream &operator<<(std::ostream &os, const CompressedMagic &rObj); 51 | }; 52 | 53 | #endif 54 | 55 | -------------------------------------------------------------------------------- /src/CompressionType.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of FuseCompress. 3 | 4 | FuseCompress is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | FuseCompress is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with FuseCompress. If not, see . 16 | */ 17 | 18 | #include "config.h" 19 | 20 | #ifdef HAVE_LIBLZMA 21 | #include 22 | #endif 23 | #ifdef HAVE_LIBZ 24 | #include 25 | #endif 26 | #ifdef HAVE_LIBBZ2 27 | #include 28 | #endif 29 | #ifdef HAVE_LIBLZO2 30 | #include 31 | #endif 32 | #include 33 | #include 34 | 35 | #include "CompressionType.hpp" 36 | 37 | #include 38 | 39 | void CompressionType::printAllSupportedMethods(std::ostream& os) 40 | { 41 | os << "none, "; 42 | #ifdef HAVE_LIBZ 43 | os << "zlib, "; 44 | #endif 45 | #ifdef HAVE_LIBLZO2 46 | os << "lzo, "; 47 | #endif 48 | #ifdef HAVE_LIBBZ2 49 | os << "bzip2, "; 50 | #endif 51 | #ifdef HAVE_LIBLZMA 52 | os << "lzma, "; 53 | #endif 54 | os << "xor"; 55 | } 56 | 57 | std::ostream& operator<<(std::ostream& os, const CompressionType& rObj) 58 | { 59 | std::string name; 60 | 61 | switch (rObj.m_Type) { 62 | case CompressionType::NONE: 63 | name = "none"; 64 | break; 65 | case CompressionType::XOR: 66 | name = "xor"; 67 | break; 68 | case CompressionType::ZLIB: 69 | name = "zlib"; 70 | break; 71 | case CompressionType::BZIP2: 72 | name = "bzip2"; 73 | break; 74 | case CompressionType::LZO: 75 | name = "lzo"; 76 | break; 77 | case CompressionType::LZMA: 78 | name = "lzma"; 79 | break; 80 | } 81 | return os << name; 82 | } 83 | 84 | template<> 85 | void CompressionType::push(io::filtering_stream& fs) const 86 | { 87 | switch (m_Type) { 88 | case NONE: 89 | break; 90 | #ifdef HAVE_LIBZ 91 | case ZLIB: 92 | fs.push(io::zlib_compressor(io::zlib_params(9, io::zlib::deflated, 15, 8, io::zlib::default_strategy, true))); 93 | break; 94 | #endif 95 | #ifdef HAVE_LIBBZ2 96 | case BZIP2: 97 | fs.push(io::bzip2_compressor()); 98 | break; 99 | #endif 100 | case XOR: 101 | fs.push(io::xor_filter('2')); 102 | break; 103 | #ifdef HAVE_LIBLZO2 104 | case LZO: 105 | fs.push(io::lzo_compressor()); 106 | break; 107 | #endif 108 | #ifdef HAVE_LIBLZMA 109 | case LZMA: 110 | fs.push(io::lzma_compressor()); 111 | break; 112 | #endif 113 | default: 114 | { 115 | // This shall never happen on OUTPUT filtering stream. 116 | 117 | assert(false); 118 | break; 119 | } 120 | } 121 | } 122 | 123 | template<> 124 | void CompressionType::push(io::filtering_stream& fs) const 125 | { 126 | switch (m_Type) { 127 | case NONE: 128 | break; 129 | #ifdef HAVE_LIBZ 130 | case ZLIB: 131 | fs.push(io::zlib_decompressor(io::zlib_params(9, io::zlib::deflated, 15, 8, io::zlib::default_strategy, true))); 132 | break; 133 | #endif 134 | #ifdef HAVE_LIBBZ2 135 | case BZIP2: 136 | fs.push(io::bzip2_decompressor()); 137 | break; 138 | #endif 139 | case XOR: 140 | fs.push(io::xor_filter('2')); 141 | break; 142 | #ifdef HAVE_LIBLZO2 143 | case LZO: 144 | fs.push(io::lzo_decompressor()); 145 | break; 146 | #endif 147 | #ifdef HAVE_LIBLZMA 148 | case LZMA: 149 | fs.push(io::lzma_decompressor()); 150 | break; 151 | #endif 152 | default: 153 | { 154 | // If input file is using unsopported version 155 | // throw an exception and FuseCompress will 156 | // process such file as uncompressed. 157 | 158 | throw BOOST_IOSTREAMS_FAILURE("unsupported compression type"); 159 | break; 160 | } 161 | } 162 | } 163 | 164 | bool CompressionType::parseType(std::string type) 165 | { 166 | if (type == "none") 167 | m_Type = NONE; 168 | #ifdef HAVE_LIBZ 169 | else if (type == "zlib") 170 | m_Type = ZLIB; 171 | #endif 172 | #ifdef HAVE_LIBBZ2 173 | else if (type == "bzip2") 174 | m_Type = BZIP2; 175 | #endif 176 | else if (type == "xor") 177 | m_Type = XOR; 178 | #ifdef HAVE_LIBLZO2 179 | else if (type == "lzo") 180 | m_Type = LZO; 181 | #endif 182 | #ifdef HAVE_LIBLZMA 183 | else if (type == "lzma") 184 | m_Type = LZMA; 185 | #endif 186 | else 187 | return false; 188 | 189 | return true; 190 | } 191 | 192 | -------------------------------------------------------------------------------- /src/CompressionType.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of FuseCompress. 3 | 4 | FuseCompress is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | FuseCompress is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with FuseCompress. If not, see . 16 | */ 17 | 18 | #ifndef COMPRESSIONTYPE_HPP 19 | #define COMPRESSIONTYPE_HPP 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | namespace io = boost::iostreams; 30 | 31 | class CompressionType 32 | { 33 | unsigned char m_Type; 34 | 35 | friend class boost::serialization::access; 36 | 37 | template 38 | void serialize(Archive& ar, unsigned int /*version*/) 39 | { 40 | ar & m_Type; 41 | } 42 | public: 43 | enum Method 44 | { 45 | NONE = 0, 46 | XOR = 1, 47 | ZLIB = 2, 48 | BZIP2 = 3, 49 | LZO = 4, 50 | LZMA = 5 51 | }; 52 | 53 | CompressionType() : 54 | #ifdef HAVE_LIBZ 55 | m_Type (ZLIB) 56 | #elif HAVE_LIBLZO2 57 | m_Type(LZO) 58 | #elif HAVE_LIBBZ2 59 | m_Type(BZIP2) 60 | #elif HAVE_LIBLZMA 61 | m_Type(LZMA) 62 | #else 63 | m_Type(NONE) 64 | #endif 65 | { } 66 | 67 | CompressionType(unsigned char type) : 68 | m_Type(type) 69 | { 70 | // These asserts checks programming error. If 71 | // some compression method is not supported no 72 | // code shall call this type of constructor 73 | // with that unsupported compression type. 74 | 75 | #ifndef HAVE_LIBZ 76 | assert(type != ZLIB); 77 | #endif 78 | #ifndef HAVE_LIBLZO2 79 | assert(type != LZO); 80 | #endif 81 | #ifndef HAVE_LIBBZ2 82 | assert(type != BZIP2); 83 | #endif 84 | #ifndef HAVE_LIBLZMA 85 | assert(type != LZMA); 86 | #endif 87 | } 88 | 89 | CompressionType(const CompressionType& src) : m_Type (src.m_Type) { } 90 | 91 | bool parseType(std::string type); 92 | 93 | template 94 | void push(io::filtering_stream& fs) const; 95 | 96 | CompressionType& operator=(const CompressionType& src) 97 | { 98 | m_Type = src.m_Type; 99 | 100 | return *this; 101 | } 102 | 103 | bool operator==(const CompressionType& t) 104 | { 105 | return (m_Type == t.m_Type); 106 | } 107 | 108 | // Minimal size: 109 | // 110 | // 1. byte : boost's serialization version (=0 => 1 byte) 111 | // 2. byte : class version (=0 => 1 byte) 112 | // 3. byte : compression type (=0 => 1 byte) 113 | 114 | static const int MinSize = 3; 115 | 116 | // Current maximal size 117 | // 118 | // 1. byte : boost's serialization version (=0 => 1 byte) 119 | // 2. byte : class version (=0 => 1 byte) 120 | // 3., 4. byte : compression type (>0 => 2 bytes) 121 | 122 | static const int MaxSize = 4; 123 | 124 | friend std::ostream& operator<<(std::ostream& os, const CompressionType& rObj); 125 | static void printAllSupportedMethods(std::ostream& os); 126 | }; 127 | 128 | BOOST_CLASS_VERSION(CompressionType, 0) 129 | 130 | #endif 131 | 132 | -------------------------------------------------------------------------------- /src/File.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "rlog/rlog.h" 29 | #include "assert.h" 30 | 31 | #include "File.hpp" 32 | #include "FileUtils.hpp" 33 | 34 | File::File(const struct stat *st, const char *name) : 35 | m_fd (-1), 36 | m_inode (st->st_ino), 37 | m_refs (0), 38 | m_name (name) 39 | { 40 | } 41 | 42 | File::~File() 43 | { 44 | assert (m_refs == 0); 45 | assert (m_fd == -1); 46 | } 47 | 48 | int File::getattr(const char *name, struct stat *st) 49 | { 50 | int r; 51 | 52 | m_name = name; 53 | 54 | if (m_fd != -1) 55 | r = ::fstat(m_fd, st); 56 | else 57 | r = ::lstat(name, st); 58 | 59 | return r; 60 | } 61 | 62 | int File::unlink(const char *name) 63 | { 64 | int r; 65 | 66 | r = ::unlink(name); 67 | 68 | return r; 69 | } 70 | 71 | int File::truncate(const char *name, off_t size) 72 | { 73 | int r; 74 | 75 | if (m_fd != -1) 76 | r = ::ftruncate(m_fd, size); 77 | else 78 | r = ::truncate(name, size); 79 | 80 | return r; 81 | } 82 | 83 | int File::utimens(const char *name, const struct timespec tv[2]) 84 | { 85 | int r; 86 | 87 | r = ::utimensat(AT_FDCWD, name, tv, AT_SYMLINK_NOFOLLOW); 88 | 89 | return r; 90 | } 91 | 92 | ssize_t File::read(char *buf, size_t size, off_t offset) const 93 | { 94 | ssize_t r; 95 | 96 | assert(m_fd >= 0); 97 | 98 | r = ::pread(m_fd, buf, size, offset); 99 | 100 | return r; 101 | } 102 | 103 | ssize_t File::write(const char *buf, size_t size, off_t offset) 104 | { 105 | ssize_t r; 106 | 107 | assert(m_fd >= 0); 108 | 109 | r = ::pwrite(m_fd, buf, size, offset); 110 | 111 | return r; 112 | } 113 | 114 | int File::open(const char *name, int flags) 115 | { 116 | // Use only one file descriptor for one file determined 117 | // by inode number. 118 | // 119 | if (m_fd != -1) 120 | { 121 | ++m_refs; 122 | return m_fd; 123 | } 124 | 125 | m_fd = FileUtils::open(name); 126 | 127 | if (m_fd != -1) 128 | { 129 | ++m_refs; 130 | } 131 | 132 | rDebug("File::open file '%s', inode %ld, m_refs: %d", 133 | name, (long int) m_inode, m_refs); 134 | 135 | return m_fd; 136 | } 137 | 138 | int File::flush(const char *name) 139 | { 140 | return 0; 141 | } 142 | 143 | int File::release(const char *name) 144 | { 145 | if (--m_refs == 0) 146 | { 147 | ::close(m_fd); 148 | m_fd = -1; 149 | } 150 | assert (m_refs >= 0); 151 | 152 | rDebug("File::release m_refs: %d", m_refs); 153 | 154 | return 0; 155 | } 156 | 157 | int File::fdatasync(const char *name) 158 | { 159 | assert(m_fd >= 0); 160 | 161 | return ::fdatasync(m_fd); 162 | } 163 | 164 | int File::fsync(const char *name) 165 | { 166 | assert(m_fd >= 0); 167 | 168 | return ::fsync(m_fd); 169 | } 170 | 171 | -------------------------------------------------------------------------------- /src/File.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #ifndef FILE_HPP 21 | #define FILE_HPP 22 | 23 | #include "Mutex.hpp" 24 | 25 | #include 26 | 27 | #include 28 | 29 | using namespace std; 30 | 31 | class File 32 | { 33 | protected: 34 | // SHARED WITH CLASSES THAT INHERITS FROM THIS CLASS 35 | 36 | // File descriptor used to read/write/etc... 37 | // 38 | int m_fd; 39 | 40 | ino_t m_inode; 41 | 42 | // Reference counter. Used to open m_fd just once even 43 | // for multiple users. If value drops to zero, m_fd is 44 | // closed. 45 | // 46 | int m_refs; 47 | 48 | private: 49 | // USED ONLY IN THIS CLASS PRIVATELY 50 | 51 | Mutex m_mutex; 52 | 53 | File(const File&); // Private copy constructor. 54 | public: 55 | std::string m_name; 56 | 57 | File(const struct stat *st, const char *name); 58 | virtual ~File(); 59 | 60 | void Lock(void) { m_mutex.Lock(); } 61 | void Unlock(void) { m_mutex.Unlock(); } 62 | 63 | ino_t getInode(void) const { return m_inode; } 64 | void setInode(ino_t inode) { m_inode = inode; } 65 | std::string getName(void) const { return m_name; } 66 | 67 | int getattr(const char *name, struct stat *st); 68 | 69 | int unlink(const char *name); 70 | 71 | int truncate(const char *name, off_t size); 72 | 73 | int utimens(const char *name, const struct timespec tv[2]); 74 | 75 | int open(const char *name, int flags); 76 | 77 | /** 78 | * Read `size` of bytes from the file with offset `offset` 79 | * and store them to the `buf` 80 | */ 81 | ssize_t read(char *buf, size_t size, off_t offset) const; 82 | 83 | /** 84 | * Write `size` of bytes from the buffer `buf` and store them 85 | * to the file with offset `offset` 86 | */ 87 | ssize_t write(const char *buf, size_t size, off_t offset); 88 | 89 | int flush(const char *name); 90 | 91 | int release(const char *name); 92 | 93 | int fdatasync(const char *name); 94 | 95 | int fsync(const char *name); 96 | }; 97 | 98 | #endif 99 | 100 | -------------------------------------------------------------------------------- /src/FileHeader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "config.h" 29 | #include "rlog/rlog.h" 30 | 31 | #include "FileHeader.hpp" 32 | #include "FileUtils.hpp" 33 | 34 | FileHeader::FileHeader(bool valid) 35 | { 36 | if (valid) 37 | { 38 | // FuseCompress identification 39 | // 40 | id_0 = '\037'; 41 | id_1 = '\135'; 42 | id_2 = '\211'; 43 | } 44 | else 45 | { 46 | id_0 = 0; 47 | id_1 = 0; 48 | id_2 = 0; 49 | } 50 | 51 | // Zero size 52 | // 53 | size = 0; 54 | 55 | // Index is not present 56 | // 57 | index = 0; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/FileHeader.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #ifndef FILEHEADER_HPP 21 | #define FILEHEADER_HPP 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include "CompressionType.hpp" 35 | 36 | using namespace std; 37 | 38 | class FileHeader 39 | { 40 | private: 41 | friend class boost::serialization::access; 42 | 43 | template 44 | void load(Archive &ar, const unsigned /*version*/) 45 | { 46 | ar >> id_0 >> id_1 >> id_2; 47 | 48 | if (isValid()) 49 | { 50 | ar >> size >> index >> type; 51 | } 52 | } 53 | template 54 | void save(Archive &ar, const unsigned /*version*/) const 55 | { 56 | assert(isValid()); 57 | 58 | ar << id_0 << id_1 << id_2; 59 | ar << size << index << type; 60 | } 61 | BOOST_SERIALIZATION_SPLIT_MEMBER() 62 | 63 | public: 64 | FileHeader(bool valid = true); 65 | 66 | FileHeader(const FileHeader& src) : 67 | id_0(src.id_0), 68 | id_1(src.id_1), 69 | id_2(src.id_2), 70 | size(src.size), 71 | index(src.index), 72 | type(src.type) 73 | {}; 74 | 75 | FileHeader& operator=(const FileHeader& src) 76 | { 77 | id_0 = src.id_0; 78 | id_1 = src.id_1; 79 | id_2 = src.id_2; 80 | size = src.size; 81 | index = src.index; 82 | type = src.type; 83 | 84 | return *this; 85 | } 86 | 87 | /* 88 | * Identify header. 89 | * 90 | * Return: 91 | * - True if header is correct (file is FuseCompress format). 92 | * - False if header is not correct. 93 | */ 94 | inline bool isValid() const 95 | { 96 | if ((id_0 != (signed char)'\037') || (id_1 != (signed char)'\135') || (id_2 != (signed char)'\211')) 97 | return false; 98 | return true; 99 | } 100 | 101 | signed char id_0; // FuseCompress identification 102 | signed char id_1; // (these meant to be unsigned, however I oversight 103 | signed char id_2; // that boost::archive stores char type as signed) 104 | off_t size; // Length of the uncompressed file 105 | off_t index; // Position of the index in the compressed file 106 | // (0 - index is not present in the file) 107 | CompressionType type; // Compression type of the index 108 | 109 | // Minimal size: 110 | // 111 | // 1., ..., 6. byte: FuseCompress identification 112 | // 7. byte : size (=0 => 1 byte) 113 | // 8. byte : index (=0 => 1 byte) 114 | // 9., ... byte : compression type 115 | 116 | static const int MinSize = 3 + 1 + 1 + CompressionType::MinSize; 117 | 118 | // Current maximal size: 119 | // 120 | // 1., ..., 6. byte: FuseCompress identification 121 | // 7., ... byte : size (>0 => 1 byte + up to 8 bytes) 122 | // ..., ... byte : index (>0 => 1 byte + up to 8 bytes) 123 | // ..., ... byte : compression type 124 | 125 | static const int MaxSize = 3 + 1 + 8 + 1 + 8 + CompressionType::MaxSize; 126 | }; 127 | 128 | // Don't need versioning info for the FileHeader. 129 | 130 | BOOST_CLASS_IMPLEMENTATION(FileHeader, boost::serialization::object_serializable) 131 | 132 | // Don't track instances of this class. Users creates 133 | // them on the stack. 134 | 135 | BOOST_CLASS_TRACKING(FileHeader, boost::serialization::track_never) 136 | 137 | #endif 138 | 139 | -------------------------------------------------------------------------------- /src/FileManager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "rlog/rlog.h" 27 | #include "assert.h" 28 | 29 | #include "FileManager.hpp" 30 | 31 | FileManager::FileManager() 32 | { 33 | } 34 | 35 | FileManager::~FileManager() 36 | { 37 | bool flag = false; 38 | CFile *file; 39 | set::iterator it = m_files.begin(); 40 | 41 | // FUSE should allow umount only when filesystem is not 42 | // in use. Therefore if m_files is not empty and some files 43 | // have m_crefs bigger than zero, we were run in debug mode 44 | // and have no responsibility for any damage 45 | // when user hits CTRL+C. 46 | // 47 | while (it != m_files.end()) 48 | { 49 | file = dynamic_cast (*it); 50 | 51 | if ((file->m_crefs > 0) & !flag) 52 | { 53 | rError("FuseCompress killed while mounted with some opened files."); 54 | flag = true; 55 | } 56 | 57 | m_files.erase(it++); 58 | delete file; 59 | } 60 | } 61 | 62 | void FileManager::Put(CFile *file) 63 | { 64 | m_mutex.Lock(); 65 | 66 | file->m_crefs--; 67 | 68 | // TODO: Invent some policy to decide when and why to 69 | // call delete file... 70 | // 71 | if (file->m_crefs < 1) 72 | { 73 | m_files.erase(file); 74 | delete file; 75 | } 76 | 77 | m_mutex.Unlock(); 78 | } 79 | 80 | void FileManager::GetUnlocked(CFile *file) 81 | { 82 | file->m_crefs++; 83 | } 84 | 85 | void FileManager::UpdateUnlocked(CFile *file, ino_t inode) 86 | { 87 | m_files.erase(file); 88 | file->setInode(inode); 89 | m_files.insert(file); 90 | } 91 | 92 | CFile *FileManager::Get(const char *name, bool create) 93 | { 94 | Lock(); 95 | CFile *file = GetUnlocked(name, create); 96 | Unlock(); 97 | 98 | return file; 99 | } 100 | 101 | CFile *FileManager::GetUnlocked(const char *name, bool create) 102 | { 103 | struct stat st; 104 | CFile *file = NULL; 105 | set::iterator it; 106 | 107 | // Get inode number from the name. If 'name' is symbolic link, 108 | // retrieve inode number of the file it points to. 109 | // 110 | if (stat(name, &st) == -1) 111 | { 112 | if ((errno != ENOENT) && (errno != ELOOP)) 113 | { 114 | // File doesn't exist. 115 | // 116 | return NULL; 117 | } 118 | 119 | // 'name' may be nonexistant file ot symbolic link that points 120 | // to nonexistant file. Figure out what 'name' is really. 121 | // 122 | if ((lstat(name, &st) == -1) || (! S_ISLNK(st.st_mode))) 123 | { 124 | // File doesn't exist. 125 | // 126 | return NULL; 127 | } 128 | 129 | // Preserve inode number - it's our index and node number 130 | // of link is better than nothing. 131 | // 132 | // Set the size to zero to let the Compress decide whatever 133 | // it use compressed or uncompressed FileRaw. 134 | // 135 | st.st_size = 0; 136 | } 137 | 138 | File search(&st, name); 139 | 140 | it = m_files.find(&search); 141 | 142 | if (it != m_files.end()) 143 | { 144 | file = dynamic_cast (*it); 145 | 146 | if (create) 147 | { 148 | file->m_crefs++; 149 | } 150 | } 151 | else 152 | if (create) 153 | { 154 | rDebug("new CFile(..., %s)", name); 155 | 156 | file = new (std::nothrow) CFile(&st, name); 157 | if (!file) 158 | { 159 | rError("No memory to allocate object of " 160 | "FileRaw interface"); 161 | abort(); 162 | } 163 | 164 | m_files.insert(file); 165 | } 166 | 167 | return file; 168 | } 169 | 170 | -------------------------------------------------------------------------------- /src/FileManager.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #ifndef FILEMANAGER_H 21 | #define FILEMANAGER_H 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | #include "Memory.hpp" 30 | #include "Compress.hpp" 31 | 32 | #include "Mutex.hpp" 33 | 34 | //typedef File PARENT_CFILE; 35 | typedef Memory PARENT_CFILE; 36 | //typedef Compress PARENT_CFILE; 37 | 38 | /** 39 | * Helper class that's only goal is to remember how many users currently 40 | * use it. m_cref counter is protected with mutex in FileManager class. 41 | */ 42 | class CFile : public PARENT_CFILE 43 | { 44 | private: 45 | friend class FileManager; 46 | 47 | /** 48 | * Number of users that currently use this File. 49 | */ 50 | int m_crefs; 51 | 52 | mode_t m_mode; 53 | 54 | CFile(); // No default constructor 55 | CFile(const CFile &); // No copy constructor 56 | CFile& operator=(const CFile &); // No assign operator 57 | 58 | 59 | public: 60 | CFile(const struct stat *st, const char *name) : 61 | PARENT_CFILE (st, name), 62 | m_crefs (1) 63 | { }; 64 | }; 65 | 66 | class FileManager 67 | { 68 | /** 69 | * Using struct instead of class only because its 70 | * default access is public. 71 | */ 72 | struct ltFile 73 | { 74 | bool operator()(const File *file1, const File *file2) const 75 | { 76 | return (file1->getInode() < file2->getInode()); 77 | } 78 | }; 79 | 80 | set m_files; 81 | 82 | /** 83 | * Protects m_files and every m_refs in CFile type instancies 84 | */ 85 | Mutex m_mutex; 86 | 87 | public: 88 | FileManager(); 89 | ~FileManager(); 90 | 91 | void Lock() { m_mutex.Lock(); } 92 | void Unlock() { m_mutex.Unlock(); } 93 | 94 | /** 95 | * Returns pointer to CFile instance that does all operations on 96 | * the requested name. It works even with hardlinks because name 97 | * is translated to inode number and that number is used as a key. 98 | * 99 | * @param name 100 | * @param create - if true, a new instance is created (with reference 101 | * counter set to one) if there is no 102 | * one in the database (set m_files). If there 103 | * is one, it's reference counter is increased. 104 | * 105 | * if false, returns a null if there is no one in 106 | * the database. If there is one, it's reference 107 | * counter is not increased. 108 | */ 109 | CFile *Get(const char *name, bool create = true); 110 | CFile *GetUnlocked(const char *name, bool create = true); 111 | 112 | void GetUnlocked(CFile *file); 113 | void Put(CFile *file); 114 | 115 | void UpdateUnlocked(CFile *file, ino_t inode); 116 | }; 117 | 118 | #endif 119 | 120 | -------------------------------------------------------------------------------- /src/FileRememberTimes.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include "FileRememberTimes.hpp" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | FileRememberTimes::FileRememberTimes(int fd) 27 | : m_fd (fd) 28 | { 29 | struct stat buf; 30 | 31 | fstat(fd, &buf); 32 | 33 | m_times[0].tv_sec = buf.st_atime; 34 | m_times[0].tv_nsec = buf.st_atim.tv_nsec; 35 | m_times[1].tv_sec = buf.st_mtime; 36 | m_times[1].tv_nsec = buf.st_mtim.tv_nsec; 37 | } 38 | 39 | FileRememberTimes::~FileRememberTimes() 40 | { 41 | futimens(m_fd, m_times); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /src/FileRememberTimes.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include 21 | 22 | class FileRememberTimes 23 | { 24 | int m_fd; 25 | struct timespec m_times[2]; 26 | public: 27 | FileRememberTimes(int fd); 28 | ~FileRememberTimes(); 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /src/FileRememberXattrs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include "config.h" 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #if defined(HAVE_ATTR_XATTR_H) 28 | # include 29 | #elif defined(HAVE_SYS_XATTR_H) 30 | # include 31 | #endif 32 | 33 | #include "rlog/rlog.h" 34 | 35 | #include 36 | 37 | void FileRememberXattrs::read(int fd_source) 38 | { 39 | size_t list_size = 1024; 40 | try_list_again: 41 | char* list = new char[list_size]; 42 | int r = ::flistxattr(fd_source, list, list_size); 43 | if (-1 == r) 44 | { 45 | delete list; 46 | 47 | if (ERANGE == errno) 48 | { 49 | list_size *= 2; 50 | goto try_list_again; 51 | } 52 | return; 53 | } 54 | char *listp = list; 55 | while (r > 0) 56 | { 57 | int attr_size = 1024; 58 | try_attr_again: 59 | char* attr = new char[attr_size]; 60 | int rr = ::fgetxattr(fd_source, listp, attr, attr_size); 61 | if (-1 == rr) 62 | { 63 | delete attr; 64 | 65 | if (ERANGE == errno) 66 | { 67 | attr_size *= 2; 68 | goto try_attr_again; 69 | } 70 | delete list; 71 | return; 72 | } 73 | std::string key(listp); 74 | std::string value(attr, rr); 75 | m_xattrs[key] = value; 76 | 77 | listp += key.length() + 1; 78 | r -= key.length() + 1; 79 | delete attr; 80 | } 81 | delete list; 82 | } 83 | 84 | void FileRememberXattrs::write(int fd_dest) 85 | { 86 | for (std::map::const_iterator it = m_xattrs.begin(); it != m_xattrs.end(); ++it) 87 | { 88 | fsetxattr(fd_dest, it->first.c_str(), it->second.c_str(), it->second.size(), 0); 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /src/FileRememberXattrs.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #ifndef FILEREMEMBERXATTRS_HPP 21 | #define FILEREMEMBERXATTRS_HPP 22 | 23 | #include 24 | #include 25 | 26 | /** Class that copies all extended file attributes from one file 27 | * to an another one. 28 | */ 29 | class FileRememberXattrs 30 | { 31 | std::map m_xattrs; 32 | public: 33 | void read(int fd_source); 34 | void write(int fd_dest); 35 | }; 36 | 37 | #endif 38 | 39 | -------------------------------------------------------------------------------- /src/FileUtils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | #include "FileUtils.hpp" 30 | 31 | int FileUtils::force(const char *name, const struct stat &buf) 32 | { 33 | int r; 34 | int fd; 35 | int tmp_errno = 0; 36 | 37 | if (::chmod(name, buf.st_mode | 0600) == -1) 38 | return -1; 39 | 40 | fd = ::open(name, O_RDWR); 41 | if (fd == -1) 42 | tmp_errno = errno; 43 | 44 | r = ::chmod(name, buf.st_mode); 45 | assert (r != -1); 46 | 47 | if (fd == -1) 48 | errno = tmp_errno; 49 | 50 | return fd; 51 | } 52 | 53 | int FileUtils::open(const char *name) 54 | { 55 | int fd; 56 | struct stat buf; 57 | 58 | if (::stat(name, &buf) == -1) 59 | return -1; 60 | 61 | if (!S_ISREG(buf.st_mode)) 62 | return -1; 63 | 64 | fd = ::open(name, O_RDWR); 65 | 66 | if ((fd == -1) && (errno == EACCES || errno == EPERM)) 67 | { 68 | fd = force(name, buf); 69 | } 70 | 71 | return fd; 72 | } 73 | 74 | bool FileUtils::copy(int source, int dest) 75 | { 76 | boost::scoped_array buffer(new char[100 * 1024]); 77 | 78 | if (::ftruncate(dest, 0) == -1) 79 | return false; 80 | if (::lseek(dest, 0, SEEK_SET) == -1) 81 | return false; 82 | if (::lseek(source, 0, SEEK_SET) == -1) 83 | return false; 84 | 85 | while (true) 86 | { 87 | ssize_t bytesRead = ::read(source, buffer.get(), 100 * 1024); 88 | if (bytesRead == -1) 89 | return false; 90 | if (bytesRead == 0) 91 | return true; 92 | 93 | off_t bytesToWrite = bytesRead; 94 | char *pbuffer = buffer.get(); 95 | 96 | while (bytesToWrite > 0) 97 | { 98 | ssize_t bytesWritten = ::write(dest, pbuffer, bytesToWrite); 99 | if (bytesWritten == -1) 100 | return false; 101 | 102 | bytesToWrite -= bytesWritten; 103 | pbuffer += bytesWritten; 104 | } 105 | } 106 | 107 | return true; 108 | } 109 | 110 | bool FileUtils::isZeroOnly(const char *buf, size_t size) 111 | { 112 | for (size_t i = 0; i < size; ++i, ++buf) 113 | if (*buf != 0) 114 | return false; 115 | return true; 116 | } 117 | 118 | 119 | -------------------------------------------------------------------------------- /src/FileUtils.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include 21 | 22 | class FileUtils 23 | { 24 | /* 25 | * Change the access rights of the file specified 26 | * by name, open it and then return original 27 | * access rights back. 28 | */ 29 | static int force(const char *name, const struct stat &buf); 30 | public: 31 | /* 32 | * Open a regular file specified by name. If the caller has 33 | * insufficient rights, the function tries to 34 | * change the access rights of the file, open it and 35 | * then return the original rights back. 36 | */ 37 | static int open(const char *name); 38 | 39 | static bool copy(int source, int dest); 40 | 41 | static bool isZeroOnly(const char *buf, size_t size); 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /src/FuseCompress.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #ifndef FUSECOMPRESS_H 21 | #define FUSECOMPRESS_H 22 | 23 | #include 24 | #include 25 | 26 | class FuseCompress 27 | { 28 | inline static const char *getpath(const char *path); 29 | static void replace(std::string& path, std::string part, std::string newpart); 30 | 31 | static int readlink (const char *, char *, size_t); 32 | static int getattr (const char *, struct stat *); 33 | static int getdir (const char *, fuse_dirh_t, fuse_dirfil_t); 34 | static int mknod (const char *, mode_t, dev_t); 35 | static int mkdir (const char *, mode_t); 36 | static int unlink (const char *); 37 | static int rmdir (const char *); 38 | static int symlink (const char *, const char *); 39 | static int rename (const char *, const char *); 40 | static int link (const char *, const char *); 41 | static int chmod (const char *, mode_t); 42 | static int chown (const char *, uid_t, gid_t); 43 | static int truncate (const char *, off_t); 44 | static int utimens (const char *, const struct timespec tv[2]); 45 | static int open (const char *, struct fuse_file_info *); 46 | static int read (const char *, char *, size_t, off_t, struct fuse_file_info *); 47 | static int write (const char *, const char *, size_t, off_t,struct fuse_file_info *); 48 | static int flush (const char *, struct fuse_file_info *); 49 | static int release (const char *, struct fuse_file_info *); 50 | static int fsync (const char *, int, struct fuse_file_info *); 51 | static int setxattr (const char *, const char *, const char *, size_t, int); 52 | static int getxattr (const char *, const char *, char *, size_t); 53 | static int listxattr (const char *, char *, size_t); 54 | static int removexattr (const char *, const char *); 55 | static int opendir (const char *, struct fuse_file_info *); 56 | static int readdir (const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *); 57 | static int releasedir (const char *, struct fuse_file_info *); 58 | static int fsyncdir (const char *, int, struct fuse_file_info *); 59 | static void *init (struct fuse_conn_info *); 60 | static void destroy (void *); 61 | static int access (const char *, int); 62 | static int create (const char *, mode_t, struct fuse_file_info *); 63 | static int ftruncate (const char *, off_t, struct fuse_file_info *); 64 | static int fgetattr (const char *, struct stat *, struct fuse_file_info *); 65 | static int statfs (const char *, struct statvfs *); 66 | 67 | struct fuse_operations m_ops; 68 | 69 | public: 70 | FuseCompress(); 71 | ~FuseCompress(); 72 | 73 | int Run(DIR *dir, int argc, const char **argv); 74 | }; 75 | 76 | #endif 77 | 78 | -------------------------------------------------------------------------------- /src/LayerMap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include 23 | 24 | #include "rlog/rlog.h" 25 | 26 | #include "LayerMap.hpp" 27 | 28 | using namespace std; 29 | 30 | std::ostream &operator<<(std::ostream &os, const LayerMap &rLm) 31 | { 32 | boost::io::ios_flags_saver ifs(os); 33 | 34 | os << std::hex; 35 | os << "-- m_MaxLevel: 0x" << rLm.m_MaxLevel << 36 | ", m_MaxLength: 0x" << rLm.m_MaxLength << 37 | ", m_IsModified: " << rLm.m_IsModified << 38 | " -------" << std::endl; 39 | 40 | for (LayerMap::con_t::const_iterator it = rLm.m_Map.begin(); it != rLm.m_Map.end(); ++it) 41 | { 42 | os << **it << std::endl; 43 | } 44 | 45 | os << "---------"; 46 | 47 | return os; 48 | } 49 | 50 | void LayerMap::Put(Block *pBl, bool bKeepLevel) 51 | { 52 | // cout << "Put Block: " << *pBl << " into following LayerMap:" << endl; 53 | // cout << *this << endl; 54 | 55 | assert(pBl->length > 0); 56 | 57 | // Preserve a level if already set. 58 | // 59 | if (!bKeepLevel) 60 | { 61 | pBl->level = m_MaxLevel++; 62 | 63 | // Check that m_MaxLevel didn't overrun. 64 | // 65 | assert(m_MaxLevel > 0); 66 | } 67 | con_t::iterator it = m_Map.insert(pBl); 68 | if (m_MaxLength < pBl->length) 69 | m_MaxLength = pBl->length; 70 | 71 | m_IsModified = true; 72 | 73 | // cout << "State after Put: " << endl << *this << endl; 74 | } 75 | 76 | void LayerMap::Truncate(off_t offset) 77 | { 78 | // std::cout << "Truncate following LayerMap to 0x" << std::hex << length << std::endl; 79 | // std::cout << *this << std::endl; 80 | 81 | con_t::iterator it = m_Map.begin(); 82 | 83 | while (it != m_Map.end()) 84 | { 85 | if ((*it)->offset >= offset) 86 | { 87 | delete (*it); 88 | m_Map.erase(it++); 89 | continue; 90 | } 91 | if ((*it)->offset + (off_t) (*it)->length > offset) 92 | { 93 | (*it)->length = offset - (*it)->offset; 94 | assert((*it)->length > 0); 95 | } 96 | ++it; 97 | } 98 | 99 | m_IsModified = true; 100 | 101 | // std::cout << "State after Truncate: " << std::endl << *this << std::endl; 102 | } 103 | 104 | /* Find the biggest leveled Block with the higher offset and higher level than 105 | * current 'it' references to. */ 106 | void LayerMap::next(off_t offset, con_t::const_iterator &it) const 107 | { 108 | unsigned int level = (*it)->level; 109 | 110 | while (++it != m_Map.end()) 111 | { 112 | if ((*it)->offset < offset) 113 | continue; 114 | if ((*it)->level > level) 115 | break; 116 | } 117 | } 118 | 119 | /* Returns number of bytes that can be read from the offset from the Block specified by 'it' iterator. */ 120 | unsigned int LayerMap::length(con_t::const_iterator &it, off_t offset) const 121 | { 122 | if ((*it)->offset > offset) 123 | { 124 | // Block starts after the offset, return 0 to 125 | // indicate that. 126 | // 127 | return 0; 128 | } 129 | 130 | con_t::const_iterator ni = it; 131 | 132 | next(offset, ni); 133 | 134 | assert((*it)->length >= 0); 135 | if ((ni == m_Map.end()) || ((*it)->offset + (off_t) (*it)->length <= (*ni)->offset)) 136 | { 137 | // 'it' block is not limited with 'no' block. 138 | // 139 | return (*it)->length - (offset - (*it)->offset); 140 | } 141 | else 142 | { 143 | return ((*ni)->offset - (*it)->offset) - (offset - (*it)->offset); 144 | } 145 | } 146 | 147 | void LayerMap::find(off_t offset, con_t::const_iterator &it) const 148 | { 149 | con_t::const_iterator si; 150 | con_t::const_iterator ti; 151 | 152 | it = m_Map.end(); 153 | 154 | unsigned int level = 0; 155 | 156 | // We want to find a block which offset + length is bigger than offset. 157 | // 158 | // Thus we want to skip all blocks with offset + length smaller or 159 | // equal to offset. 160 | // 161 | // This cannot be done in single call to stl algorithm, so we 162 | // call lower_bound to skip all blocks with offset + m_MaxLength smaller 163 | // or equal to offset. After that we simple iterate over all (if any) 164 | // blocks wich offset + length is smaller or equal to offset. 165 | 166 | off_t offset_tmp = offset > m_MaxLength ? offset - m_MaxLength : 0; 167 | Block block(offset_tmp, 0, m_MaxLevel); 168 | 169 | for (si = m_Map.lower_bound(&block); si != m_Map.end(); ++si) 170 | { 171 | assert((*si)->length >= 0); 172 | if ((*si)->offset + (off_t) (*si)->length <= offset) { 173 | continue; 174 | } 175 | 176 | if ((*si)->level > level) 177 | { 178 | it = si; 179 | level = (*si)->level; 180 | } 181 | 182 | if ((*si)->offset > offset + m_MaxLength) { 183 | return; 184 | } 185 | 186 | for (ti = si; ti != m_Map.end(); ++ti) 187 | { 188 | if ((*ti)->offset > offset) { 189 | return; 190 | } 191 | 192 | assert((*ti)->length >= 0); 193 | if (((*ti)->offset + (off_t) (*ti)->length <= offset)) { 194 | continue; 195 | } 196 | 197 | if ((*ti)->level > level) 198 | { 199 | it = ti; 200 | level = (*ti)->level; 201 | } 202 | } 203 | } 204 | } 205 | 206 | /* Returns Block that overlaps specified offset or higher offset */ 207 | bool LayerMap::Get(off_t offset, Block &rBlock, off_t &rLength) const 208 | { 209 | // std::cout << "State before Get called (looking offset: 0x" << hex << offset << ")" << std::endl << *this << std::endl; 210 | 211 | con_t::const_iterator it; 212 | 213 | find(offset, it); 214 | 215 | if (it == m_Map.end()) { 216 | // std::cout << "Get found nothing" << std::endl; 217 | return false; 218 | } 219 | 220 | // Return found block to caller. 221 | 222 | rBlock = **it; 223 | 224 | // std::cout << "Get found block: " << **it << std::endl; 225 | 226 | // Compute the maximal length uses can read from the Block 227 | // the 'it' iterator points to. 228 | 229 | rLength = length(it, offset); 230 | 231 | // std::cout << "Get found block's length: 0x" << std::hex << rLength << std::endl; 232 | 233 | return true; 234 | } 235 | 236 | -------------------------------------------------------------------------------- /src/LayerMap.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009 - 2015. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #ifndef LayerMap_H 21 | #define LayerMap_H 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "Block.hpp" 32 | 33 | class LayerMap 34 | { 35 | private: 36 | struct ltComp 37 | { 38 | // Required sorting order is as follows: 39 | // 40 | // (offset, level) 41 | // ( 0, 2 ) 42 | // ( 0, 1 ) 43 | // ( 7, 3 ) 44 | // ( 9, 5 ) 45 | // ( 9, 4 ) 46 | // 47 | bool operator()(const Block *pB1, const Block *pB2) const 48 | { 49 | if (pB1->offset < pB2->offset) 50 | return true; 51 | if (pB1->offset > pB2->offset) 52 | return false; 53 | return (pB1->level > pB2->level); 54 | } 55 | }; 56 | typedef std::multiset con_t; 57 | 58 | con_t m_Map; 59 | unsigned int m_MaxLevel; 60 | unsigned int m_MaxLength; 61 | bool m_IsModified; 62 | 63 | void next(off_t offset, con_t::const_iterator &it) const; 64 | unsigned int length(con_t::const_iterator &it, off_t offset) const; 65 | void find(off_t offset, con_t::const_iterator &it) const; 66 | 67 | friend class boost::serialization::access; 68 | 69 | template 70 | void serialize(Archive& ar, const unsigned version) 71 | { 72 | ar & m_MaxLevel; 73 | ar & m_MaxLength; 74 | ar & m_Map; 75 | } 76 | public: 77 | LayerMap() : 78 | m_MaxLevel(1), 79 | m_MaxLength(0), 80 | m_IsModified(false) 81 | {} 82 | ~LayerMap() 83 | { 84 | m_Map.clear(); 85 | } 86 | LayerMap& operator=(const LayerMap& src) 87 | { 88 | m_MaxLevel = src.m_MaxLevel; 89 | m_MaxLength = src.m_MaxLength; 90 | m_IsModified = src.m_IsModified; 91 | 92 | for (con_t::iterator it = m_Map.begin(); it != m_Map.end(); ++it) 93 | delete(*it); 94 | m_Map.clear(); 95 | m_Map = src.m_Map; 96 | 97 | return *this; 98 | } 99 | 100 | void Put(Block *pBl, bool bKeepLevel = false); 101 | 102 | /** 103 | * Description: 104 | * Return iterator that points to a Block that covers the specified offset. 105 | * Caller may read up to rLength of bytes from the Block. 106 | * 107 | * Input: 108 | * offset - caller wants to read from the specified offset 109 | * Output: 110 | * it - return iterator that fits 111 | * length - number of bytes to read from the Block pointed on to by returned iterator 112 | * Return: 113 | * bool - true if something found, otherwise false. 114 | */ 115 | bool Get(off_t offset, Block &rBlock, off_t &rLength) const; 116 | 117 | void Truncate(off_t length); 118 | 119 | bool isCompressedOnlyWith(CompressionType& type) 120 | { 121 | for (con_t::iterator it = m_Map.begin(); it != m_Map.end(); ++it) 122 | { 123 | if ((*it)->type == type) 124 | { 125 | continue; 126 | } 127 | return false; 128 | } 129 | return true; 130 | } 131 | 132 | bool isModified() const { return m_IsModified; } 133 | 134 | friend std::ostream &operator<<(std::ostream &os, const LayerMap &rLm); 135 | }; 136 | 137 | BOOST_CLASS_VERSION(LayerMap, 0) 138 | 139 | // Don't track instances of this class. Users create 140 | // them on the stack. 141 | 142 | BOOST_CLASS_TRACKING(LayerMap, boost::serialization::track_never) 143 | 144 | #endif 145 | 146 | -------------------------------------------------------------------------------- /src/LinearMap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009 - 2015. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #include "rlog/rlog.h" 24 | #include "assert.h" 25 | 26 | #include 27 | 28 | #include "LinearMap.hpp" 29 | 30 | extern size_t g_BufferedMemorySize; 31 | 32 | LinearMap::LinearMap() 33 | { 34 | } 35 | 36 | LinearMap::~LinearMap() 37 | { 38 | } 39 | 40 | LinearMap::Buffer *LinearMap::merge(Buffer *prev, Buffer *next) const 41 | { 42 | Buffer *buffer = new (std::nothrow) Buffer(prev->buf, prev->size, 43 | next->buf, next->size); 44 | assert(buffer); 45 | 46 | delete prev; 47 | delete next; 48 | 49 | return buffer; 50 | } 51 | 52 | void LinearMap::insert(off_t offset, const char *buf, size_t size) 53 | { 54 | Buffer *buffer = new Buffer(buf, size); 55 | assert(buffer); 56 | 57 | con_t::iterator it = m_map.lower_bound(offset); 58 | 59 | if (it != m_map.begin()) 60 | { 61 | con_t::iterator prev = it; --prev; 62 | 63 | if ((off_t) (prev->first + prev->second->size) == offset) 64 | { 65 | // Merge with previous Buffer 66 | // 67 | offset = prev->first; 68 | size += prev->second->size; 69 | Buffer *pb = prev->second; 70 | m_map.erase(prev); 71 | buffer = merge(pb, buffer); 72 | } 73 | } 74 | if (it != m_map.end()) 75 | { 76 | if (it->first == (off_t) (offset + size)) 77 | { 78 | // Merge with next Buffer 79 | // 80 | size += it->second->size; 81 | Buffer *nb = it->second; 82 | m_map.erase(it); 83 | buffer = merge(buffer, nb); 84 | } 85 | } 86 | m_map[offset] = buffer; 87 | } 88 | 89 | int LinearMap::put(const char *buf, size_t size, off_t offset) 90 | { 91 | char *tmp; 92 | off_t tmp_offset; 93 | size_t tmp_size; 94 | size_t len; 95 | size_t off; 96 | 97 | assert (size > 0); 98 | 99 | while (size > 0) 100 | { 101 | // Check if new buffer overlaps some existing 102 | // Buffers already there... 103 | // 104 | tmp_offset = get(offset, &tmp, &tmp_size); 105 | 106 | if (tmp_offset == -1) 107 | { 108 | // There is no Buffer there. Cheat and 109 | // set tmp_offset so next 'if' creates 110 | // Buffer with the 'size'. 111 | // 112 | tmp_offset = offset + size; 113 | } 114 | 115 | if (tmp_offset > offset) 116 | { 117 | // Create Buffer for offsets between 118 | // offset to tmp_offset and remember it. 119 | // 120 | len = std::min(tmp_offset - offset, (off_t) size); 121 | insert(offset, buf, len); 122 | } 123 | else 124 | { 125 | // There is already Buffer on this offset or 126 | // before (with the lenght that overlaps offset 127 | // we are looking for). 128 | // 129 | // tmp_offset 130 | // |---tmp_size---|(----------|) 131 | // offset 132 | // |---size---| 133 | 134 | // This is difference between offset we search and 135 | // offset we got... 136 | // 137 | off = (size_t) (offset - tmp_offset); 138 | len = std::min(size, tmp_size - off); 139 | memcpy(tmp + off, buf, len); 140 | } 141 | offset += len; 142 | buf += len; 143 | size -= len; 144 | } 145 | 146 | Check(); 147 | return 0; 148 | } 149 | 150 | /** 151 | * Return iterator that points to the Buffer that 152 | * covers the offset or higher offsets. 153 | */ 154 | LinearMap::con_t::const_iterator LinearMap::get(off_t offset) const 155 | { 156 | if (m_map.empty()) 157 | return m_map.end(); 158 | 159 | con_t::const_iterator it = m_map.lower_bound(offset); 160 | 161 | if (it != m_map.begin()) 162 | { 163 | // There is a block before. 164 | // 165 | --it; 166 | 167 | assert(it->second->size >= 0); 168 | if (it->first + (off_t) it->second->size > offset) 169 | { 170 | return it; 171 | } 172 | ++it; 173 | } 174 | 175 | return it; 176 | } 177 | 178 | /** 179 | * Find Buffer that covers the offset or it's start is higher than 180 | * offset. Returns it's parameters. 181 | */ 182 | off_t LinearMap::get(off_t offset, char **buf, size_t *size) const 183 | { 184 | con_t::const_iterator it; 185 | Buffer *buffer; 186 | 187 | it = get(offset); 188 | 189 | if (it == m_map.end()) 190 | return -1; 191 | 192 | buffer = it->second; 193 | 194 | *buf = buffer->buf; 195 | *size = buffer->size; 196 | 197 | return it->first; 198 | } 199 | 200 | void LinearMap::truncate(off_t size) 201 | { 202 | if (m_map.empty()) 203 | return; 204 | 205 | con_t::iterator it = m_map.lower_bound(size); 206 | 207 | // Check if previous block overlaps the required size. 208 | // 209 | if (it != m_map.begin()) 210 | { 211 | // There is a block before. 212 | // 213 | --it; 214 | 215 | assert(it->second->size >= 0); 216 | if (it->first + (off_t) it->second->size > size) 217 | { 218 | // Truncate this Buffer. 219 | // 220 | off_t off = (it->first + it->second->size) - size; 221 | 222 | Buffer *buffer = new (std::nothrow) 223 | Buffer(it->second->buf, 224 | it->second->size - off); 225 | 226 | delete it->second; 227 | 228 | // Replace old Buffer with new truncated one. 229 | // 230 | it->second = buffer; 231 | } 232 | 233 | ++it; 234 | } 235 | 236 | // Delete all Buffers after this iterator 237 | // 238 | while (it != m_map.end()) 239 | { 240 | delete it->second; 241 | m_map.erase(it++); 242 | } 243 | 244 | Check(); 245 | } 246 | 247 | bool LinearMap::erase(off_t *offset, char **buf, size_t *size, bool force) 248 | { 249 | size_t totalsize = 0; 250 | con_t::iterator it = m_map.begin(); 251 | 252 | if (force == false) 253 | { 254 | // Select the best block(s) to write down. 255 | 256 | while (it != m_map.end()) 257 | { 258 | if (it->second->size > g_BufferedMemorySize) 259 | break; 260 | totalsize += it->second->size; 261 | ++it; 262 | } 263 | 264 | if (it == m_map.end()) 265 | { 266 | if (totalsize > 2 * g_BufferedMemorySize) 267 | { 268 | it = m_map.begin(); 269 | } 270 | } 271 | } 272 | 273 | if (it != m_map.end()) 274 | { 275 | *offset = it->first; 276 | it->second->release(buf, size); 277 | delete it->second; 278 | m_map.erase(it); 279 | return true; 280 | } 281 | return false; 282 | } 283 | 284 | void LinearMap::Check() const 285 | { 286 | #ifdef NDEBUG 287 | return; 288 | #else 289 | con_t::const_iterator it; 290 | 291 | for (it = m_map.begin(); it != m_map.end(); ++it) 292 | { 293 | con_t::const_iterator ni = it; 294 | 295 | if (++ni != m_map.end()) 296 | { 297 | if (it->first + it->second->size > ni->first) 298 | { 299 | std::cout << *this << std::endl; 300 | abort(); 301 | } 302 | } 303 | } 304 | #endif 305 | } 306 | 307 | std::ostream &operator<<(std::ostream &os, const LinearMap &rLm) 308 | { 309 | boost::io::ios_flags_saver ifs(os); 310 | os << std::hex; 311 | 312 | LinearMap::con_t::const_iterator it; 313 | for (it = rLm.m_map.begin(); it != rLm.m_map.end(); ++it) 314 | { 315 | os << "offset: 0x" << it->first << ", size: 0x" << it->second->size << std::endl; 316 | } 317 | return os; 318 | } 319 | 320 | -------------------------------------------------------------------------------- /src/LinearMap.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of FuseCompress. 3 | 4 | FuseCompress is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | FuseCompress is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with FuseCompress. If not, see . 16 | */ 17 | 18 | #ifndef LinearMap_HPP 19 | #define LinearMap_HPP 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | class LinearMap 29 | { 30 | struct Buffer 31 | { 32 | Buffer(const char *buf, size_t size) { 33 | this->size = size; 34 | this->buf = new char[this->size]; 35 | memcpy(this->buf, buf, this->size); 36 | }; 37 | Buffer(const char *buf1, size_t size1, 38 | const char *buf2, size_t size2) { 39 | this->size = size1 + size2; 40 | this->buf = new char[this->size]; 41 | memcpy(this->buf, buf1, size1); 42 | memcpy(this->buf + size1, buf2, size2); 43 | }; 44 | 45 | ~Buffer() { 46 | delete[] this->buf; 47 | }; 48 | 49 | void release(char **buf, size_t *size) { 50 | *buf = this->buf; 51 | *size = this->size; 52 | this->buf = NULL; 53 | this->size = 0; 54 | } 55 | 56 | char *buf; 57 | size_t size; 58 | }; 59 | 60 | typedef std::map con_t; 61 | 62 | con_t m_map; 63 | 64 | con_t::const_iterator get(off_t offset) const; 65 | 66 | void inline Check() const; 67 | 68 | Buffer *merge(Buffer *prev, Buffer *next) const; 69 | void insert(off_t offset, const char *buf, size_t size); 70 | 71 | public: 72 | LinearMap(); 73 | ~LinearMap(); 74 | 75 | /** 76 | */ 77 | int put(const char *buf, size_t size, off_t offset); 78 | 79 | /** 80 | * Input: 81 | * @param offset 82 | * @param size 83 | * 84 | * Output: 85 | * @param buf 86 | * @param size 87 | */ 88 | off_t get(off_t offset, char **buf, size_t *size) const; 89 | 90 | /** 91 | * Block is returned only if it fits some criterias. Like 92 | * that the block is continuous and has at 93 | * least some length (eg. 1MiB). 94 | * 95 | * @param force - if true it returns block even if it doesn't fit 96 | * any criterias. 97 | * 98 | * @return true if some block is returned 99 | */ 100 | bool erase(off_t *offset, char **buf, size_t *size, bool force); 101 | 102 | bool empty() { return m_map.empty(); }; 103 | 104 | void truncate(off_t size); 105 | 106 | friend std::ostream &operator<<(std::ostream &os, const LinearMap &rLinearMap); 107 | }; 108 | 109 | #endif 110 | 111 | -------------------------------------------------------------------------------- /src/Lock.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #ifndef LOCK_H 21 | #define LOCK_H 22 | 23 | #include "Mutex.hpp" 24 | 25 | class Lock 26 | { 27 | Mutex &m_rMutex; 28 | public: 29 | Lock(Mutex &rMutex) : 30 | m_rMutex(rMutex) 31 | { 32 | m_rMutex.Lock(); 33 | } 34 | 35 | ~Lock() 36 | { 37 | m_rMutex.Unlock(); 38 | } 39 | }; 40 | 41 | #endif 42 | 43 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = fusecompress fusecompress_offline 2 | 3 | pkglib_LTLIBRARIES = libfusecompress.la 4 | 5 | common = \ 6 | boost/iostreams/filter/lzma.cpp \ 7 | CompressionType.cpp \ 8 | FileHeader.cpp \ 9 | CompressedMagic.cpp \ 10 | FileRememberTimes.cpp \ 11 | FileRememberXattrs.cpp \ 12 | FuseCompress.cpp \ 13 | File.cpp \ 14 | FileUtils.cpp \ 15 | Compress.cpp \ 16 | Memory.cpp \ 17 | FileManager.cpp \ 18 | Block.cpp \ 19 | LayerMap.cpp \ 20 | LinearMap.cpp 21 | 22 | noinst_HEADERS = \ 23 | assert.h \ 24 | boost/iostreams/device/nonclosable_file_descriptor.hpp \ 25 | boost/iostreams/filter/lzma.hpp \ 26 | boost/iostreams/filter/lzo.hpp \ 27 | boost/iostreams/filter/xor.hpp \ 28 | boost/archive/portable_oarchive.hpp \ 29 | boost/archive/portable_iarchive.hpp \ 30 | boost/integer/cover_operators.hpp \ 31 | boost/integer/endian.hpp 32 | 33 | include_HEADERS = \ 34 | CompressionType.hpp \ 35 | CompressedMagic.hpp \ 36 | FileRememberTimes.hpp \ 37 | FileRememberXattrs.hpp \ 38 | Mutex.hpp \ 39 | FuseCompress.hpp \ 40 | File.hpp \ 41 | FileUtils.hpp \ 42 | Compress.hpp \ 43 | Memory.hpp \ 44 | FileManager.hpp \ 45 | FileHeader.hpp \ 46 | Block.hpp \ 47 | LinearMap.hpp \ 48 | LayerMap.hpp \ 49 | Lock.hpp 50 | 51 | includedir = $(prefix)/include/fusecompress 52 | 53 | fusecompress_SOURCES = main.cpp 54 | fusecompress_LDADD = libfusecompress.la $(BOOST_SERIALIZATION_LIB) $(BOOST_IOSTREAMS_LIB) $(BOOST_PROGRAM_OPTIONS_LIB) $(BOOST_FILESYSTEM_LIB) $(FUSE_LIBS) 55 | fusecompress_offline_SOURCES = main_offline.cpp 56 | fusecompress_offline_LDADD = libfusecompress.la $(BOOST_SERIALIZATION_LIB) $(BOOST_IOSTREAMS_LIB) $(BOOST_PROGRAM_OPTIONS_LIB) $(BOOST_FILESYSTEM_LIB) $(BOOST_SYSTEM_LIB) $(FUSE_LIBS) 57 | 58 | libfusecompress_la_SOURCES = $(common) 59 | libfusecompress_la_LDFLAGS = -version-info 8:4:6 -no-undefined 60 | 61 | AM_CXXFLAGS=$(BOOST_CXXFLAGS) 62 | 63 | AM_LDFLAGS=$(BOOST_LDFLAGS) 64 | 65 | AM_CPPFLAGS = \ 66 | -D_GNU_SOURCE \ 67 | -D_REENTRANT \ 68 | -D_POSIX_C_SOURCE=200112L \ 69 | -D_POSIX_SOURCE \ 70 | -D_DEFAULT_SOURCE \ 71 | -D_XOPEN_SOURCE=500 \ 72 | -Wno-long-long \ 73 | -Wall \ 74 | -fpermissive 75 | 76 | dist_man_MANS = fusecompress.1 fusecompress_offline.1 77 | 78 | install-exec-hook: 79 | cd $(DESTDIR)$(bindir) && \ 80 | $(LN_S) -f fusecompress mount.fusecompress 81 | 82 | uninstall-hook: 83 | cd $(DESTDIR)$(bindir) && \ 84 | rm mount.fusecompress 85 | 86 | -------------------------------------------------------------------------------- /src/Memory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009 - 2015. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "rlog/rlog.h" 32 | #include "assert.h" 33 | 34 | #include "FileUtils.hpp" 35 | #include "Memory.hpp" 36 | #include "LinearMap.hpp" 37 | 38 | Memory::Memory(const struct stat *st, const char *name) : 39 | Parent (st, name), 40 | m_FileSize (0), 41 | m_FileSizeSet (false), 42 | m_TimeSet (false) 43 | { 44 | } 45 | 46 | Memory::~Memory() 47 | { 48 | assert (m_LinearMap.empty()); 49 | } 50 | 51 | ostream &operator<<(ostream &os, const Memory &rM) 52 | { 53 | os << "--- m_FileSize: " << rM.m_FileSize << ", m_FileSizeSet: " << rM.m_FileSizeSet << std::endl; 54 | os << "m_LinearMap: " << std::endl << rM.m_LinearMap << std::endl; 55 | os << "---" << std::endl; 56 | return os; 57 | } 58 | 59 | /** 60 | * Merge memory map with content in the file on the disk. 61 | */ 62 | int Memory::merge(const char *name) 63 | { 64 | assert(m_name == name); 65 | 66 | if (m_LinearMap.empty() == false) 67 | { 68 | int r; 69 | 70 | // There is (are) some block(s) to be written. 71 | 72 | r = write(true); 73 | if (r == -1) 74 | { 75 | rError("Memory::Merge('%s') failed with errno %d", 76 | m_name.c_str(), errno); 77 | 78 | // Error happend, don't try to continue. But also 79 | // don't forget to release allocated memory... 80 | 81 | m_LinearMap.truncate(0); 82 | 83 | m_FileSize = 0; 84 | m_FileSizeSet = false; 85 | return -1; 86 | } 87 | } 88 | 89 | // Let the upper layer know the real file size. 90 | 91 | Parent::truncate(name, m_FileSize); 92 | 93 | return 0; 94 | } 95 | 96 | int Memory::open(const char *name, int flags) 97 | { 98 | int r = Parent::open(name, flags); 99 | 100 | if ((m_refs == 1) && (m_FileSizeSet == false)) 101 | { 102 | struct stat st; 103 | 104 | int r = Parent::getattr(name, &st); 105 | if (r != 0) 106 | { 107 | rDebug("Memory::open('%s') failed with errno: %d", 108 | m_name.c_str(), errno); 109 | 110 | Parent::release(name); 111 | return -1; 112 | } 113 | m_FileSize = st.st_size; 114 | m_FileSizeSet = true; 115 | } 116 | 117 | return r; 118 | } 119 | 120 | int Memory::release(const char *name) 121 | { 122 | int rm = 0; 123 | int rp; 124 | 125 | if (m_refs == 1) 126 | { 127 | // Store all cached data in ram to file only 128 | // if this is last instance... 129 | // 130 | rm = merge(name); 131 | 132 | if (m_TimeSet == true) 133 | { 134 | m_TimeSet = false; 135 | Parent::utimens(name, m_Time); 136 | } 137 | m_FileSize = 0; 138 | m_FileSizeSet = false; 139 | } 140 | 141 | // Release lower file. 142 | // 143 | rp = Parent::release(name); 144 | 145 | // Return any error... 146 | // 147 | return rm ? rm : rp; 148 | } 149 | 150 | int Memory::unlink(const char *name) 151 | { 152 | assert(m_name == name); 153 | 154 | int r = Parent::unlink(name); 155 | if (r == 0) 156 | { 157 | // Lower file deleted, release all memory 158 | // buffers allocated so far... 159 | // 160 | m_LinearMap.truncate(0); 161 | 162 | m_FileSize = 0; 163 | m_FileSizeSet = false; 164 | } 165 | else 166 | { 167 | rDebug("Memory::unlink('%s') failed with errno: %d", 168 | m_name.c_str(), errno); 169 | } 170 | return r; 171 | } 172 | 173 | int Memory::truncate(const char *name, off_t size) 174 | { 175 | assert(m_name == name); 176 | 177 | m_TimeSet = false; 178 | 179 | int r = Parent::truncate(name, size); 180 | if (r == 0) 181 | { 182 | m_LinearMap.truncate(size); 183 | 184 | m_FileSize = size; 185 | m_FileSizeSet = true; 186 | } 187 | else 188 | { 189 | rWarning("Memory::truncate('%s', 0x%lx) failed with errno: %d", 190 | m_name.c_str(), (long int) size, errno); 191 | } 192 | return r; 193 | } 194 | 195 | int Memory::getattr(const char *name, struct stat *st) 196 | { 197 | int r = Parent::getattr(name, st); 198 | 199 | rDebug("Memory::getattr(%p) m_FileSize: 0x%lx, m_FileSizeSet: %d", 200 | (void *) this, (long int) m_FileSize, m_FileSizeSet); 201 | 202 | if (m_FileSizeSet == true) 203 | { 204 | st->st_size = m_FileSize; 205 | } 206 | 207 | return r; 208 | } 209 | 210 | int Memory::write(bool force) 211 | { 212 | char *buf; 213 | size_t size; 214 | ssize_t len; 215 | off_t offset; 216 | 217 | while (m_LinearMap.erase(&offset, &buf, &size, force) == true) 218 | { 219 | rDebug("Memory::write(bool %d) | offset: 0x%lx, size: 0x%lx", 220 | force, (unsigned long) offset, (unsigned long) size); 221 | 222 | len = Parent::write(buf, size, offset); 223 | delete[] buf; 224 | if (len == -1) 225 | return -1; 226 | } 227 | return 0; 228 | } 229 | 230 | ssize_t Memory::write(const char *buf, size_t size, off_t offset) 231 | { 232 | rDebug("Memory::write(%s) | m_FileSize: 0x%lx, size: 0x%lx, offset: 0x%lx", 233 | m_name.c_str(), (long int) m_FileSize, (long int) size, (long int) offset); 234 | 235 | m_TimeSet = false; 236 | 237 | if ((m_FileSize == offset) && FileUtils::isZeroOnly(buf, size)) 238 | { 239 | rDebug("Memory::write(%s) | Full of zeroes only", m_name.c_str()); 240 | 241 | assert(m_FileSizeSet == true); 242 | assert(size > 0); 243 | m_FileSize = offset + size; 244 | } 245 | else 246 | { 247 | // Store buffer to memory in LinearMap. 248 | // 249 | if (m_LinearMap.put(buf, size, offset) == -1) 250 | return -1; 251 | 252 | assert(m_FileSizeSet == true); 253 | assert(size > 0); 254 | m_FileSize = max(m_FileSize, (off_t) (offset + size)); 255 | 256 | // Try to write a block to disk if appropriate. 257 | // 258 | int r = write(false); 259 | if (r == -1) 260 | return r; 261 | } 262 | 263 | return size; 264 | } 265 | 266 | ssize_t Memory::readFullParent(char * &buf, size_t &len, off_t &offset) const 267 | { 268 | ssize_t r = Parent::read(buf, len, offset); 269 | 270 | rDebug("Memory::readFullParent(%s) | Parent::read(1) returned 0x%lx", 271 | m_name.c_str(), (long int) r); 272 | 273 | if (r == -1) 274 | return -1; 275 | 276 | buf += r; 277 | offset += r; 278 | len -= r; 279 | 280 | assert (m_FileSize >= offset); 281 | 282 | if (len > 0) 283 | { 284 | ssize_t tmp = min(m_FileSize - offset, (off_t) len); 285 | 286 | assert(tmp >= 0); 287 | assert((size_t) tmp <= len); 288 | 289 | memset(buf, 0, tmp); 290 | 291 | buf += tmp; 292 | offset += tmp; 293 | len -= tmp; 294 | } 295 | 296 | return 0; 297 | } 298 | 299 | ssize_t Memory::readParent(char * &buf, size_t &len, off_t &offset, off_t block_offset) const 300 | { 301 | size_t size = std::min(len, (size_t) (block_offset - offset)); 302 | size_t osize = size; 303 | 304 | ssize_t r = readFullParent(buf, size, offset); 305 | if (r == -1) 306 | return -1; 307 | 308 | assert (size == 0); 309 | len -= (osize - size); 310 | 311 | return 0; 312 | } 313 | 314 | void Memory::copyFromBlock(char * &buf, size_t &len, off_t &offset, char *block, size_t block_size, off_t block_offset) const 315 | { 316 | assert (offset >= block_offset); 317 | size_t block_loffset = offset - block_offset; 318 | assert (block_size >= block_loffset); 319 | size_t size = std::min(len, block_size - block_loffset); 320 | assert (size >= 0); 321 | 322 | memcpy(buf, block + block_loffset, size); 323 | 324 | buf += size; 325 | offset += size; 326 | len -= size; 327 | } 328 | 329 | ssize_t Memory::read(char *buf, size_t size, off_t offset) const 330 | { 331 | size_t osize = size; 332 | size_t len = size; 333 | 334 | rDebug("Memory::read(%s) | m_FileSize: 0x%lx, offset: 0x%lx, size: 0x%lx", 335 | m_name.c_str(), (long int) m_FileSize, (long int) offset, (long int) size); 336 | 337 | assert(m_FileSizeSet == true); 338 | 339 | if (offset > m_FileSize) 340 | { 341 | rDebug("Memory::read(%s) | offset > m_FileSize, return: 0x%lx", 342 | m_name.c_str(), (long int) 0); 343 | return 0; 344 | } 345 | while (len > 0) 346 | { 347 | char *block; 348 | size_t block_size; 349 | off_t block_offset = m_LinearMap.get(offset, &block, &block_size); 350 | 351 | rDebug("Memory::read(%s) | offset: 0x%lx, block_offset: 0x%lx, block_size: 0x%lx, block: %p", 352 | m_name.c_str(), (long int) offset, (long int) block_offset, (long int) block_size, block); 353 | 354 | if (block_offset == -1) 355 | { 356 | // Block not found, there isn't any block higher too. 357 | // Try to read the data form the Parent. Don't forget 358 | // to fill up with zeros to m_FileSize if Parent read 359 | // returns less. 360 | 361 | ssize_t r = readFullParent(buf, len, offset); 362 | if (r == -1) 363 | return -1; 364 | break; 365 | } 366 | 367 | if (block_offset > offset) 368 | { 369 | // Block found, but it covers higher offset. Read from the 370 | // parent. If parent returns less, fill the gap with zeros. 371 | 372 | ssize_t r = readParent(buf, len, offset, block_offset); 373 | if (r == -1) 374 | return -1; 375 | } 376 | else 377 | { 378 | // Block found, it covers the offset. Take as much as possible 379 | // from the block. 380 | 381 | copyFromBlock(buf, len, offset, block, block_size, block_offset); 382 | } 383 | } 384 | 385 | rDebug("Memory::read(%s) | return: 0x%lx", 386 | m_name.c_str(), (long int) (osize - len)); 387 | 388 | return osize - len; 389 | } 390 | 391 | int Memory::utimens(const char *name, const struct timespec tv[2]) 392 | { 393 | m_TimeSet = true; 394 | m_Time[0] = tv[0]; 395 | m_Time[1] = tv[1]; 396 | return 0; 397 | } 398 | 399 | 400 | -------------------------------------------------------------------------------- /src/Memory.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #ifndef MEMORY_HPP 21 | #define MEMORY_HPP 22 | 23 | #include "Compress.hpp" 24 | #include "LinearMap.hpp" 25 | 26 | #include 27 | 28 | typedef Compress PARENT_MEMORY; 29 | //typedef File PARENT_MEMORY; 30 | 31 | /** 32 | * Class Memory represents memory backed file. It caches any writes to 33 | * the file and stores them in the memory. Memory blocks of some minimal 34 | * determined size are continually written to the disk. 35 | */ 36 | class Memory : public PARENT_MEMORY 37 | { 38 | private: 39 | typedef PARENT_MEMORY Parent; 40 | 41 | int write(bool force); 42 | int merge(const char *name); 43 | ssize_t readFullParent(char * &buf, size_t &len, off_t &offset) const; 44 | ssize_t readParent(char * &buf, size_t &len, off_t &offset, off_t block_offset) const; 45 | void copyFromBlock(char * &buf, size_t &len, off_t &offset, char *block, size_t block_size, off_t block_offset) const; 46 | 47 | LinearMap m_LinearMap; 48 | 49 | // Length of the file as seen by the user via fuse mount point. 50 | // 51 | off_t m_FileSize; 52 | bool m_FileSizeSet; 53 | struct timespec m_Time[2]; 54 | bool m_TimeSet; 55 | public: 56 | 57 | Memory(const struct stat *st, const char *name); 58 | ~Memory(); 59 | 60 | int open(const char *name, int flags); 61 | 62 | int release(const char *name); 63 | 64 | int unlink(const char *name); 65 | 66 | int truncate(const char *name, off_t size); 67 | 68 | int getattr(const char *name, struct stat *st); 69 | 70 | ssize_t read(char *buf, size_t size, off_t offset) const; 71 | 72 | ssize_t write(const char *buf, size_t size, off_t offset); 73 | 74 | int utimens(const char *name, const struct timespec tv[2]); 75 | 76 | friend ostream &operator<<(ostream &os, const Memory &rMemory); 77 | }; 78 | 79 | #endif 80 | 81 | -------------------------------------------------------------------------------- /src/Mutex.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #ifndef MUTEX_H 21 | #define MUTEX_H 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "rlog/rlog.h" 28 | 29 | class Mutex 30 | { 31 | pthread_mutex_t m_Mutex; 32 | 33 | public: 34 | Mutex() 35 | { 36 | int r = pthread_mutex_init(&m_Mutex, NULL); 37 | if (r != 0) 38 | { 39 | rError("%s failed (%s)", __PRETTY_FUNCTION__, strerror(r)); 40 | kill(0, SIGABRT); 41 | } 42 | } 43 | 44 | ~Mutex() 45 | { 46 | int r = pthread_mutex_destroy(&m_Mutex); 47 | if (r != 0) 48 | { 49 | rError("%s failed (%s)", __PRETTY_FUNCTION__, strerror(r)); 50 | kill(0, SIGABRT); 51 | } 52 | } 53 | 54 | void Lock(void) 55 | { 56 | int r = pthread_mutex_lock(&m_Mutex); 57 | if (r != 0) 58 | { 59 | rError("%s failed (%s)", __PRETTY_FUNCTION__, strerror(r)); 60 | kill(0, SIGABRT); 61 | } 62 | } 63 | 64 | void Unlock(void) 65 | { 66 | int r = pthread_mutex_unlock(&m_Mutex); 67 | if (r != 0) 68 | { 69 | rError("%s failed (%s)", __PRETTY_FUNCTION__, strerror(r)); 70 | kill(0, SIGABRT); 71 | } 72 | } 73 | }; 74 | 75 | #endif 76 | 77 | -------------------------------------------------------------------------------- /src/assert.h: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #ifndef ASSERT_H 21 | #define ASSERT_H 22 | 23 | #include 24 | #include "rlog/rlog.h" 25 | 26 | #define assert(eval) \ 27 | if (!(eval)) { \ 28 | rError("ASSERT %s (%s)", __PRETTY_FUNCTION__, __STRING(eval)); \ 29 | abort(); \ 30 | } 31 | 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /src/boost/archive/polymorphic_portable_archive.hpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /** 3 | * \file polymorphic_portable_archive.hpp 4 | * \brief Needed for unit tests on portable archives. 5 | * \author christian.pfligersdorffer@gmx.at 6 | * 7 | * Header for testing portable archives with all of the serialization tests. 8 | * Before use copy all hpp files from this directory to your boost folder 9 | * boost_.../libs/serialization/test and run from there a visual studio 10 | * prompt with b2 oder bjam -sBOOST_ARCHIVE_LIST=portable_archive.hpp 11 | * 12 | * \note Since portable archives version 5.0 we depend on program_options! 13 | * Edit libs/serialization/test/Jamfile.v2 and change the requirements to 14 | * : requirements /boost/filesystem /boost/program_options 15 | */ 16 | /****************************************************************************/ 17 | 18 | #pragma warning( disable:4217 4127 4310 4244 4800 4267 ) 19 | 20 | // text_archive test header 21 | // include output archive header 22 | #include "portable_oarchive.hpp" 23 | // set name of test output archive 24 | typedef eos::polymorphic_portable_oarchive test_oarchive; 25 | // set name of test output stream 26 | typedef std::ofstream test_ostream; 27 | 28 | // repeat the above for input archive 29 | #include "portable_iarchive.hpp" 30 | typedef eos::polymorphic_portable_iarchive test_iarchive; 31 | typedef std::ifstream test_istream; 32 | 33 | // define open mode for streams 34 | // binary archives should use std::ios_base::binary 35 | #define TEST_STREAM_FLAGS std::ios_base::binary 36 | -------------------------------------------------------------------------------- /src/boost/archive/portable_archive.hpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /** 3 | * \file portable_archive.hpp 4 | * \brief Needed for unit tests on portable archives. 5 | * \author christian.pfligersdorffer@gmx.at 6 | * 7 | * Header for testing portable archives with all of the serialization tests. 8 | * Before use copy all hpp files from this directory to your boost folder 9 | * boost_.../libs/serialization/test and run from there a visual studio 10 | * prompt with b2 oder bjam -sBOOST_ARCHIVE_LIST=portable_archive.hpp 11 | * 12 | * \note Since portable archives version 5.0 we depend on program_options! 13 | * Edit libs/serialization/test/Jamfile.v2 and change the requirements to 14 | * : requirements /boost/filesystem /boost/program_options 15 | */ 16 | /****************************************************************************/ 17 | 18 | #pragma warning( disable:4217 4127 4310 4244 4800 4267 ) 19 | 20 | // text_archive test header 21 | // include output archive header 22 | #include "portable_oarchive.hpp" 23 | // set name of test output archive 24 | typedef eos::portable_oarchive test_oarchive; 25 | // set name of test output stream 26 | typedef std::ofstream test_ostream; 27 | 28 | // repeat the above for input archive 29 | #include "portable_iarchive.hpp" 30 | typedef eos::portable_iarchive test_iarchive; 31 | typedef std::ifstream test_istream; 32 | 33 | // define open mode for streams 34 | // binary archives should use std::ios_base::binary 35 | #define TEST_STREAM_FLAGS std::ios_base::binary 36 | -------------------------------------------------------------------------------- /src/boost/archive/portable_archive_exception.hpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /** 3 | * \file portable_archive_exception.hpp 4 | * \brief Provides error handling and constants. 5 | * \author christian.pfligersdorffer@gmx.at 6 | * 7 | * Portable archive exceptions derive from the boost archive exceptions 8 | * and add failure causes specific to the portable binary usecase. 9 | * 10 | * Additionally this header serves as common include for important 11 | * constants or typedefs. 12 | */ 13 | /****************************************************************************/ 14 | 15 | #pragma once 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | namespace eos { 22 | 23 | // this value is written to the top of the stream 24 | const signed char magic_byte = 'e' | 'o' | 's'; 25 | 26 | // flag for fp serialization 27 | const unsigned no_infnan = 64; 28 | 29 | // integral type for the archive version 30 | #if BOOST_VERSION < 104400 31 | typedef boost::archive::version_type archive_version_type; 32 | #else 33 | typedef boost::archive::library_version_type archive_version_type; 34 | #endif 35 | 36 | // version of the linked boost archive library 37 | const archive_version_type archive_version( 38 | #if BOOST_VERSION < 103700 39 | boost::archive::ARCHIVE_VERSION() 40 | #else 41 | boost::archive::BOOST_ARCHIVE_VERSION() 42 | #endif 43 | ); 44 | 45 | /** 46 | * \brief Exception being thrown when serialization cannot proceed. 47 | * 48 | * There are several situations in which the portable archives may fail and 49 | * hence throw an exception: 50 | * -# deserialization of an integer value that exceeds the range of the type 51 | * -# (de)serialization of inf/nan through an archive with no_infnan flag set 52 | * -# deserialization of a denormalized value without the floating point type 53 | * supporting denormalized numbers 54 | * 55 | * Note that this exception will also be thrown if you mixed up your stream 56 | * position and accidentially interpret some value for size data (in this case 57 | * the reported size will be totally amiss most of the time). 58 | */ 59 | class portable_archive_exception : public boost::archive::archive_exception 60 | { 61 | std::string msg; 62 | 63 | public: 64 | //! type size is not large enough for deserialized number 65 | portable_archive_exception(signed char invalid_size) 66 | : boost::archive::archive_exception(other_exception) 67 | , msg("requested integer size exceeds type size: ") 68 | { 69 | msg += boost::lexical_cast(invalid_size); 70 | } 71 | 72 | //! negative number in unsigned type 73 | portable_archive_exception() 74 | : boost::archive::archive_exception(other_exception) 75 | , msg("cannot read a negative number into an unsigned type") 76 | { 77 | } 78 | 79 | //! serialization of inf, nan and denormals 80 | template 81 | portable_archive_exception(const T& abnormal) 82 | : boost::archive::archive_exception(other_exception) 83 | , msg("serialization of illegal floating point value: ") 84 | { 85 | msg += boost::lexical_cast(abnormal); 86 | } 87 | 88 | //! override the base class function with our message 89 | const char* what() const throw() { return msg.c_str(); } 90 | ~portable_archive_exception() throw() {} 91 | }; 92 | 93 | } // namespace eos 94 | -------------------------------------------------------------------------------- /src/boost/integer/cover_operators.hpp: -------------------------------------------------------------------------------- 1 | // boost/integer/cover_operators.hpp ----------------------------------------// 2 | 3 | // (C) Copyright Darin Adler 2000 4 | 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | //----------------------------------------------------------------------------// 9 | 10 | #ifndef BOOST_INTEGER_COVER_OPERATORS_HPP 11 | #define BOOST_INTEGER_COVER_OPERATORS_HPP 12 | 13 | #include 14 | #include 15 | 16 | namespace boost 17 | { 18 | namespace integer 19 | { 20 | 21 | // A class that adds integer operators to an integer cover class 22 | 23 | template 24 | class cover_operators : boost::operators 25 | { 26 | // The other operations take advantage of the type conversion that's 27 | // built into unary +. 28 | 29 | // Unary operations. 30 | friend IntegerType operator+(const T& x) { return x; } 31 | friend IntegerType operator-(const T& x) { return -+x; } 32 | friend IntegerType operator~(const T& x) { return ~+x; } 33 | friend IntegerType operator!(const T& x) { return !+x; } 34 | 35 | // The basic ordering operations. 36 | friend bool operator==(const T& x, IntegerType y) { return +x == y; } 37 | friend bool operator<(const T& x, IntegerType y) { return +x < y; } 38 | 39 | // The basic arithmetic operations. 40 | friend T& operator+=(T& x, IntegerType y) { return x = +x + y; } 41 | friend T& operator-=(T& x, IntegerType y) { return x = +x - y; } 42 | friend T& operator*=(T& x, IntegerType y) { return x = +x * y; } 43 | friend T& operator/=(T& x, IntegerType y) { return x = +x / y; } 44 | friend T& operator%=(T& x, IntegerType y) { return x = +x % y; } 45 | friend T& operator&=(T& x, IntegerType y) { return x = +x & y; } 46 | friend T& operator|=(T& x, IntegerType y) { return x = +x | y; } 47 | friend T& operator^=(T& x, IntegerType y) { return x = +x ^ y; } 48 | friend T& operator<<=(T& x, IntegerType y) { return x = +x << y; } 49 | friend T& operator>>=(T& x, IntegerType y) { return x = +x >> y; } 50 | 51 | // A few binary arithmetic operations not covered by operators base class. 52 | friend IntegerType operator<<(const T& x, IntegerType y) { return +x << y; } 53 | friend IntegerType operator>>(const T& x, IntegerType y) { return +x >> y; } 54 | 55 | // Auto-increment and auto-decrement can be defined in terms of the 56 | // arithmetic operations. 57 | friend T& operator++(T& x) { return x += 1; } 58 | friend T& operator--(T& x) { return x -= 1; } 59 | 60 | /// TODO: stream I/O needs to be templatized on the stream type, so will 61 | /// work with wide streams, etc. 62 | 63 | // Stream input and output. 64 | friend std::ostream& operator<<(std::ostream& s, const T& x) 65 | { return s << +x; } 66 | friend std::istream& operator>>(std::istream& s, T& x) 67 | { 68 | IntegerType i; 69 | if (s >> i) 70 | x = i; 71 | return s; 72 | } 73 | }; 74 | } // namespace integer 75 | } // namespace boost 76 | 77 | #endif // BOOST_INTEGER_COVER_OPERATORS_HPP 78 | -------------------------------------------------------------------------------- /src/boost/iostreams/device/nonclosable_file_descriptor.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Milan Svoboda 2009. 2 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 3 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) 4 | 5 | // See http://www.boost.org/libs/iostreams for documentation. 6 | 7 | #ifndef NONCLOSABLE_FILE_DESCRIPTOR_HPP 8 | #define NONCLOSABLE_FILE_DESCRIPTOR_HPP 9 | 10 | #include 11 | #include 12 | 13 | namespace boost { namespace iostreams { 14 | 15 | #if BOOST_VERSION < 104400 16 | static const bool never_close_handle = false; 17 | #endif 18 | 19 | class BOOST_IOSTREAMS_DECL nonclosable_file_descriptor : public file_descriptor { 20 | public: 21 | struct category 22 | : seekable_device_tag 23 | { }; 24 | 25 | nonclosable_file_descriptor() : file_descriptor() { } 26 | explicit nonclosable_file_descriptor(int fd) 27 | : file_descriptor(fd, boost::iostreams::never_close_handle) 28 | { } 29 | #ifdef BOOST_IOSTREAMS_WINDOWS 30 | explicit nonclosable_file_descriptor(handle_type handle) 31 | : file_descriptor(handle, boost::iostreams::never_close_handle) 32 | { } 33 | #endif 34 | explicit nonclosable_file_descriptor( const std::string& path, 35 | BOOST_IOS::openmode mode = 36 | BOOST_IOS::in | BOOST_IOS::out ) 37 | : file_descriptor(path, mode) {} 38 | }; 39 | 40 | } } 41 | 42 | #endif 43 | 44 | -------------------------------------------------------------------------------- /src/boost/iostreams/filter/bytescounter.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Milan Svoboda 2009. 2 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 3 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) 4 | 5 | // See http://www.boost.org/libs/iostreams for documentation. 6 | 7 | #ifndef BOOST_IOSTREAMS_BYTESCOUNTER_HPP_INCLUDED 8 | #define BOOST_IOSTREAMS_BYTESCOUNTER_HPP_INCLUDED 9 | 10 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) 11 | # pragma once 12 | #endif 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | // Must come last. 20 | #include // VC7.1 C4244. 21 | 22 | namespace boost { namespace iostreams { 23 | 24 | // 25 | // Template name: basic_counter. 26 | // Template paramters: 27 | // Ch - The character type. 28 | // Description: Filter which counts . 29 | // 30 | template 31 | class basic_bytescounter { 32 | public: 33 | typedef Ch char_type; 34 | struct category 35 | : dual_use, 36 | filter_tag, 37 | multichar_tag 38 | { }; 39 | explicit basic_bytescounter(int bytes = 0) 40 | : bytes_(bytes) 41 | { } 42 | int bytes() const { return bytes_; } 43 | 44 | template 45 | std::streamsize read(Source& src, char_type* s, std::streamsize n) 46 | { 47 | std::streamsize result = iostreams::read(src, s, n); 48 | if (result == -1) 49 | return -1; 50 | bytes_ += result; 51 | return result; 52 | } 53 | 54 | template 55 | std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) 56 | { 57 | std::streamsize result = iostreams::write(snk, s, n); 58 | bytes_ += result; 59 | return result; 60 | } 61 | private: 62 | int bytes_; 63 | }; 64 | BOOST_IOSTREAMS_PIPABLE(basic_bytescounter, 1) 65 | 66 | 67 | typedef basic_bytescounter bytescounter; 68 | 69 | } } // End namespaces iostreams, boost. 70 | 71 | #include 72 | 73 | #endif // #ifndef BOOST_IOSTREAMS_BYTESCOUNTER_HPP_INCLUDED 74 | -------------------------------------------------------------------------------- /src/boost/iostreams/filter/lzma.cpp: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | // Test for presence of lzma library on the system. 4 | // 5 | // Do it simple this way until I figure out how to 6 | // change the Makefile.am to not build this file when 7 | // lzma library is not present on the system. 8 | 9 | #ifdef HAVE_LIBLZMA 10 | 11 | // (C) Copyright Jonathan Turkanis 2003. 12 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 13 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) 14 | 15 | // See http://www.boost.org/libs/iostreams for documentation. 16 | 17 | // Define BOOST_IOSTREAMS_SOURCE so that 18 | // knows that we are building the library (possibly exporting code), rather 19 | // than using it (possibly importing code). 20 | #define BOOST_IOSTREAMS_SOURCE 21 | 22 | #include 23 | #include 24 | 25 | namespace boost { namespace iostreams { 26 | 27 | namespace lzma { 28 | 29 | // Compression levels 30 | 31 | const uint32_t no_compression = 0; 32 | const uint32_t best_speed = 1; 33 | const uint32_t best_compression = 9; 34 | const uint32_t default_compression = 2; 35 | 36 | // Status codes 37 | 38 | const int okay = LZMA_OK; 39 | const int stream_end = LZMA_STREAM_END; 40 | const int unsupported_check = LZMA_UNSUPPORTED_CHECK; 41 | const int mem_error = LZMA_MEM_ERROR; 42 | const int options_error = LZMA_OPTIONS_ERROR; 43 | const int data_error = LZMA_DATA_ERROR; 44 | const int buf_error = LZMA_BUF_ERROR; 45 | const int prog_error = LZMA_PROG_ERROR; 46 | 47 | // Flush codes 48 | 49 | const lzma_action finish = LZMA_FINISH; 50 | const lzma_action full_flush = LZMA_FULL_FLUSH; 51 | const lzma_action sync_flush = LZMA_SYNC_FLUSH; 52 | const lzma_action run = LZMA_RUN; 53 | 54 | // Code for current OS 55 | 56 | } // End namespace lzma. 57 | 58 | //------------------Implementation of lzma_error------------------------------// 59 | 60 | lzma_error::lzma_error(int error) 61 | : BOOST_IOSTREAMS_FAILURE("lzma error"), error_(error) 62 | { } 63 | 64 | void lzma_error::check(int error) 65 | { 66 | switch (error) { 67 | case LZMA_OK: 68 | case LZMA_STREAM_END: 69 | return; 70 | case LZMA_MEM_ERROR: 71 | throw std::bad_alloc(); 72 | default: 73 | throw lzma_error(error); 74 | } 75 | } 76 | 77 | //------------------Implementation of lzma_base-------------------------------// 78 | 79 | namespace detail { 80 | 81 | lzma_base::lzma_base() 82 | : stream_(new lzma_stream), calculate_crc_(false), crc_(0) 83 | { } 84 | 85 | lzma_base::~lzma_base() { delete static_cast(stream_); } 86 | 87 | void lzma_base::before( const char*& src_begin, const char* src_end, 88 | char*& dest_begin, char* dest_end ) 89 | { 90 | lzma_stream* s = static_cast(stream_); 91 | s->next_in = reinterpret_cast(const_cast(src_begin)); 92 | s->avail_in = static_cast(src_end - src_begin); 93 | s->next_out = reinterpret_cast(dest_begin); 94 | s->avail_out= static_cast(dest_end - dest_begin); 95 | } 96 | 97 | void lzma_base::after(const char*& src_begin, char*& dest_begin, bool compress) 98 | { 99 | lzma_stream* s = static_cast(stream_); 100 | total_in_ = s->total_in; 101 | total_out_ = s->total_out; 102 | src_begin = const_cast(reinterpret_cast(s->next_in)); 103 | dest_begin = reinterpret_cast(s->next_out); 104 | } 105 | 106 | int lzma_base::deflate(lzma_action action) 107 | { 108 | return lzma_code(static_cast(stream_), action); 109 | } 110 | 111 | int lzma_base::inflate(lzma_action action) 112 | { 113 | return lzma_code(static_cast(stream_), action); 114 | } 115 | 116 | void lzma_base::reset(bool compress, bool realloc) 117 | { 118 | lzma_stream* s = static_cast(stream_); 119 | if (realloc) 120 | lzma_error::check(lzma_code(s, lzma::full_flush)); 121 | else 122 | lzma_end(s); 123 | } 124 | 125 | void lzma_base::do_init 126 | ( const lzma_params& p, bool compress, 127 | #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) 128 | lzma::alloc_func alloc, lzma::free_func free, 129 | #endif 130 | void* derived ) 131 | { 132 | lzma_stream* s = static_cast(stream_); 133 | 134 | memset(s, 0, sizeof(*s)); 135 | 136 | lzma_error::check( 137 | compress ? 138 | lzma_easy_encoder(s, p.level, LZMA_CHECK_CRC32) : 139 | lzma_stream_decoder(s, 100 * 1024 * 1024, 0 ) 140 | ); 141 | } 142 | 143 | } // End namespace detail. 144 | 145 | //----------------------------------------------------------------------------// 146 | 147 | } } // End namespaces iostreams, boost. 148 | 149 | #endif 150 | 151 | -------------------------------------------------------------------------------- /src/boost/iostreams/filter/lzo.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Milan Svoboda 2009. 2 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 3 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) 4 | 5 | // See http://www.boost.org/libs/iostreams for documentation. 6 | 7 | #ifndef LZO_FILTER_HPP 8 | #define LZO_FILTER_HPP 9 | 10 | #include 11 | 12 | #define HEAP_ALLOC(var,size) \ 13 | lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] 14 | 15 | #include 16 | 17 | namespace boost { namespace iostreams { 18 | 19 | template< typename Ch, typename Alloc = std::allocator > 20 | class basic_lzo_compressor : public boost::iostreams::aggregate_filter 21 | { 22 | private: 23 | 24 | typedef boost::iostreams::aggregate_filter base_type; 25 | 26 | public: 27 | 28 | typedef typename base_type::char_type char_type; 29 | typedef typename base_type::category category; 30 | typedef std::basic_string string_type; 31 | 32 | public: 33 | 34 | basic_lzo_compressor() 35 | { } 36 | 37 | private: 38 | 39 | typedef typename base_type::vector_type vector_type; 40 | 41 | void do_filter(const vector_type& src, vector_type& dest) 42 | { 43 | lzo_uint len = src.size() + src.size() / 16 + 64 + 3; 44 | 45 | HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); 46 | vector_type tmp(len); 47 | 48 | lzo1x_1_compress((lzo_bytep) &src[0], src.size(), 49 | (lzo_bytep) &tmp[0], &len, wrkmem); 50 | 51 | dest.reserve(len); 52 | for (unsigned int i = 0; i < len; ++i) 53 | dest.push_back(tmp[i]); 54 | } 55 | 56 | private: 57 | 58 | }; 59 | 60 | BOOST_IOSTREAMS_PIPABLE(basic_lzo_compressor, 1) 61 | 62 | typedef basic_lzo_compressor lzo_compressor; 63 | typedef basic_lzo_compressor wlzo_compressor; 64 | 65 | // 66 | 67 | template< typename Ch, typename Alloc = std::allocator > 68 | class basic_lzo_decompressor : public boost::iostreams::aggregate_filter 69 | { 70 | private: 71 | 72 | typedef boost::iostreams::aggregate_filter base_type; 73 | 74 | public: 75 | 76 | typedef typename base_type::char_type char_type; 77 | typedef typename base_type::category category; 78 | typedef std::basic_string string_type; 79 | 80 | public: 81 | 82 | basic_lzo_decompressor() 83 | { } 84 | 85 | private: 86 | 87 | typedef typename base_type::vector_type vector_type; 88 | 89 | void do_filter(const vector_type& src, vector_type& dest) 90 | { 91 | vector_type tmp; 92 | lzo_uint len; 93 | int compressionFactor = 10; 94 | 95 | while (true) 96 | { 97 | len = src.size() * compressionFactor; 98 | tmp.assign(len, 0); 99 | 100 | if (lzo1x_decompress_safe((lzo_bytep) &src[0], src.size(), 101 | (lzo_bytep) &tmp[0], &len, NULL) == LZO_E_OUTPUT_OVERRUN) 102 | { 103 | compressionFactor *= 2; 104 | continue; 105 | } 106 | break; 107 | } 108 | 109 | dest.assign(len, 0); 110 | for (unsigned int i = 0; i < len; ++i) 111 | dest[i] = tmp[i]; 112 | } 113 | 114 | private: 115 | 116 | }; 117 | 118 | BOOST_IOSTREAMS_PIPABLE(basic_lzo_decompressor, 1) 119 | 120 | typedef basic_lzo_decompressor lzo_decompressor; 121 | typedef basic_lzo_decompressor wlzo_decompressor; 122 | 123 | 124 | } } 125 | 126 | #endif 127 | 128 | -------------------------------------------------------------------------------- /src/boost/iostreams/filter/xor.hpp: -------------------------------------------------------------------------------- 1 | // (C) Copyright Milan Svoboda 2009. 2 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 3 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) 4 | 5 | // See http://www.boost.org/libs/iostreams for documentation. 6 | 7 | #ifndef XOR_FILTER_HPP 8 | #define XOR_FILTER_HPP 9 | 10 | #include 11 | 12 | namespace boost { namespace iostreams { 13 | 14 | template< typename Ch, typename Alloc = std::allocator > 15 | class basic_xor_filter : public boost::iostreams::aggregate_filter 16 | { 17 | private: 18 | 19 | typedef boost::iostreams::aggregate_filter base_type; 20 | 21 | public: 22 | 23 | typedef typename base_type::char_type char_type; 24 | typedef typename base_type::category category; 25 | typedef std::basic_string string_type; 26 | 27 | public: 28 | 29 | basic_xor_filter(Ch key) 30 | : key_(key) 31 | { } 32 | 33 | private: 34 | 35 | typedef typename base_type::vector_type vector_type; 36 | 37 | void do_filter(const vector_type& src, vector_type& dest) 38 | { 39 | for (size_t i = 0; i < src.size(); ++i) { 40 | dest.push_back(src[i] ^ key_); 41 | } 42 | } 43 | 44 | private: 45 | 46 | Ch key_; 47 | }; 48 | 49 | BOOST_IOSTREAMS_PIPABLE(basic_xor_filter, 1) 50 | 51 | typedef basic_xor_filter xor_filter; 52 | typedef basic_xor_filter wxor_filter; 53 | 54 | } } 55 | 56 | #endif 57 | 58 | -------------------------------------------------------------------------------- /src/boost/math/fpclassify.hpp: -------------------------------------------------------------------------------- 1 | // fpclassify.hpp 2 | 3 | #ifndef BOOST_MATH_FPCLASSIFY_HPP 4 | #define BOOST_MATH_FPCLASSIFY_HPP 5 | 6 | // Copyright (c) 2006 Johan Rade 7 | 8 | // Distributed under the Boost Software License, Version 1.0. 9 | // (See accompanying file LICENSE_1_0.txt 10 | // or copy at http://www.boost.org/LICENSE_1_0.txt) 11 | 12 | /* 13 | The following algorithm is used: 14 | 15 | If all exponent bits, the flag bit (if there is one), 16 | and all mantissa bits are 0, then the number is zero. 17 | 18 | If all exponent bits and the flag bit (if there is one) are 0, 19 | and at least one mantissa bit is 1, then the number is subnormal. 20 | 21 | If all exponent bits are 1 and all mantissa bits are 0, 22 | then the number is infinity. 23 | 24 | If all exponent bits are 1 and at least one mantissa bit is 1, 25 | then the number is a not-a-number. 26 | 27 | Otherwise the number is normal. 28 | 29 | (Note that the binary representation of infinity 30 | has flag bit 0 for Motorola 68K extended double precision, 31 | and flag bit 1 for Intel extended double precision.) 32 | 33 | To get the bits, the four or eight most significant bytes are copied 34 | into an uint32_t or uint64_t and bit masks are applied. 35 | This covers all the exponent bits and the flag bit (if there is one), 36 | but not always all the mantissa bits. 37 | Some of the functions below have two implementations, 38 | depending on whether all the mantissa bits are copied or not. 39 | */ 40 | 41 | #include 42 | 43 | #ifndef FP_INFINITE 44 | # define FP_INFINITE 0 45 | # define FP_NAN 1 46 | # define FP_NORMAL 2 47 | # define FP_SUBNORMAL 3 48 | # define FP_ZERO 4 49 | #endif 50 | 51 | #include "detail/fp_traits.hpp" 52 | 53 | namespace boost { 54 | namespace math { 55 | 56 | //------------------------------------------------------------------------------ 57 | 58 | template bool (isfinite)(T x) 59 | { 60 | typedef BOOST_DEDUCED_TYPENAME detail::fp_traits::type traits; 61 | traits::init(); 62 | 63 | BOOST_DEDUCED_TYPENAME traits::bits a; 64 | traits::get_bits(x,a); 65 | a &= traits::exponent; 66 | return a != traits::exponent; 67 | } 68 | 69 | //------------------------------------------------------------------------------ 70 | 71 | template bool (isnormal)(T x) 72 | { 73 | typedef BOOST_DEDUCED_TYPENAME detail::fp_traits::type traits; 74 | traits::init(); 75 | 76 | BOOST_DEDUCED_TYPENAME traits::bits a; 77 | traits::get_bits(x,a); 78 | a &= traits::exponent | traits::flag; 79 | return (a != 0) && (a < traits::exponent); 80 | } 81 | 82 | //------------------------------------------------------------------------------ 83 | 84 | namespace detail { 85 | 86 | template bool isinf_impl(T x, all_bits) 87 | { 88 | typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; 89 | 90 | BOOST_DEDUCED_TYPENAME traits::bits a; 91 | traits::get_bits(x,a); 92 | a &= traits::exponent | traits::mantissa; 93 | return a == traits::exponent; 94 | } 95 | 96 | template bool isinf_impl(T x, not_all_bits) 97 | { 98 | typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; 99 | 100 | BOOST_DEDUCED_TYPENAME traits::bits a; 101 | traits::get_bits(x,a); 102 | a &= traits::exponent | traits::mantissa; 103 | if(a != traits::exponent) 104 | return false; 105 | 106 | traits::set_bits(x,0); 107 | return x == 0; 108 | } 109 | 110 | } // namespace detail 111 | 112 | template bool (isinf)(T x) 113 | { 114 | typedef BOOST_DEDUCED_TYPENAME detail::fp_traits::type traits; 115 | traits::init(); 116 | return detail::isinf_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage()); 117 | } 118 | 119 | //------------------------------------------------------------------------------ 120 | 121 | namespace detail { 122 | 123 | template bool isnan_impl(T x, all_bits) 124 | { 125 | typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; 126 | traits::init(); 127 | 128 | BOOST_DEDUCED_TYPENAME traits::bits a; 129 | traits::get_bits(x,a); 130 | a &= traits::exponent | traits::mantissa; 131 | return a > traits::exponent; 132 | } 133 | 134 | template bool isnan_impl(T x, not_all_bits) 135 | { 136 | typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; 137 | traits::init(); 138 | 139 | BOOST_DEDUCED_TYPENAME traits::bits a; 140 | traits::get_bits(x,a); 141 | 142 | a &= traits::exponent | traits::mantissa; 143 | if(a < traits::exponent) 144 | return false; 145 | 146 | a &= traits::mantissa; 147 | traits::set_bits(x,a); 148 | return x != 0; 149 | } 150 | 151 | } // namespace detail 152 | 153 | template bool (isnan)(T x) 154 | { 155 | typedef BOOST_DEDUCED_TYPENAME detail::fp_traits::type traits; 156 | traits::init(); 157 | return detail::isnan_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage()); 158 | } 159 | 160 | //------------------------------------------------------------------------------ 161 | 162 | namespace detail { 163 | 164 | template int fpclassify_impl(T x, all_bits) 165 | { 166 | typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; 167 | 168 | BOOST_DEDUCED_TYPENAME traits::bits a; 169 | traits::get_bits(x,a); 170 | a &= traits::exponent | traits::flag | traits::mantissa; 171 | 172 | if(a <= traits::mantissa) { 173 | if(a == 0) 174 | return FP_ZERO; 175 | else 176 | return FP_SUBNORMAL; 177 | } 178 | 179 | if(a < traits::exponent) 180 | return FP_NORMAL; 181 | 182 | a &= traits::mantissa; 183 | if(a == 0) 184 | return FP_INFINITE; 185 | 186 | return FP_NAN; 187 | } 188 | 189 | template int fpclassify_impl(T x, not_all_bits) 190 | { 191 | typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; 192 | 193 | BOOST_DEDUCED_TYPENAME traits::bits a; 194 | traits::get_bits(x,a); 195 | a &= traits::exponent | traits::flag | traits::mantissa; 196 | 197 | if(a <= traits::mantissa) { 198 | if(x == 0) 199 | return FP_ZERO; 200 | else 201 | return FP_SUBNORMAL; 202 | } 203 | 204 | if(a < traits::exponent) 205 | return FP_NORMAL; 206 | 207 | a &= traits::mantissa; 208 | traits::set_bits(x,a); 209 | if(x == 0) 210 | return FP_INFINITE; 211 | 212 | return FP_NAN; 213 | } 214 | 215 | } // namespace detail 216 | 217 | template int (fpclassify)(T x) 218 | { 219 | typedef BOOST_DEDUCED_TYPENAME detail::fp_traits::type traits; 220 | traits::init(); 221 | return detail::fpclassify_impl(x, BOOST_DEDUCED_TYPENAME traits::coverage()); 222 | } 223 | 224 | //------------------------------------------------------------------------------ 225 | 226 | } // namespace math 227 | } // namespace boost 228 | 229 | #endif 230 | -------------------------------------------------------------------------------- /src/boost/math/signbit.hpp: -------------------------------------------------------------------------------- 1 | // signbit.hpp 2 | 3 | #ifndef BOOST_MATH_SIGNBIT_HPP 4 | #define BOOST_MATH_SIGNBIT_HPP 5 | 6 | // Copyright (c) 2006 Johan Rade 7 | 8 | // Distributed under the Boost Software License, Version 1.0. 9 | // (See accompanying file LICENSE_1_0.txt 10 | // or copy at http://www.boost.org/LICENSE_1_0.txt) 11 | 12 | #include "detail/fp_traits.hpp" 13 | 14 | namespace boost { 15 | namespace math { 16 | 17 | //------------------------------------------------------------------------------ 18 | 19 | template bool (signbit)(T x) 20 | { 21 | typedef BOOST_DEDUCED_TYPENAME detail::fp_traits::type traits; 22 | traits::init(); 23 | 24 | BOOST_DEDUCED_TYPENAME traits::bits a; 25 | traits::get_bits(x,a); 26 | a &= traits::sign; 27 | return a != 0; 28 | } 29 | 30 | //------------------------------------------------------------------------------ 31 | 32 | namespace detail { 33 | 34 | template T copysign_impl(T x, T y) 35 | { 36 | typedef BOOST_DEDUCED_TYPENAME fp_traits::type traits; 37 | traits::init(); 38 | 39 | BOOST_DEDUCED_TYPENAME traits::bits a; 40 | traits::get_bits(x,a); 41 | a &= ~traits::sign; 42 | 43 | BOOST_DEDUCED_TYPENAME traits::bits b; 44 | traits::get_bits(y,b); 45 | b &= traits::sign; 46 | 47 | traits::set_bits(x,a|b); 48 | return x; 49 | } 50 | } 51 | 52 | inline float (copysign)(float x, float y) // magnitude of x and sign of y 53 | { 54 | return detail::copysign_impl(x,y); 55 | } 56 | 57 | inline double (copysign)(double x, double y) 58 | { 59 | return detail::copysign_impl(x,y); 60 | } 61 | 62 | inline long double (copysign)(long double x, long double y) 63 | { 64 | return detail::copysign_impl(x,y); 65 | } 66 | 67 | //------------------------------------------------------------------------------ 68 | 69 | template T (changesign)(T x) 70 | { 71 | typedef BOOST_DEDUCED_TYPENAME detail::fp_traits::type traits; 72 | traits::init(); 73 | 74 | BOOST_DEDUCED_TYPENAME traits::bits a; 75 | traits::get_bits(x,a); 76 | a ^= traits::sign; 77 | traits::set_bits(x,a); 78 | return x; 79 | } 80 | 81 | //------------------------------------------------------------------------------ 82 | 83 | } // namespace math 84 | } // namespace boost 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/fusecompress.1: -------------------------------------------------------------------------------- 1 | .de Vb \" Begin verbatim text 2 | .ft CW 3 | .nf 4 | .ne \\$1 5 | .. 6 | .de Ve \" End verbatim text 7 | .ft R 8 | .fi 9 | .. 10 | .TH FUSECOMPRESS 1 "2008-06-06" "1.99.16" "Compressed filesystem" 11 | .SH NAME 12 | fusecompress \- mounts an compressed virtual filesystem 13 | .SH SYNOPSIS 14 | .B fusecompress [OPTION]... rootDir mountPoint 15 | .SH DESCRIPTION 16 | FuseCompress creates a virtual compressed filesystem which stores compressed data in the rootDir directory and makes the uncompressed data visible at the mountPoint directory. 17 | 18 | Compression type (or uncompressed state) of files in the rootDir is not changed during work. Use fusecompress_offline if you want to decompress file(s) or change compression type of the file(s). 19 | 20 | .B Examples: 21 | 22 | Storage directory is /tmp/fc and mount point is /mnt/fc in all following examples. 23 | 24 | o Mount directory 25 | 26 | fusecompress /tmp/fc /mnt/fc 27 | 28 | o Unmount directory 29 | 30 | fusermount \-u /mnt/fc 31 | 32 | .B Tips and tricks: 33 | 34 | How to obtain compression ratio? 35 | 36 | o Run this command in the mountPoint directory when mounted with FuseCompress: 37 | 38 | .Vb 2 39 | du \-sh # actual size on disk 40 | du \-sh \-\-apparent-size # actual size of files 41 | .Ve 42 | 43 | .B File and magic utilities: 44 | 45 | Put this config into ~/.magic or /etc/magic file to allow file utility recognize FuseCompress file format: 46 | 47 | .Vb 8 48 | \& 0 string \\037\\135\\211 FuseCompress(ed) data 49 | .Ve 50 | 51 | .SH OPTIONS 52 | .TP 53 | .B \-h, \-\-help 54 | Prints help. 55 | .TP 56 | .B \-v, \-\-version 57 | Prints version. 58 | .TP 59 | .B \-o, \-\-options 60 | 61 | .B fc_c:arg 62 | set compression method (lzo/bzip2/zlib/lzma) (default:zlib) 63 | 64 | .B fc_b:arg 65 | set size of the blocks in kilobytes (default:100) 66 | 67 | .B fc_d 68 | run in debug mode 69 | 70 | .B fc_ma:"arg1;arg2" 71 | files with passed mime types to be always not compressed 72 | 73 | .B fc_mr:"arg1;arg2" 74 | files with passed mime types to be always compressed 75 | 76 | Other options are passed directly to the fuse library. See fuse documentation for full list of supported options. 77 | 78 | Useful parameters for fuse library: 79 | 80 | Fuse library must be configured to support this features - configuration file /etc/fuse.conf must contains at least this option: user_allow_other. 81 | 82 | .B allow_other 83 | 84 | This option overrides the security measure restricting file access to the user mounting the filesystem. So all users (including root) can access the files. This option is by default only allowed to root, but this restriction can be removed with a configuration option described in the previous section. 85 | 86 | .B allow_root 87 | 88 | This option is similar to 'allow_other' but file access is limited to the user mounting the filesystem and root. This option and 'allow_other' are mutually exclusive. 89 | 90 | .B nonempty 91 | 92 | This option allows you to use the same directory for rootDir and mountPoint. 93 | 94 | Lzo is the fastest, bzip2 has high compression ratio, but it is the slowest, zlib is somewhere between them in terms of speed and compression ratio and lzma has highest compression ratio, it's compression speed is better than bzip2 and decompression is fast. The none compression method is there for testing only as it doesn't compress data, it copies the data without any modification (fusecompress' header is added). 95 | 96 | Block size influences compression ratio. Bigger block size allows better compression ratio, but random access to data will be slower and memory requirements will be bigger. 97 | 98 | .SH DISCLAIMER 99 | 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. Please refer to the "COPYING" file distributed with fusecompress for complete details. 100 | .SH AUTHORS 101 | fusecompress was written by Milan Svoboda . 102 | .SH "SEE ALSO" 103 | fusecompress_offline 104 | -------------------------------------------------------------------------------- /src/fusecompress_offline.1: -------------------------------------------------------------------------------- 1 | .TH FUSECOMPRESS_OFFLINE 1 "2008-06-06" "1.99.16" "Compressed filesystem offline" 2 | .SH NAME 3 | fusecompress_offline \- decompress or compress data without need to mount the compressed virtual filesystem 4 | .SH SYNOPSIS 5 | .B fusecompress_offline 6 | [\-h] [\-v] [\-o OPTIONS] path 7 | .SH DESCRIPTION 8 | 9 | If compression method is set the data will be compressed by required compression method. Files already compressed by a different compression method are recompressed to the required compression method. Files already compressed by the required compression method are left untouched. 10 | If compression method is not set (using -o fc_c) then file(s) are decompressed. 11 | 12 | Path may be directory or file. Directories are processed recursively. 13 | 14 | This allows you to, among other things, "compress" an existing folder (ex:) 15 | $ fusecompress_offline -o fc_c:lzma formerly_uncompressed_folder 16 | 17 | and to "decompress" an existing compressed folder (ex:) 18 | 19 | $ fusecompress_offline compressed_folder 20 | 21 | .SH OPTIONS 22 | .TP 23 | .B \-h, \-\-help 24 | Prints help. 25 | .TP 26 | .B \-v, \-\-version 27 | Prints version. 28 | .TP 29 | .B \-o, \-\-options 30 | 31 | .B fc_c:arg 32 | set compression method (lzo/bzip2/zlib/lzma) (default:zlib) 33 | 34 | .B fc_b:arg 35 | set size of the blocks in kilobytes (default:100) 36 | 37 | .B fc_d 38 | run in debug mode 39 | 40 | .B fc_ma:"arg1;arg2" 41 | files with passed mime types to be always not compressed 42 | 43 | .B fc_mr:"arg1;arg2" 44 | files with passed mime types to be always compressed 45 | 46 | Lzo is the fastest, bzip2 has high compression ratio, but it is the slowest, zlib is somewhere between them in terms of speed and compression ratio and lzma has highest compression ratio, it's compression speed is better than bzip2 and decompression is fast. 47 | 48 | Block size influences compression ratio. Bigger block size allows better compression ratio, but random access to data will be slower and memory requirements will be bigger. 49 | 50 | .SH DISCLAIMER 51 | 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. Please refer to the "COPYING" file distributed with fusecompress for complete details. 52 | .SH AUTHORS 53 | fusecompress_offline was written by Milan Svoboda . 54 | .SH "SEE ALSO" 55 | fusecompress 56 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #include "config.h" 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "CompressedMagic.hpp" 29 | #include "FuseCompress.hpp" 30 | #include "CompressionType.hpp" 31 | 32 | #include 33 | #if BOOST_VERSION >= 105600 34 | #define BOOST_DISABLE_ASSERTS 35 | #endif 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | #include "rlog/rlog.h" 49 | 50 | using namespace std; 51 | 52 | namespace po = boost::program_options; 53 | 54 | bool g_DebugMode; 55 | unsigned int g_BufferedMemorySize; 56 | CompressedMagic g_CompressedMagic; 57 | CompressionType g_CompressionType; 58 | std::string g_dirLower; 59 | std::string g_dirMount; 60 | rlog::RLog *g_RLog; 61 | 62 | static void init_log(void) 63 | { 64 | g_RLog = new rlog::RLog("FuseCompress", g_DebugMode ? LOG_DEBUG : LOG_INFO, g_DebugMode); 65 | } 66 | 67 | void print_license() 68 | { 69 | printf("%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION); 70 | printf("Copyright (C) 2007,2008 Milan Svoboda.\n"); 71 | printf("This is free software; see the source for copying conditions. There is NO\n"); 72 | printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"); 73 | } 74 | 75 | void print_help(const po::options_description &rDesc) 76 | { 77 | cout << rDesc << endl; 78 | cout << "Supported compression methods:" << endl; 79 | cout << "\t"; CompressionType::printAllSupportedMethods(cout); cout << endl << endl; 80 | cout << "Files with any of the following mime type will not be compressed:" << endl; 81 | cout << g_CompressedMagic << endl; 82 | } 83 | 84 | int main(int argc, char **argv) 85 | { 86 | g_BufferedMemorySize = 100; 87 | g_DebugMode = false; 88 | 89 | string compressorName; 90 | string commandLineOptions; 91 | 92 | vector fuseOptions; 93 | fuseOptions.push_back(argv[0]); 94 | 95 | po::options_description desc("Usage: " PACKAGE " [options] dir_lower dir_mount\n" "\nAllowed options"); 96 | desc.add_options() 97 | ("options,o", po::value(&commandLineOptions), 98 | "fc_c:arg - compression method\n" 99 | " (lzo/bzip2/zlib/lzma)\n" 100 | " (default: zlib)\n" 101 | "fc_b:arg - size of blocks in kilobytes\n" 102 | " (default: 100)\n" 103 | "fc_d - run in debug mode\n" 104 | "fc_ma:\"arg1;arg2\" - files with passed mime types to be\n" 105 | " always not compressed\n" 106 | "fc_mr:\"arg1;arg2\" - files with passed mime types to be\n" 107 | " always compressed\n" 108 | "\nOther options are passed directly to fuse library. See fuse documentation for full list of supported options.\n") 109 | ("dir_lower", po::value(&g_dirLower), "storage directory") 110 | ("dir_mount", po::value(&g_dirMount), "mount point") 111 | ("help,h", "print this help") 112 | ("version,v", "print version") 113 | ; 114 | 115 | po::positional_options_description pdesc; 116 | pdesc.add("dir_lower", 1); 117 | pdesc.add("dir_mount", 1); 118 | 119 | po::variables_map vm; 120 | try { 121 | po::store(po::command_line_parser(argc, argv).options(desc).positional(pdesc).run(), vm); 122 | } catch (...) { 123 | print_help(desc); 124 | exit(EXIT_FAILURE); 125 | } 126 | po::notify(vm); 127 | 128 | if (vm.count("help")) 129 | { 130 | print_help(desc); 131 | exit(EXIT_SUCCESS); 132 | } 133 | if (vm.count("version")) 134 | { 135 | print_license(); 136 | exit(EXIT_SUCCESS); 137 | } 138 | if (vm.count("options")) 139 | { 140 | typedef boost::tokenizer > tokenizer; 141 | boost::char_separator sep(","); 142 | tokenizer tokens(commandLineOptions, sep); 143 | 144 | for (tokenizer::iterator tok_it = tokens.begin(); tok_it != tokens.end(); ++tok_it) 145 | { 146 | if ((*tok_it).find_first_of("fc_", 0, 3) == 0) 147 | { 148 | typedef boost::tokenizer > tokenizer; 149 | boost::char_separator sep(":"); 150 | tokenizer tokens(*tok_it, sep); 151 | 152 | tokenizer::iterator key = tokens.begin(); 153 | tokenizer::iterator value = key; ++value; 154 | 155 | if (*key == "fc_c") 156 | { 157 | if (value == tokens.end()) 158 | { 159 | std::cerr << "Compression type not set!" << std::endl; 160 | exit(EXIT_FAILURE); 161 | } 162 | compressorName = *value; 163 | } 164 | if (*key == "fc_b") 165 | { 166 | if (value == tokens.end()) 167 | { 168 | std::cerr << "Block size not set!" << std::endl; 169 | exit(EXIT_FAILURE); 170 | } 171 | g_BufferedMemorySize = boost::lexical_cast(*value); 172 | } 173 | if (*key == "fc_d") 174 | { 175 | fuseOptions.push_back("-f"); 176 | g_DebugMode = true; 177 | } 178 | if (*key == "fc_ma") 179 | { 180 | if (value == tokens.end()) 181 | { 182 | std::cerr << "Mime type(s) not set!" << std::endl; 183 | exit(EXIT_FAILURE); 184 | } 185 | g_CompressedMagic.Add(*value); 186 | } 187 | if (*key == "fc_mr") 188 | { 189 | if (value == tokens.end()) 190 | { 191 | std::cerr << "Mime type(s) not set!" << std::endl; 192 | exit(EXIT_FAILURE); 193 | } 194 | g_CompressedMagic.Remove(*value); 195 | } 196 | } 197 | else 198 | { 199 | fuseOptions.push_back("-o"); 200 | fuseOptions.push_back(*tok_it); 201 | } 202 | } 203 | } 204 | if (vm.count("dir_lower")) 205 | { 206 | g_dirLower = vm["dir_lower"].as(); 207 | } 208 | else 209 | { 210 | print_help(desc); 211 | exit(EXIT_FAILURE); 212 | } 213 | if (vm.count("dir_mount")) 214 | { 215 | g_dirMount = vm["dir_mount"].as(); 216 | } 217 | else 218 | { 219 | print_help(desc); 220 | exit(EXIT_FAILURE); 221 | } 222 | 223 | g_BufferedMemorySize *= 1024; 224 | 225 | // Set up default options for fuse. 226 | // 227 | fuseOptions.push_back("-o"); 228 | fuseOptions.push_back("default_permissions,use_ino,kernel_cache"); 229 | fuseOptions.push_back(g_dirMount); 230 | 231 | // Set default transformation as user wanted. 232 | // 233 | if ((compressorName != "") && 234 | (g_CompressionType.parseType(compressorName) == false)) 235 | { 236 | cerr << "Compressor " << compressorName << " not found!" << endl; 237 | exit(EXIT_FAILURE); 238 | } 239 | 240 | DIR *dir; 241 | if ((dir = opendir(g_dirLower.c_str())) == NULL) 242 | { 243 | int errns = errno; 244 | 245 | cerr << "Failed to open storage directory " 246 | << "'" << g_dirLower << "': " << strerror(errns) << endl; 247 | exit(EXIT_FAILURE); 248 | } 249 | 250 | vector fuse_c_str; 251 | for (unsigned int i = 0; i < fuseOptions.size(); ++i) 252 | { 253 | fuse_c_str.push_back((fuseOptions[i].c_str())); 254 | } 255 | 256 | init_log(); 257 | FuseCompress fusecompress; 258 | 259 | umask(0); 260 | return fusecompress.Run(dir, fuse_c_str.size(), &fuse_c_str[0]); 261 | } 262 | 263 | -------------------------------------------------------------------------------- /src/rlog/rlog.h: -------------------------------------------------------------------------------- 1 | /* 2 | (C) Copyright Milan Svoboda 2009. 3 | 4 | This file is part of FuseCompress. 5 | 6 | FuseCompress is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | FuseCompress is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with FuseCompress. If not, see . 18 | */ 19 | 20 | #ifndef RLOG_H 21 | #define RLOG_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace rlog { 29 | 30 | class RLog 31 | { 32 | int m_level; 33 | bool m_toConsole; 34 | public: 35 | RLog(const char *name, int level, bool toConsole) 36 | { 37 | m_level = level; 38 | m_toConsole = toConsole; 39 | 40 | if (!m_toConsole) 41 | openlog(name, 0, 0); 42 | } 43 | 44 | ~RLog() 45 | { 46 | if (!m_toConsole) 47 | closelog(); 48 | } 49 | 50 | void setLevel(int level) 51 | { 52 | m_level = level; 53 | } 54 | 55 | void log(int level, const char *fmt, ...) 56 | { 57 | if (level > m_level) 58 | return; 59 | 60 | va_list ap; 61 | 62 | va_start(ap, fmt); 63 | 64 | // Send debug messages only to console. 65 | 66 | if (m_toConsole || (level == LOG_DEBUG)) 67 | { 68 | vprintf(fmt, ap); 69 | } 70 | else 71 | { 72 | vsyslog(level, fmt, ap); 73 | } 74 | 75 | va_end(ap); 76 | } 77 | }; 78 | 79 | } 80 | 81 | extern rlog::RLog *g_RLog; 82 | 83 | #define rError(fmt, ...) g_RLog->log(LOG_ERR, fmt "\n", ## __VA_ARGS__) 84 | #define rWarning(fmt, ...) g_RLog->log(LOG_WARNING, fmt "\n", ## __VA_ARGS__) 85 | #define rDebug(fmt, ...) g_RLog->log(LOG_DEBUG, fmt "\n", ## __VA_ARGS__) 86 | #define rInfo(fmt, ...) g_RLog->log(LOG_INFO, fmt "\n", ## __VA_ARGS__) 87 | 88 | #endif 89 | 90 | -------------------------------------------------------------------------------- /src/tests/Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = print_compress xattrs 2 | 3 | xattrs_SOURCES = xattrs.cpp 4 | xattrs_LDADD =../libfusecompress.la \ 5 | $(BOOST_SERIALIZATION_LIB) $(BOOST_IOSTREAMS_LIB) $(BOOST_PROGRAM_OPTIONS_LIB) $(BOOST_FILESYSTEM_LIB) $(BOOST_SYSTEM_LIB) $(FUSE_LIBS) 6 | 7 | 8 | print_compress_SOURCES = print_compress.cpp 9 | print_compress_LDADD =../libfusecompress.la \ 10 | $(BOOST_SERIALIZATION_LIB) $(BOOST_IOSTREAMS_LIB) $(BOOST_PROGRAM_OPTIONS_LIB) $(BOOST_FILESYSTEM_LIB) $(BOOST_SYSTEM_LIB) $(FUSE_LIBS) 11 | 12 | AM_CXXFLAGS = $(BOOST_CXXFLAGS) 13 | 14 | AM_LDFLAGS=$(BOOST_LDFLAGS) 15 | 16 | AM_CPPFLAGS = \ 17 | -D_GNU_SOURCE \ 18 | -D_REENTRANT \ 19 | -D_POSIX_C_SOURCE=200112L \ 20 | -D_POSIX_SOURCE \ 21 | -D_DEFAULT_SOURCE \ 22 | -D_XOPEN_SOURCE=500 \ 23 | -Wno-long-long \ 24 | -Wall \ 25 | -I.. \ 26 | -fpermissive -O0 -g 27 | 28 | -------------------------------------------------------------------------------- /src/tests/TLayerMap.cpp: -------------------------------------------------------------------------------- 1 | #define BOOST_TEST_MAIN 2 | #include 3 | 4 | #include "LayerMap.hpp" 5 | 6 | BOOST_AUTO_TEST_CASE(t1) 7 | { 8 | LayerMap m; 9 | 10 | Block block; 11 | off_t length; 12 | /* 13 | 0 15 20 25 30 14 | |---------| 15 | |---------| 16 | */ 17 | m.Put(new Block(15, 10)); 18 | m.Put(new Block(25, 5)); 19 | 20 | m.Get(0, block, length); 21 | 22 | BOOST_CHECK(block.offset == 15); 23 | BOOST_CHECK(block.length == 10); 24 | BOOST_CHECK(length == 0); 25 | } 26 | 27 | BOOST_AUTO_TEST_CASE(t2) 28 | { 29 | LayerMap m; 30 | 31 | Block block; 32 | off_t length; 33 | /* 34 | 0 5 10 15 20 25 35 | |---------| 36 | |---------| 37 | */ 38 | m.Put(new Block(5, 10)); 39 | m.Put(new Block(15, 5)); 40 | 41 | m.Get(0, block, length); 42 | 43 | BOOST_CHECK(block.offset == 5); 44 | BOOST_CHECK(block.length == 10); 45 | BOOST_CHECK(length == 0); 46 | } 47 | 48 | BOOST_AUTO_TEST_CASE(t3) 49 | { 50 | LayerMap m; 51 | 52 | Block block; 53 | off_t length; 54 | bool r; 55 | 56 | /* 57 | 0 5 10 15 58 | |----------| 59 | |----------| 60 | */ 61 | 62 | m.Put(new Block(0, 10)); 63 | m.Put(new Block(5, 10)); 64 | 65 | m.Get(0, block, length); 66 | 67 | BOOST_CHECK(block.offset == 0); 68 | BOOST_CHECK(block.length == 10); 69 | BOOST_CHECK(length == 5); 70 | 71 | m.Get(4, block, length); 72 | 73 | BOOST_CHECK(block.offset == 0); 74 | BOOST_CHECK(block.length == 10); 75 | BOOST_CHECK(length == 1); 76 | 77 | m.Get(5, block, length); 78 | 79 | BOOST_CHECK(block.offset == 5); 80 | BOOST_CHECK(block.length == 10); 81 | BOOST_CHECK(length == 10); 82 | 83 | m.Get(6, block, length); 84 | 85 | BOOST_CHECK(block.offset == 5); 86 | BOOST_CHECK(block.length == 10); 87 | BOOST_CHECK(length == 9); 88 | 89 | m.Get(9, block, length); 90 | 91 | BOOST_CHECK(block.offset == 5); 92 | BOOST_CHECK(block.length == 10); 93 | BOOST_CHECK(length == 6); 94 | 95 | m.Get(10, block, length); 96 | 97 | BOOST_CHECK(block.offset == 5); 98 | BOOST_CHECK(block.length == 10); 99 | BOOST_CHECK(length == 5); 100 | 101 | m.Get(11, block, length); 102 | 103 | BOOST_CHECK(block.offset == 5); 104 | BOOST_CHECK(block.length == 10); 105 | BOOST_CHECK(length == 4); 106 | 107 | r = m.Get(15, block, length); 108 | 109 | BOOST_CHECK(r == false); 110 | BOOST_CHECK(block.offset == 5); // Unmodified previous result 111 | BOOST_CHECK(block.length == 10); 112 | BOOST_CHECK(length == 4); 113 | } 114 | 115 | BOOST_AUTO_TEST_CASE(t4) 116 | { 117 | LayerMap m; 118 | 119 | Block block; 120 | off_t length; 121 | /* 122 | 0 5 10 15 20 25 123 | |---------| 124 | |---------| 125 | |----| 126 | */ 127 | m.Put(new Block(0, 10)); 128 | m.Put(new Block(5, 10)); 129 | m.Put(new Block(20, 5)); 130 | 131 | m.Get(14, block, length); 132 | 133 | BOOST_CHECK(block.offset == 5); 134 | BOOST_CHECK(block.length == 10); 135 | BOOST_CHECK(length == 1); 136 | 137 | m.Get(15, block, length); 138 | 139 | BOOST_CHECK(block.offset == 20); 140 | BOOST_CHECK(block.length == 5); 141 | BOOST_CHECK(length == 0); 142 | } 143 | 144 | BOOST_AUTO_TEST_CASE(t5) 145 | { 146 | LayerMap m; 147 | 148 | Block block; 149 | off_t length; 150 | 151 | /* 152 | 0 5 10 15 20 24 25 153 | |--------| 154 | |---------| 155 | |---| 156 | |-------------| 157 | */ 158 | m.Put(new Block(0, 10)); 159 | m.Put(new Block(5, 10)); 160 | m.Put(new Block(20, 5)); 161 | m.Put(new Block(10, 14)); 162 | 163 | m.Get(15, block, length); 164 | 165 | BOOST_CHECK(block.offset == 10); 166 | BOOST_CHECK(block.length == 14); 167 | BOOST_CHECK(length == 9); 168 | 169 | m.Get(20, block, length); 170 | 171 | BOOST_CHECK(block.offset == 10); 172 | BOOST_CHECK(block.length == 14); 173 | BOOST_CHECK(length == 4); 174 | 175 | m.Get(24, block, length); 176 | 177 | BOOST_CHECK(block.offset == 20); 178 | BOOST_CHECK(block.length == 5); 179 | BOOST_CHECK(length == 1); 180 | } 181 | 182 | BOOST_AUTO_TEST_CASE(t6) 183 | { 184 | LayerMap m; 185 | 186 | Block block; 187 | off_t length; 188 | 189 | /* 190 | 0 5 10 15 17 19 25 30 191 | |--------| 192 | |-----------| 193 | |------------| 194 | |------| 195 | 196 | */ 197 | m.Put(new Block(0, 10)); 198 | m.Put(new Block(15, 15)); 199 | m.Put(new Block(5, 14)); 200 | m.Put(new Block(17, 7)); 201 | 202 | m.Get(3, block, length); 203 | 204 | BOOST_CHECK(block.offset == 0); 205 | BOOST_CHECK(block.length == 10); 206 | BOOST_CHECK(length == 2); 207 | 208 | m.Get(5, block, length); 209 | 210 | BOOST_CHECK(block.offset == 5); 211 | BOOST_CHECK(block.length == 14); 212 | BOOST_CHECK(length == 12); 213 | 214 | m.Get(9, block, length); 215 | 216 | BOOST_CHECK(block.offset == 5); 217 | BOOST_CHECK(block.length == 14); 218 | BOOST_CHECK(length == 8); 219 | 220 | m.Get(14, block, length); 221 | 222 | BOOST_CHECK(block.offset == 5); 223 | BOOST_CHECK(block.length == 14); 224 | BOOST_CHECK(length == 3); 225 | 226 | m.Get(15, block, length); 227 | 228 | BOOST_CHECK(block.offset == 5); 229 | BOOST_CHECK(block.length == 14); 230 | BOOST_CHECK(length == 2); 231 | 232 | m.Get(17, block, length); 233 | 234 | BOOST_CHECK(block.offset == 17); 235 | BOOST_CHECK(block.length == 7); 236 | BOOST_CHECK(length == 7); 237 | 238 | m.Get(25, block, length); 239 | 240 | BOOST_CHECK(block.offset == 15); 241 | BOOST_CHECK(block.length == 15); 242 | BOOST_CHECK(length == 5); 243 | } 244 | 245 | BOOST_AUTO_TEST_CASE(t7) 246 | { 247 | LayerMap m; 248 | 249 | Block block; 250 | off_t length; 251 | bool r; 252 | 253 | m.Put(new Block(0x2a50, 0x5b0, 0xdf9d), true); 254 | m.Put(new Block(0x3000, 0x1000, 0xdf9e),true); 255 | m.Put(new Block(0x4000, 0x1000, 0xdf9f),true); 256 | m.Put(new Block(0x5000, 0xd4b, 0xdfa0),true); 257 | m.Put(new Block(0x52f5, 0xd0b, 0xdff3),true); 258 | m.Put(new Block(0x6000, 0x1000, 0xdff4),true); 259 | m.Put(new Block(0x6d67, 0x299, 0xdff8),true); 260 | m.Put(new Block(0x7000, 0x1000, 0xdff9),true); 261 | m.Put(new Block(0x7000, 0x1000, 0xdff5),true); 262 | m.Put(new Block(0x7d0f, 0x2f1, 0xe042),true); 263 | 264 | m.Put(new Block(0x8000, 0x1000, 0xe043),true); 265 | m.Put(new Block(0x8000, 0x1000, 0xdffa),true); 266 | m.Put(new Block(0x8000, 0x1000, 0xdff6),true); 267 | m.Put(new Block(0x884f, 0xd9, 0xe07b),true); 268 | m.Put(new Block(0x8b04, 0x4fc, 0xe07c),true); 269 | m.Put(new Block(0x9000, 0x1000, 0xe07d),true); 270 | m.Put(new Block(0x9000, 0x1000, 0xe044),true); 271 | m.Put(new Block(0x9000, 0x1000, 0xdffb),true); 272 | m.Put(new Block(0x9000, 0x8e7, 0xdff7),true); 273 | 274 | r = m.Get(0x8b00, block, length); 275 | 276 | BOOST_CHECK(block.offset == 0x8000); 277 | BOOST_CHECK(block.length == 0x1000); 278 | BOOST_CHECK(block.level == 0xe043); 279 | BOOST_CHECK(length == 0x4); 280 | 281 | r = m.Get(0x8b04, block, length); 282 | 283 | BOOST_CHECK(block.offset == 0x8b04); 284 | BOOST_CHECK(block.length == 0x4fc); 285 | BOOST_CHECK(length == 0x4fc); 286 | 287 | 288 | m.Put(new Block(0x9d35, 0x172, 0xdfd4),true); 289 | m.Put(new Block(0x9d94, 0x26c, 0xe04a),true); 290 | m.Put(new Block(0xa000, 0x1000, 0xe07e),true); 291 | m.Put(new Block(0xa000, 0x1000, 0xe04b),true); 292 | m.Put(new Block(0xa000, 0x1000, 0xe045),true); 293 | m.Put(new Block(0xa000, 0xea8, 0xdffc),true); 294 | m.Put(new Block(0xb000, 0x1000, 0xe07f),true); 295 | m.Put(new Block(0xb000, 0x1000, 0xe04c),true); 296 | m.Put(new Block(0xb000, 0x1000, 0xe046),true); 297 | m.Put(new Block(0xc000, 0x1000, 0xe080),true); 298 | m.Put(new Block(0xc000, 0x1000, 0xe04d),true); 299 | m.Put(new Block(0xc000, 0x1000, 0xe047),true); 300 | m.Put(new Block(0xd000, 0x1000, 0xe081),true); 301 | m.Put(new Block(0xd000, 0x1000, 0xe04e),true); 302 | m.Put(new Block(0xd000, 0x1000, 0xe048),true); 303 | m.Put(new Block(0xe000, 0x1000, 0xe082),true); 304 | m.Put(new Block(0xe000, 0x1000, 0xe04f),true); 305 | m.Put(new Block(0xe000, 0x2ca, 0xe049),true); 306 | m.Put(new Block(0xf000, 0x1000, 0xe083),true); 307 | m.Put(new Block(0xf000, 0x1000, 0xe050),true); 308 | m.Put(new Block(0x10000, 0x1000, 0xe084),true); 309 | m.Put(new Block(0x10000, 0x1000, 0xe051),true); 310 | m.Put(new Block(0x11000, 0x634, 0xe085),true); 311 | m.Put(new Block(0x11000, 0xdf6, 0xe052),true); 312 | 313 | r = m.Get(0x0, block, length); 314 | 315 | BOOST_CHECK(block.offset == 0x2a50); 316 | BOOST_CHECK(block.length == 0x5b0); 317 | BOOST_CHECK(block.level == 0xdf9d); 318 | BOOST_CHECK(length == 0x0); 319 | 320 | r = m.Get(0x1000, block, length); 321 | 322 | BOOST_CHECK(block.offset == 0x2a50); 323 | BOOST_CHECK(block.length == 0x5b0); 324 | BOOST_CHECK(block.level == 0xdf9d); 325 | BOOST_CHECK(length == 0x0); 326 | 327 | r = m.Get(0x2000, block, length); 328 | 329 | BOOST_CHECK(block.offset == 0x2a50); 330 | BOOST_CHECK(block.length == 0x5b0); 331 | BOOST_CHECK(block.level == 0xdf9d); 332 | BOOST_CHECK(length == 0x0); 333 | 334 | r = m.Get(0x3000, block, length); 335 | 336 | BOOST_CHECK(block.offset == 0x3000); 337 | BOOST_CHECK(block.length == 0x1000); 338 | BOOST_CHECK(block.level == 0xdf9e); 339 | BOOST_CHECK(length == 0x1000); 340 | 341 | 342 | } 343 | 344 | BOOST_AUTO_TEST_CASE(t8) 345 | { 346 | LayerMap m; 347 | 348 | Block block; 349 | off_t length; 350 | bool r; 351 | 352 | 353 | m.Put(new Block(0x8000, 0x1000, 0x5e433), true); 354 | m.Put(new Block(0x8000, 0x1000, 0x5e3fe), true); 355 | m.Put(new Block(0x81ce, 0x3bb, 0x5e481), true); 356 | m.Put(new Block(0x8aea, 0x516, 0x5e464), true); 357 | m.Put(new Block(0x9000, 0x1000, 0x5e465), true); 358 | 359 | r = m.Get(0x8000, block, length); 360 | 361 | BOOST_CHECK(block.offset == 0x8000); 362 | BOOST_CHECK(block.length == 0x1000); 363 | BOOST_CHECK(block.level == 0x5e433); 364 | BOOST_CHECK(length == 0x1ce); 365 | 366 | r = m.Get(0x81ce, block, length); 367 | 368 | BOOST_CHECK(block.offset == 0x81ce); 369 | BOOST_CHECK(block.length == 0x3bb); 370 | BOOST_CHECK(length == 0x3bb); 371 | 372 | r = m.Get(0x8aea, block, length); 373 | 374 | BOOST_CHECK(block.offset == 0x8aea); 375 | BOOST_CHECK(block.length == 0x516); 376 | BOOST_CHECK(block.level == 0x5e464); 377 | BOOST_CHECK(length == 0x516); 378 | 379 | r = m.Get(0x8589, block, length); 380 | 381 | BOOST_CHECK(block.offset == 0x8000); 382 | BOOST_CHECK(block.length == 0x1000); 383 | BOOST_CHECK(block.level == 0x5e433); 384 | BOOST_CHECK(length == 0x561); 385 | 386 | } 387 | 388 | BOOST_AUTO_TEST_CASE(t9) 389 | { 390 | LayerMap m; 391 | 392 | Block block; 393 | off_t length; 394 | bool r; 395 | 396 | m.Put(new Block(0x8, 0x12, 0x2e7), true); 397 | m.Put(new Block(0x4f, 0x234, 0x345), true); 398 | m.Put(new Block(0xbd, 0x805e, 0x368), true); 399 | m.Put(new Block(0x24b, 0x38, 0x34d), true); 400 | m.Put(new Block(0x1edf, 0x452c, 0x364), true); 401 | m.Put(new Block(0x24d9, 0x5c42, 0x365), true); 402 | 403 | r = m.Get(0x5000, block, length); 404 | 405 | BOOST_CHECK(block.offset == 0xbd); 406 | BOOST_CHECK(block.length == 0x805e); 407 | BOOST_CHECK(block.level == 0x368); 408 | BOOST_CHECK(length == 0x311b); 409 | 410 | r = m.Get(0x5447, block, length); 411 | 412 | BOOST_CHECK(block.offset == 0xbd); 413 | BOOST_CHECK(block.length == 0x805e); 414 | BOOST_CHECK(block.level == 0x368); 415 | BOOST_CHECK(length == 0x2cd4); 416 | } 417 | 418 | BOOST_AUTO_TEST_CASE(t10) 419 | { 420 | LayerMap m; 421 | 422 | Block block; 423 | off_t length; 424 | bool r; 425 | 426 | m.Put(new Block(0x25, 0x26, 0x1), true); 427 | m.Put(new Block(0x2a3, 0xea1, 0x2), true); 428 | m.Put(new Block(0x1144, 0x1502, 0x3), true); 429 | m.Put(new Block(0x2646, 0x4bbc, 0x4), true); 430 | m.Put(new Block(0x7202, 0x4242, 0x5), true); 431 | m.Put(new Block(0xd1c9, 0x8cd8, 0x6), true); 432 | m.Put(new Block(0x2c83d, 0x6313, 0x7), true); 433 | m.Put(new Block(0x32b50, 0x872d, 0x8), true); 434 | m.Put(new Block(0x3ff88c, 0xe00, 0x9), true); 435 | 436 | r = m.Get(0xec000, block, length); 437 | 438 | BOOST_CHECK(block.offset == 0x3ff88c); 439 | BOOST_CHECK(block.length == 0xe00); 440 | BOOST_CHECK(block.level == 0x9); 441 | BOOST_CHECK(length == 0x0); 442 | 443 | r = m.Get(0xed000, block, length); 444 | 445 | BOOST_CHECK(block.offset == 0x3ff88c); 446 | BOOST_CHECK(block.length == 0xe00); 447 | BOOST_CHECK(block.level == 0x9); 448 | BOOST_CHECK(length == 0x0); 449 | } 450 | 451 | -------------------------------------------------------------------------------- /src/tests/print_compress.cpp: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "rlog/rlog.h" 15 | 16 | #include "Compress.hpp" 17 | #include "CompressedMagic.hpp" 18 | #include "CompressionType.hpp" 19 | #include "FileManager.hpp" 20 | 21 | #include 22 | #if BOOST_VERSION >= 105600 23 | #define BOOST_DISABLE_ASSERTS 24 | #endif 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "boost/filesystem/operations.hpp" // includes boost/filesystem/path.hpp 32 | #include "boost/filesystem/fstream.hpp" // ditto 33 | 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | using namespace std; 40 | 41 | namespace po = boost::program_options; 42 | namespace fs = boost::filesystem; 43 | 44 | bool g_DebugMode = true; 45 | unsigned int g_BufferedMemorySize; 46 | CompressedMagic g_CompressedMagic; 47 | CompressionType g_CompressionType; 48 | std::string g_dirLower; 49 | std::string g_dirMount; 50 | rlog::RLog *g_RLog; 51 | 52 | bool g_RawOutput = true; 53 | 54 | void init_log(void) 55 | { 56 | g_RLog = new rlog::RLog("print_compress", g_DebugMode ? LOG_DEBUG : LOG_INFO, g_DebugMode); 57 | } 58 | 59 | int main(int argc, char **argv) 60 | { 61 | g_BufferedMemorySize = 100 * 1024; 62 | 63 | string filename; 64 | 65 | po::options_description desc; 66 | desc.add_options() 67 | ("filename", po::value(&filename), "filename") 68 | ; 69 | 70 | po::positional_options_description pdesc; 71 | pdesc.add("filename", 1); 72 | 73 | po::variables_map vm; 74 | try { 75 | po::store(po::command_line_parser(argc, argv).options(desc).positional(pdesc).run(), vm); 76 | } catch (...) { 77 | exit(EXIT_FAILURE); 78 | } 79 | po::notify(vm); 80 | 81 | if (!vm.count("filename")) 82 | { 83 | exit(EXIT_FAILURE); 84 | } 85 | 86 | std::cout << "Processing: " << filename << std::endl; 87 | 88 | init_log(); 89 | 90 | struct stat filename_stat; 91 | stat(filename.c_str(), &filename_stat); 92 | Compress input(&filename_stat, filename.c_str()); 93 | input.open(filename.c_str(), 0); 94 | 95 | std::cout << "isCompressed: " << input.isCompressed() << std::endl; 96 | std::cout << input; 97 | 98 | exit(EXIT_SUCCESS); 99 | } 100 | 101 | -------------------------------------------------------------------------------- /src/tests/xattrs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "rlog/rlog.h" 6 | 7 | #include "FileRememberXattrs.hpp" 8 | #include "CompressedMagic.hpp" 9 | #include "CompressionType.hpp" 10 | 11 | bool g_DebugMode = true; 12 | unsigned int g_BufferedMemorySize; 13 | CompressedMagic g_CompressedMagic; 14 | CompressionType g_CompressionType; 15 | std::string g_dirLower; 16 | std::string g_dirMount; 17 | rlog::RLog *g_RLog; 18 | 19 | int main(int argc, char **argv) 20 | { 21 | g_RLog = new rlog::RLog("xattrs", g_DebugMode ? LOG_DEBUG : LOG_INFO, g_DebugMode); 22 | 23 | int fd_s = open(argv[1], O_RDONLY); 24 | int fd_d = open(argv[2], O_WRONLY); 25 | FileRememberXattrs xattrs; 26 | xattrs.read(fd_s); 27 | xattrs.write(fd_d); 28 | return 0; 29 | } 30 | 31 | --------------------------------------------------------------------------------