|
Network Block Device @PACKAGE_VERSION@
|
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
1.7.3