nbd-client: Add support for setting /sys/block/nbdN/backend
[nbd/ericb.git] / treefiles.c
bloba55522260b9ec9ce426e32082249bebfe6b708ad
1 #include <fcntl.h>
2 #include <limits.h> // for PATH_MAX
3 #include <inttypes.h>
4 #include <stdio.h>
5 #include <unistd.h>
6 #include <sys/stat.h>
7 #include <sys/types.h>
9 #include "config.h"
10 #include "cliserv.h"
11 #include "treefiles.h"
12 #include "nbd-debug.h"
14 /**
15 * Tree structure helper functions
17 void construct_path(char* name, int lenmax, off_t size, off_t pos, off_t* ppos) {
18 if (lenmax<10)
19 err("Char buffer overflow. This is likely a bug.");
21 if (size<TREEDIRSIZE*TREEPAGESIZE) {
22 // we are done, add filename
23 snprintf(name,lenmax,"/FILE%04" PRIX64,(pos/TREEPAGESIZE) % TREEDIRSIZE);
24 *ppos = pos / (TREEPAGESIZE*TREEDIRSIZE);
25 } else {
26 construct_path(name+9,lenmax-9,size/TREEDIRSIZE,pos,ppos);
27 char buffer[10];
28 snprintf(buffer,sizeof(buffer),"/TREE%04jX",(intmax_t)(*ppos % TREEDIRSIZE));
29 memcpy(name,buffer,9); // copy into string without trailing zero
30 *ppos/=TREEDIRSIZE;
34 void delete_treefile(char* name, off_t size, off_t pos) {
35 char filename[PATH_MAX];
36 off_t ppos;
38 strncpy(filename,name,PATH_MAX-1);
39 filename[PATH_MAX-1] = '\0';
40 construct_path(filename+strlen(name),PATH_MAX-strlen(name)-1,size,pos,&ppos);
42 DEBUG("Deleting treefile: %s",filename);
44 if (unlink(filename)==-1)
45 DEBUG("Deleting failed : %s",strerror(errno));
48 void mkdir_path(char* path) {
49 char *subpath=path+1;
50 while ((subpath=strchr(subpath,'/'))) {
51 *subpath='\0'; // path is modified in place with terminating null char instead of slash
52 if (mkdir(path,0700)==-1) {
53 if (errno!=EEXIST)
54 err("Path access error! %m");
56 *subpath='/';
57 subpath++;
61 int open_treefile(char* name, mode_t mode, off_t size, off_t pos, pthread_mutex_t* mutex) {
62 char filename[PATH_MAX];
63 off_t ppos;
65 strncpy(filename,name,PATH_MAX-1);
66 filename[PATH_MAX - 1] = '\0';
67 construct_path(filename+strlen(name),PATH_MAX-strlen(name)-1,size,pos,&ppos);
69 DEBUG("Accessing treefile %s (offset %llu of %llu)",filename,(unsigned long long)pos,(unsigned long long)size);
71 pthread_mutex_lock(mutex);
72 int handle=open(filename, mode, 0600);
73 if (handle<0 && errno==ENOENT) {
74 if (mode & O_RDWR) {
76 DEBUG("Creating new treepath");
78 mkdir_path(filename);
79 handle=open(filename, O_RDWR|O_CREAT, 0600);
80 if (handle<0) {
81 err("Error opening tree block file %m");
83 } else {
85 DEBUG("Creating a dummy tempfile for reading");
86 char tmpname[] = "dummy-XXXXXX";
87 mode_t oldmode = umask(077);
88 handle = mkstemp(tmpname);
89 umask(oldmode);
90 if (handle>0) {
91 unlink(tmpname); /* File will stick around whilst FD open */
92 } else {
93 err("Error opening tree block file %m");
96 char* n = "\0";
97 if(lseek(handle,TREEPAGESIZE-1, SEEK_SET) < 0) {
98 err("Could not create tree file!\n");
100 ssize_t c = write(handle,n,1);
101 if (c<1) {
102 err("Error setting tree block file size %m");
105 pthread_mutex_unlock(mutex);
106 return handle;