public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/autodep:master commit in: logger/src/autodep/logfs/, /, logger/src/hook_fusefs/, logger/
@ 2011-06-08 12:25 Александр Берсенев
  0 siblings, 0 replies; only message in thread
From: Александр Берсенев @ 2011-06-08 12:25 UTC (permalink / raw
  To: gentoo-commits

commit:     8ba60e9425177e713e9112192038012c66f4caa5
Author:     Alexander Bersenev <bay <AT> hackerdom <DOT> ru>
AuthorDate: Wed Jun  8 18:24:30 2011 +0000
Commit:     Александр Берсенев <bay <AT> hackerdom <DOT> ru>
CommitDate: Wed Jun  8 18:24:30 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/autodep.git;a=commit;h=8ba60e94

big commit: add one more logger and refactor existing

---
 NOTES                                      |   10 +
 logger/src/autodep/logfs/logger_fusefs.py  |   98 +++
 logger/src/autodep/logfs/logger_hooklib.py |   21 +
 logger/src/hook_fusefs/Makefile            |    7 +
 logger/src/hook_fusefs/hookfs              |  Bin 0 -> 30961 bytes
 logger/src/hook_fusefs/hookfs.c            |  959 ++++++++++++++++++++++++++++
 6 files changed, 1095 insertions(+), 0 deletions(-)

diff --git a/NOTES b/NOTES
new file mode 100644
index 0000000..05d63f0
--- /dev/null
+++ b/NOTES
@@ -0,0 +1,10 @@
+This is few notes mainly for myself.
+
+1. Format of log record:
+ <time of event sec since 1970>
+ <event type: stat, open, read, write>
+ <name of file>
+ <returned value>
+ <errno>
+ <parent processes>(will be pid)
+ <allowed/denied>
\ No newline at end of file

diff --git a/logger/Makefile b/logger/Makefile
new file mode 100644
index 0000000..e69de29

diff --git a/logger/src/autodep/logfs/logger_fusefs.py b/logger/src/autodep/logfs/logger_fusefs.py
new file mode 100644
index 0000000..fbd8100
--- /dev/null
+++ b/logger/src/autodep/logfs/logger_fusefs.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python2
+
+import subprocess
+import time
+import os
+import sys
+
+
+class logger:
+  socketname=''
+  readytolaunch=False
+  mountlist=["/dev/","/proc/","/sys/"]
+#  rootmountpath="/mnt/logfs_root_"+str(time.time())+"/"
+  rootmountpath="/mnt/logfs_roott_"+"/"
+  
+  def __init__(self, socketname):
+	self.socketname=socketname
+	
+	if os.geteuid() != 0:
+	  print "only root user can use FUSE approach for logging"
+	  exit(1)
+	
+	print "mounting root filesystem into %s. Please, DON'T DELETE THIS FOLDER!!" % self.rootmountpath
+	
+	for mount in self.mountlist:
+	  try:
+		os.makedirs(self.rootmountpath+mount)
+	  except OSError,e:
+		if e.errno==17: # 17 is a "file exists" errno
+		  pass			# all is ok
+		else:
+		  print "failed to make mount directory %s: %s" % (self.rootmountpath+mount,e)
+		  print "this error is fatal"
+		  exit(1)
+		  
+	ret=subprocess.call(['mount','-o','bind','/',self.rootmountpath])
+	if ret!=0:
+	  print "failed to bind root filesystem to %s. Check messages above"%self.rootmountpath
+	  exit(1)
+	
+	#env["LOG_SOCKET"]=self.socketname
+	os.environ["LOG_SOCKET"]=self.socketname
+
+
+	ret=subprocess.call(['/home/bay/gsoc/logger/src/hook_fusefs/hookfs',self.rootmountpath,
+						 '-o','allow_other,suid'])
+	if ret!=0:
+	  print "failed to launch FUSE logger. Check messages above"
+	
+	for mount in self.mountlist:
+	  ret=subprocess.call(['mount','-o','bind',mount,self.rootmountpath+mount])
+	  if ret!=0:
+		print "failed to mount bind %s directory to %s. Check messages above" % (
+			   mount,self.rootmountpath)
+		exit(1)
+	self.readytolaunch=True;
+	
+  def __del__(self):
+	#we will delete the object manually after execprog
+	pass
+  
+  def execprog(self,prog_name,arguments):
+	pid=os.fork()
+	if pid==0:
+	  try:
+		cwd=os.getcwd()
+		os.chroot(self.rootmountpath)
+		os.chdir(cwd)
+		
+		env=os.environ.copy()
+
+		os.execvpe(prog_name, arguments, env)
+		sys.exit(1)
+	  except OSError, e:
+		print "Error while chrooting and starting a program: %s" % e
+		sys.exit(1)
+	  
+	else:
+	  exitcode=os.wait()[1];
+	  try:
+		# unmount all manually
+		self.mountlist.reverse()
+		for mount in self.mountlist:
+		  ret=subprocess.call(['umount',self.rootmountpath+mount])
+		  if ret!=0:
+			print "failed to umount bind %s directory. Check messages above" % ( self.rootmountpath+mount)
+		ret=subprocess.call(['fusermount','-u',self.rootmountpath]);
+		if ret!=0:
+		  print "Error while unmounting fuse filesystem. Check messages above"
+		ret=subprocess.call(['umount',self.rootmountpath]);
+		if ret!=0:
+		  print "Error while unmounting %s Check messages above" % (self.rootmountpath)
+
+	  except OSError, e:
+		print "Error while unmounting fuse filesystem: %s" % e
+		sys.exit(1)
+		
+	  sys.exit(int(exitcode/256))

diff --git a/logger/src/autodep/logfs/logger_hooklib.py b/logger/src/autodep/logfs/logger_hooklib.py
new file mode 100644
index 0000000..cf677f4
--- /dev/null
+++ b/logger/src/autodep/logfs/logger_hooklib.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python2
+
+import os
+
+class logger:
+  socketname=''
+  hooklibpath='/home/bay/gsoc/logger/src/hook_lib/file_hook.so' # TODO: change
+  
+  def __init__(self,socketname):
+	self.socketname=socketname
+	
+  def execprog(self,prog_name,arguments):
+	try:
+	  env=os.environ.copy()
+	  env["LD_PRELOAD"]=self.hooklibpath
+	  env["LOG_SOCKET"]=self.socketname
+	  
+	  os.execvpe(prog_name, arguments, env)
+	except OSError, e:
+	  print "Failed to launch the programm: %s" % e
+	  sys.exit(1)

diff --git a/logger/src/hook_fusefs/Makefile b/logger/src/hook_fusefs/Makefile
new file mode 100644
index 0000000..9b79a5c
--- /dev/null
+++ b/logger/src/hook_fusefs/Makefile
@@ -0,0 +1,7 @@
+all: hookfs
+
+hookfs: hookfs.c
+	$(CC) -std=c99 -Wall `pkg-config fuse --cflags --libs` -lulockmgr $(CFLAGS) $(LDFLAGS) hookfs.c -o hookfs
+
+clean:
+	rm -f hookfs

diff --git a/logger/src/hook_fusefs/hookfs b/logger/src/hook_fusefs/hookfs
new file mode 100755
index 0000000..b27efc2
Binary files /dev/null and b/logger/src/hook_fusefs/hookfs differ

diff --git a/logger/src/hook_fusefs/hookfs.c b/logger/src/hook_fusefs/hookfs.c
new file mode 100644
index 0000000..2047320
--- /dev/null
+++ b/logger/src/hook_fusefs/hookfs.c
@@ -0,0 +1,959 @@
+/*
+  FUSE: Filesystem in Userspace
+  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
+  Copyright (C) 2011       Sebastian Pipping <sebastian@pipping.org>
+  Copyright (C) 2011       Alexander Bersenev <bay@hackerdom.ru>
+
+  This program can be distributed under the terms of the GNU GPL.
+*/
+
+#define PACKAGE_NAME "hookfs"
+#define PACKAGE_VERSION "0.1"
+
+#define FUSE_USE_VERSION 26
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+
+#include <fuse.h>
+#include <ulockmgr.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <stddef.h>
+#include <assert.h>
+#include <sys/mman.h>
+#ifdef HAVE_SETXATTR
+#include <sys/xattr.h>
+#endif
+#include <sys/socket.h>
+#include <sys/un.h>
+
+
+#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
+
+#define MAXSOCKETPATHLEN 108
+
+struct hookfs_config {
+     int argv_debug;
+};
+
+
+int mountpoint_fd = -1;
+char *mountpoint = NULL;
+FILE * log_file = NULL;
+int log_socket=-1;
+struct hookfs_config config;
+
+/*
+ * Prints a string escaping spaces and '\'
+ * Does not check input variables
+*/
+void __print_escaped(FILE *fh ,const char *s){
+	for(;(*s)!=0; s++) {
+		if(*s==' ')
+		  fprintf(fh,"\\ ");
+		else if(*s==',')
+		  fprintf(fh,"\\,");
+		else if(*s=='\r')
+		  fprintf(fh,"\\r");
+		else if(*s=='\n')
+		  fprintf(fh,"\\n");
+		else if(*s=='\\')
+		  fprintf(fh,"\\\\");
+		else
+		  fprintf(fh,"%c", *s);
+	}
+}
+
+/*
+ * Format of log string: time event file flags result parents
+*/
+void log_event(const char *event_type, const char *filename, int result, int err, pid_t pid) {
+
+  fprintf(log_file,"%lld ",(unsigned long long)time(NULL));
+
+  __print_escaped(log_file, event_type);
+  fprintf(log_file," ");
+  __print_escaped(log_file, filename);
+  fprintf(log_file," %d %d %d\n", result, err, pid);
+  fflush(log_file);
+}
+
+
+static int post_getattr(const char *path, int res) {
+	struct fuse_context * context = fuse_get_context();
+	log_event("stat",path,res,errno,context->pid);
+	return 0;
+}
+
+static int post_read(const char *path, int res) {
+	struct fuse_context * context = fuse_get_context();
+	log_event("read",path,res,errno,context->pid);
+	return 0;
+}
+
+static int post_write(const char *path, int res) {
+	struct fuse_context * context = fuse_get_context();
+	log_event("write",path,res,errno,context->pid);
+	return 0;
+}
+
+static int post_open(const char *path, int fd) {
+	struct fuse_context * context = fuse_get_context();
+	log_event("open",path,fd,errno,context->pid);
+	return 0;
+}
+
+static int post_truncate(const char *path, int res) {
+	struct fuse_context * context = fuse_get_context();
+	log_event("write",path,res,errno,context->pid);
+	return 0;
+}
+
+struct hook_operations {
+	int (*post_read)(const char *path, int res);
+	int (*post_write)(const char *path, int res);
+	int (*post_open)(const char *path, int fd);
+	//int (*post_rename)(const char *from, const char *to, int res);
+	int (*post_getattr)(const char *path, int res);
+	int (*post_truncate)(const char *path, int res);
+};
+
+static struct hook_operations hooks = {
+	.post_read = post_read,
+	.post_write = post_write,
+	.post_open = post_open,
+	//.post_unlink = post_unlink,
+	//.post_rename = post_rename,
+	.post_getattr = post_getattr,
+	.post_truncate = post_truncate,
+};
+
+#define NOTIFY(function, ...) \
+	if (hooks.function) { \
+		hooks.function(__VA_ARGS__); \
+	}
+
+static char * malloc_relative_path(const char *path) {
+	int len = strlen(path);
+	char * buf = malloc(1 + len + 1);
+	if (! buf) {
+		return NULL;
+	}
+
+	strcpy(buf, ".");
+	strcpy(buf + 1, path);
+	return buf;
+}
+
+static void give_to_creator_fd(int fd) {
+	struct fuse_context * context = fuse_get_context();
+	fchown(fd, context->uid, context->gid);
+}
+
+static void give_to_creator_path(const char *path) {
+	struct fuse_context * context = fuse_get_context();
+	lchown(path, context->uid, context->gid);
+}
+
+static int hookfs_getattr(const char *path, struct stat *stbuf)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = lstat(rel_path, stbuf);
+	free(rel_path);
+
+	NOTIFY(post_getattr, path, res);
+		
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_fgetattr(const char *path, struct stat *stbuf,
+			struct fuse_file_info *fi)
+{
+	int res;
+
+	(void) path;
+
+	res = fstat(fi->fh, stbuf);
+	
+	NOTIFY(post_getattr, path, res);
+
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_access(const char *path, int mask)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = access(rel_path, mask);
+	free(rel_path);
+	
+	NOTIFY(post_getattr, path, res);
+
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_readlink(const char *path, char *buf, size_t size)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = readlink(rel_path, buf, size - 1);
+	free(rel_path);
+
+	if (res == -1)
+		return -errno;
+
+	buf[res] = '\0';
+	return 0;
+}
+
+struct hookfs_dirp {
+	DIR *dp;
+	struct dirent *entry;
+	off_t offset;
+};
+
+static int hookfs_opendir(const char *path, struct fuse_file_info *fi)
+{
+	struct hookfs_dirp *d = malloc(sizeof(struct hookfs_dirp));
+	if (d == NULL)
+		return -ENOMEM;
+
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	d->dp = opendir(rel_path);
+	free(rel_path);
+	if (d->dp == NULL) {
+		free(d);
+		return -errno;
+	}
+	d->offset = 0;
+	d->entry = NULL;
+
+	fi->fh = (unsigned long) d;
+	return 0;
+}
+
+static inline struct hookfs_dirp *get_dirp(struct fuse_file_info *fi)
+{
+	return (struct hookfs_dirp *) (uintptr_t) fi->fh;
+}
+
+static int hookfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+		       off_t offset, struct fuse_file_info *fi)
+{
+	struct hookfs_dirp *d = get_dirp(fi);
+
+	(void) path;
+	if (offset != d->offset) {
+		seekdir(d->dp, offset);
+		d->entry = NULL;
+		d->offset = offset;
+	}
+	while (1) {
+		struct stat st;
+		off_t nextoff;
+
+		if (!d->entry) {
+			d->entry = readdir(d->dp);
+			if (!d->entry)
+				break;
+		}
+
+		memset(&st, 0, sizeof(st));
+		st.st_ino = d->entry->d_ino;
+		st.st_mode = d->entry->d_type << 12;
+		nextoff = telldir(d->dp);
+		if (filler(buf, d->entry->d_name, &st, nextoff))
+			break;
+
+		d->entry = NULL;
+		d->offset = nextoff;
+	}
+
+	return 0;
+}
+
+static int hookfs_releasedir(const char *path, struct fuse_file_info *fi)
+{
+	struct hookfs_dirp *d = get_dirp(fi);
+	(void) path;
+	closedir(d->dp);
+	free(d);
+	return 0;
+}
+
+static int hookfs_mknod(const char *path, mode_t mode, dev_t rdev)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res;
+	if (S_ISFIFO(mode))
+		res = mkfifo(rel_path, mode);
+	else
+		res = mknod(rel_path, mode, rdev);
+	if (res == 0)
+		give_to_creator_path(rel_path);
+	free(rel_path);
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_mkdir(const char *path, mode_t mode)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = mkdir(rel_path, mode);
+	if (res == 0)
+		give_to_creator_path(rel_path);
+	free(rel_path);
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_unlink(const char *path)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = unlink(rel_path);
+	free(rel_path);
+	//NOTIFY(post_unlink, path, res);
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_rmdir(const char *path)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = rmdir(rel_path);
+	free(rel_path);
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_symlink(const char *from, const char *to)
+{
+	char * rel_to = malloc_relative_path(to);
+	if (! rel_to) {
+		return -errno;
+	}
+
+	int res = symlink(from, rel_to);
+	if (res == 0)
+		give_to_creator_path(rel_to);
+	free(rel_to);
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_rename(const char *from, const char *to)
+{
+	char * rel_from = malloc_relative_path(from);
+	if (! rel_from) {
+		return -errno;
+	}
+	char * rel_to = malloc_relative_path(to);
+	if (! rel_to) {
+		free(rel_from);
+		return -errno;
+	}
+
+	int res = rename(rel_from, rel_to);
+	//NOTIFY(post_rename, from, to, res);
+	free(rel_from);
+	free(rel_to);
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_link(const char *from, const char *to)
+{
+	char * rel_from = malloc_relative_path(from);
+	if (! rel_from) {
+		return -errno;
+	}
+	char * rel_to = malloc_relative_path(to);
+	if (! rel_to) {
+		free(rel_from);
+		return -errno;
+	}
+
+	int res = link(rel_from, rel_to);
+	free(rel_from);
+	if (res == 0)
+		give_to_creator_path(rel_to);
+	free(rel_to);
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_chmod(const char *path, mode_t mode)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = chmod(rel_path, mode);
+	free(rel_path);
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_chown(const char *path, uid_t uid, gid_t gid)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = lchown(rel_path, uid, gid);
+	free(rel_path);
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_truncate(const char *path, off_t size)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = truncate(rel_path, size);
+	free(rel_path);
+
+	NOTIFY(post_truncate, path, res);
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_ftruncate(const char *path, off_t size,
+			 struct fuse_file_info *fi)
+{
+	int res;
+
+	(void) path;
+
+	res = ftruncate(fi->fh, size);
+	NOTIFY(post_truncate, path, res);
+
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_utimens(const char *path, const struct timespec ts[2])
+{
+	int res;
+	struct timeval tv[2];
+	char * rel_path = NULL;
+
+	tv[0].tv_sec = ts[0].tv_sec;
+	tv[0].tv_usec = ts[0].tv_nsec / 1000;
+	tv[1].tv_sec = ts[1].tv_sec;
+	tv[1].tv_usec = ts[1].tv_nsec / 1000;
+
+	rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	res = utimes(rel_path, tv);
+	free(rel_path);
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int writing_flags(mode_t mode) {
+	if (((mode & O_WRONLY) == O_WRONLY)
+			|| ((mode & O_RDWR) == O_RDWR)
+			|| ((mode & O_CREAT) == O_CREAT)) {
+		return 1;
+	}
+	return 0;
+}
+
+static int open_safely(const char *rel_path, int flags, mode_t mode) {
+	int fd = -1;
+	if (writing_flags(flags)) {
+		fd = open(rel_path, flags | O_CREAT | O_EXCL, mode);
+		if (fd == -1) {
+			/* Try again with original flags */
+			fd = open(rel_path, flags, mode);
+		} else {
+			give_to_creator_fd(fd);
+		}
+	} else {
+		fd = open(rel_path, flags, mode);
+	}
+	return fd;
+}
+
+static int hookfs_create(const char *path, mode_t mode, struct fuse_file_info *fi)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int fd = open_safely(rel_path, fi->flags, mode);
+	free(rel_path);
+	NOTIFY(post_open, path, fd);
+	if (fd == -1)
+		return -errno;
+
+	fi->fh = fd;
+	return 0;
+}
+
+static int hookfs_open(const char *path, struct fuse_file_info *fi)
+{
+	int fd;
+	char * rel_path = NULL;
+
+	rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	fd = open_safely(rel_path, fi->flags, 0000);
+	free(rel_path);
+	NOTIFY(post_open, path, fd);
+
+	if (fd == -1)
+		return -errno;
+
+	fi->fh = fd;
+	return 0;
+}
+
+static int hookfs_read(const char *path, char *buf, size_t size, off_t offset,
+		    struct fuse_file_info *fi)
+{
+	int res;
+
+	(void) path;
+	res = pread(fi->fh, buf, size, offset);
+	if (res == -1)
+		res = -errno;
+
+	NOTIFY(post_read, path, res);
+	return res;
+}
+
+static int hookfs_write(const char *path, const char *buf, size_t size,
+		     off_t offset, struct fuse_file_info *fi)
+{
+	int res;
+
+	(void) path;
+	res = pwrite(fi->fh, buf, size, offset);
+	if (res == -1)
+		res = -errno;
+
+	NOTIFY(post_write, path, res);
+
+	return res;
+}
+
+static int hookfs_statfs(const char *path, struct statvfs *stbuf)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = statvfs(rel_path, stbuf);
+	free(rel_path);
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_flush(const char *path, struct fuse_file_info *fi)
+{
+	int res;
+
+	(void) path;
+	/* This is called from every close on an open file, so call the
+	   close on the underlying filesystem.	But since flush may be
+	   called multiple times for an open file, this must not really
+	   close the file.  This is important if used on a network
+	   filesystem like NFS which flush the data/metadata on close() */
+	res = close(dup(fi->fh));
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+static int hookfs_release(const char *path, struct fuse_file_info *fi)
+{
+	(void) path;
+
+	//int res = 
+	close(fi->fh);
+
+	return 0;
+}
+
+static int hookfs_fsync(const char *path, int isdatasync,
+		     struct fuse_file_info *fi)
+{
+	int res;
+	(void) path;
+
+#ifndef HAVE_FDATASYNC
+	(void) isdatasync;
+#else
+	if (isdatasync)
+		res = fdatasync(fi->fh);
+	else
+#endif
+		res = fsync(fi->fh);
+	if (res == -1)
+		return -errno;
+
+	return 0;
+}
+
+#ifdef HAVE_SETXATTR
+/* xattr operations are optional and can safely be left unimplemented */
+static int hookfs_setxattr(const char *path, const char *name, const char *value,
+			size_t size, int flags)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = lsetxattr(rel_path, name, value, size, flags);
+	free(rel_path);
+	if (res == -1)
+		return -errno;
+	return 0;
+}
+
+static int hookfs_getxattr(const char *path, const char *name, char *value,
+			size_t size)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = lgetxattr(rel_path, name, value, size);
+	free(rel_path);
+	if (res == -1)
+		return -errno;
+	return res;
+}
+
+static int hookfs_listxattr(const char *path, char *list, size_t size)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = llistxattr(rel_path, list, size);
+	free(rel_path);
+	if (res == -1)
+		return -errno;
+	return res;
+}
+
+static int hookfs_removexattr(const char *path, const char *name)
+{
+	char * rel_path = malloc_relative_path(path);
+	if (! rel_path) {
+		return -errno;
+	}
+
+	int res = lremovexattr(rel_path, name);
+	free(rel_path);
+	if (res == -1)
+		return -errno;
+	return 0;
+}
+#endif /* HAVE_SETXATTR */
+
+static int hookfs_lock(const char *path, struct fuse_file_info *fi, int cmd,
+		    struct flock *lock)
+{
+	(void) path;
+
+	return ulockmgr_op(fi->fh, cmd, lock, &fi->lock_owner,
+			   sizeof(fi->lock_owner));
+}
+
+static void * hookfs_init(struct fuse_conn_info *conn) {
+	int res = fchdir(mountpoint_fd);
+	assert(! res);
+
+	close(mountpoint_fd);
+	mountpoint_fd = -1;
+
+	return NULL;
+}
+
+static void hookfs_destroy() {
+	fflush(log_file);
+}
+
+static struct fuse_operations hookfs_oper = {
+	.getattr	= hookfs_getattr,
+	.fgetattr	= hookfs_fgetattr,
+	.access		= hookfs_access,
+	.readlink	= hookfs_readlink,
+	.opendir	= hookfs_opendir,
+	.readdir	= hookfs_readdir,
+	.releasedir	= hookfs_releasedir,
+	.mknod		= hookfs_mknod,
+	.mkdir		= hookfs_mkdir,
+	.symlink	= hookfs_symlink,
+	.unlink		= hookfs_unlink,
+	.rmdir		= hookfs_rmdir,
+	.rename		= hookfs_rename,
+	.link		= hookfs_link,
+	.chmod		= hookfs_chmod,
+	.chown		= hookfs_chown,
+	.truncate	= hookfs_truncate,
+	.ftruncate	= hookfs_ftruncate,
+	.utimens	= hookfs_utimens,
+	.create		= hookfs_create,
+	.open		= hookfs_open,
+	.read		= hookfs_read,
+	.write		= hookfs_write,
+	.statfs		= hookfs_statfs,
+	.flush		= hookfs_flush,
+	.release	= hookfs_release,
+	.fsync		= hookfs_fsync,
+#ifdef HAVE_SETXATTR
+	.setxattr	= hookfs_setxattr,
+	.getxattr	= hookfs_getxattr,
+	.listxattr	= hookfs_listxattr,
+	.removexattr	= hookfs_removexattr,
+#endif
+	.lock		= hookfs_lock,
+	.init		= hookfs_init,
+	.destroy	= hookfs_destroy,
+
+	.flag_nullpath_ok = 1,
+};
+
+static int try_chdir_to_mountpoint(int argc, char *argv[]) {
+	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+	int err = -1;
+
+	err = fuse_parse_cmdline(&args, &mountpoint, NULL, NULL);
+	fuse_opt_free_args(&args);
+	if (err || ! mountpoint) {
+		fprintf(stderr, "Mountpoint missing\n");
+		return 0;
+	}
+
+	mountpoint_fd = open(mountpoint, O_DIRECTORY|O_RDONLY);
+	if (err || (mountpoint_fd == -1)) {
+		fprintf(stderr, "Could not open \"%s\" as a directory.\n", mountpoint);
+		return 0;
+	}
+
+	fprintf(stderr, "Switching workdir to mountpoint \"%s\"...\n", mountpoint);
+	return 1;
+}
+
+void default_config(struct hookfs_config * config) {
+	config->argv_debug = 0;
+}
+
+enum {
+	 KEY_HELP,
+	 KEY_VERSION,
+};
+
+#define HOOKFS_OPT(t, p, v) { t, offsetof(struct hookfs_config, p), v }
+
+static struct fuse_opt hookfs_opts[] = {
+	HOOKFS_OPT("--argv-debug", argv_debug, 1),
+
+	FUSE_OPT_KEY("-V", KEY_VERSION),
+	FUSE_OPT_KEY("--version", KEY_VERSION),
+	FUSE_OPT_KEY("-h", KEY_HELP),
+	FUSE_OPT_KEY("--help", KEY_HELP),
+	FUSE_OPT_END
+};
+
+void debug_argv(int argc, char *argv[], const struct hookfs_config * config) {
+	if (! config->argv_debug) {
+		return;
+	}
+
+	for (int i = 0; i < argc; i++) {
+		fprintf(stderr, "[%d] '%s'\n", i, argv[i]);
+	}
+}
+
+static int hookfs_handle_opt(void *data, const char *arg, int key, struct fuse_args *outargs) {
+	struct hookfs_config * config = (struct hookfs_config *)data;
+
+	switch (key) {
+	case KEY_HELP:
+			fuse_opt_add_arg(outargs, "-ho");
+			debug_argv(outargs->argc, outargs->argv, config);
+
+			fprintf(stderr,
+					 "usage: %s mountpoint [options]\n"
+					 "\n"
+					 "%s options:\n"
+					 "    --argv-debug           enable argv debugging\n"
+					 "    --flush                flush log after each write\n"
+					 "\n"
+					 "general options:\n"
+					 "    -o opt,[opt...]        mount options\n"
+					 "    -h   --help            print help\n"
+					 "    -V   --version         print version\n"
+					 "\n"
+					 , outargs->argv[0], PACKAGE_NAME);
+			fuse_main(outargs->argc, outargs->argv, &hookfs_oper, NULL);
+			exit(1);
+
+	case KEY_VERSION:
+			fuse_opt_add_arg(outargs, "--version");
+			debug_argv(outargs->argc, outargs->argv, config);
+
+			fprintf(stderr, "%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+			fuse_main(outargs->argc, outargs->argv, &hookfs_oper, NULL);
+			exit(0);
+	}
+	return 1;
+}
+
+int main(int argc, char *argv[]) {
+  struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+
+  default_config(&config);
+
+  fuse_opt_parse(&args, &config, hookfs_opts, hookfs_handle_opt);
+
+  fuse_opt_add_arg(&args, "-o" "nonempty");  /* to allow shadowing */
+  fuse_opt_add_arg(&args, "-o" "use_ino");  /* to keep hardlinks working */
+  fuse_opt_add_arg(&args, "-o" "default_permissions");  /* to enable access checks */
+
+  debug_argv(args.argc, args.argv, &config);
+
+  char *log_socket_name=getenv("LOG_SOCKET");
+  if(log_socket_name==NULL) {
+	  fprintf(stderr,"Using stderr as output for logs "
+			  "because the LOG_SOCKET environment variable isn't defined.\n");
+	  log_file=stderr;
+  } else {
+	if(strlen(log_socket_name)>=MAXSOCKETPATHLEN) {
+	  fprintf(stderr,"Unable to create a unix-socket %s: socket name is too long,exiting\n", log_socket_name);
+	  return 1;
+	}
+
+	log_socket=socket(AF_UNIX, SOCK_STREAM, 0);
+	if(log_socket==-1) {
+	  fprintf(stderr,"Unable to create a unix-socket %s: %s\n", log_socket_name, strerror(errno));
+	  return 1;
+	}
+	
+	struct sockaddr_un serveraddr;
+	memset(&serveraddr, 0, sizeof(serveraddr));
+	serveraddr.sun_family = AF_UNIX;
+	strcpy(serveraddr.sun_path, log_socket_name);
+	
+	int ret=connect(log_socket, (struct sockaddr *)&serveraddr, SUN_LEN(&serveraddr));
+	if(ret==-1) {
+	  fprintf(stderr,"Unable to connect a unix-socket: %s\n", strerror(errno));
+	  return 1;
+	}
+	
+	log_file=fdopen(log_socket,"r+");
+	
+	if(log_file==NULL) {
+	  fprintf(stderr,"Unable to open a socket for a steam writing: %s\n", strerror(errno));
+	  exit(1);
+	}
+  }
+  
+  if (! try_chdir_to_mountpoint(args.argc, args.argv)) {
+	  return 1;
+  }
+
+  umask(0);
+  int res = fuse_main(args.argc, args.argv, &hookfs_oper, NULL);
+  fflush(log_file);
+  fclose(log_file);
+  return res;
+}



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2011-06-08 12:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-08 12:25 [gentoo-commits] proj/autodep:master commit in: logger/src/autodep/logfs/, /, logger/src/hook_fusefs/, logger/ Александр Берсенев

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox