Network Block Device @PACKAGE_VERSION@

treefiles.c

Go to the documentation of this file.
00001 #include "lfs.h"
00002 #include <fcntl.h>
00003 #include <inttypes.h>
00004 #include <stdio.h>
00005 #include <unistd.h>
00006 #include <sys/stat.h>
00007 #include <sys/types.h>
00008 
00009 #include <glib.h>
00010 
00011 #include <backend.h>
00012 #include <config.h>
00013 #include <cliserv.h>
00014 #include <treefiles.h>
00015 #include <nbd-debug.h>
00016 #include <nbdsrv.h>
00017 /**
00018  * Tree structure helper functions
00019  */
00020 void construct_path(char* name,int lenmax,off_t size, off_t pos, off_t * ppos) {
00021         if (lenmax<10)
00022                 err("Char buffer overflow. This is likely a bug.");
00023 
00024         if (size<TREEDIRSIZE*TREEPAGESIZE) {
00025                 // we are done, add filename
00026                 snprintf(name,lenmax,"/FILE%04" PRIX64,(pos/TREEPAGESIZE) % TREEDIRSIZE);
00027                 *ppos = pos / (TREEPAGESIZE*TREEDIRSIZE);
00028         } else {
00029                 construct_path(name+9,lenmax-9,size/TREEDIRSIZE,pos,ppos);
00030                 char buffer[10];
00031                 snprintf(buffer,sizeof(buffer),"/TREE%04jX",(intmax_t)(*ppos % TREEDIRSIZE));
00032                 memcpy(name,buffer,9); // copy into string without trailing zero
00033                 *ppos/=TREEDIRSIZE;
00034         }
00035 }
00036 
00037 void delete_treefile(char* name,off_t size,off_t pos) {
00038         char filename[256+strlen(name)];
00039         strcpy(filename,name);
00040         off_t ppos;
00041         construct_path(filename+strlen(name),256,size,pos,&ppos);
00042 
00043         DEBUG("Deleting treefile: %s",filename);
00044 
00045         if (unlink(filename)==-1)
00046                 DEBUG("Deleting failed : %s",strerror(errno));
00047 }
00048 
00049 void mkdir_path(char * path) {
00050         char *subpath=path+1;
00051         while ((subpath=strchr(subpath,'/'))) {
00052                 *subpath='\0'; // path is modified in place with terminating null char instead of slash
00053                 if (mkdir(path,0700)==-1) {
00054                         if (errno!=EEXIST)
00055                                 err("Path access error! %m");
00056                 }
00057                 *subpath='/';
00058                 subpath++;
00059         }
00060 }
00061 
00062 int open_treefile(char* name,mode_t mode,off_t size,off_t pos, pthread_mutex_t *mutex) {
00063         char filename[256+strlen(name)];
00064         strcpy(filename,name);
00065         off_t ppos;
00066         construct_path(filename+strlen(name),256,size,pos,&ppos);
00067 
00068         DEBUG("Accessing treefile %s ( offset %llu of %llu)",filename,(unsigned long long)pos,(unsigned long long)size);
00069 
00070         pthread_mutex_lock(mutex);
00071         int handle=open(filename, mode, 0600);
00072         if (handle<0 && errno==ENOENT) {
00073                 if (mode & O_RDWR) {
00074 
00075                         DEBUG("Creating new treepath");
00076 
00077                         mkdir_path(filename);
00078                         handle=open(filename, O_RDWR|O_CREAT, 0600);
00079                         if (handle<0) {
00080                                 err("Error opening tree block file %m");
00081                         }
00082                 } else {
00083 
00084                         DEBUG("Creating a dummy tempfile for reading");
00085                         gchar * tmpname;
00086                         tmpname = g_strdup_printf("dummy-XXXXXX");
00087                         handle = mkstemp(tmpname);
00088                         if (handle>0) {
00089                                 unlink(tmpname); /* File will stick around whilst FD open */
00090                         } else {
00091                                 err("Error opening tree block file %m");
00092                         }
00093                         g_free(tmpname);
00094                 }
00095                 char *n = "\0";
00096                 myseek(handle,TREEPAGESIZE-1);
00097                 ssize_t c = write(handle,n,1);
00098                 if (c<1) {
00099                         err("Error setting tree block file size %m");
00100                 }
00101         }
00102         pthread_mutex_unlock(mutex);
00103         return handle;
00104 }
00105