Revert "Fix memory leak"
[platform/upstream/nbd.git] / treefiles.c
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[PATH_MAX];
39         off_t ppos;
40
41         strncpy(filename,name,PATH_MAX-1);
42         filename[PATH_MAX-1] = '\0';
43         construct_path(filename+strlen(name),PATH_MAX-strlen(name)-1,size,pos,&ppos);
44
45         DEBUG("Deleting treefile: %s",filename);
46
47         if (unlink(filename)==-1)
48                 DEBUG("Deleting failed : %s",strerror(errno));
49 }
50
51 void mkdir_path(char * path) {
52         char *subpath=path+1;
53         while ((subpath=strchr(subpath,'/'))) {
54                 *subpath='\0'; // path is modified in place with terminating null char instead of slash
55                 if (mkdir(path,0700)==-1) {
56                         if (errno!=EEXIST)
57                                 err("Path access error! %m");
58                 }
59                 *subpath='/';
60                 subpath++;
61         }
62 }
63
64 int open_treefile(char* name,mode_t mode,off_t size,off_t pos, pthread_mutex_t *mutex) {
65         char filename[PATH_MAX];
66         off_t ppos;
67
68         strncpy(filename,name,PATH_MAX-1);
69         filename[PATH_MAX - 1] = '\0';
70         construct_path(filename+strlen(name),PATH_MAX-strlen(name)-1,size,pos,&ppos);
71
72         DEBUG("Accessing treefile %s ( offset %llu of %llu)",filename,(unsigned long long)pos,(unsigned long long)size);
73
74         pthread_mutex_lock(mutex);
75         int handle=open(filename, mode, 0600);
76         if (handle<0 && errno==ENOENT) {
77                 if (mode & O_RDWR) {
78
79                         DEBUG("Creating new treepath");
80
81                         mkdir_path(filename);
82                         handle=open(filename, O_RDWR|O_CREAT, 0600);
83                         if (handle<0) {
84                                 err("Error opening tree block file %m");
85                         }
86                 } else {
87
88                         DEBUG("Creating a dummy tempfile for reading");
89                         gchar * tmpname;
90                         tmpname = g_strdup_printf("dummy-XXXXXX");
91                         mode_t oldmode = umask(77);
92                         handle = mkstemp(tmpname);
93                         umask(oldmode);
94                         if (handle>0) {
95                                 unlink(tmpname); /* File will stick around whilst FD open */
96                         } else {
97                                 err("Error opening tree block file %m");
98                         }
99                         g_free(tmpname);
100                 }
101                 char *n = "\0";
102                 if(lseek(handle,TREEPAGESIZE-1, SEEK_SET) < 0) {
103                         err("Could not create tree file!\n");
104                 }
105                 ssize_t c = write(handle,n,1);
106                 if (c<1) {
107                         err("Error setting tree block file size %m");
108                 }
109         }
110         pthread_mutex_unlock(mutex);
111         return handle;
112 }
113