Don't forget to EXTRA_DIST the .in.sgml file, too
[nbd.git] / treefiles.c
blob71f45da440e82a6d41cb5a96be808216bd5dd74c
1 #include <fcntl.h>
2 #include <inttypes.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <sys/stat.h>
6 #include <sys/types.h>
8 #include <glib.h>
10 #include <backend.h>
11 #include <config.h>
12 #include <cliserv.h>
13 #include <treefiles.h>
14 #include <nbd-debug.h>
15 #include <nbdsrv.h>
16 /**
17 * Tree structure helper functions
19 void construct_path(char* name,int lenmax,off_t size, off_t pos, off_t * ppos) {
20 if (lenmax<10)
21 err("Char buffer overflow. This is likely a bug.");
23 if (size<TREEDIRSIZE*TREEPAGESIZE) {
24 // we are done, add filename
25 snprintf(name,lenmax,"/FILE%04" PRIX64,(pos/TREEPAGESIZE) % TREEDIRSIZE);
26 *ppos = pos / (TREEPAGESIZE*TREEDIRSIZE);
27 } else {
28 construct_path(name+9,lenmax-9,size/TREEDIRSIZE,pos,ppos);
29 char buffer[10];
30 snprintf(buffer,sizeof(buffer),"/TREE%04jX",(intmax_t)(*ppos % TREEDIRSIZE));
31 memcpy(name,buffer,9); // copy into string without trailing zero
32 *ppos/=TREEDIRSIZE;
36 void delete_treefile(char* name,off_t size,off_t pos) {
37 char filename[256+strlen(name)];
38 strcpy(filename,name);
39 off_t ppos;
40 construct_path(filename+strlen(name),256,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) {
62 char filename[256+strlen(name)];
63 strcpy(filename,name);
64 off_t ppos;
65 construct_path(filename+strlen(name),256,size,pos,&ppos);
67 DEBUG("Accessing treefile %s ( offset %llu of %llu)",filename,(unsigned long long)pos,(unsigned long long)size);
69 int handle=open(filename, mode, 0600);
70 if (handle<0 && errno==ENOENT) {
71 if (mode & O_RDWR) {
73 DEBUG("Creating new treepath");
75 mkdir_path(filename);
76 handle=open(filename, O_RDWR|O_CREAT, 0600);
77 if (handle<0) {
78 err("Error opening tree block file %m");
80 } else {
82 DEBUG("Creating a dummy tempfile for reading");
83 gchar * tmpname;
84 tmpname = g_strdup_printf("dummy-XXXXXX");
85 handle = mkstemp(tmpname);
86 if (handle>0) {
87 unlink(tmpname); /* File will stick around whilst FD open */
88 } else {
89 err("Error opening tree block file %m");
91 g_free(tmpname);
93 char *n = "\0";
94 myseek(handle,TREEPAGESIZE-1);
95 ssize_t c = write(handle,n,1);
96 if (c<1) {
97 err("Error setting tree block file size %m");
100 return handle;