Network Block Device  @PACKAGE_VERSION@
treefiles.c
Go to the documentation of this file.
1 #include "lfs.h"
2 #include <fcntl.h>
3 #include <inttypes.h>
4 #include <stdio.h>
5 #include <unistd.h>
6 #include <sys/stat.h>
7 #include <sys/types.h>
8 
9 #include <glib.h>
10 
11 #include <backend.h>
12 #include <config.h>
13 #include <cliserv.h>
14 #include <treefiles.h>
15 #include <nbd-debug.h>
16 #include <nbdsrv.h>
17 /**
18  * Tree structure helper functions
19  */
20 void construct_path(char* name,int lenmax,off_t size, off_t pos, off_t * ppos) {
21  if (lenmax<10)
22  err("Char buffer overflow. This is likely a bug.");
23 
24  if (size<TREEDIRSIZE*TREEPAGESIZE) {
25  // we are done, add filename
26  snprintf(name,lenmax,"/FILE%04" PRIX64,(pos/TREEPAGESIZE) % TREEDIRSIZE);
27  *ppos = pos / (TREEPAGESIZE*TREEDIRSIZE);
28  } else {
29  construct_path(name+9,lenmax-9,size/TREEDIRSIZE,pos,ppos);
30  char buffer[10];
31  snprintf(buffer,sizeof(buffer),"/TREE%04jX",(intmax_t)(*ppos % TREEDIRSIZE));
32  memcpy(name,buffer,9); // copy into string without trailing zero
33  *ppos/=TREEDIRSIZE;
34  }
35 }
36 
37 void delete_treefile(char* name,off_t size,off_t pos) {
38  char filename[256+strlen(name)];
39  strcpy(filename,name);
40  off_t ppos;
41  construct_path(filename+strlen(name),256,size,pos,&ppos);
42 
43  DEBUG("Deleting treefile: %s",filename);
44 
45  if (unlink(filename)==-1)
46  DEBUG("Deleting failed : %s",strerror(errno));
47 }
48 
49 void mkdir_path(char * path) {
50  char *subpath=path+1;
51  while ((subpath=strchr(subpath,'/'))) {
52  *subpath='\0'; // path is modified in place with terminating null char instead of slash
53  if (mkdir(path,0700)==-1) {
54  if (errno!=EEXIST)
55  err("Path access error! %m");
56  }
57  *subpath='/';
58  subpath++;
59  }
60 }
61 
62 int open_treefile(char* name,mode_t mode,off_t size,off_t pos, pthread_mutex_t *mutex) {
63  char filename[256+strlen(name)];
64  strcpy(filename,name);
65  off_t ppos;
66  construct_path(filename+strlen(name),256,size,pos,&ppos);
67 
68  DEBUG("Accessing treefile %s ( offset %llu of %llu)",filename,(unsigned long long)pos,(unsigned long long)size);
69 
70  pthread_mutex_lock(mutex);
71  int handle=open(filename, mode, 0600);
72  if (handle<0 && errno==ENOENT) {
73  if (mode & O_RDWR) {
74 
75  DEBUG("Creating new treepath");
76 
77  mkdir_path(filename);
78  handle=open(filename, O_RDWR|O_CREAT, 0600);
79  if (handle<0) {
80  err("Error opening tree block file %m");
81  }
82  } else {
83 
84  DEBUG("Creating a dummy tempfile for reading");
85  gchar * tmpname;
86  tmpname = g_strdup_printf("dummy-XXXXXX");
87  handle = mkstemp(tmpname);
88  if (handle>0) {
89  unlink(tmpname); /* File will stick around whilst FD open */
90  } else {
91  err("Error opening tree block file %m");
92  }
93  g_free(tmpname);
94  }
95  char *n = "\0";
96  myseek(handle,TREEPAGESIZE-1);
97  ssize_t c = write(handle,n,1);
98  if (c<1) {
99  err("Error setting tree block file size %m");
100  }
101  }
102  pthread_mutex_unlock(mutex);
103  return handle;
104 }
105 
void delete_treefile(char *name, off_t size, off_t pos)
Definition: treefiles.c:37
void mkdir_path(char *path)
Definition: treefiles.c:49
void err(const char *s)
Definition: cliserv.c:59
#define TREEPAGESIZE
tree (block) files uses those chunks
Definition: treefiles.h:5
void construct_path(char *name, int lenmax, off_t size, off_t pos, off_t *ppos)
Tree structure helper functions.
Definition: treefiles.c:20
void myseek(int handle, off_t a)
seek to a position in a file, with error handling.
Definition: nbdsrv.c:289
#define DEBUG(...)
Definition: nbd-debug.h:8
char handle[8]
Definition: nbd.h:39
#define TREEDIRSIZE
number of files per subdirectory (or subdirs per subdirectory)
Definition: treefiles.h:4
int open_treefile(char *name, mode_t mode, off_t size, off_t pos, pthread_mutex_t *mutex)
Definition: treefiles.c:62