first import
This commit is contained in:
62
src/Makefile.am
Normal file
62
src/Makefile.am
Normal file
@ -0,0 +1,62 @@
|
||||
## Makefile for program src directory in davfs.
|
||||
## Copyright (C) 2006, 2007, 2008, 2009 Werner Baumann
|
||||
##
|
||||
## This file is part of davfs2.
|
||||
##
|
||||
## davfs2 is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## davfs2 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 General Public License
|
||||
## along with davfs2; if not, write to the Free Software Foundation,
|
||||
## Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
localedir = $(datadir)/locale
|
||||
pkgsysconfdir = $(sysconfdir)/@PACKAGE@
|
||||
pkglocalstatedir = $(dav_localstatedir)/mount.davfs
|
||||
pkgsyscachedir = $(dav_syscachedir)/@PACKAGE@
|
||||
ssbindir = @ssbindir@
|
||||
|
||||
sbin_PROGRAMS = mount.davfs umount.davfs
|
||||
mount_davfs_SOURCES = cache.c dav_coda.c \
|
||||
dav_fuse.c kernel_interface.c mount_davfs.c webdav.c \
|
||||
cache.h coda.h defaults.h fuse_kernel.h \
|
||||
kernel_interface.h mount_davfs.h webdav.h
|
||||
umount_davfs_SOURCES = umount_davfs.c defaults.h
|
||||
|
||||
AM_CFLAGS = -Wall
|
||||
DEFS = -DPROGRAM_NAME=\"mount.davfs\" \
|
||||
-DDAV_SYS_CONF_DIR=\"$(pkgsysconfdir)\" \
|
||||
-DDAV_SYS_RUN=\"$(pkglocalstatedir)\" \
|
||||
-DDAV_SYS_CACHE=\"$(pkgsyscachedir)\" \
|
||||
-DDAV_SECRETS=\"secrets\" \
|
||||
-DDAV_CONFIG=\"$(PACKAGE).conf\" \
|
||||
-DDAV_CERTS_DIR=\"certs\" \
|
||||
-DDAV_CLICERTS_DIR=\"private\" \
|
||||
-DDAV_DATA_DIR=\"$(pkgdatadir)\" \
|
||||
-DLOCALEDIR=\"$(localedir)\" \
|
||||
-DDAV_USER=\"$(dav_user)\" \
|
||||
-DDAV_GROUP=\"$(dav_group)\" @DEFS@
|
||||
LIBS = $(NEON_LIBS) @LIBS@
|
||||
|
||||
install-exec-hook:
|
||||
chmod u+s $(DESTDIR)$(sbindir)/mount.davfs; \
|
||||
if test "$(sbindir)" != "$(ssbindir)"; then \
|
||||
$(mkinstalldirs) $(DESTDIR)$(ssbindir); \
|
||||
$(LN_S) -f $(DESTDIR)$(sbindir)/mount.davfs $(DESTDIR)$(ssbindir)/mount.davfs; \
|
||||
$(LN_S) -f $(DESTDIR)$(sbindir)/umount.davfs $(DESTDIR)$(ssbindir)/umount.davfs; \
|
||||
fi
|
||||
|
||||
uninstall-hook:
|
||||
if test "$(sbindir)" != "$(ssbindir)"; then \
|
||||
rm -f $(DESTDIR)$(ssbindir)/mount.davfs; \
|
||||
rm -f $(DESTDIR)$(ssbindir)/umount.davfs; \
|
||||
fi
|
3692
src/cache.c
Normal file
3692
src/cache.c
Normal file
File diff suppressed because it is too large
Load Diff
428
src/cache.h
Normal file
428
src/cache.h
Normal file
@ -0,0 +1,428 @@
|
||||
/* cache.h: directory and file cache.
|
||||
Copyright (C) 2006, 2007, 2008, 2009 Werner Baumann
|
||||
|
||||
This file is part of davfs2.
|
||||
|
||||
davfs2 is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
davfs2 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 General Public License
|
||||
along with davfs2; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
|
||||
#ifndef DAV_CACHE_H
|
||||
#define DAV_CACHE_H
|
||||
|
||||
|
||||
/* Constants */
|
||||
/*===========*/
|
||||
|
||||
/* A mask to separate access bits from mode. */
|
||||
#define DAV_A_MASK (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX)
|
||||
|
||||
|
||||
/* Data Types */
|
||||
/*============*/
|
||||
|
||||
/* File descriptors for open files are stored within a dav_node in a linked
|
||||
list. As coda does not return the file descriptor when closing a file,
|
||||
this data structure contains additional information to identify the
|
||||
appropriate file descriptor. */
|
||||
typedef struct dav_handle dav_handle;
|
||||
struct dav_handle {
|
||||
dav_handle *next; /* Next in the list. */
|
||||
int fd; /* File descriptor of the open file. */
|
||||
int flags; /* Access mode flags only. */
|
||||
pid_t pid; /* id of requesting process. */
|
||||
pid_t pgid; /* Group id of requesting process. */
|
||||
uid_t uid; /* User id of requesting process. */
|
||||
};
|
||||
|
||||
|
||||
/* A node in the cache. It represents a directory or a regular file.
|
||||
Nodes that are direct childs of the same directory-node are linked together
|
||||
by the next-pointer to a linked list.
|
||||
The hierarchical directory structure is formed by pointers to the parent
|
||||
direcotry and to the first member in the linked list of direct childs.
|
||||
Nodes are also stored in a hash table. The hash is derived from the nodes
|
||||
address. Nodes with the same hash value are linked together by table_next. */
|
||||
typedef struct dav_node dav_node;
|
||||
struct dav_node {
|
||||
/* The parent directory. */
|
||||
dav_node *parent;
|
||||
/* The first node in the linked list of childs. Will be NULL for files.*/
|
||||
dav_node *childs;
|
||||
/* The next node in the linked list of childs. */
|
||||
dav_node *next;
|
||||
/* The next node in the linked list of nodes with the same hash value. */
|
||||
dav_node *table_next;
|
||||
/* The unescaped absolute path of the resource on the server. This must
|
||||
conform to RFC 2518. For collections it must have a trailing slash, for
|
||||
non-collections it must not have one. */
|
||||
char *path;
|
||||
/* The name of the node (not path) without leading or trailing slash. The
|
||||
name of the root node is the empty string. Name may be different from
|
||||
the last component of path if the servers uses display-names. */
|
||||
char *name;
|
||||
/* Path of the file where the contents of the node is cached. These files
|
||||
are only created when needed, and they are deleted when there is
|
||||
information that the contents is no langer valid.
|
||||
So cache_path may be NULL.
|
||||
For directories: A file containing the directory entries.
|
||||
For regular files: A local copy of the file.
|
||||
File times are set according the values from the server when the file
|
||||
is downloaded. As long as the file is cached only dav_set_attr() may
|
||||
changed file attributes directly, but they may be changed by open,
|
||||
read, write and close. */
|
||||
char *cache_path;
|
||||
/* Etag from the server. Set when the resource is downloaded. Used for
|
||||
conditional GET requests and to detect whether a resource has been
|
||||
changed remotely. If present it overrides information from the
|
||||
Last-Modified time (smtime). */
|
||||
char *etag;
|
||||
/* The media-type as in HTTP-header Content-Type. */
|
||||
char *mime_type;
|
||||
/* A linked list of handles for open files. */
|
||||
dav_handle *handles;
|
||||
/* Size of the contents of the node.
|
||||
Files: Initially set to the value of the content-lenght header. When
|
||||
the file is open it is updated to the size of the cached file.
|
||||
Directories: Size of the file containing the directory entries. */
|
||||
off_t size;
|
||||
/* Initially set to the value of mtime. Updated by some upcalls
|
||||
Files: When a local copy exists its atime is also used for update. */
|
||||
time_t atime;
|
||||
/* Initially set to the last-modified time from the server, or the system
|
||||
time if created locally.
|
||||
Files: When a local cache file exists updated to mtime of this cache file.
|
||||
Used to evaluate whether a file is dirty. */
|
||||
time_t mtime;
|
||||
/* Initially set to the value of mtime. Updated by dav_setattr(). */
|
||||
time_t ctime;
|
||||
/* Files: Last-modified time from the server. Like etag frozen when the
|
||||
file is opened for writing. Used to check whether the file has
|
||||
been changed remotely. */
|
||||
time_t smtime;
|
||||
/* Time when the node has last been updated from the server. */
|
||||
time_t utime;
|
||||
/* Files: Time when the lock expires.
|
||||
0 if not locked. -1 locked infinitely. */
|
||||
time_t lock_expire;
|
||||
/* Directories: Number of subdirectories, including "." and "..".
|
||||
Files: Allways 1. */
|
||||
int nref;
|
||||
/* Files: File exists on the server. For locally created files that have
|
||||
not been put to the server it will be 0.
|
||||
Note: Some server create an empty file when locking. Maybe the RFC will
|
||||
be changed this way. */
|
||||
int remote_exists;
|
||||
/* Files: Dirty flag. Must be set, when a file is opened for writing, and
|
||||
reset, when the file is saved back. */
|
||||
int dirty;
|
||||
/* mode, uid and gid are initially set to the default values, but may be
|
||||
changed by dav_setattr(). */
|
||||
mode_t mode;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
};
|
||||
|
||||
|
||||
/* An item in a linked list. Each item holds a pointer to a dav_node.*/
|
||||
typedef struct dav_node_item dav_node_list_item;
|
||||
struct dav_node_item {
|
||||
dav_node_list_item *next;
|
||||
dav_node *node;
|
||||
time_t save_at;
|
||||
};
|
||||
|
||||
|
||||
/* Returned by dav_statfs(). */
|
||||
typedef struct dav_stat dav_stat;
|
||||
struct dav_stat {
|
||||
off_t blocks;
|
||||
off_t bfree;
|
||||
off_t bavail;
|
||||
off_t files;
|
||||
off_t ffree;
|
||||
off_t bsize;
|
||||
off_t namelen;
|
||||
};
|
||||
|
||||
|
||||
/* Call back function that writes a directory entry to file descriptor fd.
|
||||
fd : An open file descriptor to write to.
|
||||
off : The current file size.
|
||||
node : The pointer to node is taken as inode/file number (shrinked to
|
||||
fit if necessary).
|
||||
name : File name; if NULL, the last, empty entry is written (if the
|
||||
kernel file system wants one).
|
||||
return value : New size of the file. -1 in case of an error. */
|
||||
typedef off_t (*dav_write_dir_entry_fn)(int fd, off_t off, const dav_node *node,
|
||||
const char *name);
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
/*=====================*/
|
||||
|
||||
/* Initializing and closing the cache. */
|
||||
|
||||
/* Sets a lot of private global variables that govern the behaviour of the
|
||||
cache, taking the values from parameters.
|
||||
It registers dummy functions for the callbacks from kernel interface.
|
||||
Creates the root node and restores the nodes from the permanent cache.
|
||||
Finally it retrieves the root directory entries from the server.
|
||||
If the connection to the server fails because of authentication failure
|
||||
it prints an error message and terminates the programm. If the connection
|
||||
fails due to other reasons, it will nevertheless return with success, as the
|
||||
filesystem can be mounted, but will only get useable when the connection
|
||||
comes up.
|
||||
paramters: if not self explaining, please see mount_davfs.c, struct args. */
|
||||
void
|
||||
dav_init_cache(const dav_args *args, const char *mpoint);
|
||||
|
||||
|
||||
/* Tries to write back to the server all open files that have been changed or
|
||||
newly created. If a file from cache can not be stored back to the server,
|
||||
a local backup file is created. All local copies of files and the necessary
|
||||
directories are stored in the permanent cache. A new index file of the
|
||||
permanent cache is created.
|
||||
If got_sigterm is 1, dirty files will not be stored back to the server.
|
||||
Finally it frees all nodes. */
|
||||
void
|
||||
dav_close_cache(int got_sigterm);
|
||||
|
||||
|
||||
/* Registers the kernel_interface.
|
||||
Sets pointers to the write_dir_entry_fn flush_flag.
|
||||
If blksize is not NULL, the preferred bloksize for IO is asigned.
|
||||
It returns the value of alignment. */
|
||||
size_t
|
||||
dav_register_kernel_interface(dav_write_dir_entry_fn write_fn, int *flush_flag,
|
||||
unsigned int *blksize);
|
||||
|
||||
|
||||
/* Scans the hash table for file nodes to be saved them back on the server,
|
||||
locks to be refreshed and locks to be released.
|
||||
If maximum cache size is reached, it removes the file with the lowest
|
||||
access time from the cache.
|
||||
It must be called regularly.
|
||||
The return value indicates whether another run would be useful.
|
||||
return value: 0 there is nothing left to do.
|
||||
1 another call of dav_tidy_cache would be useful. */
|
||||
int
|
||||
dav_tidy_cache(void);
|
||||
|
||||
|
||||
/* Upcalls from the kernel, via the interface module. */
|
||||
|
||||
/* All these functions will first check if the node addressed in the
|
||||
parameters exists.
|
||||
|
||||
Common parameters (not all of this must be present in one function):
|
||||
dav_node **nodep : Used to return a pointer to a node.
|
||||
dav_node *node : A pointer to the node that shall be acted on.
|
||||
dav_node *parent : A pointer to the parent directory of the node in question.
|
||||
const char *name : Name of the node in question. It's is just one name, not
|
||||
a path, and without any trailing or leading slashes.
|
||||
uid_t uid : ID of the user that requested the operation.
|
||||
|
||||
Common return values:
|
||||
0 Success.
|
||||
EACCES Access is denied to user uid according to the acces bits.
|
||||
EAGAIN A temporary failure in the connection to the WebDAV server.
|
||||
EBUSY The action on the node can not be performed, as somebody else uses
|
||||
it allready in a way that would collide with the requested action.
|
||||
EEXIST Cration of a new node is requested with flag O_EXCL, but it exists.
|
||||
EINVAL One of the parameters has an invalid value.
|
||||
EIO Error performing I/O-operation. Usually there are problems in the
|
||||
communication with the WebDAV server.
|
||||
EISDIR The node is a directory but should not be.
|
||||
ENOENT The file or directory does not exist.
|
||||
ENOSPC There is not enough space on the server.
|
||||
ENOTDIR The node is not a directory but the requested action needs it to be.
|
||||
EPERM The reuested action is not allowed to user uid. */
|
||||
|
||||
|
||||
/* Tests whether user uid has access described by how to node.
|
||||
int how : A bit mask describing the kind of acces. It may be any combination
|
||||
of R_OK, W_OK, X_OK and F_OK. */
|
||||
int
|
||||
dav_access(dav_node *node, uid_t uid, int how);
|
||||
|
||||
|
||||
/* Closed file descriptor fd of node.
|
||||
Permissions are not checked, but flags are compared to the ones used for
|
||||
opening. If fd is 0 (coda), flags, pid and pgid are used to find the best
|
||||
matching file descriptor.
|
||||
Only access mode bits must be set in flags.*/
|
||||
int
|
||||
dav_close(dav_node *node, int fd, int flags, pid_t pid, pid_t pgid);
|
||||
|
||||
|
||||
/* Creates a new file node with name name in directory parent. The file is
|
||||
locked on the server. The new node is returned in nodep.
|
||||
There must no node with name name allready exist in parent.
|
||||
The new node is owned by uid; group is the primary group of uid. Mode is
|
||||
set to mode, but with the bits from file_umask removed.
|
||||
Permissions:
|
||||
uid must have execute permission for parent and all of its ancestors, as
|
||||
well as write permission for parent. */
|
||||
int
|
||||
dav_create(dav_node **nodep, dav_node *parent, const char *name, uid_t uid,
|
||||
mode_t mode);
|
||||
|
||||
|
||||
/* Checks whether node exists and uid has permissions. The kernel interface
|
||||
may then translate attributes from node.
|
||||
Permissions:
|
||||
uid must have execute permission for parent and all of its ancestors, as
|
||||
well as read permission for parent. */
|
||||
int
|
||||
dav_getattr(dav_node *node, uid_t uid);
|
||||
|
||||
|
||||
/* Checks whether node exists and uid has permissions. The value of
|
||||
extended attribute name is copied into buf. If its size is greater
|
||||
than size, EOVERFLOW is returned.
|
||||
Permissions:
|
||||
uid must have execute permission for parent and all of its ancestors, as
|
||||
well as read permission for parent. */
|
||||
int
|
||||
dav_getxattr(dav_node *node, const char *name, char *buf, size_t *size,
|
||||
uid_t uid);
|
||||
|
||||
|
||||
/* Returns the list of supported extended attributes. This is just
|
||||
user.mime_type. */
|
||||
int
|
||||
dav_listxattr(dav_node *node, char *buf, size_t *size, uid_t uid);
|
||||
|
||||
|
||||
/* Searches for a node with name name in the directory parent and returns the
|
||||
node in nodep.
|
||||
Permissions:
|
||||
uid must have execute permission for parent and all of its ancestors, as
|
||||
well as read permission for parent. */
|
||||
int
|
||||
dav_lookup(dav_node **nodep, dav_node *parent, const char *name, uid_t uid);
|
||||
|
||||
|
||||
/* Creates a new directory named name in direcotry parent. The directory must
|
||||
not yet exist. The new node is returned in nodep.
|
||||
Owner will be uid, group the primary group of uid. Mode will be mode with
|
||||
the bits from dir_umask removed.
|
||||
Permissions:
|
||||
uid must have execute permission for parent and all of its ancestors, as
|
||||
well as write permission for parent. */
|
||||
int
|
||||
dav_mkdir(dav_node **nodep, dav_node *parent, const char *name, uid_t uid,
|
||||
mode_t mode);
|
||||
|
||||
|
||||
/* Opens file or directory node according to flags and returns file descriptor
|
||||
fd. fd, together with pid, pgid and uid, is stored in node for read, write
|
||||
and close operations.
|
||||
Only the O_ACCESSMOE, O_APPEND and O_TRUNC bits in flags will be honoured.
|
||||
O_CREATE and O_EXCL are not allowed.
|
||||
Permissions:
|
||||
uid must have execute permission for parent and all of its ancestors, as
|
||||
as well as read and/or write permission for node, according to the
|
||||
accessmode. */
|
||||
int
|
||||
dav_open(int *fd, dav_node *node, int flags, pid_t pid, pid_t pgid, uid_t uid);
|
||||
|
||||
/* Reads size bytes from file descriptor fd, starting at position offset
|
||||
and copies them into buf.
|
||||
The number of bytes read is returned in len.
|
||||
The file must be opened readonly or readwrite. */
|
||||
int
|
||||
dav_read(ssize_t *len, dav_node * node, int fd, char *buf, size_t size,
|
||||
off_t offset);
|
||||
|
||||
|
||||
/* Removes file node name in directory parent from the cache and on the server.
|
||||
The file must not be locked by another WebDAV client.
|
||||
Permissions:
|
||||
uid must have execute permission for parent and all of its ancestors, as
|
||||
well as write permission for parent. */
|
||||
int
|
||||
dav_remove(dav_node *parent, const char *name, uid_t uid);
|
||||
|
||||
|
||||
/* Moves file or directory src_name from directory src_parent to directory
|
||||
dst_parent and renames it to dst_name.
|
||||
If dst_name allready exists in dst_parent and is a directory, there must
|
||||
be no files opened for writing in it.
|
||||
Moves into the backup directory are not allowed.
|
||||
Permissions:
|
||||
uid must have execute permission for src_parent and dst_parent and all of
|
||||
their ancestors, as well as write permission for src_parent and
|
||||
dst_parent. */
|
||||
int
|
||||
dav_rename(dav_node *src_parent, const char *src_name, dav_node *dst_parent,
|
||||
const char *dst_name, uid_t uid);
|
||||
|
||||
|
||||
/* Removes direcotry name in directory parent.
|
||||
The directory must be empty and not the local backup directory.
|
||||
uid must have execute permission for parent and all of its ancestors, as
|
||||
well as write permission for parent. */
|
||||
int
|
||||
dav_rmdir(dav_node *parent, const char *name, uid_t uid);
|
||||
|
||||
|
||||
/* Returns a pointer to the root node in nodep.
|
||||
Permissions:
|
||||
uid must be root, as this function is only called when the file system is
|
||||
mounted. */
|
||||
int
|
||||
dav_root(dav_node **nodep, uid_t uid);
|
||||
|
||||
|
||||
/* Changes attributes of the node.
|
||||
sm, so, ... are flags. A value of 1 indicates that the respective
|
||||
attribute is to be changed.
|
||||
Permissions:
|
||||
uid must have execute permission for parent directory of node and all of
|
||||
its ancestors.
|
||||
To change mode, owner, or gid, uid must be owner of the node or root.
|
||||
To change atime, mtime or size, uid must have write permission for
|
||||
node.
|
||||
To change gid, uid must be member of the new group or root.
|
||||
Note: This attributes, except size and the execute bit of mode, are only
|
||||
changed locally and not on the server. */
|
||||
int
|
||||
dav_setattr(dav_node *node, uid_t uid, int sm, mode_t mode, int so,
|
||||
uid_t owner, int sg, gid_t gid, int sat, time_t atime, int smt,
|
||||
time_t mtime, int ssz, off_t size);
|
||||
|
||||
/* Returns struct dav_stat which currently is mainly fake.
|
||||
No permissions necessary. */
|
||||
dav_stat dav_statfs(void);
|
||||
|
||||
|
||||
/* Calls fsync() for all filedescriptors of node, that are not read only.
|
||||
No permissions are checked. */
|
||||
int
|
||||
dav_sync(dav_node *node);
|
||||
|
||||
|
||||
/* Writes size bytes from buf to file descriptor fd, starting at position
|
||||
offset.
|
||||
The number of bytes written is returned in len.
|
||||
The file must be opened writeonly or readwrite. */
|
||||
/* TODO: Remove pid; check flags. */
|
||||
int
|
||||
dav_write(size_t *written, dav_node * node, int fd, char *buf, size_t size,
|
||||
off_t offset);
|
||||
|
||||
|
||||
#endif /* DAV_CACHE_H */
|
643
src/coda.h
Normal file
643
src/coda.h
Normal file
@ -0,0 +1,643 @@
|
||||
/* This header file was taken from Linux kernel 2.6.18.
|
||||
From the two alternative licences the Carnegie Mellon University
|
||||
specific licence has been chosen.
|
||||
Definitions intended for use by the kernel and not for userspace,
|
||||
old API definitions and other parts unused by davfs2 have been removed.
|
||||
Modifications by Werner Baumann, 2009-04-14. */
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Coda: an Experimental Distributed File System
|
||||
Release 4.0
|
||||
|
||||
Copyright (c) 1987-1999 Carnegie Mellon University
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify and distribute this software and its
|
||||
documentation is hereby granted, provided that both the copyright
|
||||
notice and this permission notice appear in all copies of the
|
||||
software, derivative works or modified versions, and any portions
|
||||
thereof, and that both notices appear in supporting documentation, and
|
||||
that credit is given to Carnegie Mellon University in all documents
|
||||
and publicity pertaining to direct or indirect use of this code or its
|
||||
derivatives.
|
||||
|
||||
CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
|
||||
SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
|
||||
FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
|
||||
DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
|
||||
RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
|
||||
ANY DERIVATIVE WORK.
|
||||
|
||||
Carnegie Mellon encourages users of this software to return any
|
||||
improvements or extensions that they make, and to grant Carnegie
|
||||
Mellon the rights to redistribute these changes without encumbrance.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* Based on cfs.h from Mach, but revamped for increased simplicity.
|
||||
* Linux modifications by
|
||||
* Peter Braam, Aug 1996
|
||||
*/
|
||||
|
||||
#ifndef _CODA_HEADER_
|
||||
#define _CODA_HEADER_
|
||||
|
||||
#define cdev_t dev_t
|
||||
|
||||
#ifndef __BIT_TYPES_DEFINED__
|
||||
#define __BIT_TYPES_DEFINED__
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char u_int8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short u_int16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int u_int32_t;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Cfs constants
|
||||
*/
|
||||
#define CODA_MAXNAMLEN 255
|
||||
#define CODA_MAXPATHLEN 1024
|
||||
#define CODA_MAXSYMLINK 10
|
||||
|
||||
/* these are Coda's version of O_RDONLY etc combinations
|
||||
* to deal with VFS open modes
|
||||
*/
|
||||
#define C_O_READ 0x001
|
||||
#define C_O_WRITE 0x002
|
||||
#define C_O_TRUNC 0x010
|
||||
#define C_O_EXCL 0x100
|
||||
#define C_O_CREAT 0x200
|
||||
|
||||
/* these are to find mode bits in Venus */
|
||||
#define C_M_READ 00400
|
||||
#define C_M_WRITE 00200
|
||||
|
||||
/* for access Venus will use */
|
||||
#define C_A_C_OK 8 /* Test for writing upon create. */
|
||||
#define C_A_R_OK 4 /* Test for read permission. */
|
||||
#define C_A_W_OK 2 /* Test for write permission. */
|
||||
#define C_A_X_OK 1 /* Test for execute permission. */
|
||||
#define C_A_F_OK 0 /* Test for existence. */
|
||||
|
||||
|
||||
|
||||
#ifndef _VENUS_DIRENT_T_
|
||||
#define _VENUS_DIRENT_T_ 1
|
||||
struct venus_dirent {
|
||||
u_int32_t d_fileno; /* file number of entry */
|
||||
u_int16_t d_reclen; /* length of this record */
|
||||
u_int8_t d_type; /* file type, see below */
|
||||
u_int8_t d_namlen; /* length of string in d_name */
|
||||
char d_name[CODA_MAXNAMLEN + 1];/* name must be no longer than this */
|
||||
};
|
||||
#undef DIRSIZ
|
||||
#define DIRSIZ(dp) ((sizeof (struct venus_dirent) - (CODA_MAXNAMLEN+1)) + \
|
||||
(((dp)->d_namlen+1 + 3) &~ 3))
|
||||
|
||||
/*
|
||||
* File types
|
||||
*/
|
||||
#define CDT_UNKNOWN 0
|
||||
#define CDT_FIFO 1
|
||||
#define CDT_CHR 2
|
||||
#define CDT_DIR 4
|
||||
#define CDT_BLK 6
|
||||
#define CDT_REG 8
|
||||
#define CDT_LNK 10
|
||||
#define CDT_SOCK 12
|
||||
#define CDT_WHT 14
|
||||
|
||||
/*
|
||||
* Convert between stat structure types and directory types.
|
||||
*/
|
||||
#define IFTOCDT(mode) (((mode) & 0170000) >> 12)
|
||||
#define CDTTOIF(dirtype) ((dirtype) << 12)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef _VUID_T_
|
||||
#define _VUID_T_
|
||||
typedef u_int32_t vuid_t;
|
||||
typedef u_int32_t vgid_t;
|
||||
#endif /*_VUID_T_ */
|
||||
|
||||
struct CodaFid {
|
||||
u_int32_t opaque[4];
|
||||
};
|
||||
|
||||
#define coda_f2i(fid)\
|
||||
(fid ? (fid->opaque[3] ^ (fid->opaque[2]<<10) ^ (fid->opaque[1]<<20) ^ fid->opaque[0]) : 0)
|
||||
|
||||
|
||||
#ifndef _VENUS_VATTR_T_
|
||||
#define _VENUS_VATTR_T_
|
||||
/*
|
||||
* Vnode types. VNON means no type.
|
||||
*/
|
||||
enum coda_vtype { C_VNON, C_VREG, C_VDIR, C_VBLK, C_VCHR, C_VLNK, C_VSOCK, C_VFIFO, C_VBAD };
|
||||
|
||||
struct coda_vattr {
|
||||
long va_type; /* vnode type (for create) */
|
||||
u_short va_mode; /* files access mode and type */
|
||||
short va_nlink; /* number of references to file */
|
||||
vuid_t va_uid; /* owner user id */
|
||||
vgid_t va_gid; /* owner group id */
|
||||
long va_fileid; /* file id */
|
||||
u_quad_t va_size; /* file size in bytes */
|
||||
long va_blocksize; /* blocksize preferred for i/o */
|
||||
struct timespec va_atime; /* time of last access */
|
||||
struct timespec va_mtime; /* time of last modification */
|
||||
struct timespec va_ctime; /* time file changed */
|
||||
u_long va_gen; /* generation number of file */
|
||||
u_long va_flags; /* flags defined for file */
|
||||
cdev_t va_rdev; /* device special file represents */
|
||||
u_quad_t va_bytes; /* bytes of disk space held by file */
|
||||
u_quad_t va_filerev; /* file modification number */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* structure used by CODA_STATFS for getting cache information from venus */
|
||||
struct coda_statfs {
|
||||
int32_t f_blocks;
|
||||
int32_t f_bfree;
|
||||
int32_t f_bavail;
|
||||
int32_t f_files;
|
||||
int32_t f_ffree;
|
||||
};
|
||||
|
||||
/*
|
||||
* Kernel <--> Venus communications.
|
||||
*/
|
||||
|
||||
#define CODA_ROOT 2
|
||||
#define CODA_OPEN_BY_FD 3
|
||||
#define CODA_OPEN 4
|
||||
#define CODA_CLOSE 5
|
||||
#define CODA_IOCTL 6
|
||||
#define CODA_GETATTR 7
|
||||
#define CODA_SETATTR 8
|
||||
#define CODA_ACCESS 9
|
||||
#define CODA_LOOKUP 10
|
||||
#define CODA_CREATE 11
|
||||
#define CODA_REMOVE 12
|
||||
#define CODA_LINK 13
|
||||
#define CODA_RENAME 14
|
||||
#define CODA_MKDIR 15
|
||||
#define CODA_RMDIR 16
|
||||
#define CODA_SYMLINK 18
|
||||
#define CODA_READLINK 19
|
||||
#define CODA_FSYNC 20
|
||||
#define CODA_VGET 22
|
||||
#define CODA_SIGNAL 23
|
||||
#define CODA_REPLACE 24 /* DOWNCALL */
|
||||
#define CODA_FLUSH 25 /* DOWNCALL */
|
||||
#define CODA_PURGEUSER 26 /* DOWNCALL */
|
||||
#define CODA_ZAPFILE 27 /* DOWNCALL */
|
||||
#define CODA_ZAPDIR 28 /* DOWNCALL */
|
||||
#define CODA_PURGEFID 30 /* DOWNCALL */
|
||||
#define CODA_OPEN_BY_PATH 31
|
||||
#define CODA_RESOLVE 32
|
||||
#define CODA_REINTEGRATE 33
|
||||
#define CODA_STATFS 34
|
||||
#define CODA_STORE 35
|
||||
#define CODA_RELEASE 36
|
||||
#define CODA_NCALLS 37
|
||||
|
||||
#define DOWNCALL(opcode) (opcode >= CODA_REPLACE && opcode <= CODA_PURGEFID)
|
||||
|
||||
#define VC_MAXDATASIZE 8192
|
||||
#define VC_MAXMSGSIZE sizeof(union inputArgs)+sizeof(union outputArgs) +\
|
||||
VC_MAXDATASIZE
|
||||
|
||||
#define CIOC_KERNEL_VERSION _IOWR('c', 10, size_t)
|
||||
|
||||
#define CODA_KERNEL_VERSION 3 /* 128-bit file identifiers */
|
||||
|
||||
|
||||
/*
|
||||
* Venus <-> Coda RPC arguments
|
||||
*/
|
||||
struct coda_in_hdr {
|
||||
u_int32_t opcode;
|
||||
u_int32_t unique; /* Keep multiple outstanding msgs distinct */
|
||||
pid_t pid;
|
||||
pid_t pgid;
|
||||
vuid_t uid;
|
||||
};
|
||||
|
||||
/* Really important that opcode and unique are 1st two fields! */
|
||||
struct coda_out_hdr {
|
||||
u_int32_t opcode;
|
||||
u_int32_t unique;
|
||||
u_int32_t result;
|
||||
};
|
||||
|
||||
/* coda_root: NO_IN */
|
||||
struct coda_root_out {
|
||||
struct coda_out_hdr oh;
|
||||
struct CodaFid VFid;
|
||||
};
|
||||
|
||||
struct coda_root_in {
|
||||
struct coda_in_hdr in;
|
||||
};
|
||||
|
||||
/* coda_open: */
|
||||
struct coda_open_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct coda_open_out {
|
||||
struct coda_out_hdr oh;
|
||||
cdev_t dev;
|
||||
ino_t inode;
|
||||
};
|
||||
|
||||
|
||||
/* coda_store: */
|
||||
struct coda_store_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct coda_store_out {
|
||||
struct coda_out_hdr out;
|
||||
};
|
||||
|
||||
/* coda_release: */
|
||||
struct coda_release_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct coda_release_out {
|
||||
struct coda_out_hdr out;
|
||||
};
|
||||
|
||||
/* coda_close: */
|
||||
struct coda_close_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct coda_close_out {
|
||||
struct coda_out_hdr out;
|
||||
};
|
||||
|
||||
/* coda_ioctl: */
|
||||
struct coda_ioctl_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
int cmd;
|
||||
int len;
|
||||
int rwflag;
|
||||
char *data; /* Place holder for data. */
|
||||
};
|
||||
|
||||
struct coda_ioctl_out {
|
||||
struct coda_out_hdr oh;
|
||||
int len;
|
||||
caddr_t data; /* Place holder for data. */
|
||||
};
|
||||
|
||||
|
||||
/* coda_getattr: */
|
||||
struct coda_getattr_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
};
|
||||
|
||||
struct coda_getattr_out {
|
||||
struct coda_out_hdr oh;
|
||||
struct coda_vattr attr;
|
||||
};
|
||||
|
||||
|
||||
/* coda_setattr: NO_OUT */
|
||||
struct coda_setattr_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
struct coda_vattr attr;
|
||||
};
|
||||
|
||||
struct coda_setattr_out {
|
||||
struct coda_out_hdr out;
|
||||
};
|
||||
|
||||
/* coda_access: NO_OUT */
|
||||
struct coda_access_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct coda_access_out {
|
||||
struct coda_out_hdr out;
|
||||
};
|
||||
|
||||
|
||||
/* lookup flags */
|
||||
#define CLU_CASE_SENSITIVE 0x01
|
||||
#define CLU_CASE_INSENSITIVE 0x02
|
||||
|
||||
/* coda_lookup: */
|
||||
struct coda_lookup_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
int name; /* Place holder for data. */
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct coda_lookup_out {
|
||||
struct coda_out_hdr oh;
|
||||
struct CodaFid VFid;
|
||||
int vtype;
|
||||
};
|
||||
|
||||
|
||||
/* coda_create: */
|
||||
struct coda_create_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
struct coda_vattr attr;
|
||||
int excl;
|
||||
int mode;
|
||||
int name; /* Place holder for data. */
|
||||
};
|
||||
|
||||
struct coda_create_out {
|
||||
struct coda_out_hdr oh;
|
||||
struct CodaFid VFid;
|
||||
struct coda_vattr attr;
|
||||
};
|
||||
|
||||
|
||||
/* coda_remove: NO_OUT */
|
||||
struct coda_remove_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
int name; /* Place holder for data. */
|
||||
};
|
||||
|
||||
struct coda_remove_out {
|
||||
struct coda_out_hdr out;
|
||||
};
|
||||
|
||||
/* coda_link: NO_OUT */
|
||||
struct coda_link_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid sourceFid; /* cnode to link *to* */
|
||||
struct CodaFid destFid; /* Directory in which to place link */
|
||||
int tname; /* Place holder for data. */
|
||||
};
|
||||
|
||||
struct coda_link_out {
|
||||
struct coda_out_hdr out;
|
||||
};
|
||||
|
||||
|
||||
/* coda_rename: NO_OUT */
|
||||
struct coda_rename_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid sourceFid;
|
||||
int srcname;
|
||||
struct CodaFid destFid;
|
||||
int destname;
|
||||
};
|
||||
|
||||
struct coda_rename_out {
|
||||
struct coda_out_hdr out;
|
||||
};
|
||||
|
||||
/* coda_mkdir: */
|
||||
struct coda_mkdir_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
struct coda_vattr attr;
|
||||
int name; /* Place holder for data. */
|
||||
};
|
||||
|
||||
struct coda_mkdir_out {
|
||||
struct coda_out_hdr oh;
|
||||
struct CodaFid VFid;
|
||||
struct coda_vattr attr;
|
||||
};
|
||||
|
||||
|
||||
/* coda_rmdir: NO_OUT */
|
||||
struct coda_rmdir_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
int name; /* Place holder for data. */
|
||||
};
|
||||
|
||||
struct coda_rmdir_out {
|
||||
struct coda_out_hdr out;
|
||||
};
|
||||
|
||||
/* coda_symlink: NO_OUT */
|
||||
struct coda_symlink_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid; /* Directory to put symlink in */
|
||||
int srcname;
|
||||
struct coda_vattr attr;
|
||||
int tname;
|
||||
};
|
||||
|
||||
struct coda_symlink_out {
|
||||
struct coda_out_hdr out;
|
||||
};
|
||||
|
||||
/* coda_readlink: */
|
||||
struct coda_readlink_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
};
|
||||
|
||||
struct coda_readlink_out {
|
||||
struct coda_out_hdr oh;
|
||||
int count;
|
||||
caddr_t data; /* Place holder for data. */
|
||||
};
|
||||
|
||||
|
||||
/* coda_fsync: NO_OUT */
|
||||
struct coda_fsync_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
};
|
||||
|
||||
struct coda_fsync_out {
|
||||
struct coda_out_hdr out;
|
||||
};
|
||||
|
||||
/* coda_vget: */
|
||||
struct coda_vget_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
};
|
||||
|
||||
struct coda_vget_out {
|
||||
struct coda_out_hdr oh;
|
||||
struct CodaFid VFid;
|
||||
int vtype;
|
||||
};
|
||||
|
||||
|
||||
/* CODA_SIGNAL is out-of-band, doesn't need data. */
|
||||
/* CODA_INVALIDATE is a venus->kernel call */
|
||||
/* CODA_FLUSH is a venus->kernel call */
|
||||
|
||||
/* coda_purgeuser: */
|
||||
/* CODA_PURGEUSER is a venus->kernel call */
|
||||
struct coda_purgeuser_out {
|
||||
struct coda_out_hdr oh;
|
||||
vuid_t uid;
|
||||
};
|
||||
|
||||
/* coda_zapfile: */
|
||||
/* CODA_ZAPFILE is a venus->kernel call */
|
||||
struct coda_zapfile_out {
|
||||
struct coda_out_hdr oh;
|
||||
struct CodaFid CodaFid;
|
||||
};
|
||||
|
||||
/* coda_zapdir: */
|
||||
/* CODA_ZAPDIR is a venus->kernel call */
|
||||
struct coda_zapdir_out {
|
||||
struct coda_out_hdr oh;
|
||||
struct CodaFid CodaFid;
|
||||
};
|
||||
|
||||
/* coda_purgefid: */
|
||||
/* CODA_PURGEFID is a venus->kernel call */
|
||||
struct coda_purgefid_out {
|
||||
struct coda_out_hdr oh;
|
||||
struct CodaFid CodaFid;
|
||||
};
|
||||
|
||||
/* coda_replace: */
|
||||
/* CODA_REPLACE is a venus->kernel call */
|
||||
struct coda_replace_out { /* coda_replace is a venus->kernel call */
|
||||
struct coda_out_hdr oh;
|
||||
struct CodaFid NewFid;
|
||||
struct CodaFid OldFid;
|
||||
};
|
||||
|
||||
/* coda_open_by_fd: */
|
||||
struct coda_open_by_fd_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct coda_open_by_fd_out {
|
||||
struct coda_out_hdr oh;
|
||||
int fd;
|
||||
};
|
||||
|
||||
/* coda_open_by_path: */
|
||||
struct coda_open_by_path_in {
|
||||
struct coda_in_hdr ih;
|
||||
struct CodaFid VFid;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct coda_open_by_path_out {
|
||||
struct coda_out_hdr oh;
|
||||
int path;
|
||||
};
|
||||
|
||||
/* coda_statfs: NO_IN */
|
||||
struct coda_statfs_in {
|
||||
struct coda_in_hdr in;
|
||||
};
|
||||
|
||||
struct coda_statfs_out {
|
||||
struct coda_out_hdr oh;
|
||||
struct coda_statfs stat;
|
||||
};
|
||||
|
||||
union inputArgs {
|
||||
struct coda_in_hdr ih; /* NB: every struct below begins with an ih */
|
||||
struct coda_open_in coda_open;
|
||||
struct coda_store_in coda_store;
|
||||
struct coda_release_in coda_release;
|
||||
struct coda_close_in coda_close;
|
||||
struct coda_ioctl_in coda_ioctl;
|
||||
struct coda_getattr_in coda_getattr;
|
||||
struct coda_setattr_in coda_setattr;
|
||||
struct coda_access_in coda_access;
|
||||
struct coda_lookup_in coda_lookup;
|
||||
struct coda_create_in coda_create;
|
||||
struct coda_remove_in coda_remove;
|
||||
struct coda_link_in coda_link;
|
||||
struct coda_rename_in coda_rename;
|
||||
struct coda_mkdir_in coda_mkdir;
|
||||
struct coda_rmdir_in coda_rmdir;
|
||||
struct coda_symlink_in coda_symlink;
|
||||
struct coda_readlink_in coda_readlink;
|
||||
struct coda_fsync_in coda_fsync;
|
||||
struct coda_vget_in coda_vget;
|
||||
struct coda_open_by_fd_in coda_open_by_fd;
|
||||
struct coda_open_by_path_in coda_open_by_path;
|
||||
struct coda_statfs_in coda_statfs;
|
||||
};
|
||||
|
||||
union outputArgs {
|
||||
struct coda_out_hdr oh; /* NB: every struct below begins with an oh */
|
||||
struct coda_root_out coda_root;
|
||||
struct coda_open_out coda_open;
|
||||
struct coda_ioctl_out coda_ioctl;
|
||||
struct coda_getattr_out coda_getattr;
|
||||
struct coda_lookup_out coda_lookup;
|
||||
struct coda_create_out coda_create;
|
||||
struct coda_mkdir_out coda_mkdir;
|
||||
struct coda_readlink_out coda_readlink;
|
||||
struct coda_vget_out coda_vget;
|
||||
struct coda_purgeuser_out coda_purgeuser;
|
||||
struct coda_zapfile_out coda_zapfile;
|
||||
struct coda_zapdir_out coda_zapdir;
|
||||
struct coda_purgefid_out coda_purgefid;
|
||||
struct coda_replace_out coda_replace;
|
||||
struct coda_open_by_fd_out coda_open_by_fd;
|
||||
struct coda_open_by_path_out coda_open_by_path;
|
||||
struct coda_statfs_out coda_statfs;
|
||||
};
|
||||
|
||||
union coda_downcalls {
|
||||
/* CODA_INVALIDATE is a venus->kernel call */
|
||||
/* CODA_FLUSH is a venus->kernel call */
|
||||
struct coda_purgeuser_out purgeuser;
|
||||
struct coda_zapfile_out zapfile;
|
||||
struct coda_zapdir_out zapdir;
|
||||
struct coda_purgefid_out purgefid;
|
||||
struct coda_replace_out replace;
|
||||
};
|
||||
|
||||
|
||||
/* Data passed to mount */
|
||||
|
||||
#define CODA_MOUNT_VERSION 1
|
||||
|
||||
struct coda_mount_data {
|
||||
int version;
|
||||
int fd; /* Opened device */
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
810
src/dav_coda.c
Normal file
810
src/dav_coda.c
Normal file
@ -0,0 +1,810 @@
|
||||
/* dav_coda.c: interface to the Coda kernel module CODA_KERNEL_VERSION 3.
|
||||
Copyright (C) 2006, 2007, 2008, 2009 Werner Baumann
|
||||
|
||||
This file is part of davfs2.
|
||||
|
||||
davfs2 is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
davfs2 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 General Public License
|
||||
along with davfs2; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIBINTL_H
|
||||
#include <libintl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDDEF_H
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include "defaults.h"
|
||||
#include "mount_davfs.h"
|
||||
#include "cache.h"
|
||||
#include "kernel_interface.h"
|
||||
#include "coda.h"
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
#define _(String) gettext(String)
|
||||
#else
|
||||
#define _(String) String
|
||||
#endif
|
||||
|
||||
|
||||
/* Constants */
|
||||
/*===========*/
|
||||
|
||||
/* Size of buffer for communication with the kernel module. */
|
||||
#define BUF_SIZE 2048
|
||||
|
||||
/* This constants are used by davfs2 to fill fields of struct CodaFid that
|
||||
are not used by davfs2, but are expected by coda. */
|
||||
#define DAV_VOL 0x01234567
|
||||
#define DAV_VNODE 0xffffffff
|
||||
|
||||
|
||||
/* Private global variables */
|
||||
/*==========================*/
|
||||
|
||||
/* Buffer used for communication with the kernel module (in and out). */
|
||||
static char *buf;
|
||||
|
||||
/* The preferred blocksize used by the local filesystem for cache files.
|
||||
Used by set_attr(). */
|
||||
static unsigned int blocksize;
|
||||
|
||||
/* Alignment boundary of dav_node in byte.
|
||||
Used to compute file numbers from node pointers. */
|
||||
static size_t alignment;
|
||||
|
||||
/* Send debug messages to syslog if != 0. */
|
||||
int debug;
|
||||
|
||||
|
||||
/* Private function prototypes */
|
||||
/*=============================*/
|
||||
|
||||
/* Functions to handle upcalls fromthe kernel module. */
|
||||
|
||||
static uint32_t
|
||||
coda_access(void);
|
||||
|
||||
static uint32_t
|
||||
coda_close(void);
|
||||
|
||||
static uint32_t
|
||||
coda_create(void);
|
||||
|
||||
static uint32_t
|
||||
coda_getattr(void);
|
||||
|
||||
static uint32_t
|
||||
coda_lookup(void);
|
||||
|
||||
static uint32_t
|
||||
coda_mkdir(void);
|
||||
|
||||
static uint32_t
|
||||
coda_open_by_fd(void);
|
||||
|
||||
static uint32_t
|
||||
coda_root(void);
|
||||
|
||||
static uint32_t
|
||||
coda_setattr(void);
|
||||
|
||||
static uint32_t
|
||||
coda_statfs(void);
|
||||
|
||||
/* Functions that will do a downcall to the kernel module. */
|
||||
|
||||
static void
|
||||
coda_flush(int device);
|
||||
|
||||
/* Auxiliary functions. */
|
||||
|
||||
static off_t
|
||||
write_dir_entry(int fd, off_t off, const dav_node *node, const char *name);
|
||||
|
||||
static void
|
||||
set_attr(struct coda_vattr *attr, const dav_node *node);
|
||||
|
||||
|
||||
/* Public functions */
|
||||
/*==================*/
|
||||
|
||||
void
|
||||
dav_coda_loop(int device, size_t bufsize, time_t idle_time,
|
||||
dav_is_mounted_fn is_mounted, volatile int *keep_on_running,
|
||||
int dbg)
|
||||
{
|
||||
debug = dbg;
|
||||
if (debug)
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "coda kernel version 3");
|
||||
|
||||
buf = malloc(BUF_SIZE);
|
||||
if (!buf) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_ERR),
|
||||
_("can't allocate message buffer"));
|
||||
return;
|
||||
}
|
||||
static int flush = 0;
|
||||
alignment = dav_register_kernel_interface(&write_dir_entry, &flush,
|
||||
&blocksize);
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = idle_time;
|
||||
tv.tv_usec = 0;
|
||||
time_t last_tidy_cache = time(NULL);
|
||||
|
||||
while (*keep_on_running) {
|
||||
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(device, &fds);
|
||||
int ret = select(device + 1, &fds, NULL, NULL, &tv);
|
||||
|
||||
if (ret > 0) {
|
||||
ssize_t bytes_read = read(device, buf, BUF_SIZE);
|
||||
if (bytes_read <= 0) {
|
||||
if (bytes_read == 0 || errno == EINTR || errno == EAGAIN) {
|
||||
if (time(NULL) < (last_tidy_cache + idle_time)) {
|
||||
tv.tv_sec = last_tidy_cache + idle_time - time(NULL);
|
||||
} else {
|
||||
tv.tv_sec = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (ret == 0) {
|
||||
if (!is_mounted())
|
||||
break;
|
||||
if (dav_tidy_cache() == 0) {
|
||||
tv.tv_sec = idle_time;
|
||||
last_tidy_cache = time(NULL);
|
||||
} else {
|
||||
tv.tv_sec = 0;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
struct coda_in_hdr *ih = (struct coda_in_hdr *) buf;
|
||||
struct coda_out_hdr *oh = (struct coda_out_hdr *) buf;
|
||||
uint32_t len;
|
||||
switch (ih->opcode) {
|
||||
case CODA_ROOT:
|
||||
len = coda_root();
|
||||
break;
|
||||
case CODA_OPEN_BY_FD:
|
||||
len = coda_open_by_fd();
|
||||
break;
|
||||
case CODA_OPEN:
|
||||
if (debug)
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_OPEN:");
|
||||
oh->result = ENOTSUP;
|
||||
len = sizeof(struct coda_out_hdr);
|
||||
break;
|
||||
case CODA_CLOSE:
|
||||
len = coda_close();
|
||||
last_tidy_cache = 0;
|
||||
break;
|
||||
case CODA_IOCTL:
|
||||
if (debug)
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_IOCTL:");
|
||||
oh->result = ENOTSUP;
|
||||
len = sizeof(struct coda_out_hdr);
|
||||
break;
|
||||
case CODA_GETATTR:
|
||||
len = coda_getattr();
|
||||
break;
|
||||
case CODA_SETATTR:
|
||||
len = coda_setattr();
|
||||
break;
|
||||
case CODA_ACCESS:
|
||||
len = coda_access();
|
||||
break;
|
||||
case CODA_LOOKUP:
|
||||
len = coda_lookup();
|
||||
break;
|
||||
case CODA_CREATE:
|
||||
len = coda_create();
|
||||
break;
|
||||
case CODA_REMOVE: {
|
||||
struct coda_remove_in *in = (struct coda_remove_in *) buf;
|
||||
dav_node *node = *((dav_node **) &(in->VFid.opaque[2]));
|
||||
if (debug) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_REMOVE:");
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " p %p, %s", node,
|
||||
buf + in->name);
|
||||
}
|
||||
oh->result = dav_remove(node, buf + in->name, ih->uid);
|
||||
len = sizeof(struct coda_out_hdr);
|
||||
break; }
|
||||
case CODA_LINK:
|
||||
if (debug)
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_LINK:");
|
||||
oh->result = ENOTSUP;
|
||||
len = sizeof(struct coda_out_hdr);
|
||||
break;
|
||||
case CODA_RENAME: {
|
||||
struct coda_rename_in *in = (struct coda_rename_in *) buf;
|
||||
dav_node *src = *((dav_node **) &(in->sourceFid.opaque[2]));
|
||||
dav_node *dst = *((dav_node **) &(in->destFid.opaque[2]));
|
||||
if (debug) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_RENAME:");
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " sp %p, %s", src,
|
||||
buf + in->srcname);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " dp %p, %s", dst,
|
||||
buf + in->destname);
|
||||
}
|
||||
oh->result = dav_rename(src, buf + in->srcname, dst,
|
||||
buf + in->destname, ih->uid);
|
||||
len = sizeof(struct coda_out_hdr);
|
||||
break; }
|
||||
case CODA_MKDIR:
|
||||
len = coda_mkdir();
|
||||
break;
|
||||
case CODA_RMDIR: {
|
||||
struct coda_rmdir_in *in = (struct coda_rmdir_in *) buf;
|
||||
dav_node *node = *((dav_node **) &(in->VFid.opaque[2]));
|
||||
if (debug) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_RMDIR:");
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " p %p, %s", node,
|
||||
buf + in->name);
|
||||
}
|
||||
oh->result = dav_rmdir(node, buf + in->name, ih->uid);
|
||||
len = sizeof(struct coda_out_hdr);
|
||||
break; }
|
||||
case CODA_SYMLINK:
|
||||
if (debug)
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_SYMLINK:");
|
||||
oh->result = ENOTSUP;
|
||||
len = sizeof(struct coda_out_hdr);
|
||||
break;
|
||||
case CODA_READLINK:
|
||||
if (debug)
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_READLINK:");
|
||||
oh->result = ENOTSUP;
|
||||
len = sizeof(struct coda_out_hdr);
|
||||
break;
|
||||
case CODA_FSYNC: {
|
||||
struct coda_fsync_in *in = (struct coda_fsync_in *) buf;
|
||||
dav_node *node = *((dav_node **) &(in->VFid.opaque[2]));
|
||||
if (debug) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_FSYNC:");
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " n %p", node);
|
||||
}
|
||||
oh->result = dav_sync(node);
|
||||
len = sizeof(struct coda_out_hdr);
|
||||
break; }
|
||||
case CODA_VGET:
|
||||
if (debug)
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_VGET:");
|
||||
oh->result = ENOTSUP;
|
||||
len = sizeof(struct coda_out_hdr);
|
||||
break;
|
||||
case CODA_OPEN_BY_PATH:
|
||||
if (debug)
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
|
||||
"CODA_OPEN_BY_PATH:");
|
||||
oh->result = ENOTSUP;
|
||||
len = sizeof(struct coda_out_hdr);
|
||||
break;
|
||||
case CODA_STATFS:
|
||||
len = coda_statfs();
|
||||
break;
|
||||
case CODA_STORE: {
|
||||
struct coda_store_in *in = (struct coda_store_in *) buf;
|
||||
dav_node *node = *((dav_node **) &(in->VFid.opaque[2]));
|
||||
if (debug) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_STORE:");
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " n %p, f 0x%x",
|
||||
node, in->flags);
|
||||
}
|
||||
oh->result = dav_sync(node);
|
||||
len = sizeof(struct coda_out_hdr);
|
||||
break; }
|
||||
case CODA_RELEASE:
|
||||
len = coda_close();
|
||||
last_tidy_cache = 0;
|
||||
break;
|
||||
default:
|
||||
if (debug)
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
|
||||
"UNKNOWN CODA CALL %u", ih->opcode);
|
||||
oh->result = ENOTSUP;
|
||||
len = sizeof(struct coda_out_hdr);
|
||||
break;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "RET: %s",
|
||||
strerror(oh->result));
|
||||
|
||||
ssize_t n = 0;
|
||||
ssize_t w = 0;
|
||||
while (n < len && w >= 0) {
|
||||
w = write(device, buf + n, len - n);
|
||||
n += w;
|
||||
}
|
||||
|
||||
if (time(NULL) < (last_tidy_cache + idle_time)) {
|
||||
tv.tv_sec = last_tidy_cache + idle_time - time(NULL);
|
||||
} else {
|
||||
dav_tidy_cache();
|
||||
tv.tv_sec = idle_time;
|
||||
last_tidy_cache = time(NULL);
|
||||
}
|
||||
|
||||
if (flush) {
|
||||
coda_flush(device);
|
||||
flush = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Private functions */
|
||||
/*===================*/
|
||||
|
||||
/* Functions to handle upcalls fromthe kernel module.
|
||||
The cache module only uses data types from the C-library. For file access,
|
||||
mode and the like it only uses symbolic constants defined in the C-library.
|
||||
So the main porpose of this functions is to translate from kernel specific
|
||||
types and constants to types and constants from the C-library, and back.
|
||||
All of this functions return the amount of data in buf that is to be
|
||||
send to the kernel module. */
|
||||
|
||||
static uint32_t
|
||||
coda_access(void)
|
||||
{
|
||||
struct coda_in_hdr *ih = (struct coda_in_hdr *) buf;
|
||||
struct coda_access_in *in = (struct coda_access_in *) buf;
|
||||
dav_node *node = *((dav_node **) &(in->VFid.opaque[2]));
|
||||
struct coda_out_hdr *oh = (struct coda_out_hdr *) buf;
|
||||
if (debug) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_ACCESS:");
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " n %p, f %x",
|
||||
node, in->flags);
|
||||
}
|
||||
|
||||
int how = (in->flags & C_A_R_OK) ? R_OK : 0;
|
||||
how |= (in->flags & C_A_W_OK) ? W_OK : 0;
|
||||
how |= (in->flags & C_A_X_OK) ? X_OK : 0;
|
||||
how |= (in->flags & C_A_F_OK) ? F_OK : 0;
|
||||
|
||||
oh->result = dav_access(node, ih->uid, how);
|
||||
|
||||
return sizeof(struct coda_out_hdr);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
coda_close(void)
|
||||
{
|
||||
struct coda_in_hdr *ih = (struct coda_in_hdr *) buf;
|
||||
struct coda_close_in *in = (struct coda_close_in *) buf;
|
||||
dav_node *node = *((dav_node **) &(in->VFid.opaque[2]));
|
||||
struct coda_out_hdr *oh = (struct coda_out_hdr *) buf;
|
||||
if (debug) {
|
||||
if (ih->opcode == CODA_CLOSE) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_CLOSE:");
|
||||
} else {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_RELEASE:");
|
||||
}
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " n %p, f %x",
|
||||
node, in->flags);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " pid %i, pgid %i",
|
||||
ih->pid, ih->pgid);
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
if ((in->flags & C_O_READ) && (in->flags & C_O_WRITE)) {
|
||||
flags = O_RDWR;
|
||||
} else if (in->flags & C_O_READ) {
|
||||
flags = O_RDONLY;
|
||||
} else if (in->flags & C_O_WRITE) {
|
||||
flags = O_WRONLY;
|
||||
}
|
||||
|
||||
oh->result = dav_close(node, 0, flags, ih->pid, ih->pgid);
|
||||
|
||||
return sizeof(struct coda_out_hdr);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
coda_create(void)
|
||||
{
|
||||
struct coda_in_hdr *ih = (struct coda_in_hdr *) buf;
|
||||
struct coda_create_in *in = (struct coda_create_in *) buf;
|
||||
dav_node *parent = *((dav_node **) &(in->VFid.opaque[2]));
|
||||
struct coda_out_hdr *oh = (struct coda_out_hdr *) buf;
|
||||
struct coda_create_out *out = (struct coda_create_out *) buf;
|
||||
if (debug) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_CREATE:");
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " p %p, m %o",
|
||||
parent, in->mode);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " %s", buf + in->name);
|
||||
}
|
||||
|
||||
dav_node *node = NULL;
|
||||
oh->result = dav_create(&node, parent, buf + in->name, ih->uid,
|
||||
in->mode & DAV_A_MASK);
|
||||
|
||||
if (oh->result || !node) {
|
||||
if (!oh->result)
|
||||
oh->result = EIO;
|
||||
return sizeof(struct coda_out_hdr);
|
||||
}
|
||||
|
||||
out->VFid.opaque[0] = DAV_VOL;
|
||||
out->VFid.opaque[1] = DAV_VNODE;
|
||||
out->VFid.opaque[3] = 0;
|
||||
*((dav_node **) &(out->VFid.opaque[2])) = node;
|
||||
set_attr(&out->attr, node);
|
||||
|
||||
return sizeof(struct coda_create_out);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
coda_getattr(void)
|
||||
{
|
||||
struct coda_in_hdr *ih = (struct coda_in_hdr *) buf;
|
||||
struct coda_getattr_in *in = (struct coda_getattr_in *) buf;
|
||||
dav_node *node = *((dav_node **) &(in->VFid.opaque[2]));
|
||||
struct coda_out_hdr *oh = (struct coda_out_hdr *) buf;
|
||||
struct coda_getattr_out *out = (struct coda_getattr_out *) buf;
|
||||
if (debug) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_GETATTR:");
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " n %p", node);
|
||||
}
|
||||
|
||||
oh->result = dav_getattr(node, ih->uid);
|
||||
|
||||
if (oh->result)
|
||||
return sizeof(struct coda_out_hdr);
|
||||
|
||||
set_attr(&out->attr, node);
|
||||
|
||||
return sizeof(struct coda_getattr_out);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
coda_lookup(void)
|
||||
{
|
||||
struct coda_in_hdr *ih = (struct coda_in_hdr *) buf;
|
||||
struct coda_lookup_in *in = (struct coda_lookup_in *) buf;
|
||||
dav_node *parent = *((dav_node **) &(in->VFid.opaque[2]));
|
||||
struct coda_out_hdr *oh = (struct coda_out_hdr *) buf;
|
||||
struct coda_lookup_out *out = (struct coda_lookup_out *) buf;
|
||||
if (debug) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_LOOKUP:");
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " p %p, %s", parent,
|
||||
buf + in->name);
|
||||
}
|
||||
|
||||
dav_node *node = NULL;
|
||||
oh->result = dav_lookup(&node, parent, buf + in->name, ih->uid);
|
||||
|
||||
if (oh->result || !node) {
|
||||
if (!oh->result)
|
||||
oh->result = EIO;
|
||||
return sizeof(struct coda_out_hdr);
|
||||
}
|
||||
|
||||
out->VFid.opaque[0] = DAV_VOL;
|
||||
out->VFid.opaque[1] = DAV_VNODE;
|
||||
out->VFid.opaque[3] = 0;
|
||||
*((dav_node **) &(out->VFid.opaque[2])) = node;
|
||||
out->vtype = (node->mode & S_IFDIR) ? CDT_DIR : CDT_REG;
|
||||
|
||||
return sizeof(struct coda_lookup_out);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
coda_mkdir(void)
|
||||
{
|
||||
struct coda_in_hdr *ih = (struct coda_in_hdr *) buf;
|
||||
struct coda_mkdir_in *in = (struct coda_mkdir_in *) buf;
|
||||
dav_node *parent = *((dav_node **) &(in->VFid.opaque[2]));
|
||||
struct coda_out_hdr *oh = (struct coda_out_hdr *) buf;
|
||||
struct coda_mkdir_out *out = (struct coda_mkdir_out *) buf;
|
||||
if (debug) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_MKDIR:");
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " p %p, %s", parent,
|
||||
buf + in->name);
|
||||
}
|
||||
|
||||
dav_node *node = NULL;
|
||||
oh->result = dav_mkdir(&node, parent, buf + in->name, ih->uid,
|
||||
in->attr.va_mode & DAV_A_MASK);
|
||||
|
||||
if (oh->result || !node) {
|
||||
if (!oh->result)
|
||||
oh->result = EIO;
|
||||
return sizeof(struct coda_out_hdr);
|
||||
}
|
||||
|
||||
out->VFid.opaque[0] = DAV_VOL;
|
||||
out->VFid.opaque[1] = DAV_VNODE;
|
||||
out->VFid.opaque[3] = 0;
|
||||
*((dav_node **) &(out->VFid.opaque[2])) = node;
|
||||
set_attr(&out->attr, node);
|
||||
|
||||
return sizeof(struct coda_mkdir_out);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
coda_open_by_fd(void)
|
||||
{
|
||||
struct coda_in_hdr *ih = (struct coda_in_hdr *) buf;
|
||||
struct coda_open_by_fd_in *in = (struct coda_open_by_fd_in *) buf;
|
||||
dav_node *node = *((dav_node **) &(in->VFid.opaque[2]));
|
||||
struct coda_out_hdr *oh = (struct coda_out_hdr *) buf;
|
||||
struct coda_open_by_fd_out *out = (struct coda_open_by_fd_out *) buf;
|
||||
if (debug) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_OPEN_BY_FD:");
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " n %p, f %x", node,
|
||||
in->flags);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " pid %i, pgid %i",
|
||||
ih->pid, ih->pgid);
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
if ((in->flags & C_O_READ) && (in->flags & C_O_WRITE)) {
|
||||
flags = O_RDWR;
|
||||
} else if (in->flags & C_O_READ) {
|
||||
flags = O_RDONLY;
|
||||
} else if (in->flags & C_O_WRITE) {
|
||||
flags = O_WRONLY;
|
||||
}
|
||||
flags |= (in->flags & C_O_TRUNC) ? O_TRUNC : 0;
|
||||
|
||||
oh->result = dav_open(&out->fd, node, flags, ih->pid, ih->pgid, ih->uid);
|
||||
|
||||
if (oh->result || !out->fd) {
|
||||
if (!oh->result)
|
||||
oh->result = EIO;
|
||||
return sizeof(struct coda_out_hdr);
|
||||
}
|
||||
|
||||
return sizeof(struct coda_open_by_fd_out);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
coda_root(void)
|
||||
{
|
||||
struct coda_in_hdr *ih = (struct coda_in_hdr *) buf;
|
||||
struct coda_out_hdr *oh = (struct coda_out_hdr *) buf;
|
||||
struct coda_root_out *out = (struct coda_root_out *) buf;
|
||||
if (debug)
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_ROOT:");
|
||||
|
||||
dav_node *node = NULL;
|
||||
oh->result = dav_root(&node, ih->uid);
|
||||
|
||||
if (oh->result || !node) {
|
||||
if (!oh->result)
|
||||
oh->result = EIO;
|
||||
return sizeof(struct coda_out_hdr);
|
||||
}
|
||||
|
||||
out->VFid.opaque[0] = DAV_VOL;
|
||||
out->VFid.opaque[1] = DAV_VNODE;
|
||||
out->VFid.opaque[3] = 0;
|
||||
*((dav_node **) &(out->VFid.opaque[2])) = node;
|
||||
|
||||
return sizeof(struct coda_root_out);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
coda_setattr(void)
|
||||
{
|
||||
struct coda_in_hdr *ih = (struct coda_in_hdr *) buf;
|
||||
struct coda_setattr_in *in = (struct coda_setattr_in *) buf;
|
||||
dav_node *node = *((dav_node **) &(in->VFid.opaque[2]));
|
||||
struct coda_out_hdr *oh = (struct coda_out_hdr *) buf;
|
||||
if (debug) {
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_SETATTR:");
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " n %p, m %o", node,
|
||||
in->attr.va_mode);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " uid: %i, gid: %i",
|
||||
in->attr.va_uid, in->attr.va_gid);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " at %li, mt %li",
|
||||
in->attr.va_atime.tv_sec, in->attr.va_mtime.tv_sec);
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " ct %li, sz %llu",
|
||||
in->attr.va_ctime.tv_sec, in->attr.va_size);
|
||||
}
|
||||
|
||||
oh->result = dav_setattr(node, ih->uid, in->attr.va_mode != USHRT_MAX,
|
||||
in->attr.va_mode & DAV_A_MASK,
|
||||
in->attr.va_uid != UINT32_MAX, in->attr.va_uid,
|
||||
in->attr.va_gid != UINT32_MAX, in->attr.va_gid,
|
||||
in->attr.va_atime.tv_sec != -1,
|
||||
in->attr.va_atime.tv_sec,
|
||||
in->attr.va_mtime.tv_sec != -1,
|
||||
in->attr.va_mtime.tv_sec,
|
||||
in->attr.va_size != UINT64_MAX,
|
||||
in->attr.va_size);
|
||||
|
||||
return sizeof(struct coda_out_hdr);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
coda_statfs(void)
|
||||
{
|
||||
struct coda_out_hdr *oh = (struct coda_out_hdr *) buf;
|
||||
struct coda_statfs_out *out = (struct coda_statfs_out *) buf;
|
||||
if (debug)
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "CODA_STATFS:");
|
||||
|
||||
dav_stat st = dav_statfs();
|
||||
|
||||
out->stat.f_blocks = st.blocks;
|
||||
out->stat.f_bfree = st.bfree;
|
||||
out->stat.f_bavail = st.bavail;
|
||||
out->stat.f_files = st.files;
|
||||
out->stat.f_ffree = st.ffree;
|
||||
|
||||
oh->result = 0;
|
||||
return sizeof(struct coda_statfs_out);
|
||||
}
|
||||
|
||||
|
||||
/* Functions that will do a downcall to the kernel module. */
|
||||
|
||||
/* Downcall to inform the kernel that nodes have been added or removed. */
|
||||
static void
|
||||
coda_flush(int device)
|
||||
{
|
||||
struct coda_out_hdr *oh = (struct coda_out_hdr *) buf;
|
||||
if (debug)
|
||||
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " CODA_FLUSH:");
|
||||
|
||||
oh->opcode = CODA_FLUSH;
|
||||
oh->unique = 0;
|
||||
oh->result = 0;
|
||||
|
||||
ssize_t n = 0;
|
||||
ssize_t w = 0;
|
||||
while (n < sizeof(struct coda_out_hdr) && w >= 0) {
|
||||
w = write(device, buf + n, sizeof(struct coda_out_hdr) - n);
|
||||
n += w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Auxiliary functions. */
|
||||
|
||||
/* Writes a struct venus_dirent to file with file descriptor fd.
|
||||
fd : An open file descriptor to write to.
|
||||
off : The current file size.
|
||||
name : File name; if NULL, the last, empty entry is written.
|
||||
return value : New size of the file. -1 in case of an error. */
|
||||
static off_t
|
||||
write_dir_entry(int fd, off_t off, const dav_node *node, const char *name)
|
||||
{
|
||||
struct venus_dirent entry;
|
||||
size_t head = offsetof(struct venus_dirent, d_name);
|
||||
|
||||
if (name) {
|
||||
entry.d_fileno = (size_t) node / alignment;
|
||||
entry.d_type = (S_ISDIR(node->mode)) ? CDT_DIR : CDT_REG;
|
||||
entry.d_namlen = (strlen(name) > CODA_MAXNAMLEN)
|
||||
? CODA_MAXNAMLEN : strlen(name);
|
||||
entry.d_reclen = (head + entry.d_namlen +4) & ~3;
|
||||
} else {
|
||||
entry.d_fileno = 0;
|
||||
entry.d_type = 0;
|
||||
entry.d_namlen = 0;
|
||||
entry.d_reclen = (head + 4) & ~3;
|
||||
}
|
||||
|
||||
size_t size = 0;
|
||||
ssize_t ret = 0;
|
||||
while (ret >= 0 && size < head) {
|
||||
ret = write(fd, (char *) &entry + size, head - size);
|
||||
size += ret;
|
||||
}
|
||||
if (size != head)
|
||||
return -1;
|
||||
|
||||
ret = 0;
|
||||
while (ret >= 0 && size < (head + entry.d_namlen)) {
|
||||
ret = write(fd, name + size - head, entry.d_namlen - size + head);
|
||||
size += ret;
|
||||
}
|
||||
if (size != (head + entry.d_namlen))
|
||||
return -1;
|
||||
|
||||
ret = 0;
|
||||
while (ret >= 0 && size < entry.d_reclen) {
|
||||
ret = write(fd, "\0", 1);
|
||||
size += ret;
|
||||
}
|
||||
if (size != entry.d_reclen)
|
||||
return -1;
|
||||
|
||||
return off + entry.d_reclen;
|
||||
}
|
||||
|
||||
|
||||
/* Translates attribute from node to attr.
|
||||
Note: Members va_fileid, v_gen, va_flags, va_rdev and va_filerev have no
|
||||
meaning for davfs. va_fileid is treated like d_fileno in struct venus_dirent,
|
||||
the other are set to zero. The meaning of va_type is not clear at all.
|
||||
Times are only set with 1 second precision, as this is the precision of the
|
||||
last-modified time in HTTP. */
|
||||
static void
|
||||
set_attr(struct coda_vattr *attr, const dav_node *node)
|
||||
{
|
||||
attr->va_type = 0;
|
||||
attr->va_mode = node->mode;
|
||||
if (S_ISDIR(node->mode)) {
|
||||
attr->va_nlink = node->nref;
|
||||
} else {
|
||||
attr->va_nlink = 1;
|
||||
}
|
||||
attr->va_uid = node->uid;
|
||||
attr->va_gid = node->gid;
|
||||
attr->va_fileid = (size_t) node / alignment;
|
||||
attr->va_size = node->size;
|
||||
attr->va_blocksize = blocksize;
|
||||
attr->va_atime.tv_sec = node->atime;
|
||||
attr->va_atime.tv_nsec = 0;
|
||||
attr->va_mtime.tv_sec = node->mtime;
|
||||
attr->va_mtime.tv_nsec = 0;
|
||||
attr->va_ctime.tv_sec = node->ctime;
|
||||
attr->va_ctime.tv_nsec = 0;
|
||||
attr->va_gen = 0;
|
||||
attr->va_flags = 0;
|
||||
attr->va_rdev = 0;
|
||||
attr->va_bytes = node->size;
|
||||
attr->va_filerev = 0;
|
||||
}
|
1112
src/dav_fuse.c
Normal file
1112
src/dav_fuse.c
Normal file
File diff suppressed because it is too large
Load Diff
193
src/defaults.h
Normal file
193
src/defaults.h
Normal file
@ -0,0 +1,193 @@
|
||||
/* defauls.h: default values of configuration options and constants.
|
||||
Copyright (C) 2006, 2007, 2008, 2009 Werner Baumann
|
||||
|
||||
This file is part of davfs2.
|
||||
|
||||
davfs2 is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
davfs2 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 General Public License
|
||||
along with davfs2; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
|
||||
#ifndef DAV_DEFAULTS_H
|
||||
#define DAV_DEFAULTS_H
|
||||
|
||||
|
||||
/* Misc. */
|
||||
/*=======*/
|
||||
|
||||
#define DAV_HOME "http://dav.sourceforge.net"
|
||||
|
||||
/* File system type to be used with 'mount -t' and fstab. */
|
||||
#define DAV_FS_TYPE "davfs"
|
||||
|
||||
/* Mount options set by mount program in case of mounting by an
|
||||
ordinary user. */
|
||||
#define DAV_USER_MOPTS (MS_MGC_VAL | MS_NOSUID | MS_NOEXEC | MS_NODEV)
|
||||
|
||||
/* This mount options will allways be set by davfs2. Different values from
|
||||
command line and even fstab will be silently ignored. */
|
||||
#define DAV_MOPTS (MS_MGC_VAL | MS_NOSUID | MS_NODEV)
|
||||
|
||||
/* XML namespace for the cache index file. */
|
||||
#define DAV_XML_NS "http://dav.sf.net/"
|
||||
|
||||
|
||||
/* Directories and Files */
|
||||
/*=======================*/
|
||||
|
||||
/* The device directory. */
|
||||
#define DAV_DEV_DIR "/dev"
|
||||
|
||||
/* The file davfs reads mtab entries from. If not available it will
|
||||
use _PATH_MOUNTED. */
|
||||
#define DAV_MOUNTS "/proc/mounts"
|
||||
|
||||
/* The directory where the cache files will be stored, when mounted by
|
||||
a non root users; relative to DAV_USER_DIR.
|
||||
May be overridden by user config file. */
|
||||
#define DAV_CACHE "cache"
|
||||
|
||||
/* The name of index files. */
|
||||
#define DAV_INDEX "index"
|
||||
|
||||
/* Name of the directory within the davfs2 filesystem that holds local
|
||||
backup files.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_BACKUP_DIR "lost+found"
|
||||
|
||||
/* Buffer size for reading the XML index files of persistent cache. */
|
||||
#define DAV_XML_BUF_SIZE 16 * 1024
|
||||
|
||||
|
||||
/* Cache Optimization */
|
||||
/*====================*/
|
||||
|
||||
/* Cache size in MiByte.
|
||||
May be overridden by system config file and user config file.
|
||||
(1 MiByte = 1,048,576 Byte; Mi = Mebi = Mega Binary according to IEC) */
|
||||
#define DAV_CACHE_SIZE 50
|
||||
|
||||
/* Size of the hash table to store nodes. Should be a power of 2.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_TABLE_SIZE 1024
|
||||
|
||||
/* How long in seconds a cached directory is valid. After this time
|
||||
a new PROPFIND request for this directory must be performed.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_DIR_REFRESH 60
|
||||
|
||||
/* Wait at least that many seconds from last file access until a new
|
||||
GET If-Modified request is send to the server. If set to 0 a request
|
||||
will be send every time the file is opened. But some applications do
|
||||
open and close calls in short sequence that cause - mostly - unnecessary
|
||||
traffic.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_FILE_REFRESH 1
|
||||
|
||||
/* How long to delay uploading of locally changed files after closing.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_DELAY_UPLOAD 10
|
||||
|
||||
/* Use PROPFIND to get the Last-Modified time of all files in a directory
|
||||
instead of GET If-Modified_Since for single files.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_GUI_OPTIMIZE 0
|
||||
|
||||
|
||||
/* HTTP */
|
||||
/*======*/
|
||||
|
||||
/* The default proxy port.
|
||||
May be overridden by system config file, user config file or environment
|
||||
variable. */
|
||||
#define DAV_DEFAULT_PROXY_PORT 8080
|
||||
|
||||
/* Whether to use a proxy if one is specified.
|
||||
May be overridden by command line or fstab. */
|
||||
#define DAV_USE_PROXY 1
|
||||
|
||||
/* Whether to ask user for credentials if not given.
|
||||
May be overridden by command line, fstab or system config file. */
|
||||
#define DAV_ASKAUTH 1
|
||||
|
||||
/* Whether to use locks.
|
||||
May be overridden by command line or fstab. */
|
||||
#define DAV_LOCKS 1
|
||||
|
||||
/* Send expect 100-continue header in PUT requests.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_EXPECT100 0
|
||||
|
||||
/* If If-Match and If-None-Match does not work on the server, set to 1.
|
||||
Default is 1, as Apache has this bug.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_IF_MATCH_BUG 0
|
||||
|
||||
/* Some servers sends a weak invalid etag that turns into a valid strong etag
|
||||
after one second. With this flag set, the etag will not be used,
|
||||
otherwise the weakness indicator will be removed and the etag be trated
|
||||
as if it was strong.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_DROP_WEAK_ETAGS 0
|
||||
|
||||
/* Wether to allow a cookie to be set and included in requests.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_ALLOW_COOKIE 0
|
||||
|
||||
/* Check on server whether a file exists or has been modified before
|
||||
locking a new file or changing an existant one.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_PRECHECK 1
|
||||
|
||||
/* Ignore the information in the DAV-header, if any, because it
|
||||
may be a lie.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_IGNORE_DAV_HEADER 0
|
||||
|
||||
/* Timeout in seconds used when libneon supports non blocking io
|
||||
A value of zero means use the TCP default
|
||||
May be overriden by system config file and user config file. */
|
||||
#define DAV_CONNECT_TIMEOUT 10
|
||||
|
||||
/* Timeout in seconds used when reading from a socket.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_READ_TIMEOUT 30
|
||||
|
||||
/* Default retry time after a PROPFIND request failed. When the request fails
|
||||
again, the retry time will subsequently be increased up to DAV_MAX_RETRY.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_RETRY 30
|
||||
|
||||
/* Maximum retry time after a PROPFIND request failed.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_MAX_RETRY 300
|
||||
|
||||
/* Preferred live time of locks in seconds, before they have to be refreshed.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_LOCK_TIMEOUT 1800
|
||||
|
||||
/* How many seconds before a lock expires it should be refreshed.
|
||||
May be overridden by system config file and user config file. */
|
||||
#define DAV_LOCK_REFRESH 60
|
||||
|
||||
|
||||
/* Debug Constants */
|
||||
/*=================*/
|
||||
|
||||
#define DAV_DBG_CONFIG 0x1
|
||||
#define DAV_DBG_KERNEL 0x2
|
||||
#define DAV_DBG_CACHE 0x4
|
||||
#define DAV_DBG_SECRETS 0x8
|
||||
|
||||
|
||||
#endif /* DAV_DEFAULTS_H */
|
314
src/fuse_kernel.h
Normal file
314
src/fuse_kernel.h
Normal file
@ -0,0 +1,314 @@
|
||||
/* This file is taken from FUSE 2.5.3.
|
||||
From the two alternative licences the BSD licence has been chosen.
|
||||
#include and #ifdef directives have been removed.
|
||||
Modifications by Werner Baumann, 2009-04-14. */
|
||||
|
||||
|
||||
/* This file defines the kernel interface of FUSE */
|
||||
|
||||
/*
|
||||
Copyright (C) 2001-2006 Miklos Szeredi. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#define __u64 uint64_t
|
||||
#define __u32 uint32_t
|
||||
#define __s32 int32_t
|
||||
|
||||
/** Version number of this interface */
|
||||
#define FUSE_KERNEL_VERSION 7
|
||||
|
||||
/** Minor version number of this interface */
|
||||
#define FUSE_KERNEL_MINOR_VERSION 5
|
||||
|
||||
/** The node ID of the root inode */
|
||||
#define FUSE_ROOT_ID 1
|
||||
|
||||
/** The major number of the fuse character device */
|
||||
#define FUSE_MAJOR 10
|
||||
|
||||
/** The minor number of the fuse character device */
|
||||
#define FUSE_MINOR 229
|
||||
|
||||
/* Make sure all structures are padded to 64bit boundary, so 32bit
|
||||
userspace works under 64bit kernels */
|
||||
|
||||
struct fuse_attr {
|
||||
__u64 ino;
|
||||
__u64 size;
|
||||
__u64 blocks;
|
||||
__u64 atime;
|
||||
__u64 mtime;
|
||||
__u64 ctime;
|
||||
__u32 atimensec;
|
||||
__u32 mtimensec;
|
||||
__u32 ctimensec;
|
||||
__u32 mode;
|
||||
__u32 nlink;
|
||||
__u32 uid;
|
||||
__u32 gid;
|
||||
__u32 rdev;
|
||||
};
|
||||
|
||||
struct fuse_kstatfs {
|
||||
__u64 blocks;
|
||||
__u64 bfree;
|
||||
__u64 bavail;
|
||||
__u64 files;
|
||||
__u64 ffree;
|
||||
__u32 bsize;
|
||||
__u32 namelen;
|
||||
__u32 frsize;
|
||||
__u32 padding;
|
||||
__u32 spare[6];
|
||||
};
|
||||
|
||||
#define FATTR_MODE (1 << 0)
|
||||
#define FATTR_UID (1 << 1)
|
||||
#define FATTR_GID (1 << 2)
|
||||
#define FATTR_SIZE (1 << 3)
|
||||
#define FATTR_ATIME (1 << 4)
|
||||
#define FATTR_MTIME (1 << 5)
|
||||
#define FATTR_FH (1 << 6)
|
||||
|
||||
/**
|
||||
* Flags returned by the OPEN request
|
||||
*
|
||||
* FOPEN_DIRECT_IO: bypass page cache for this open file
|
||||
* FOPEN_KEEP_CACHE: don't invalidate the data cache on open
|
||||
*/
|
||||
#define FOPEN_DIRECT_IO (1 << 0)
|
||||
#define FOPEN_KEEP_CACHE (1 << 1)
|
||||
|
||||
enum fuse_opcode {
|
||||
FUSE_LOOKUP = 1,
|
||||
FUSE_FORGET = 2, /* no reply */
|
||||
FUSE_GETATTR = 3,
|
||||
FUSE_SETATTR = 4,
|
||||
FUSE_READLINK = 5,
|
||||
FUSE_SYMLINK = 6,
|
||||
FUSE_MKNOD = 8,
|
||||
FUSE_MKDIR = 9,
|
||||
FUSE_UNLINK = 10,
|
||||
FUSE_RMDIR = 11,
|
||||
FUSE_RENAME = 12,
|
||||
FUSE_LINK = 13,
|
||||
FUSE_OPEN = 14,
|
||||
FUSE_READ = 15,
|
||||
FUSE_WRITE = 16,
|
||||
FUSE_STATFS = 17,
|
||||
FUSE_RELEASE = 18,
|
||||
FUSE_FSYNC = 20,
|
||||
FUSE_SETXATTR = 21,
|
||||
FUSE_GETXATTR = 22,
|
||||
FUSE_LISTXATTR = 23,
|
||||
FUSE_REMOVEXATTR = 24,
|
||||
FUSE_FLUSH = 25,
|
||||
FUSE_INIT = 26,
|
||||
FUSE_OPENDIR = 27,
|
||||
FUSE_READDIR = 28,
|
||||
FUSE_RELEASEDIR = 29,
|
||||
FUSE_FSYNCDIR = 30,
|
||||
FUSE_ACCESS = 34,
|
||||
FUSE_CREATE = 35
|
||||
};
|
||||
|
||||
/* The read buffer is required to be at least 8k, but may be much larger */
|
||||
/* 2009-04-14, increased size of FUSE_MIN_READ_BUFFER, Werner Baumann */
|
||||
#define FUSE_MIN_READ_BUFFER 16384
|
||||
|
||||
struct fuse_entry_out {
|
||||
__u64 nodeid; /* Inode ID */
|
||||
__u64 generation; /* Inode generation: nodeid:gen must
|
||||
be unique for the fs's lifetime */
|
||||
__u64 entry_valid; /* Cache timeout for the name */
|
||||
__u64 attr_valid; /* Cache timeout for the attributes */
|
||||
__u32 entry_valid_nsec;
|
||||
__u32 attr_valid_nsec;
|
||||
struct fuse_attr attr;
|
||||
};
|
||||
|
||||
struct fuse_forget_in {
|
||||
__u64 nlookup;
|
||||
};
|
||||
|
||||
struct fuse_attr_out {
|
||||
__u64 attr_valid; /* Cache timeout for the attributes */
|
||||
__u32 attr_valid_nsec;
|
||||
__u32 dummy;
|
||||
struct fuse_attr attr;
|
||||
};
|
||||
|
||||
struct fuse_mknod_in {
|
||||
__u32 mode;
|
||||
__u32 rdev;
|
||||
};
|
||||
|
||||
struct fuse_mkdir_in {
|
||||
__u32 mode;
|
||||
__u32 padding;
|
||||
};
|
||||
|
||||
struct fuse_rename_in {
|
||||
__u64 newdir;
|
||||
};
|
||||
|
||||
struct fuse_link_in {
|
||||
__u64 oldnodeid;
|
||||
};
|
||||
|
||||
struct fuse_setattr_in {
|
||||
__u32 valid;
|
||||
__u32 padding;
|
||||
__u64 fh;
|
||||
__u64 size;
|
||||
__u64 unused1;
|
||||
__u64 atime;
|
||||
__u64 mtime;
|
||||
__u64 unused2;
|
||||
__u32 atimensec;
|
||||
__u32 mtimensec;
|
||||
__u32 unused3;
|
||||
__u32 mode;
|
||||
__u32 unused4;
|
||||
__u32 uid;
|
||||
__u32 gid;
|
||||
__u32 unused5;
|
||||
};
|
||||
|
||||
struct fuse_open_in {
|
||||
__u32 flags;
|
||||
__u32 mode;
|
||||
};
|
||||
|
||||
struct fuse_open_out {
|
||||
__u64 fh;
|
||||
__u32 open_flags;
|
||||
__u32 padding;
|
||||
};
|
||||
|
||||
struct fuse_release_in {
|
||||
__u64 fh;
|
||||
__u32 flags;
|
||||
__u32 padding;
|
||||
};
|
||||
|
||||
struct fuse_flush_in {
|
||||
__u64 fh;
|
||||
__u32 flush_flags;
|
||||
__u32 padding;
|
||||
};
|
||||
|
||||
struct fuse_read_in {
|
||||
__u64 fh;
|
||||
__u64 offset;
|
||||
__u32 size;
|
||||
__u32 padding;
|
||||
};
|
||||
|
||||
struct fuse_write_in {
|
||||
__u64 fh;
|
||||
__u64 offset;
|
||||
__u32 size;
|
||||
__u32 write_flags;
|
||||
};
|
||||
|
||||
struct fuse_write_out {
|
||||
__u32 size;
|
||||
__u32 padding;
|
||||
};
|
||||
|
||||
#define FUSE_COMPAT_STATFS_SIZE 48
|
||||
|
||||
struct fuse_statfs_out {
|
||||
struct fuse_kstatfs st;
|
||||
};
|
||||
|
||||
struct fuse_fsync_in {
|
||||
__u64 fh;
|
||||
__u32 fsync_flags;
|
||||
__u32 padding;
|
||||
};
|
||||
|
||||
struct fuse_setxattr_in {
|
||||
__u32 size;
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
struct fuse_getxattr_in {
|
||||
__u32 size;
|
||||
__u32 padding;
|
||||
};
|
||||
|
||||
struct fuse_getxattr_out {
|
||||
__u32 size;
|
||||
__u32 padding;
|
||||
};
|
||||
|
||||
struct fuse_access_in {
|
||||
__u32 mask;
|
||||
__u32 padding;
|
||||
};
|
||||
|
||||
struct fuse_init_in {
|
||||
__u32 major;
|
||||
__u32 minor;
|
||||
};
|
||||
|
||||
struct fuse_init_out {
|
||||
__u32 major;
|
||||
__u32 minor;
|
||||
__u32 unused[3];
|
||||
__u32 max_write;
|
||||
};
|
||||
|
||||
struct fuse_in_header {
|
||||
__u32 len;
|
||||
__u32 opcode;
|
||||
__u64 unique;
|
||||
__u64 nodeid;
|
||||
__u32 uid;
|
||||
__u32 gid;
|
||||
__u32 pid;
|
||||
__u32 padding;
|
||||
};
|
||||
|
||||
struct fuse_out_header {
|
||||
__u32 len;
|
||||
__s32 error;
|
||||
__u64 unique;
|
||||
};
|
||||
|
||||
struct fuse_dirent {
|
||||
__u64 ino;
|
||||
__u64 off;
|
||||
__u32 namelen;
|
||||
__u32 type;
|
||||
char name[0];
|
||||
};
|
||||
|
||||
#define FUSE_NAME_OFFSET ((unsigned) ((struct fuse_dirent *) 0)->name)
|
||||
#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1))
|
||||
#define FUSE_DIRENT_SIZE(d) \
|
||||
FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
|
265
src/kernel_interface.c
Normal file
265
src/kernel_interface.c
Normal file
@ -0,0 +1,265 @@
|
||||
/* kernel_interface.c: interface to fuse and coda kernel mocule.
|
||||
Copyright (C) 2006, 2007, 2008, 2009 Werner Baumann
|
||||
|
||||
This file is part of davfs2.
|
||||
|
||||
davfs2 is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
davfs2 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 General Public License
|
||||
along with davfs2; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <error.h>
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIBINTL_H
|
||||
#include <libintl.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDDEF_H
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_MOUNT_H
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
|
||||
#include "defaults.h"
|
||||
#include "mount_davfs.h"
|
||||
#include "cache.h"
|
||||
#include "coda.h"
|
||||
#include "fuse_kernel.h"
|
||||
#include "kernel_interface.h"
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
#define _(String) gettext(String)
|
||||
#else
|
||||
#define _(String) String
|
||||
#endif
|
||||
|
||||
|
||||
/* Private constants */
|
||||
/*===================*/
|
||||
|
||||
/* Name, major number and minor number of the devices to communicate with the
|
||||
kernel file system. */
|
||||
#define FUSE_DEV_NAME "fuse"
|
||||
#define CODA_DEV_NAME "cfs"
|
||||
#define CODA_MAJOR 67
|
||||
#define MAX_CODADEVS 5 /* Coda minor number may be from 0 to 4. */
|
||||
|
||||
|
||||
/* Private function prototypes */
|
||||
/*=============================*/
|
||||
|
||||
static int
|
||||
init_coda(int *dev, dav_run_msgloop_fn *msg_loop, void **mdata);
|
||||
|
||||
static int
|
||||
init_fuse(int *dev, dav_run_msgloop_fn *msg_loop, void **mdata,
|
||||
size_t *buf_size, const char *url, const char *mpoint,
|
||||
unsigned long int mopts, uid_t owner, gid_t group, mode_t mode);
|
||||
|
||||
|
||||
/* Public functions */
|
||||
/*==================*/
|
||||
|
||||
int
|
||||
dav_init_kernel_interface(int *dev, dav_run_msgloop_fn *msg_loop, void **mdata,
|
||||
char **kernel_fs, size_t *buf_size, const char *url,
|
||||
const char *mpoint, const dav_args *args)
|
||||
{
|
||||
uid_t orig = geteuid();
|
||||
seteuid(0);
|
||||
|
||||
if (!*kernel_fs)
|
||||
*kernel_fs = strdup("fuse");
|
||||
if (!*kernel_fs) abort();
|
||||
|
||||
int mounted = 0;
|
||||
if (strcmp(*kernel_fs, "coda") == 0) {
|
||||
|
||||
if (init_coda(dev, msg_loop, mdata) != 0) {
|
||||
error(0, 0, _("trying fuse kernel file system"));
|
||||
if (init_fuse(dev, msg_loop, mdata, buf_size, url, mpoint,
|
||||
args->mopts, args->uid, args->gid, args->dir_mode)
|
||||
== 0) {
|
||||
free(*kernel_fs);
|
||||
*kernel_fs = strdup("fuse");
|
||||
if (!*kernel_fs) abort();
|
||||
mounted = 1;
|
||||
error(0, 0, _("fuse device opened successfully"));
|
||||
} else {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (strcmp(*kernel_fs, "fuse") == 0) {
|
||||
|
||||
if (init_fuse(dev, msg_loop, mdata, buf_size, url, mpoint, args->mopts,
|
||||
args->uid, args->gid, args->dir_mode) == 0) {
|
||||
mounted = 1;
|
||||
} else {
|
||||
error(0, 0, _("trying coda kernel file system"));
|
||||
if (init_coda(dev, msg_loop, mdata) == 0) {
|
||||
free(*kernel_fs);
|
||||
*kernel_fs = strdup("coda");
|
||||
if (*kernel_fs == NULL)
|
||||
abort();
|
||||
error(0, 0, _("coda device opened successfully"));
|
||||
} else {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
error(EXIT_FAILURE, 0, _("unknown kernel file system %s"), *kernel_fs);
|
||||
}
|
||||
|
||||
seteuid(orig);
|
||||
return mounted;
|
||||
}
|
||||
|
||||
|
||||
/* Private functions */
|
||||
/*===================*/
|
||||
|
||||
static int
|
||||
init_coda(int *dev, dav_run_msgloop_fn *msg_loop, void **mdata)
|
||||
{
|
||||
*dev = 0;
|
||||
int minor = 0;
|
||||
while (*dev <= 0 && minor < MAX_CODADEVS) {
|
||||
char *path;
|
||||
if (asprintf(&path, "%s/%s%i", DAV_DEV_DIR, CODA_DEV_NAME, minor) < 0)
|
||||
abort();
|
||||
*dev = open(path, O_RDWR | O_NONBLOCK);
|
||||
free(path);
|
||||
++minor;
|
||||
}
|
||||
|
||||
if (*dev <= 0) {
|
||||
system("/sbin/modprobe coda &>/dev/null");
|
||||
minor = 0;
|
||||
while (*dev <= 0 && minor < MAX_CODADEVS) {
|
||||
char *path;
|
||||
if (asprintf(&path, "%s/%s%i",
|
||||
DAV_DEV_DIR, CODA_DEV_NAME, minor) < 0)
|
||||
abort();
|
||||
*dev = open(path, O_RDWR | O_NONBLOCK);
|
||||
if (*dev <= 0) {
|
||||
if (mknod(path, S_IFCHR, makedev(CODA_MAJOR, minor)) == 0) {
|
||||
chown(path, 0, 0);
|
||||
chmod(path, S_IRUSR | S_IWUSR);
|
||||
*dev = open(path, O_RDWR | O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
free(path);
|
||||
++minor;
|
||||
}
|
||||
}
|
||||
|
||||
if (*dev <= 0) {
|
||||
error(0, 0, _("no free coda device to mount"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
int version = 0;
|
||||
ioctl(*dev, CIOC_KERNEL_VERSION, &version);
|
||||
if (version == 3) {
|
||||
*msg_loop = dav_coda_loop;
|
||||
} else {
|
||||
error(0, 0, _("CODA_KERNEL_VERSION %u not supported"), version);
|
||||
close(*dev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct coda_mount_data *md = malloc(sizeof(struct coda_mount_data));
|
||||
if (!md) abort();
|
||||
md->version = CODA_MOUNT_VERSION;
|
||||
md->fd = *dev;
|
||||
*mdata = md;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
init_fuse(int *dev, dav_run_msgloop_fn *msg_loop, void **mdata,
|
||||
size_t *buf_size, const char *url, const char *mpoint,
|
||||
unsigned long int mopts, uid_t owner, gid_t group, mode_t mode)
|
||||
{
|
||||
char *path;
|
||||
if (asprintf(&path, "%s/%s", DAV_DEV_DIR, FUSE_DEV_NAME) < 0)
|
||||
abort();
|
||||
|
||||
*dev = open(path, O_RDWR | O_NONBLOCK);
|
||||
if (*dev <= 0) {
|
||||
system("/sbin/modprobe fuse &>/dev/null");
|
||||
*dev = open(path, O_RDWR | O_NONBLOCK);
|
||||
}
|
||||
if (*dev <= 0) {
|
||||
if (mknod(path, S_IFCHR, makedev(FUSE_MAJOR, FUSE_MINOR)) == 0) {
|
||||
chown(path, 0, 0);
|
||||
chmod(path, S_IRUSR | S_IWUSR);
|
||||
*dev = open(path, O_RDWR | O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
free(path);
|
||||
if (*dev <= 0) {
|
||||
error(0, 0, _("can't open fuse device"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*buf_size < (FUSE_MIN_READ_BUFFER + 4096)) {
|
||||
*buf_size = FUSE_MIN_READ_BUFFER + 4096;
|
||||
}
|
||||
|
||||
#if SIZEOF_VOID_P == 8
|
||||
if (asprintf((char **) mdata, "fd=%i,rootmode=%o,user_id=%i,group_id=%i,"
|
||||
"allow_other,max_read=%lu", *dev, mode, owner, group,
|
||||
*buf_size - 4096) < 0)
|
||||
abort();
|
||||
#else
|
||||
if (asprintf((char **) mdata, "fd=%i,rootmode=%o,user_id=%i,group_id=%i,"
|
||||
"allow_other,max_read=%u", *dev, mode, owner, group,
|
||||
*buf_size - 4096) < 0)
|
||||
abort();
|
||||
#endif
|
||||
if (mount(url, mpoint, "fuse", mopts, *mdata) == 0) {
|
||||
*msg_loop = dav_fuse_loop;
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(*mdata);
|
||||
close(*dev);
|
||||
error(0, 0, _("can't mount using fuse kernel file system"));
|
||||
return -1;
|
||||
}
|
96
src/kernel_interface.h
Normal file
96
src/kernel_interface.h
Normal file
@ -0,0 +1,96 @@
|
||||
/* kernel_interface.h: interface to fuse and coda kernel mocule.
|
||||
Copyright (C) 2006, 2007, 2008, 2009 Werner Baumann
|
||||
|
||||
This file is part of davfs2.
|
||||
|
||||
davfs2 is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
davfs2 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 General Public License
|
||||
along with davfs2; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
|
||||
#ifndef DAV_KERNEL_INTERFACE_H
|
||||
#define DAV_KERNEL_INTERFACE_H
|
||||
|
||||
|
||||
/* Function type definitions */
|
||||
/*===========================*/
|
||||
|
||||
/* Call back function to be passed to dav_init_kernel_interface(). Will be
|
||||
called to see whether the file system is still mounted.
|
||||
return value : 1 is mounted, 0 is not mounted. */
|
||||
typedef int (*dav_is_mounted_fn)(void);
|
||||
|
||||
|
||||
/* Typedef of the message loop of the specific kernel interfaces. The real
|
||||
function will be returned by dav_init_kernel_interface().
|
||||
device : File descriptor of the open fuse device.
|
||||
buf_size : Size of the buffer for communication with the kernel
|
||||
module.
|
||||
idle_t : Time to wait for upcalls before calling dav_tidy_cache().
|
||||
is_mounted_fn : Call back function to check of still mounted.
|
||||
keep_on_running : Pointer to run flag.
|
||||
dbg : send debug messages to syslog if dbg != 0 */
|
||||
typedef void (*dav_run_msgloop_fn)(int device, size_t bufsize, time_t idle_time,
|
||||
dav_is_mounted_fn is_mounted,
|
||||
volatile int *keep_on_running, int dbg);
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
/*=====================*/
|
||||
|
||||
/* Opens the device for communication with the kernel file system, if possible
|
||||
mounts the file system and updates the interface data (dev,
|
||||
dav_ran_msgloop_fn, mdata, kernel_fs and buf_size).
|
||||
In case of an error it prints an error message and terminates the program.
|
||||
dev : File descriptor of the open device for communication with the
|
||||
kernel file system.
|
||||
msg_loop : The specific message loop function that will process the kernel
|
||||
upcalls.
|
||||
mdata : That mount data that will be passed to the mount function.
|
||||
kernel_fs : Type of the kernel file system to us (fuse or coda). If this
|
||||
does not work, the other file system will be tried. The name
|
||||
of the file system that is really used is returned.
|
||||
If NULL, fuse is tried first.
|
||||
buf_size : Size of the buffer for communication with the kernel file system
|
||||
(fuse only). The size passed to this function is checked against
|
||||
the requirements of the kernel fs and updated if necessary.
|
||||
url : Server url.
|
||||
mpoint : Mount point.
|
||||
mopts : Mount options.
|
||||
owner : The owner of the file system (fuse only).
|
||||
group : Group the file system belongs to (fuse only).
|
||||
mode : Mode of the root node (fuse only).
|
||||
return value : 0: the file system has not yet been mounted
|
||||
1: the file system has been mounted successfully. */
|
||||
int
|
||||
dav_init_kernel_interface(int *dev, dav_run_msgloop_fn *msg_loop, void **mdata,
|
||||
char **kernel_fs, size_t *buf_size, const char *url,
|
||||
const char *mpoint, const dav_args *args);
|
||||
|
||||
|
||||
/* Message loop for coda kernel module CODA_KERNEL_VERSION 3.
|
||||
Parameters see dav_run_msgloop_fn(). */
|
||||
void dav_coda_loop(int device, size_t bufsize, time_t idle_time,
|
||||
dav_is_mounted_fn is_mounted,
|
||||
volatile int *keep_on_running, int dbg);
|
||||
|
||||
|
||||
/* Message loop for fuse kernel module with major number 7.
|
||||
Parameters see dav_run_msgloop_fn(). */
|
||||
void
|
||||
dav_fuse_loop(int device, size_t bufsize, time_t idle_time,
|
||||
dav_is_mounted_fn is_mounted, volatile int *keep_on_running,
|
||||
int dbg);
|
||||
|
||||
|
||||
#endif /* DAV_KERNEL_INTERFACE_H */
|
2538
src/mount_davfs.c
Normal file
2538
src/mount_davfs.c
Normal file
File diff suppressed because it is too large
Load Diff
157
src/mount_davfs.h
Normal file
157
src/mount_davfs.h
Normal file
@ -0,0 +1,157 @@
|
||||
/* mount_davfs.h: structure to collect arguments and options.
|
||||
Copyright (C) 2006, 2007, 2008, 2009 Werner Baumann
|
||||
|
||||
This file is part of davfs2.
|
||||
|
||||
davfs2 is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
davfs2 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 General Public License
|
||||
along with davfs2; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
|
||||
#ifndef DAV_MOUNT_DAVFS_H
|
||||
#define DAV_MOUNT_DAVFS_H
|
||||
|
||||
|
||||
/* Data Types */
|
||||
/*============*/
|
||||
|
||||
/* This data structure holds almost everything davfs gathers while reading and
|
||||
checking command line and configuration files. (See comment for data origin;
|
||||
highest precedence first.)
|
||||
Some data will be copied into global or local variables to be available in
|
||||
daemon mode. The rest will be freed when forking into daemon mode. */
|
||||
typedef struct {
|
||||
char *dav_user; /* System config file */
|
||||
char *dav_group; /* System config file */
|
||||
char *ignore_home; /* System config file */
|
||||
char *conf; /* Command line */
|
||||
/* Mount options */
|
||||
int user; /* Command line */
|
||||
int netdev; /* Command line */
|
||||
unsigned long int mopts; /* Command line */
|
||||
char *add_mopts;
|
||||
char *kernel_fs; /* User config file, system config file */
|
||||
size_t buf_size; /* User config file, system config file */
|
||||
/* File mode */
|
||||
uid_t uid; /* Command line */
|
||||
gid_t gid; /* Command line */
|
||||
mode_t dir_umask;
|
||||
mode_t file_umask;
|
||||
mode_t dir_mode; /* Command line */
|
||||
mode_t file_mode; /* Command line */
|
||||
/* WebDAV-resource */
|
||||
char *scheme; /* Command line */
|
||||
char *host; /* Command line */
|
||||
int port; /* Command line */
|
||||
char *path; /* Command line */
|
||||
char *servercert; /* User config file, system config file */
|
||||
char *secrets; /* User config file */
|
||||
char *username; /* User secrets file, system secrets file */
|
||||
char *password; /* User secrets file, system secrets file */
|
||||
char *clicert; /* User config file, system config file */
|
||||
char *clicert_pw; /* User secrets file, system secrets file */
|
||||
char *p_host; /* User config file, sys conf f., environment */
|
||||
int p_port; /* User config file, sys conf f., environment */
|
||||
char *p_user; /* User secrets file, system secrets file */
|
||||
char *p_passwd; /* User secrets file, system secrets file */
|
||||
int useproxy; /* User config file, sys conf f., command line */
|
||||
int askauth; /* User config file, sys conf f., command line */
|
||||
int locks; /* User config file, sys conf f., command line */
|
||||
char * lock_owner; /* User config file, system config file */
|
||||
time_t lock_timeout; /* User config file, system config file */
|
||||
time_t lock_refresh; /* User config file, system config file */
|
||||
int expect100; /* User config file, system config file */
|
||||
int if_match_bug; /* User config file, system config file */
|
||||
int drop_weak_etags; /* User config file, system config file */
|
||||
int allow_cookie; /* User config file, system config file */
|
||||
int precheck; /* User config file, system config file */
|
||||
int ignore_dav_header; /* User config file, system config file */
|
||||
time_t connect_timeout; /* User config file, system config file */
|
||||
time_t read_timeout; /* User config file, system config file */
|
||||
time_t retry; /* User config file, system config file */
|
||||
time_t max_retry; /* User config file, system config file */
|
||||
char * s_charset; /* User config file, system config file */
|
||||
char * header; /* User config file, system config file */
|
||||
/* Cache */
|
||||
char *sys_cache; /* System config file */
|
||||
char *cache_dir; /* User config file */
|
||||
char *backup_dir; /* User config file, system config file */
|
||||
size_t cache_size; /* User config file, system config file */
|
||||
size_t table_size; /* User config file, system config file */
|
||||
time_t dir_refresh; /* User config file, system config file */
|
||||
time_t file_refresh; /* User config file, system config file */
|
||||
int delay_upload; /* User config file, system config file */
|
||||
int gui_optimize; /* User config file, system config file */
|
||||
/* Debugging */
|
||||
int debug; /* User config file, system config file */
|
||||
int neon_debug; /* User config file, system config file */
|
||||
} dav_args;
|
||||
|
||||
|
||||
/* Public functions. */
|
||||
/*===================*/
|
||||
|
||||
/* Main launches a daemon program that runs a directory and file cache and
|
||||
is connected to the WbDAV resource and the kernel file system module.
|
||||
It must run setuid root. After forking into daemon mode it releases root
|
||||
permissions permanently. The daemon runs with the uid of the user that owns
|
||||
the file system. (If invoked by root and the mounted file system is owned
|
||||
by root, the daemon runs as root. This should be avoided.)
|
||||
Launching the daemon (and stopping) is done in 5 steps.
|
||||
Step 1:
|
||||
- Gathering information from command line, configuration files and
|
||||
environment.
|
||||
- Checking this information for consistency and any errors that would
|
||||
prevent successful running of the daemon.
|
||||
- Checking whether the the user has permissions to mount.
|
||||
- Checking whether the neccessary files and directories for running the
|
||||
daemon are available.
|
||||
Step 2:
|
||||
- The modules for connecting to the kernel, connecting to the WebDAV resource
|
||||
and for caching are initialised.
|
||||
If an error accurs during step 1 or step 2 an error message is printed and
|
||||
the program dies immediately. Clean up is left to the operating system.
|
||||
Step 3:
|
||||
- Forking into daemon mode.
|
||||
- While the daemon (child) writes the pid file and starts reading upcalls
|
||||
from the kernel in an endless loop, the parent process tries to mount the
|
||||
file system and write an entry into mtab (_PROC_MOUNTS).
|
||||
- If an error occurs in one of the processes it sends SIGTERM to the other.
|
||||
While the parent just dies, the daemon will run its normal exit code
|
||||
(see step 5). In rare cases this might nevertheless leave stale pid files
|
||||
or entries in mtab that must be cleaned manually by the administrator.
|
||||
- If mounting is successful the parent process exits with success.
|
||||
Step 4:
|
||||
- Running as daemon.
|
||||
Step 5:
|
||||
- Terminating.
|
||||
- The daemon has set a signal handler for SIGTERM and SIGHUP. If it gets one
|
||||
of these signals it tries to unmount the file system and resets the global
|
||||
variable keep_on_running. This will terminate the message loop gracefully.
|
||||
- If the file system is unmounted (by the umount programm), the message
|
||||
loop will terminate gracefully.
|
||||
- The close functions of the modules are called, that will clean up the
|
||||
cache, save cached information if neccessary and close the connections. */
|
||||
int
|
||||
main(int argc, char *argv[]);
|
||||
|
||||
|
||||
/* Prints prompt to stdout and reads a line from stdin.
|
||||
Echoing the user input to stdout is prohibited.
|
||||
A trailing newline is removed.
|
||||
return value : the user input. */
|
||||
char *
|
||||
dav_user_input_hidden(const char *prompt);
|
||||
|
||||
|
||||
#endif /* DAV_MOUNT_DAVFS_H */
|
212
src/umount_davfs.c
Normal file
212
src/umount_davfs.c
Normal file
@ -0,0 +1,212 @@
|
||||
/* umount_davfs.c: unmount the davfs file system.
|
||||
Copyright (C) 2006, 2007, 2008, 2009 Werner Baumann
|
||||
|
||||
This file is part of davfs2.
|
||||
|
||||
davfs2 is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
davfs2 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 General Public License
|
||||
along with davfs2; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <error.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#ifdef HAVE_LIBINTL_H
|
||||
#include <libintl.h>
|
||||
#endif
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <ne_string.h>
|
||||
|
||||
#include "defaults.h"
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
#define _(String) gettext(String)
|
||||
#else
|
||||
#define _(String) String
|
||||
#define textdomain(Domainname)
|
||||
#define bindtextdomain(Domainname, Dirname)
|
||||
#endif
|
||||
|
||||
|
||||
/* This is lazy programming. All the dirty work is left to the real umount
|
||||
program, while we just sit and wait for mount.davfs to terminate.
|
||||
umount.davfs is a umount helper. It is usually called by umount and makes
|
||||
sure, that umount will not return until mount.davfs has synchronized all
|
||||
files.
|
||||
It first reads the pid-file and identifies the mount.davfs process. Then
|
||||
it calls mount again, with option -i (to not be called again), to do the
|
||||
real unmounting. In a loop it will watch the process list. When the
|
||||
mount.davfs process terminates, it will return.
|
||||
If it can't identify the mount.davfs process, it will call umount -i anyway,
|
||||
but warn the user. */
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
setuid(getuid());
|
||||
setgid(getgid());
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
char *short_options = "Vhflnrv";
|
||||
static const struct option options[] = {
|
||||
{"version", no_argument, NULL, 'V'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
int o;
|
||||
o = getopt_long(argc, argv, short_options, options, NULL);
|
||||
while (o != -1) {
|
||||
switch (o) {
|
||||
case 'V':
|
||||
printf("%s <%s>\n\n", PACKAGE_STRING, DAV_HOME);
|
||||
printf(_("This is free software; see the source for copying "
|
||||
"conditions. There is NO\n"
|
||||
"warranty; not even for MERCHANTABILITY or FITNESS "
|
||||
"FOR A PARTICULAR PURPOSE.\n"));
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'h':
|
||||
printf(_("Usage:\n"
|
||||
" u%s -V,--version : print version string\n"
|
||||
" u%s -h,--help : print this message\n\n"),
|
||||
PROGRAM_NAME, PROGRAM_NAME);
|
||||
printf(_("To umount a WebDAV-resource don't call u%s directly, "
|
||||
"but use\n"
|
||||
"`umount' instead.\n"), PROGRAM_NAME);
|
||||
printf(_(" umount <mountpoint> : umount the WebDAV-resource as "
|
||||
"specified in\n"
|
||||
" /etc/fstab.\n"));
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'f':
|
||||
case 'l':
|
||||
case 'n':
|
||||
case 'r':
|
||||
case 'v':
|
||||
case '?':
|
||||
break;
|
||||
default:
|
||||
error(EXIT_FAILURE, 0, _("unknown error parsing arguments"));
|
||||
}
|
||||
o = getopt_long(argc, argv, short_options, options, NULL);
|
||||
}
|
||||
|
||||
if (optind > (argc - 1))
|
||||
error(EXIT_FAILURE, 0, _("missing argument"));
|
||||
if (optind < (argc - 1))
|
||||
error(EXIT_FAILURE, 0, _("too many arguments"));
|
||||
|
||||
char *mpoint = canonicalize_file_name(argv[optind]);
|
||||
if (!mpoint)
|
||||
mpoint = argv[optind];
|
||||
if (!mpoint || *mpoint != '/')
|
||||
error(EXIT_FAILURE, 0, _("can't determine mount point"));
|
||||
|
||||
char *m = mpoint;
|
||||
while (*m == '/')
|
||||
m++;
|
||||
char *mp = ne_strdup(m);
|
||||
m = strchr(mp, '/');
|
||||
while (m) {
|
||||
*m = '-';
|
||||
m = strchr(mp, '/');
|
||||
}
|
||||
char *pidfile = ne_concat(DAV_SYS_RUN, "/", mp, ".pid", NULL);
|
||||
free(mp);
|
||||
|
||||
char *umount_command = ne_concat("umount -i ", mpoint, NULL);
|
||||
|
||||
char *pid = NULL;
|
||||
FILE *file = fopen(pidfile, "r");
|
||||
if (!file || fscanf(file, "%a[0-9]", &pid) != 1 || !pid) {
|
||||
error(0, 0,
|
||||
_("\n"
|
||||
" can't read PID from file %s;\n"
|
||||
" trying to unmount anyway;\n"
|
||||
" please wait for %s to terminate"), pidfile, PROGRAM_NAME);
|
||||
return system(umount_command);
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
char *ps_command = ne_concat("ps -p ", pid, NULL);
|
||||
FILE *ps_in = popen(ps_command, "r");
|
||||
if (!ps_in) {
|
||||
error(0, 0,
|
||||
_("\n"
|
||||
" can't read process list;\n"
|
||||
" trying to unmount anyway;\n"
|
||||
" please wait for %s to terminate"), PROGRAM_NAME);
|
||||
return system(umount_command);
|
||||
}
|
||||
|
||||
int found = 0;
|
||||
size_t n = 0;
|
||||
char *ps_line = NULL;
|
||||
while (!found && getline(&ps_line, &n, ps_in) > 0)
|
||||
found = (strstr(ps_line, pid) && strstr(ps_line, PROGRAM_NAME));
|
||||
pclose(ps_in);
|
||||
|
||||
if (!found) {
|
||||
error(0, 0,
|
||||
_("\n"
|
||||
" can't find %s-process with pid %s;\n"
|
||||
" trying to unmount anyway.\n"
|
||||
" you propably have to remove %s manually"),
|
||||
PROGRAM_NAME, pid, pidfile);
|
||||
return system(umount_command);
|
||||
}
|
||||
|
||||
if (system(umount_command) != 0)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
printf(_("%s: waiting while %s (pid %s) synchronizes the cache ."),
|
||||
argv[0], PROGRAM_NAME, pid);
|
||||
fflush(stdout);
|
||||
|
||||
while (found) {
|
||||
|
||||
sleep(3);
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
|
||||
ps_in = popen(ps_command, "r");
|
||||
if (!ps_in) {
|
||||
printf("\n");
|
||||
error(EXIT_FAILURE, 0, _("an error occured while waiting; "
|
||||
"please wait for %s to terminate"), PROGRAM_NAME);
|
||||
}
|
||||
|
||||
found = 0;
|
||||
while (!found && getline(&ps_line, &n, ps_in) > 0)
|
||||
found = (strstr(ps_line, pid) && strstr(ps_line, PROGRAM_NAME));
|
||||
|
||||
pclose(ps_in);
|
||||
}
|
||||
printf(" OK\n");
|
||||
|
||||
return 0;
|
||||
}
|
1915
src/webdav.c
Normal file
1915
src/webdav.c
Normal file
File diff suppressed because it is too large
Load Diff
278
src/webdav.h
Normal file
278
src/webdav.h
Normal file
@ -0,0 +1,278 @@
|
||||
/* webdav.h: send requests to the WebDAV server.
|
||||
Copyright (C) 2006, 2007, 2008, 2009 Werner Baumann
|
||||
|
||||
This file is part of davfs2.
|
||||
|
||||
davfs2 is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
davfs2 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 General Public License
|
||||
along with davfs2; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
|
||||
#ifndef DAV_WEBDAV_H
|
||||
#define DAV_WEBDAV_H
|
||||
|
||||
|
||||
/* Data Types */
|
||||
/*============*/
|
||||
|
||||
/* This structure holds the properties retrieved from the server.
|
||||
Usually a linked list of these is returned by dav_get_collection().
|
||||
Unused pointers should be set to NULL, integer types to 0. */
|
||||
typedef struct dav_props dav_props;
|
||||
struct dav_props {
|
||||
char *path; /* The unescaped path of the resource. */
|
||||
char *name; /* The name of the file or directory. Only the last
|
||||
component (no path), no slashes. */
|
||||
char *etag; /* The etag string, including quotation characters,
|
||||
but without the mark for weak etags. */
|
||||
off_t size; /* File size in bytes (regular files only). */
|
||||
time_t ctime; /* Creation date. */
|
||||
time_t mtime; /* Date of last modification. */
|
||||
int is_dir; /* Boolean; 1 if a directory. */
|
||||
int is_exec; /* -1 if not specified; 1 is executeable;
|
||||
0 not executeable. */
|
||||
dav_props *next; /* Next in the list. */
|
||||
};
|
||||
|
||||
|
||||
/* Function prototypes */
|
||||
/*=====================*/
|
||||
|
||||
/* Creates and initializes a neon_session, using configuration information
|
||||
given as parameters, and checks the WebDAV class of the server.
|
||||
If the server does not support class 2, locking is disabled.
|
||||
It must only be initialized once, as it depends on global variables.
|
||||
If an error occurs, the program is terminated.
|
||||
paramters: if not self explaining, please see mount_davfs.h, struct args. */
|
||||
void
|
||||
dav_init_webdav(const dav_args* args);
|
||||
|
||||
|
||||
/* Does an OPTIONS request to check the server capabilities. In case of
|
||||
success it will set the global variable initialized. If the server
|
||||
does not support locks, it will remove the lockstore and set locks
|
||||
to NULL.
|
||||
path : Path to the root collection.
|
||||
return value : 0 on success or an apropriate error code. */
|
||||
int
|
||||
dav_init_connection(const char *path);
|
||||
|
||||
|
||||
/* Releases all locks (if possible) and closes the session.
|
||||
Does not free memory held by the session. */
|
||||
void
|
||||
dav_close_webdav(void);
|
||||
|
||||
|
||||
/* Converts the character encoding of s from and to the local encoding.
|
||||
Converter handles are taken from global variables from_utf_8, to_utf_8,
|
||||
from_server_enc and to_server_enc.
|
||||
If no conversion is necessary, it just returns a copy of s.
|
||||
name : string to be converted.
|
||||
return value : the converted string, newly allocated. */
|
||||
char *
|
||||
dav_conv_from_utf_8(const char *s);
|
||||
char *
|
||||
dav_conv_to_utf_8(const char *s);
|
||||
char *
|
||||
dav_conv_from_server_enc(const char *s);
|
||||
char *
|
||||
dav_conv_to_server_enc(const char *s);
|
||||
|
||||
|
||||
/* Deletes file path on the server.
|
||||
On success locks for this file are removed from the lock store.
|
||||
path : Absolute path of the file.
|
||||
expire : If not 0, the resource is assumed to be locked and the lock
|
||||
will be removed after successful delete.
|
||||
return value : 0 on success; an appropriate file error code otherwise. */
|
||||
int
|
||||
dav_delete(const char *path, time_t *expire);
|
||||
|
||||
|
||||
/* Deletes collection path on the server.
|
||||
path : Absolute path of the collection.
|
||||
return value : 0 on success; an appropriate file error code otherwise. */
|
||||
int dav_delete_dir(const char *path);
|
||||
|
||||
|
||||
/* Frees any resources held by props and finally frees props. */
|
||||
void
|
||||
dav_delete_props(dav_props *props);
|
||||
|
||||
|
||||
/* Retrieves properties for the directory named by path and its
|
||||
direct childs (depth 1) from the server.
|
||||
The properties are returned as a linked list of dav_props. If successfull,
|
||||
this list contains at least one entry (the directory itself; its name is
|
||||
the empty string). The calling function is responsible for freeing the list
|
||||
and all the strings included.
|
||||
path : The absolute path of the directory with trailing slash.
|
||||
*props : Will point to the list of properties on return. NULL in case of
|
||||
an error.
|
||||
return value : 0 on success; an appropriate file error code otherwise. */
|
||||
int
|
||||
dav_get_collection(const char *path, dav_props **props);
|
||||
|
||||
|
||||
/* Fetches file path from the server, stores it in cache_path and updates
|
||||
size, etag and mtime.
|
||||
If etag and/or mtime are supplied, a conditional GET will be performed.
|
||||
If the file has not been modified on the server, size, etag, mtime and
|
||||
mime will not be changed.
|
||||
If the GET request fails none of size, etag and mtime are changed.
|
||||
cache_path : Name of the cache file to store the file in.
|
||||
path : Absolute path of the file on the server.
|
||||
size : Points to the size of the cached file and will be updated if a
|
||||
new version of the file is retrieved.
|
||||
etag : Points to the ETag string of the cached version. If a new
|
||||
version of the file is retrieved this will be replaced by the
|
||||
new ETag value. May be NULL or point to NULL.
|
||||
mtime : Points to the Last-Modified value of the cached version. Will
|
||||
be updated if a new version of the file is retrieved.
|
||||
May be NULL.
|
||||
mime : Points to the mime_type string of the cached version. Will
|
||||
be updated by the value of the Content-Type header, if any.
|
||||
May be NULL;
|
||||
modified : Points to a flag that will be set 1 if the file cache_path
|
||||
has been replaced by a new version. May be NULL.
|
||||
return value : 0 on success; an appropriate file error code otherwise.
|
||||
Not-Modified counts as success. */
|
||||
int
|
||||
dav_get_file(const char *path, const char *cache_path, off_t *size,
|
||||
char **etag, time_t *mtime, char **mime, int *modified);
|
||||
|
||||
|
||||
/* Returns the error string from the last WebDAV request.
|
||||
Note: This will not be usefull in any case, because the last function
|
||||
called may have done more then one request (e.g. an additional
|
||||
lock discover. But it is usefull for dav_get_collection(). */
|
||||
const char *
|
||||
dav_get_webdav_error(void);
|
||||
|
||||
|
||||
/* Tests for the existence of file path and uptdates etag, mtime and length.
|
||||
In case of an error etag and mtime are not changed. If the server does not
|
||||
send ETag or Last-Modified the corresponding value will not be changed.
|
||||
path : absolute path of the file on the server.
|
||||
etag : Points to the Etag; will be updated on success. May be NULL.
|
||||
mtime : Points to mtime; will be updated on success. May be NULL.
|
||||
length: Points to length; will be updated on success. May be NULL.
|
||||
mime : Points to mime_type; will be updated on success. May be NULL.
|
||||
return value : 0 if the file exists; an appropriate file error code
|
||||
otherwise. */
|
||||
int
|
||||
dav_head(const char *path, char **etag, time_t *mtime, off_t *length,
|
||||
char **mime);
|
||||
|
||||
|
||||
/* Locks the file path on the server with an excluse write lock and updates
|
||||
expire and exists. If a lock for path allready exists it will be refreshed.
|
||||
On success expire will be updated to the time when the lock expires.
|
||||
If the file does not yet exist and server creates a new file (as opposed to
|
||||
creating a locked-null-resource) exists will be set to 1.
|
||||
If the file is already locked, but not by this instance of davfs2, it will
|
||||
try if the lock is from the same user using davfs2, and if so, to use this
|
||||
lock.
|
||||
If it can't get a lock it will return an appropriate error code and set
|
||||
expire to 0.
|
||||
If the session is initialized with the nolocks option, it does nothing,
|
||||
but allways returns success and sets expire to 0.
|
||||
path : absolute path of the file on the server.
|
||||
expire : Points to the time when the lock expires. 0 if not locked.
|
||||
Will be updated.
|
||||
exists : Indicates whether the file exists on the server. If the server
|
||||
responds with "201 CREATED", it will be set to 1.
|
||||
return value : 0 on success; an appropriate file error code
|
||||
otherwise. */
|
||||
int
|
||||
dav_lock(const char *path, time_t *expire, int *exists);
|
||||
|
||||
|
||||
/* Refreshes the lock for file path and updates expire.
|
||||
If no lock can be found for path expire is set to 0.
|
||||
If it can't refresh the lock it will do nothing.
|
||||
path : Absolute path of the file on the server.
|
||||
expire : The time when the lock expires, will be updated. */
|
||||
void dav_lock_refresh(const char *path, time_t *expire);
|
||||
|
||||
|
||||
/* Creates a new collection on the server.
|
||||
path : Absolute path of the new collection on the server.
|
||||
return value : 0 on success; an appropriate file error code otherwise. */
|
||||
int
|
||||
dav_make_collection(const char *path);
|
||||
|
||||
|
||||
/* Moves resource src to the new name/location dst.
|
||||
src : Absolute path of the resource on the server.
|
||||
dst : New absolute path of the resource on the server.
|
||||
return value : 0 on success; an appropriate file error code otherwise. */
|
||||
int
|
||||
dav_move(const char *src, const char *dst);
|
||||
|
||||
|
||||
/* Stores the contents of file cache_path on the server location path and
|
||||
updates the value of exists, etag and mtime.
|
||||
Before uploading the file it tests whether the file on the server has been
|
||||
changed (compared to the values of exists, etag and mtime). If it has been
|
||||
changed the file will *not* be uploaded and an error returned instead.
|
||||
Sometimes a lock may be discovered during dav_put(). In this case expire
|
||||
will be updated.
|
||||
path : Absolute path of the file on the server.
|
||||
cache_path : Name of the local file to be stored on the server.
|
||||
exists : Indicates whether the file exists on the server. Used to check
|
||||
for changes on the server. If the upload is successful it will
|
||||
be set to 1.
|
||||
etag : The value of ETag used to check for changes on the server.
|
||||
Updated on success. May be NULL.
|
||||
mtime : The Last_Modified value used to check for changes on the
|
||||
server. Updated on success. May be NULL.
|
||||
mime : The value of mime_type. Updated on successMay be NULL.
|
||||
If a mime_type is set, the Content-Type header will be sent.
|
||||
execute : if 1 set execute property, else no change of execute property.
|
||||
return value : 0 on success; an appropriate file error code otherwise. */
|
||||
int
|
||||
dav_put(const char *path, const char *cache_path, int *exists, time_t *expire,
|
||||
char **etag, time_t *mtime, char **mime, int execute);
|
||||
|
||||
/* Makes a PROPFIND request for path to get quota information (RFC 4331)
|
||||
and places them in available and used. If quota information is not
|
||||
available, an error is returned and available and used are not changed. */
|
||||
int
|
||||
dav_quota(const char *path, off_t *available, off_t *used);
|
||||
|
||||
|
||||
/* Sets or resets the execute property of file path.
|
||||
path : Absolute path of the file on the server.
|
||||
set : boolean value; 0 reset execute property; 1 set execute property. */
|
||||
int
|
||||
dav_set_execute(const char *path, int set);
|
||||
|
||||
|
||||
/* Tells webdav that no more terminal is available, so errors can only
|
||||
* be logged. Before this function is invoced webdav tries to
|
||||
* communicate with the user when problems occur. */
|
||||
void
|
||||
dav_set_no_terminal(void);
|
||||
|
||||
|
||||
/* Releases the lock on file path on the serverand sets expire to 0.
|
||||
path : Absolute path of the file on the server.
|
||||
return value : 0 if no error occured; an appropriate file error code
|
||||
otherwise. */
|
||||
int
|
||||
dav_unlock(const char *path, time_t *expire);
|
||||
|
||||
|
||||
#endif /* DAV_WEBDAV_H */
|
Reference in New Issue
Block a user