fuse-zip-0.2.13/.hg_archival.txt 0000644 0000000 0000000 00000000225 11477217250 016370 0 ustar root root 0000000 0000000 repo: 38472f434ab14d41686baaa73679d7fe4773f0f2
node: 3bd5d9cfa78b573ab7ef042255e7a279463c32f6
branch: default
latesttag: 0.2.13
latesttagdistance: 1
fuse-zip-0.2.13/.hgignore 0000644 0000000 0000000 00000000357 11477217250 015113 0 ustar root root 0000000 0000000 syntax: glob
# ignore vim swapfiles
.*.swp
# ignore source archives
fuse-zip*.tar.gz
# ignore generated files
*.o
fuse-zip
fuse-zip.1.gz
lib/*.a
# tests
tests/whitebox/*.x
# other related projects (needed for performance tests)
others
fuse-zip-0.2.13/.hgtags 0000644 0000000 0000000 00000001443 11477217250 014563 0 ustar root root 0000000 0000000 0ac39c893b9516994afab8e0524765a1cd54739b 0.2.0
0d5865a7fb53959088bfd4b1edc028de8c64de53 0.2.6
1e34f469bf9d39a34cf2dcd74be3762f75787cf9 0.2.5
581b06b7cee2b7691125e2907683f4e834e90301 0.1.0
5e0f0c7ae8049eb675386622c53d5f0b487512a6 0.2.3
9513e1d44bf99244b9a037ea30cc01fbe8ea5856 0.2.1
9ab3241a6822263558b2db2a9e26c0f4d2ca524f 0.2.4
fd88cde887ac7405b81f2c9a73a61ed6af2fc99a 0.2.2
80ad596796392ffedd0281c822d8f4bfd537134f 0.2.7
ab463806418aff3429772941253e0f63503b58a2 0.2.8
5edac8c7e535a992741658de1ba1fcb6058e1305 0.2.9
5edac8c7e535a992741658de1ba1fcb6058e1305 0.2.9
95321b27fefb951c3026beddbe5820ef4c3ac4b1 0.2.9
19110f42d5f6ed094bbdeead843a969845b18907 0.2.10
256f2f59af7b8e099479157507852cfd00bbf085 0.2.11
e941c5cc7a9c1eb115fd1f4db7907dddc2cbc8dc 0.2.12
3dd1661895752bb47dc11b37f0c8afa7fff9e272 0.2.13
fuse-zip-0.2.13/INSTALL 0000644 0000000 0000000 00000000706 11477217250 014337 0 ustar root root 0000000 0000000 You need the following libraries:
libfuse >= 2.7 http://fuse.sourceforge.net
libzip >= 0.8 http://www.nih.at/libzip/
The following tools are required:
C++ compiler g++ 4.2.3 or other modern C++ compiler
pkg-config http://pkg-config.freedesktop.org/
GNU make http://www.gnu.org/software/make/
To build fuse-zip do the following:
$ make release
To install do:
# make install
as root or use sudo.
To uninstall:
# make uninstall
fuse-zip-0.2.13/LICENSE 0000644 0000000 0000000 00000016727 11477217250 014325 0 ustar root root 0000000 0000000 GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
fuse-zip-0.2.13/Makefile 0000644 0000000 0000000 00000003262 11477217250 014746 0 ustar root root 0000000 0000000 DEST=fuse-zip
LIBS=$(shell pkg-config fuse --libs) $(shell pkg-config libzip --libs) -Llib -lfusezip
LIB=lib/libfusezip.a
CXXFLAGS=-g -O2 -Wall -Wextra
RELEASE_CXXFLAGS=-O2 -Wall -Wextra
FUSEFLAGS=$(shell pkg-config fuse --cflags)
SOURCES=main.cpp
OBJECTS=$(SOURCES:.cpp=.o)
MANSRC=fuse-zip.1
MAN=fuse-zip.1.gz
CLEANFILES=$(OBJECTS) $(MAN)
DOCFILES=README changelog
INSTALLPREFIX=/usr
all: $(DEST)
doc: $(MAN)
doc-clean: man-clean
$(DEST): $(OBJECTS) $(LIB)
$(CXX) $(LDFLAGS) $(OBJECTS) $(LIBS) \
-o $@
# main.cpp must be compiled separately with FUSEFLAGS
main.o: main.cpp
$(CXX) -c $(CXXFLAGS) $(FUSEFLAGS) $< \
-Ilib \
-o $@
$(LIB):
make -C lib
lib-clean:
make -C lib clean
distclean: clean doc-clean
rm -f $(DEST)
clean: lib-clean all-clean test-clean tarball-clean
all-clean:
rm -f $(CLEANFILES)
$(MAN): $(MANSRC)
gzip -c9 $< > $@
man-clean:
rm -f $(MANSRC).gz
install: all doc
mkdir -p "$(INSTALLPREFIX)/bin"
install -m 755 -s "$(DEST)" "$(INSTALLPREFIX)/bin"
mkdir -p "$(INSTALLPREFIX)/share/doc/$(DEST)"
cp $(DOCFILES) "$(INSTALLPREFIX)/share/doc/$(DEST)"
mkdir -p "$(INSTALLPREFIX)/share/man/man1"
cp $(MAN) "$(INSTALLPREFIX)/share/man/man1"
uninstall:
rm "$(INSTALLPREFIX)/bin/$(DEST)"
rm -r "$(INSTALLPREFIX)/share/doc/$(DEST)"
rm "$(INSTALLPREFIX)/share/man/man1/$(MAN)"
tarball:
./makeArchives.sh
tarball-clean:
rm -f fuse-zip-*.tar.gz fuse-zip-tests-*.tar.gz
release:
make CXXFLAGS="$(RELEASE_CXXFLAGS)" all doc
test: $(DEST)
make -C tests
test-clean:
make -C tests clean
valgrind:
make -C tests valgrind
.PHONY: all release doc clean all-clean lib-clean doc-clean test-clean tarball-clean distclean install uninstall tarball test valgrind
fuse-zip-0.2.13/README 0000644 0000000 0000000 00000004260 11477217250 014165 0 ustar root root 0000000 0000000 = ABOUT =
fuse-zip is a FUSE file system to navigate, extract, create and modify ZIP
archives based in libzip implemented in C++.
With fuse-zip you really can work with ZIP archives as real directories.
Unlike KIO or Gnome VFS, it can be used in any application without
modifications.
Unlike other FUSE filesystems, _only_ fuse-zip provides write support to ZIP
archives. Also, fuse-zip is faster that all known implementations on large
archives with many files.
You can download fuse-zip at http://code.google.com/p/fuse-zip
= AUTHOR =
Alexander Galanin
* E-mail: al@galanin.nnov.ru
* XMPP: gaa@jabber.ru
* Homepage: http://galanin.nnov.ru/~al/
= LICENSE =
fuse-zip are licensed under GNU LGPL v3.
= USAGE =
{{{
$ mkdir /tmp/zipArchive
$ fuse-zip foobar.zip /tmp/zipArchive
(do something with the mounted file system)
$ fusermount -u /tmp/zipArchive
}}}
If ZIP file does not exists, it will be created after filesystem unmounting.
Be patient. Wait for fuse-zip process finish after unmounting especially on
a big archives.
If you want to specify character set conversion for file names in archive,
use the following fusermount options:
-omodules=iconv,from_code=$charset1,to_code=$charset2
Those Russian who uses archives from the "other OS" should use CP866 as
'charset1' and locale charset as 'charset2'.
See FUSE documentation for details.
Look at /var/log/user.log in case of any errors.
= PERFORMANCE =
On a small archives fuse-zip have the same performance with commonly used
virtual filesystems like KIO, Gnome GVFS, mc vfs, unpackfs, avfs, fuse-j-zip.
But on large archives with many file (like zipped Linux kernel sources)
fuse-zip have the greatest speed.
You can download test suite from the web-site and make sure that it is true.
See PerformancePage for details.
= HINTS =
# Added/changed files resides into memory until you unmount file system.
# Adding/unpacking very big files(more than one half of available memory) may cause your system swapping. It is a good idea to use zip/unzip in that case :)
# After adding/modifying files in archive it will be repacked at filesystem unmount. Hence, your file system must have enough space to keep tempopary files.
fuse-zip-0.2.13/TODO 0000644 0000000 0000000 00000001034 11477217250 013771 0 ustar root root 0000000 0000000 * whitebox test suite
* more unified exceptions and error cases handling
* replace vector with (s)list in BigBuffer
* rewrite files tree: keep only short path information to simplify rename(), use hash_map (unordered_map) instead of map
* log zip file errors to syslog
* truncate() without open-close file
* incapsulate call for zip_* into FileNode
* speed up position determination using bitwise operations
* iterate over chunks by iterator instead of indexing
* write memory cache to /tmp on fsync(). May be write compressed stream
fuse-zip-0.2.13/changelog 0000644 0000000 0000000 00000006423 11477217250 015162 0 ustar root root 0000000 0000000 2010-12-06 Alexander Galanin
* Released 0.2.13:
- Fixed issue #27: Android APK Support
- Fixed issue #28: doesn't honor the -r flag for some zip files
2010-02-07 Alexander Galanin
* Released 0.2.12:
- Fixed problem with lost new file after truncate().
- Fixed problems with rename(): Fixed various rename() problems: lost
path for subdirectory entries, duplicates of moved directories in a
hierarchy, invalid key in map after rename.
- Fixed unitialized values in read() call.
- Fixed memory leaks: buffer allocated for file content not freeed in
NEW state, incorrect buffer size in truncate().
- Fixed non-fatal memory leaks: FUSE options not freeed after use,
memory leak in help/version mode, internal data structures not freeed
if FUSE setup failed.
- More correct corrupted files handling.
- More correct memory insufficiency errors handling.
2010-01-26 Alexander Galanin
* Released 0.2.11:
- Fixed issue #25: does not compile with libfuse <= 2.8
2010-01-09 Alexander Galanin
* Released 0.2.10:
- Fixed issue #14: added '-r' option description.
- Added note about converting file names inside archive (for Russians
who uses 'another OS')
2010-01-08 Alexander Galanin
* Released 0.2.9:
- Fixed issue #22, now command-line options are correctly processed
2009-11-18 Alexander Galanin
* Released 0.2.8:
- Fixed issue #20: incorrect directory size reported
2008-12-06 Alexander Galanin
* Released 0.2.7:
- Fixed segfault if user tried to re-open corrupted file from an
invalid archive.
2008-09-29 Alexander Galanin
* Released 0.2.6:
- Fixed: Compilation error on FreeBSD/Mac OS X with FUSE 2.7
2008-08-24 Alexander Galanin
* Released 0.2.5:
- Fixed: Archives containing files whose parent directory does not
present in archive, reported as broken.
2008-08-09 Alexander Galanin
* Released 0.2.4:
- fixed wrong directory size on 32-bit Linux machines
2008-06-26 Alexander Galanin
* Released 0.2.3:
- fixed problem with time and size of new files
- free space on file system now equal to free space in archive dir
- added missing includes
- removed GNU-specific commands in Makefile
2008-06-16 Alexander Galanin
* Released 0.2.2:
- re-licensed under LGPLv3+
- fixed problem with file modification time
- fixed problems with compilation on non-Linux systems
2008-06-14 Alexander Galanin
* Released 0.2.1:
- fixed bug with file size on 32-bit systems
- fixed compilation problems on non-GNU platforms
- fixed compilation problems on GCC 4.3+
- added stubs for *xattr() system calls
- more checks for error cases
2008-06-11 Alexander Galanin
* Released 0.2.0:
- implemented all functions to mount archive read-write
- big internal refactoring
- added performance tests
- fixed problem with simultaneous file access
- fixed problem with one-character file names
* Known limitations:
- archives with items like '../../somefile' recognited as broken
2008-06-04 Alexander Galanin
* Initial release 0.1.0:
- implemented all base functions for read-only archive support
fuse-zip-0.2.13/config.h 0000644 0000000 0000000 00000003201 11477217250 014715 0 ustar root root 0000000 0000000 ////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2010 by Alexander Galanin //
// al@galanin.nnov.ru //
// http://galanin.nnov.ru/~al //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU Lesser General Public License as //
// published by the Free Software Foundation; either version 3 of the //
// License, or (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU Lesser General Public //
// License along with this program; if not, write to the //
// Free Software Foundation, Inc., //
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
////////////////////////////////////////////////////////////////////////////
#ifndef CONFIG_H
#define CONFIG_H
#define FUSE_USE_VERSION 27
#define PROGRAM "fuse-zip"
#define VERSION "0.2.13"
#endif
fuse-zip-0.2.13/fuse-zip.1 0000644 0000000 0000000 00000004140 11477217250 015126 0 ustar root root 0000000 0000000 .\" '\" t
.\" ** The above line should force tbl to be a preprocessor **
.\" Man page for fuse-zip
.TH "fuse-zip" "1" "January 2010" "FUSE filesystem to read and modify ZIP archives" "FUSE filesystem to read and modify ZIP archives"
.SH "NAME"
fuse\-zip \- a FUSE filesystem for zip archives with write support
.SH "SYNOPSIS"
.\" The general command line
.B fuse\-zip
.RI [\| options \|]
zip\-file
mount\-point
.SH "OPTIONS"
.TP
\fB-h\fP
print help
.TP
\fB-V\fP
print version
.TP
\fB-r\fP
open archive in read\-only mode
.TP
\fB-o opt[,opt...]\fP
mount options
.TP
\fB-f\fP
don't detach from terminal
.TP
\fB-d\fP
turn on debugging, also implies \-f
.PP
If you want to specify character set conversion for file names in archive,
use the following fusermount options:
\-omodules=iconv,from_code=$charset1,to_code=$charset2
See FUSE documentation for details.
.SH "DESCRIPTION"
.B fuse\-zip
is a fuse filesystem, that enables any program to work with a ZIP archive as though it is a plain directory.
Unlike KIO or Gnome VFS, it can be used in any application without modifications.
Unlike other FUSE filesystems, only fuse\-zip provides write support to ZIP archives.
Also, fuse\-zip is faster that all known implementations on large archives with many files.
.SH "USAGE"
General usage would look like this
.TS
tab (@);
l l.
1@mkdir\ /tmp/zipArchive
2@fuse\-zip foobar.zip /tmp/zipArchive
3@(do something with the mounted file system)
4@fusermount \-u /tmp/zipArchive
.TE
.PP
Be patient. Wait for fuse-zip process finish after unmounting, especially on a big archives.
.SH "FILES"
.TP
.if !'po4a'hide' .I /var/log/user.log
see this file in case any errors occur
.SH "SEE ALSO"
.BR fusermount (1).
.SH "LICENSE"
.
This is Free Software; this software is licensed under the LGPL version 3, as published by the Free Software Foundation, or later.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.
.SH "AUTHORS"
.
Alexander Galanin http://galanin.nnov.ru/~al
.br
.
This manual page was originally written by Kirill Zaitsev . Updated by Alexander Galanin.
fuse-zip-0.2.13/lib/Makefile 0000644 0000000 0000000 00000001255 11477217250 015514 0 ustar root root 0000000 0000000 DEST=libfusezip.a
LIBS=$(shell pkg-config fuse --libs) $(shell pkg-config libzip --libs)
CXXFLAGS=-g -O2 -Wall -Wextra
RELEASE_CXXFLAGS=-O2 -Wall -Wextra
FUSEFLAGS=$(shell pkg-config fuse --cflags)
ZIPFLAGS=$(shell pkg-config libzip --cflags)
SOURCES=$(wildcard *.cpp)
OBJECTS=$(SOURCES:.cpp=.o)
CLEANFILES=$(OBJECTS) $(DEST)
all: $(DEST)
release:
make CXXFLAGS="$(RELEASE_CXXFLAGS)" all
$(DEST): $(OBJECTS)
$(AR) -cq $@ $(OBJECTS)
# fuse-zip.cpp must be compiled separately with FUSEFLAGS
fuse-zip.o: fuse-zip.cpp
$(CXX) -c $(CXXFLAGS) $(FUSEFLAGS) $(ZIPFLAGS) $< -o $@
.cpp.o:
$(CXX) -c $(CXXFLAGS) $(ZIPFLAGS) $< -o $@
clean:
rm -f $(DEST) $(OBJECTS)
.PHONY: all clean
fuse-zip-0.2.13/lib/bigBuffer.cpp 0000644 0000000 0000000 00000020426 11477217250 016454 0 ustar root root 0000000 0000000 ////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2010 by Alexander Galanin //
// al@galanin.nnov.ru //
// http://galanin.nnov.ru/~al //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU Lesser General Public License as //
// published by the Free Software Foundation; either version 3 of the //
// License, or (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU Lesser General Public //
// License along with this program; if not, write to the //
// Free Software Foundation, Inc., //
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
////////////////////////////////////////////////////////////////////////////
#include
#include
#include
#include "bigBuffer.h"
/**
* Class that keep chunk of file data.
*/
class BigBuffer::ChunkWrapper {
private:
/**
* Pointer that keeps data for chunk. Can be NULL.
*/
char *m_ptr;
public:
/**
* By default internal buffer is NULL, so this can be used for creating
* sparse files.
*/
ChunkWrapper(): m_ptr(NULL) {
}
/**
* Take ownership on internal pointer from 'other' object.
*/
ChunkWrapper(const ChunkWrapper &other) {
m_ptr = other.m_ptr;
const_cast(&other)->m_ptr = NULL;
}
/**
* Free pointer if allocated.
*/
~ChunkWrapper() {
if (m_ptr != NULL) {
free(m_ptr);
}
}
/**
* Take ownership on internal pointer from 'other' object.
*/
ChunkWrapper &operator=(const ChunkWrapper &other) {
if (&other != this) {
m_ptr = other.m_ptr;
const_cast(&other)->m_ptr = NULL;
}
return *this;
}
/**
* Return pointer to internal storage and initialize it if needed.
* @throws
* std::bad_alloc If memory can not be allocated
*/
char *ptr(bool init = false) {
if (init && m_ptr == NULL) {
m_ptr = (char *)malloc(chunkSize);
if (m_ptr == NULL) {
throw std::bad_alloc();
}
}
return m_ptr;
}
/**
* Fill 'dest' with internal buffer content.
* If m_ptr is NULL, destination bytes is zeroed.
*
* @param dest Destination buffer.
* @param offset Offset in internal buffer to start reading from.
* @param count Number of bytes to be read.
*
* @return Number of bytes actually read. It can differ with 'count'
* if offset+count>chunkSize.
*/
size_t read(char *dest, offset_t offset, size_t count) const {
if (offset + count > chunkSize) {
count = chunkSize - offset;
}
if (m_ptr != NULL) {
memcpy(dest, m_ptr + offset, count);
} else {
memset(dest, 0, count);
}
return count;
}
/**
* Fill internal buffer with bytes from 'src'.
* If m_ptr is NULL, memory for buffer is malloc()-ed and then head of
* allocated space is zeroed. After that byte copying is performed.
*
* @param src Source buffer.
* @param offset Offset in internal buffer to start writting from.
* @param count Number of bytes to be written.
*
* @return Number of bytes actually written. It can differ with
* 'count' if offset+count>chunkSize.
* @throws
* std::bad_alloc If there are no memory for buffer
*/
size_t write(const char *src, offset_t offset, size_t count) {
if (offset + count > chunkSize) {
count = chunkSize - offset;
}
if (m_ptr == NULL) {
m_ptr = (char *)malloc(chunkSize);
if (m_ptr == NULL) {
throw std::bad_alloc();
}
if (offset > 0) {
memset(m_ptr, 0, offset);
}
}
memcpy(m_ptr + offset, src, count);
return count;
}
/**
* Clear tail of internal buffer with zeroes starting from 'offset'.
*/
void clearTail(offset_t offset) {
if (m_ptr != NULL && offset < chunkSize) {
memset(m_ptr + offset, 0, chunkSize - offset);
}
}
};
BigBuffer::BigBuffer(): len(0) {
}
BigBuffer::BigBuffer(struct zip *z, int nodeId, ssize_t length): len(length) {
struct zip_file *zf = zip_fopen_index(z, nodeId, 0);
if (zf == NULL) {
throw std::exception();
}
chunks.resize(chunksCount(length), ChunkWrapper());
unsigned int chunk = 0;
ssize_t nr;
while (length > 0) {
nr = zip_fread(zf, chunks[chunk].ptr(true), chunkSize);
if (nr < 0) {
zip_fclose(zf);
throw std::exception();
}
++chunk;
length -= nr;
}
if (zip_fclose(zf)) {
throw std::exception();
}
}
BigBuffer::~BigBuffer() {
}
int BigBuffer::read(char *buf, size_t size, offset_t offset) const {
if (offset > len) {
return 0;
}
int chunk = chunkNumber(offset);
int pos = chunkOffset(offset);
if (size > unsigned(len - offset)) {
size = len - offset;
}
int nread = size;
while (size > 0) {
size_t r = chunks[chunk].read(buf, pos, size);
size -= r;
buf += r;
++chunk;
pos = 0;
}
return nread;
}
int BigBuffer::write(const char *buf, size_t size, offset_t offset) {
int chunk = chunkNumber(offset);
int pos = chunkOffset(offset);
int nwritten = size;
if (offset > len) {
if (len > 0) {
chunks[chunkNumber(len)].clearTail(chunkOffset(len));
}
len = size + offset;
} else if (size > unsigned(len - offset)) {
len = size + offset;
}
chunks.resize(chunksCount(len));
while (size > 0) {
size_t w = chunks[chunk].write(buf, pos, size);
size -= w;
buf += w;
++ chunk;
pos = 0;
}
return nwritten;
}
void BigBuffer::truncate(offset_t offset) {
chunks.resize(chunksCount(offset));
if (offset > len && len > 0) {
// Fill end of last non-empty chunk with zeroes
chunks[chunkNumber(len)].clearTail(chunkOffset(len));
}
len = offset;
}
ssize_t BigBuffer::zipUserFunctionCallback(void *state, void *data, size_t len, enum zip_source_cmd cmd) {
CallBackStruct *b = (CallBackStruct*)state;
switch (cmd) {
case ZIP_SOURCE_OPEN: {
b->pos = 0;
return 0;
}
case ZIP_SOURCE_READ: {
int r = b->buf->read((char*)data, len, b->pos);
b->pos += r;
return r;
}
case ZIP_SOURCE_STAT: {
struct zip_stat *st = (struct zip_stat*)data;
zip_stat_init(st);
st->size = b->buf->len;
st->mtime = b->mtime;
return sizeof(struct zip_stat);
}
case ZIP_SOURCE_FREE: {
delete b;
return 0;
}
default: {
return 0;
}
}
}
int BigBuffer::saveToZip(time_t mtime, struct zip *z, const char *fname,
bool newFile, int index) {
struct zip_source *s;
struct CallBackStruct *cbs = new CallBackStruct();
cbs->buf = this;
cbs->mtime = mtime;
if ((s=zip_source_function(z, zipUserFunctionCallback, cbs)) == NULL) {
delete cbs;
return -ENOMEM;
}
if ((newFile && zip_add(z, fname, s) < 0) || (!newFile && zip_replace(z, index, s) < 0)) {
delete cbs;
zip_source_free(s);
return -ENOMEM;
}
return 0;
}
fuse-zip-0.2.13/lib/bigBuffer.h 0000644 0000000 0000000 00000012245 11477217250 016121 0 ustar root root 0000000 0000000 ////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2010 by Alexander Galanin //
// al@galanin.nnov.ru //
// http://galanin.nnov.ru/~al //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU Lesser General Public License as //
// published by the Free Software Foundation; either version 3 of the //
// License, or (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU Lesser General Public //
// License along with this program; if not, write to the //
// Free Software Foundation, Inc., //
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
////////////////////////////////////////////////////////////////////////////
#ifndef BIG_BUFFER_H
#define BIG_BUFFER_H
#include
#include
#include
#include "types.h"
class BigBuffer {
private:
//TODO: use >> and <<
static const unsigned int chunkSize = 4*1024; //4 Kilobytes
class ChunkWrapper;
typedef std::vector chunks_t;
struct CallBackStruct {
size_t pos;
const BigBuffer *buf;
time_t mtime;
};
chunks_t chunks;
/**
* Callback for zip_source_function.
* ZIP_SOURCE_CLOSE is not needed to be handled, ZIP_SOURCE_ERROR is
* never called because read() always successfull.
* See zip_source_function(3) for details.
*/
static ssize_t zipUserFunctionCallback(void *state, void *data, size_t len, enum zip_source_cmd cmd);
/**
* Return number of chunks needed to keep 'offset' bytes.
*/
inline static unsigned int chunksCount(offset_t offset) {
return (offset + chunkSize - 1) / chunkSize;
}
/**
* Return number of chunk where 'offset'-th byte is located.
*/
inline static unsigned int chunkNumber(offset_t offset) {
return offset / chunkSize;
}
/**
* Return offset inside chunk to 'offset'-th byte.
*/
inline static int chunkOffset(offset_t offset) {
return offset % chunkSize;
}
public:
offset_t len;
/**
* Create new file buffer without mapping to file in a zip archive
*/
BigBuffer();
/**
* Read file data from file inside zip archive
*
* @param z Zip file
* @param nodeId Node index inside zip file
* @param length File length
* @throws
* std::exception On file read error
* std::bad_alloc On memory insufficiency
*/
BigBuffer(struct zip *z, int nodeId, ssize_t length);
~BigBuffer();
/**
* Dispatch read requests to chunks of a file and write result to
* resulting buffer.
* Reading after end of file is not allowed, so 'size' is decreased to
* fit file boundaries.
*
* @param buf destination buffer
* @param size requested bytes count
* @param offset offset to start reading from
* @return always 0
*/
int read(char *buf, size_t size, offset_t offset) const;
/**
* Dispatch write request to chunks of a file and grow 'chunks' vector if
* necessary.
* If 'offset' is after file end, tail of last chunk cleared before growing.
*
* @param buf Source buffer
* @param size Number of bytes to be written
* @param offset Offset in file to start writing from
* @return number of bytes written
* @throws
* std::bad_alloc If there are no memory for buffer
*/
int write(const char *buf, size_t size, offset_t offset);
/**
* Create (or replace) file element in zip file. Class instance should
* not be destroyed until zip_close() is called.
*
* @param mtime File modification time
* @param z ZIP archive structure
* @param fname File name
* @param newFile Is file not yet created?
* @param index File index in ZIP archive
* @return
* 0 If successfull
* -ENOMEM If there are no memory
*/
int saveToZip(time_t mtime, struct zip *z, const char *fname,
bool newFile, int index);
/**
* Truncate buffer at position offset.
* 1. Free chunks after offset
* 2. Resize chunks vector to a new size
* 3. Fill data block that made readable by resize with zeroes
*
* @throws
* std::bad_alloc If insufficient memory available
*/
void truncate(offset_t offset);
};
#endif
fuse-zip-0.2.13/lib/fileNode.cpp 0000644 0000000 0000000 00000016141 11477217250 016305 0 ustar root root 0000000 0000000 ////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2010 by Alexander Galanin //
// al@galanin.nnov.ru //
// http://galanin.nnov.ru/~al //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU Lesser General Public License as //
// published by the Free Software Foundation; either version 3 of the //
// License, or (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU Lesser General Public //
// License along with this program; if not, write to the //
// Free Software Foundation, Inc., //
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
////////////////////////////////////////////////////////////////////////////
#include
#include
#include
#include
#include
#include "fileNode.h"
#include "fuseZipData.h"
const int FileNode::ROOT_NODE_INDEX = -1;
const int FileNode::NEW_NODE_INDEX = -2;
FileNode::FileNode(FuseZipData *_data, const char *fname, int id): data(_data) {
this->id = id;
this->is_dir = false;
this->open_count = 0;
if (id == NEW_NODE_INDEX) {
state = NEW;
buffer = new BigBuffer();
if (!buffer) {
throw std::bad_alloc();
}
zip_stat_init(&stat);
stat.mtime = time(NULL);
stat.size = 0;
} else {
state = CLOSED;
if (id != ROOT_NODE_INDEX) {
zip_stat_index(data->m_zip, this->id, 0, &stat);
} else {
zip_stat_init(&stat);
stat.mtime = time(NULL);
stat.size = 0;
}
}
char *t = strdup(fname);
if (t == NULL) {
throw std::bad_alloc();
}
parse_name(t);
try {
attach();
}
catch (...) {
free(full_name);
throw;
}
}
FileNode::~FileNode() {
free(full_name);
if (state == OPENED || state == CHANGED || state == NEW) {
delete buffer;
}
}
void FileNode::parse_name(char *fname) {
this->full_name = fname;
if (*fname == '\0') {
// in case of root directory of a virtual filesystem
this->name = this->full_name;
this->is_dir = true;
} else {
char *lsl = full_name;
while (*lsl++) {}
lsl--;
while (lsl > full_name && *lsl != '/') {
lsl--;
}
// If the last symbol in file name is '/' then it is a directory
if (*lsl == '/' && *(lsl+1) == '\0') {
// It will produce two \0s at the end of file name. I think that it is not a problem
*lsl = '\0';
this->is_dir = true;
while (lsl > full_name && *lsl != '/') {
lsl--;
}
}
// Setting short name of node
if (*lsl == '/') {
lsl++;
}
this->name = lsl;
}
}
void FileNode::attach() {
filemap_t::const_iterator other_iter =
this->data->files.find(this->full_name);
// If Node with the same name already exists...
if (other_iter != this->data->files.end()) {
FileNode *other = other_iter->second;
if (other->id != FileNode::NEW_NODE_INDEX) {
throw std::exception();
}
// ... update existing node information
other->id = this->id;
other->stat = this->stat;
other->state = this->state;
throw AlreadyExists();
}
if (*this->full_name != '\0') {
// Adding new child to parent node. For items without '/' in fname it will be root_node.
char *lsl = this->name;
if (lsl > this->full_name) {
lsl--;
}
char c = *lsl;
*lsl = '\0';
// Searching for parent node...
filemap_t::const_iterator parent_iter = data->files.find(this->full_name);
if (parent_iter == data->files.end()) {
// Relative paths are not supported
if (strcmp(this->full_name, ".") == 0 || strcmp(this->full_name, "..") == 0) {
throw std::exception();
}
FileNode *p = new FileNode(data, this->full_name);
p->is_dir = true;
this->parent = p;
} else {
this->parent = parent_iter->second;
}
this->parent->childs.push_back(this);
*lsl = c;
}
this->data->files[this->full_name] = this;
}
void FileNode::detach() {
data->files.erase(full_name);
parent->childs.remove(this);
}
void FileNode::rename(char *fname) {
detach();
free(full_name);
parse_name(fname);
attach();
}
void FileNode::rename_wo_reparenting(char *new_name) {
data->files.erase(full_name);
free(full_name);
parse_name(new_name);
data->files[new_name] = this;
}
int FileNode::open() {
if (state == NEW) {
return 0;
}
if (state == OPENED) {
if (open_count == INT_MAX) {
return -EMFILE;
} else {
++open_count;
}
}
if (state == CLOSED) {
open_count = 1;
try {
buffer = new BigBuffer(data->m_zip, id, stat.size);
state = OPENED;
}
catch (std::bad_alloc) {
return -ENOMEM;
}
catch (std::exception) {
return -EIO;
}
}
return 0;
}
int FileNode::read(char *buf, size_t size, offset_t offset) const {
return buffer->read(buf, size, offset);
}
int FileNode::write(const char *buf, size_t size, offset_t offset) {
if (state == OPENED) {
state = CHANGED;
}
return buffer->write(buf, size, offset);
}
int FileNode::close() {
stat.size = buffer->len;
if (state == OPENED && --open_count == 0) {
delete buffer;
state = CLOSED;
}
if (state == CHANGED) {
stat.mtime = time(NULL);
}
return 0;
}
int FileNode::save() {
return buffer->saveToZip(stat.mtime, data->m_zip, full_name,
state == NEW, id);
}
int FileNode::truncate(offset_t offset) {
if (state != CLOSED) {
if (state != NEW) {
state = CHANGED;
}
try {
buffer->truncate(offset);
return 0;
}
catch (const std::bad_alloc &) {
return EIO;
}
} else {
return EBADF;
}
}
offset_t FileNode::size() const {
if (state == NEW || state == OPENED || state == CHANGED) {
return buffer->len;
} else {
return stat.size;
}
}
fuse-zip-0.2.13/lib/fileNode.h 0000644 0000000 0000000 00000006413 11477217250 015753 0 ustar root root 0000000 0000000 ////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2010 by Alexander Galanin //
// al@galanin.nnov.ru //
// http://galanin.nnov.ru/~al //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU Lesser General Public License as //
// published by the Free Software Foundation; either version 3 of the //
// License, or (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU Lesser General Public //
// License along with this program; if not, write to the //
// Free Software Foundation, Inc., //
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
////////////////////////////////////////////////////////////////////////////
#ifndef FILE_NODE_H
#define FILE_NODE_H
#include
#include "types.h"
#include "bigBuffer.h"
class FileNode {
private:
enum nodeState {
CLOSED,
OPENED,
CHANGED,
NEW
};
BigBuffer *buffer;
FuseZipData *data;
int open_count;
nodeState state;
void parse_name(char *fname);
void attach();
public:
static const int ROOT_NODE_INDEX, NEW_NODE_INDEX;
FileNode(FuseZipData *_data, const char *fname, int id = NEW_NODE_INDEX);
~FileNode();
void detach();
void rename(char *fname);
/**
* Rename file without reparenting.
*
* 1. Remove file item from tree
* 2. Free ols file name string
* 3. Parse new name
* 4. Create link to new name in tree
*/
void rename_wo_reparenting(char *new_name);
int open();
int read(char *buf, size_t size, offset_t offset) const;
int write(const char *buf, size_t size, offset_t offset);
int close();
/**
* Invoke zip_add() or zip_replace() for file to save it.
* Should be called only if item is needed to ba saved into zip file.
*
* @return 0 if success, != 0 on error
*/
int save();
/**
* Truncate file.
*
* @return
* 0 If successful
* EBADF If file is currently closed
* EIO If insufficient memory available (because ENOMEM not
* listed in truncate() error codes)
*/
int truncate(offset_t offset);
inline bool isChanged() const {
return state == CHANGED || state == NEW;
}
offset_t size() const;
char *name, *full_name;
bool is_dir;
int id;
nodelist_t childs;
FileNode *parent;
struct zip_stat stat;
class AlreadyExists {
};
};
#endif
fuse-zip-0.2.13/lib/fuse-zip.cpp 0000644 0000000 0000000 00000031041 11477217250 016316 0 ustar root root 0000000 0000000 ////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2010 by Alexander Galanin //
// al@galanin.nnov.ru //
// http://galanin.nnov.ru/~al //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU Lesser General Public License as //
// published by the Free Software Foundation; either version 3 of the //
// License, or (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU Lesser General Public //
// License along with this program; if not, write to the //
// Free Software Foundation, Inc., //
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
////////////////////////////////////////////////////////////////////////////
#define STANDARD_BLOCK_SIZE (512)
#define ERROR_STR_BUF_LEN 0x100
#include "../config.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "fuse-zip.h"
#include "types.h"
#include "fileNode.h"
#include "fuseZipData.h"
#include "libZipWrapper.h"
using namespace std;
//TODO: Move printf-s out this function
FuseZipData *initFuseZip(const char *program, const char *fileName) {
FuseZipData *data = NULL;
int err;
struct zip *zip_file;
if ((zip_file = zip_open(fileName, ZIP_CREATE, &err)) == NULL) {
char err_str[ERROR_STR_BUF_LEN];
zip_error_to_str(err_str, ERROR_STR_BUF_LEN, err, errno);
fprintf(stderr, "%s: cannot open zip archive %s: %s\n", program, fileName, err_str);
return data;
}
try {
// current working directory
char *cwd = (char*)malloc(PATH_MAX + 1);
if (getcwd(cwd, PATH_MAX) == NULL) {
perror(NULL);
return data;
}
data = new FuseZipData(fileName, zip_file, cwd);
if (data == NULL) {
throw std::bad_alloc();
}
}
catch (std::bad_alloc) {
fprintf(stderr, "%s: no enough memory\n", program);
}
catch (std::exception) {
fprintf(stderr, "%s: ZIP file corrupted\n", program);
}
return data;
}
void *fusezip_init(struct fuse_conn_info *conn) {
(void) conn;
FuseZipData *data = (FuseZipData*)fuse_get_context()->private_data;
syslog(LOG_INFO, "Mounting file system on %s (cwd=%s)", data->m_archiveName, data->m_cwd);
return data;
}
void fusezip_destroy(void *data) {
FuseZipData *d = (FuseZipData*)data;
// Saving changed data
for (filemap_t::const_iterator i = d->files.begin(); i != d->files.end(); ++i) {
if (i->second->isChanged() && !i->second->is_dir) {
int res = i->second->save();
if (res != 0) {
syslog(LOG_ERR, "Error while saving file %s in ZIP archive: %d", i->second->full_name, res);
}
}
}
delete d;
syslog(LOG_INFO, "File system unmounted");
}
inline FuseZipData *get_data() {
return (FuseZipData*)fuse_get_context()->private_data;
}
FileNode *get_file_node(const char *fname) {
FuseZipData *data = get_data();
filemap_t::iterator i = data->files.find(fname);
if (i == data->files.end()) {
return NULL;
} else {
return i->second;
}
}
inline struct zip *get_zip() {
return get_data()->m_zip;
}
int fusezip_getattr(const char *path, struct stat *stbuf) {
memset(stbuf, 0, sizeof(struct stat));
if (*path == '\0') {
return -ENOENT;
}
FileNode *node = get_file_node(path + 1);
if (node == NULL) {
return -ENOENT;
}
struct zip_stat_64 zstat;
zip_stat_assign_64_to_default(&zstat, &node->stat);
if (node->is_dir) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2 + node->childs.size();
} else {
stbuf->st_mode = S_IFREG | 0644;
stbuf->st_nlink = 1;
}
stbuf->st_blksize = STANDARD_BLOCK_SIZE;
stbuf->st_ino = node->id;
stbuf->st_blocks = (node->size() + STANDARD_BLOCK_SIZE - 1) / STANDARD_BLOCK_SIZE;
stbuf->st_size = node->size();
stbuf->st_atime = stbuf->st_mtime = stbuf->st_ctime = zstat.mtime;
stbuf->st_uid = geteuid();
stbuf->st_gid = getegid();
return 0;
}
int fusezip_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) {
(void) offset;
(void) fi;
if (*path == '\0') {
return -ENOENT;
}
FileNode *node = get_file_node(path + 1);
if (node == NULL) {
return -ENOENT;
}
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
for (nodelist_t::const_iterator i = node->childs.begin(); i != node->childs.end(); ++i) {
filler(buf, (*i)->name, NULL, 0);
}
return 0;
}
int fusezip_statfs(const char *path, struct statvfs *buf) {
(void) path;
// Getting amount of free space in directory with archive
struct statvfs st;
int err;
if ((err = statvfs(get_data()->m_cwd,&st)) != 0) {
return -err;
}
buf->f_bavail = buf->f_bfree = st.f_frsize * st.f_bavail;
buf->f_bsize = 1;
//TODO: may be append archive size?
buf->f_blocks = buf->f_bavail + 0;
buf->f_ffree = 0;
buf->f_favail = 0;
buf->f_files = get_data()->files.size() - 1;
buf->f_namemax = 255;
return 0;
}
int fusezip_open(const char *path, struct fuse_file_info *fi) {
if (*path == '\0') {
return -ENOENT;
}
FileNode *node = get_file_node(path + 1);
if (node == NULL) {
return -ENOENT;
}
if (node->is_dir) {
return -EISDIR;
}
fi->fh = (uint64_t)node;
try {
return node->open();
}
catch (std::bad_alloc) {
return -ENOMEM;
}
catch (std::exception) {
return -EIO;
}
}
int fusezip_create(const char *path, mode_t mode, struct fuse_file_info *fi) {
(void) mode;
if (*path == '\0') {
return -EACCES;
}
FileNode *node = get_file_node(path + 1);
if (node != NULL) {
return -EEXIST;
}
node = new FileNode(get_data(), path + 1);
if (!node) {
return -ENOMEM;
}
fi->fh = (uint64_t)node;
return node->open();
}
int fusezip_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
(void) path;
return ((FileNode*)fi->fh)->read(buf, size, offset);
}
int fusezip_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
(void) path;
return ((FileNode*)fi->fh)->write(buf, size, offset);
}
int fusezip_release (const char *path, struct fuse_file_info *fi) {
(void) path;
return ((FileNode*)fi->fh)->close();
}
int fusezip_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi) {
(void) path;
return -((FileNode*)fi->fh)->truncate(offset);
}
int fusezip_truncate(const char *path, off_t offset) {
if (*path == '\0') {
return -EACCES;
}
FileNode *node = get_file_node(path + 1);
if (node == NULL) {
return -ENOENT;
}
if (node->is_dir) {
return -EISDIR;
}
int res;
if ((res = node->open()) != 0) {
return res;
}
if ((res = node->truncate(offset)) != 0) {
node->close();
return -res;
}
return node->close();
}
int fusezip_unlink(const char *path) {
if (*path == '\0') {
return -ENOENT;
}
FileNode *node = get_file_node(path + 1);
if (node == NULL) {
return -ENOENT;
}
if (node->is_dir) {
return -EISDIR;
}
return -get_data()->removeNode(node);
}
int fusezip_rmdir(const char *path) {
if (*path == '\0') {
return -ENOENT;
}
FileNode *node = get_file_node(path + 1);
if (node == NULL) {
return -ENOENT;
}
if (!node->is_dir) {
return -ENOTDIR;
}
if (!node->childs.empty()) {
return -ENOTEMPTY;
}
return -get_data()->removeNode(node);
}
int fusezip_mkdir(const char *path, mode_t mode) {
(void) mode;
if (*path == '\0') {
return -ENOENT;
}
int idx = zip_add_dir(get_zip(), path + 1);
if (idx < 0) {
return -ENOMEM;
}
FileNode *node = new FileNode(get_data(), path + 1, idx);
if (!node) {
return -ENOMEM;
}
node->is_dir = true;
return 0;
}
int fusezip_rename(const char *path, const char *new_path) {
if (*path == '\0') {
return -ENOENT;
}
FileNode *node = get_file_node(path + 1);
if (node == NULL) {
return -ENOENT;
}
if (*new_path == '\0') {
return -EINVAL;
}
FileNode *new_node = get_file_node(new_path + 1);
if (new_node != NULL) {
int res = get_data()->removeNode(new_node);
if (res !=0) {
return -res;
}
}
int len = strlen(new_path);
int oldLen = strlen(path + 1) + 1;
char *new_name;
if (!node->is_dir) {
--len;
--oldLen;
}
new_name = (char*)malloc(len + 1);
if (new_path == NULL) {
return -ENOMEM;
}
strcpy(new_name, new_path + 1);
if (node->is_dir) {
new_name[len - 1] = '/';
new_name[len] = '\0';
}
try {
struct zip *z = get_zip();
// Renaming directory and its content recursively
if (node->is_dir) {
queue q;
q.push(node);
while (!q.empty()) {
FileNode *n = q.front();
q.pop();
for (nodelist_t::const_iterator i = n->childs.begin(); i != n->childs.end(); ++i) {
FileNode *nn = *i;
q.push(nn);
char *name = (char*)malloc(len + strlen(nn->full_name) - oldLen + (nn->is_dir ? 2 : 1));
if (name == NULL) {
//TODO: check that we are have enough memory before entering this loop
return -ENOMEM;
}
strcpy(name, new_name);
strcpy(name + len, nn->full_name + oldLen);
if (nn->is_dir) {
strcat(name, "/");
}
zip_rename(z, nn->id, name);
nn->rename_wo_reparenting(name);
}
}
}
zip_rename(z, node->id, new_name);
// Must be called after loop because new_name will be truncated
node->rename(new_name);
return 0;
}
catch (...) {
return -EIO;
}
}
int fusezip_utimens(const char *path, const struct timespec tv[2]) {
if (*path == '\0') {
return -ENOENT;
}
FileNode *node = get_file_node(path + 1);
if (node == NULL) {
return -ENOENT;
}
node->stat.mtime = tv[1].tv_sec;
return 0;
}
#if ( __FreeBSD__ >= 10 )
int fusezip_setxattr(const char *, const char *, const char *, size_t, int, uint32_t) {
#else
int fusezip_setxattr(const char *, const char *, const char *, size_t, int) {
#endif
return -ENOTSUP;
}
#if ( __FreeBSD__ >= 10 )
int fusezip_getxattr(const char *, const char *, char *, size_t, uint32_t) {
#else
int fusezip_getxattr(const char *, const char *, char *, size_t) {
#endif
return -ENOTSUP;
}
int fusezip_listxattr(const char *, char *, size_t) {
return -ENOTSUP;
}
int fusezip_removexattr(const char *, const char *) {
return -ENOTSUP;
}
int fusezip_chmod(const char *, mode_t) {
return 0;
}
int fusezip_chown(const char *, uid_t, gid_t) {
return 0;
}
int fusezip_flush(const char *, struct fuse_file_info *) {
return 0;
}
int fusezip_fsync(const char *, int, struct fuse_file_info *) {
return 0;
}
int fusezip_fsyncdir(const char *, int, struct fuse_file_info *) {
return 0;
}
int fusezip_opendir(const char *, struct fuse_file_info *) {
return 0;
}
int fusezip_releasedir(const char *, struct fuse_file_info *) {
return 0;
}
int fusezip_access(const char *, int) {
return 0;
}
fuse-zip-0.2.13/lib/fuse-zip.h 0000644 0000000 0000000 00000010442 11477217250 015765 0 ustar root root 0000000 0000000 ////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2010 by Alexander Galanin //
// al@galanin.nnov.ru //
// http://galanin.nnov.ru/~al //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU Lesser General Public License as //
// published by the Free Software Foundation; either version 3 of the //
// License, or (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU Lesser General Public //
// License along with this program; if not, write to the //
// Free Software Foundation, Inc., //
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
////////////////////////////////////////////////////////////////////////////
#ifndef FUSE_ZIP_H
#define FUSE_ZIP_H
/**
* Main functions of fuse-zip file system (to be called by FUSE library)
*/
extern "C" {
/**
* Initialize libzip and fuse-zip structures.
*
* @param program Program name
* @param fileName ZIP file name
* @return NULL if an error occured, otherwise pointer to FuseZipData structure.
*/
class FuseZipData *initFuseZip(const char *program, const char *fileName);
/**
* Initialize filesystem
*
* Report current working dir and archive file name to syslog.
*
* @return filesystem-private data
*/
void *fusezip_init(struct fuse_conn_info *conn);
/**
* Destroy filesystem
*
* Save all modified data back to ZIP archive and report to syslog about completion.
* Note that filesystem unmounted before this method finishes
* (see http://code.google.com/p/fuse-zip/issues/detail?id=7).
*/
void fusezip_destroy(void *data);
int fusezip_getattr(const char *path, struct stat *stbuf);
int fusezip_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi);
int fusezip_statfs(const char *path, struct statvfs *buf);
int fusezip_open(const char *path, struct fuse_file_info *fi);
int fusezip_create(const char *path, mode_t mode, struct fuse_file_info *fi);
int fusezip_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi);
int fusezip_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi);
int fusezip_release (const char *path, struct fuse_file_info *fi);
int fusezip_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi);
int fusezip_truncate(const char *path, off_t offset);
int fusezip_unlink(const char *path);
int fusezip_rmdir(const char *path);
int fusezip_mkdir(const char *path, mode_t mode);
int fusezip_rename(const char *path, const char *new_path);
int fusezip_utimens(const char *path, const struct timespec tv[2]);
#if ( __FreeBSD__ >= 10 )
int fusezip_setxattr(const char *, const char *, const char *, size_t, int, uint32_t);
int fusezip_getxattr(const char *, const char *, char *, size_t, uint32_t);
#else
int fusezip_setxattr(const char *, const char *, const char *, size_t, int);
int fusezip_getxattr(const char *, const char *, char *, size_t);
#endif
int fusezip_listxattr(const char *, char *, size_t);
int fusezip_removexattr(const char *, const char *);
int fusezip_chmod(const char *, mode_t);
int fusezip_chown(const char *, uid_t, gid_t);
int fusezip_flush(const char *, struct fuse_file_info *);
int fusezip_fsync(const char *, int, struct fuse_file_info *);
int fusezip_fsyncdir(const char *, int, struct fuse_file_info *);
int fusezip_opendir(const char *, struct fuse_file_info *);
int fusezip_releasedir(const char *, struct fuse_file_info *);
int fusezip_access(const char *, int);
}
#endif
fuse-zip-0.2.13/lib/fuseZipData.cpp 0000644 0000000 0000000 00000005775 11477217250 017012 0 ustar root root 0000000 0000000 ////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2010 by Alexander Galanin //
// al@galanin.nnov.ru //
// http://galanin.nnov.ru/~al //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU Lesser General Public License as //
// published by the Free Software Foundation; either version 3 of the //
// License, or (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU Lesser General Public //
// License along with this program; if not, write to the //
// Free Software Foundation, Inc., //
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
////////////////////////////////////////////////////////////////////////////
#include
#include
#include
#include "fuseZipData.h"
FuseZipData::FuseZipData(const char *archiveName, struct zip *z, char *cwd): m_zip(z), m_archiveName(archiveName), m_cwd(cwd) {
if (cwd == NULL) {
throw std::bad_alloc();
}
build_tree();
}
FuseZipData::~FuseZipData() {
if (chdir(m_cwd) != 0) {
syslog(LOG_ERR, "Unable to chdir() to archive directory %s. Trying to save file into /tmp", m_cwd);
if (chdir(getenv("TMP")) != 0) {
chdir("/tmp");
}
}
int res = zip_close(m_zip);
if (res != 0) {
syslog(LOG_ERR, "Error while closing archive: %s", zip_strerror(m_zip));
}
for (filemap_t::iterator i = files.begin(); i != files.end(); ++i) {
delete i->second;
}
free(m_cwd);
}
void FuseZipData::build_tree() {
FileNode *root_node = new FileNode(this, "", FileNode::ROOT_NODE_INDEX);
root_node->is_dir = true;
int n = zip_get_num_files(m_zip);
for (int i = 0; i < n; ++i) {
const char *name = zip_get_name(m_zip, i, 0);
try {
FileNode *node = new FileNode(this, name, i);
(void) node;
}
catch (const FileNode::AlreadyExists &e) {
// Only need to skip node creation
}
}
}
int FuseZipData::removeNode(FileNode *node) const {
node->detach();
int id = node->id;
delete node;
if (id >= 0) {
return (zip_delete (m_zip, id) == 0)? 0 : ENOENT;
} else {
return 0;
}
}
fuse-zip-0.2.13/lib/fuseZipData.h 0000644 0000000 0000000 00000004405 11477217250 016444 0 ustar root root 0000000 0000000 ////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2010 by Alexander Galanin //
// al@galanin.nnov.ru //
// http://galanin.nnov.ru/~al //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU Lesser General Public License as //
// published by the Free Software Foundation; either version 3 of the //
// License, or (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU Lesser General Public //
// License along with this program; if not, write to the //
// Free Software Foundation, Inc., //
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
////////////////////////////////////////////////////////////////////////////
#ifndef FUSEZIP_DATA
#define FUSEZIP_DATA
#include "types.h"
#include "fileNode.h"
class FuseZipData {
private:
void build_tree();
public:
filemap_t files;
struct zip *m_zip;
const char *m_archiveName;
char *m_cwd;
/**
* Keep archiveName and cwd in class fields and build file tree from z.
*
* 'cwd' and 'z' free()-ed in destructor.
* 'archiveName' should be managed externally.
*/
FuseZipData(const char *archiveName, struct zip *z, char *cwd);
~FuseZipData();
/**
* Detach node from tree, and delete associated entry in zip file if
* present.
*
* @param node Node to remove
* @return Error code or 0 is successful
*/
int removeNode(FileNode *node) const;
};
#endif
fuse-zip-0.2.13/lib/libZipWrapper.cpp 0000644 0000000 0000000 00000003672 11477217250 017357 0 ustar root root 0000000 0000000 ////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2010 by Alexander Galanin //
// al@galanin.nnov.ru //
// http://galanin.nnov.ru/~al //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU Lesser General Public License as //
// published by the Free Software Foundation; either version 3 of the //
// License, or (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU Lesser General Public //
// License along with this program; if not, write to the //
// Free Software Foundation, Inc., //
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
////////////////////////////////////////////////////////////////////////////
#include
#include "libZipWrapper.h"
void zip_stat_assign_64_to_default(struct zip_stat_64 *dest, const struct zip_stat *src) {
dest->name = src->name;
dest->index = src->index;
dest->crc = src->crc;
dest->mtime = src->mtime;
dest->comp_method = src->comp_method;
dest->encryption_method = src->encryption_method;
dest->size = offset_t(src->size);
dest->comp_size = offset_t(src->comp_size);
}
fuse-zip-0.2.13/lib/libZipWrapper.h 0000644 0000000 0000000 00000005204 11477217250 017015 0 ustar root root 0000000 0000000 ////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2010 by Alexander Galanin //
// al@galanin.nnov.ru //
// http://galanin.nnov.ru/~al //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU Lesser General Public License as //
// published by the Free Software Foundation; either version 3 of the //
// License, or (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU Lesser General Public //
// License along with this program; if not, write to the //
// Free Software Foundation, Inc., //
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
////////////////////////////////////////////////////////////////////////////
#ifndef LIBZIPWRAPPER_H
#define LIBZIPWRAPPER_H
//
// This is compatibility layer to support libzip compiled without large file
// support on 32-bit system.
//
// If on your system libzip compiled with -D_FILE_OFFSET_BITS=64 then you must
// add -D_FILE_OFFSET_BITS=64 to CXXFLAGS when running make.
//
// make CXXFLAGS="$CXXFLAGS -D_FILE_OFFSET_BITS=64" clean all
//
#include
#include
#include
#include "types.h"
struct zip_stat_64 {
const char *name; /* name of the file */
int index; /* index within archive */
unsigned int crc; /* crc of file data */
time_t mtime; /* modification time */
//modified type
offset_t size; /* size of file (uncompressed) */
//modified type
offset_t comp_size; /* size of file (compressed) */
unsigned short comp_method; /* compression method used */
unsigned short encryption_method; /* encryption method used */
};
void zip_stat_assign_64_to_default(struct zip_stat_64 *dest, const struct zip_stat *src);
#endif
fuse-zip-0.2.13/lib/types.h 0000644 0000000 0000000 00000003763 11477217250 015377 0 ustar root root 0000000 0000000 ////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2008-2010 by Alexander Galanin //
// al@galanin.nnov.ru //
// http://galanin.nnov.ru/~al //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU Lesser General Public License as //
// published by the Free Software Foundation; either version 3 of the //
// License, or (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU Lesser General Public //
// License along with this program; if not, write to the //
// Free Software Foundation, Inc., //
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
////////////////////////////////////////////////////////////////////////////
#ifndef FUSEZIP_TYPES_H
#define FUSEZIP_TYPES_H
#include
#include
#include
#include
#include