1    	#include "clusterautoconfig.h"
2    	
3    	#include <string.h>
4    	#include <inttypes.h>
5    	#include <sys/types.h>
6    	#include <sys/stat.h>
7    	#include <fcntl.h>
8    	#include <unistd.h>
9    	#include <time.h>
10   	
11   	#include "libgfs2.h"
12   	
13   	#define PAGE_SIZE (4096)
14   	#define DIV_RU(x, y) (((x) + (y) - 1) / (y))
15   	
16   	int lgfs2_compute_heightsize(unsigned bsize, uint64_t *heightsize,
17   		uint32_t *maxheight, uint32_t bsize1, int diptrs, int inptrs)
18   	{
19   		heightsize[0] = bsize - sizeof(struct gfs2_dinode);
20   		heightsize[1] = (uint64_t)bsize1 * diptrs;
21   		for (*maxheight = 2;; (*maxheight)++) {
22   			uint64_t space, d;
23   			uint32_t m;
24   	
25   			space = heightsize[*maxheight - 1] * inptrs;
26   			m = space % inptrs;
27   			d = space / inptrs;
28   	
29   			if (d != heightsize[*maxheight - 1] || m)
30   				break;
31   			heightsize[*maxheight] = space;
32   		}
33   		if (*maxheight > GFS2_MAX_META_HEIGHT) {
34   			errno = EINVAL;
35   			return -1;
36   		}
37   		return 0;
38   	}
39   	
40   	int lgfs2_compute_constants(struct lgfs2_sbd *sdp)
41   	{
42   		sdp->md.next_inum = 1;
43   		sdp->sd_time = time(NULL);
44   	
45   		sdp->sd_bsize_shift = ffs(sdp->sd_bsize) - 1;
46   		sdp->sd_fsb2bb_shift = sdp->sd_bsize_shift -
47   			GFS2_BASIC_BLOCK_SHIFT;
48   		sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift;
49   		sdp->sd_diptrs = (sdp->sd_bsize - sizeof(struct gfs2_dinode)) /
50   			sizeof(uint64_t);
51   		sdp->sd_inptrs = (sdp->sd_bsize - sizeof(struct gfs2_meta_header)) /
52   			sizeof(uint64_t);
53   		sdp->sd_jbsize = sdp->sd_bsize - sizeof(struct gfs2_meta_header);
54   		sdp->sd_hash_bsize = sdp->sd_bsize / 2;
55   		sdp->sd_hash_bsize_shift = sdp->sd_bsize_shift - 1;
56   		sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
57   		sdp->sd_blocks_per_bitmap = (sdp->sd_bsize - sizeof(struct gfs2_meta_header))
58   		                             * GFS2_NBBY;
59   	
60   		if (lgfs2_compute_heightsize(sdp->sd_bsize, sdp->sd_heightsize, &sdp->sd_max_height,
61   					sdp->sd_bsize, sdp->sd_diptrs, sdp->sd_inptrs)) {
62   			return -1;
63   		}
64   		if (lgfs2_compute_heightsize(sdp->sd_bsize, sdp->sd_jheightsize, &sdp->sd_max_jheight,
65   					sdp->sd_jbsize, sdp->sd_diptrs, sdp->sd_inptrs)) {
66   			return -1;
67   		}
68   		return 0;
69   	}
70   	
71   	/* Returns 0 if fd1 and fd2 refer to the same device/file, 1 otherwise, or -1 on error */
72   	static int fdcmp(int fd1, int fd2)
73   	{
74   		struct stat st1, st2;
75   	
76   		if (fd1 < 0 || fd2 < 0)
77   			return -1;
78   		if ((fstat(fd1, &st1) != 0) || (fstat(fd2, &st2) != 0))
79   			return -1;
80   		if (S_ISBLK(st1.st_mode) && S_ISBLK(st2.st_mode)) {
81   			if (st1.st_rdev == st2.st_rdev) {
82   				return 0;
83   			}
84   		} else if ((st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino)) {
85   				return 0;
86   		}
87   		return 1;
88   	}
89   	
90   	int lgfs2_open_mnt(const char *path, int dirflags, int *dirfd, int devflags, int *devfd, struct mntent **mnt)
91   	{
92   		FILE *fp = setmntent("/proc/mounts", "r");
(1) Event cond_false: Condition "fp == NULL", taking false branch.
93   		if (fp == NULL) {
94   			perror("open: /proc/mounts");
95   			return 1;
(2) Event if_end: End of if statement.
96   		}
97   		/* Assume path is mount point until we know better. */
(3) Event open_fn: Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.]
(4) Event assign: Assigning: "*dirfd" = "open(path, dirflags)".
98   		*dirfd = open(path, dirflags);
(5) Event cond_false: Condition "*dirfd < 0", taking false branch.
99   		if (*dirfd < 0)
(6) Event if_end: End of if statement.
100  			return 1;
101  	
(7) Event cond_true: Condition "(*mnt = getmntent(fp)) != NULL", taking true branch.
102  		while ((*mnt = getmntent(fp)) != NULL) {
103  			int fd;
(8) Event cond_false: Condition "strcmp((*mnt)->mnt_type, "gfs2") != 0", taking false branch.
104  			if (strcmp((*mnt)->mnt_type, "gfs2") != 0)
(9) Event if_end: End of if statement.
105  				continue;
106  			*devfd = open((*mnt)->mnt_fsname, devflags);
107  			/* Defer checking *devfd until later: whether it's ok to ignore
108  			 * the error depends on whether we find the mount point. */
109  	
(10) Event cond_true: Condition "strcmp(path, (*mnt)->mnt_dir) == 0", taking true branch.
110  			if (strcmp(path, (*mnt)->mnt_dir) == 0)
(11) Event break: Breaking from loop.
111  				break;
112  			if (strcmp(path, (*mnt)->mnt_fsname) == 0 || fdcmp(*dirfd, *devfd) == 0) {
113  				/* We have a match but our above assumption was
114  				   incorrect and *dirfd is actually the device. */
115  				close(*dirfd);
116  				*dirfd = open((*mnt)->mnt_dir, dirflags);
117  				break;
118  			}
119  	
120  			fd = open((*mnt)->mnt_dir, dirflags);
121  			if (fd >= 0) {
122  				int diff = fdcmp(*dirfd, fd);
123  				close(fd);
124  				if (diff == 0)
125  					break;
126  			}
127  			if (*devfd >= 0)
128  				close(*devfd);
(12) Event loop_end: Reached end of loop.
129  		}
130  		endmntent(fp);
(13) Event cond_false: Condition "*mnt == NULL", taking false branch.
131  		if (*mnt == NULL) {
132  			close(*dirfd);
133  			return 0; /* Success. Answer is no. Both fds closed. */
(14) Event if_end: End of if statement.
134  		}
(15) Event cond_false: Condition "*dirfd < 0", taking false branch.
135  		if (*dirfd < 0) {
136  			close(*devfd);
137  			return 1;
(16) Event if_end: End of if statement.
138  		}
(17) Event cond_false: Condition "*devfd < 0", taking false branch.
139  		if (*devfd < 0) {
140  			close(*dirfd);
141  			return 1;
(18) Event if_end: End of if statement.
142  		}
143  		return 0; /* Success. Answer is yes. Both fds open. */
144  	}
145  	
146  	int lgfs2_open_mnt_dev(const char *path, int flags, struct mntent **mnt)
147  	{
148  		int dirfd = -1;
149  		int devfd = -1;
(1) Event open_arg: "lgfs2_open_mnt" opens handle stored into "dirfd". [details]
(2) Event cond_false: Condition "lgfs2_open_mnt(path, 0, &dirfd, flags, &devfd, mnt) != 0", taking false branch.
Also see events: [leaked_handle]
150  		if (lgfs2_open_mnt(path, O_RDONLY, &dirfd, flags, &devfd, mnt) != 0)
(3) Event if_end: End of if statement.
151  			return -1;
(4) Event cond_false: Condition "*mnt != NULL", taking false branch.
152  		if (*mnt != NULL)
(5) Event if_end: End of if statement.
153  			close(dirfd);
(6) Event leaked_handle: Handle variable "dirfd" going out of scope leaks the handle.
Also see events: [open_arg]
154  		return devfd;
155  	}
156  	
157  	int lgfs2_open_mnt_dir(const char *path, int flags, struct mntent **mnt)
158  	{
159  		int dirfd = -1;
160  		int devfd = -1;
161  		if (lgfs2_open_mnt(path, flags, &dirfd, O_RDONLY, &devfd, mnt) != 0)
162  			return -1;
163  		if (*mnt != NULL)
164  			close(devfd);
165  		return dirfd;
166  	}
167