Merge branch 'vendor/GCC50'
[dragonfly.git] / lib / libhammer / info.c
1 /*
2  * Copyright (c) 2011 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Antonio Huete <tuxillo@quantumachine.net>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #include <dirent.h>
36 #include <err.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <sys/param.h>
43 #include <sys/stat.h>
44 #include <unistd.h>
45
46 #include "libhammer.h"
47
48 static u_int32_t count_snapshots(u_int32_t, char *, char *, int *);
49
50 libhammer_volinfo_t
51 libhammer_get_volinfo(const char *path)
52 {
53         struct hammer_pseudofs_data *pfs_od;
54         struct hammer_ioc_pfs_iterate pi;
55         struct hammer_ioc_info info;
56         libhammer_pfsinfo_t pfstmp;
57         libhammer_volinfo_t hvi;
58         int error = 0;
59         int fd;
60
61         if ((fd = open(path, O_RDONLY)) < 0)
62                 return NULL;
63
64         hvi = _libhammer_malloc(sizeof(*hvi));
65         TAILQ_INIT(&hvi->list_pseudo);
66         if ((ioctl(fd, HAMMERIOC_GET_INFO, &info)) < 0) {
67                 libhammer_free_volinfo(hvi);
68                 close(fd);
69                 return NULL;
70         }
71
72         /* Fill volume information */
73         snprintf(hvi->vol_name, TXTLEN, "%s", info.vol_name);
74         hvi->vol_fsid = info.vol_fsid;
75         hvi->version = info.version;
76         hvi->nvolumes = info.nvolumes;
77         hvi->inodes = info.inodes;
78         hvi->bigblocks = info.bigblocks;
79         hvi->freebigblocks = info.freebigblocks;
80         hvi->rsvbigblocks = info.rsvbigblocks;
81
82         bzero(&pi, sizeof(pi));
83         pi.ondisk = _libhammer_malloc(sizeof(*pfs_od));
84         while(error == 0) {
85                 error = ioctl(fd, HAMMERIOC_PFS_ITERATE, &pi);
86                 if (error == 0 &&
87                     ((pi.head.flags & HAMMER_PFSD_DELETED) == 0)) {
88                         /*
89                          * XXX - In the case the path passed is on PFS#0 but it
90                          * is not the mountpoint itself, it could produce a
91                          * wrong type of PFS.
92                          */
93                         pfstmp = _libhammer_malloc(sizeof(*pfstmp));
94                         pfs_od = pi.ondisk;
95                         pfstmp->ismaster =
96                             (pfs_od->mirror_flags & HAMMER_PFSD_SLAVE) ? 0 : 1;
97
98                         /*
99                          * Fill in structs used in the library. We don't rely on
100                          * HAMMER own struct but we do fill our own.
101                          */
102                         pfstmp->version = hvi->version;
103                         pfstmp->pfs_id = pi.pos;
104                         pfstmp->mirror_flags = pfs_od->mirror_flags;
105                         pfstmp->beg_tid = pfs_od->sync_beg_tid;
106                         pfstmp->end_tid = pfs_od->sync_end_tid;
107                         pfstmp->mountedon =
108                             libhammer_find_pfs_mount(&pfs_od->unique_uuid);
109                         pfstmp->snapcount = count_snapshots(hvi->version,
110                             pfstmp->snapshots, pfstmp->mountedon,
111                             &pfstmp->head.error);
112
113                         TAILQ_INSERT_TAIL(&hvi->list_pseudo, pfstmp, entries);
114                 }
115                 pi.pos++;
116         }
117         free(pi.ondisk);
118
119         close (fd);
120
121         return (hvi);
122 }
123
124 void
125 libhammer_free_volinfo(libhammer_volinfo_t volinfo)
126 {
127         struct libhammer_pfsinfo *pfstmp;
128
129         while(!TAILQ_EMPTY(&volinfo->list_pseudo)) {
130                 pfstmp = TAILQ_FIRST(&volinfo->list_pseudo);
131                 free(pfstmp->mountedon);
132                 TAILQ_REMOVE(&volinfo->list_pseudo, pfstmp, entries);
133                 free(pfstmp);
134         }
135         free(volinfo);
136 }
137
138 static u_int32_t
139 count_snapshots(u_int32_t version, char *pfs_snapshots, char *mountedon,
140     int *errorp)
141 {
142         struct hammer_ioc_snapshot snapinfo;
143         char *snapshots_path, *fpath;
144         struct dirent *den;
145         struct stat st;
146         DIR *dir;
147         u_int32_t snapshot_count;
148         int fd;
149         int spallocated;
150
151         snapshot_count = 0;
152
153         bzero(&snapinfo, sizeof(struct hammer_ioc_snapshot));
154
155         fd = open(mountedon, O_RDONLY);
156         if (fd < 0) {
157                 *errorp = errno;
158                 return 0;
159         }
160
161         if (version < 3) {
162                 /*
163                  * old style: count the number of softlinks in the snapshots dir
164                  */
165                 if (pfs_snapshots[0]) {
166                         snapshots_path = pfs_snapshots;
167                         spallocated = 0;
168                 } else {
169                         asprintf(&snapshots_path, "%s/snapshots", mountedon);
170                         spallocated = 1;
171                 }
172                 if ((dir = opendir(snapshots_path)) != NULL) {
173                         while ((den = readdir(dir)) != NULL) {
174                                 if (den->d_name[0] == '.')
175                                         continue;
176                                 asprintf(&fpath, "%s/%s", snapshots_path,
177                                     den->d_name);
178                                 if (lstat(fpath, &st) == 0 &&
179                                     S_ISLNK(st.st_mode))
180                                         snapshot_count++;
181                                 free(fpath);
182                         }
183                         closedir(dir);
184                 }
185                 if (spallocated)
186                         free(snapshots_path);
187         } else {
188                 /*
189                  * new style: file system meta-data
190                  */
191                 do {
192                         if (ioctl(fd, HAMMERIOC_GET_SNAPSHOT, &snapinfo) < 0) {
193                                 *errorp = errno;
194                                 goto out;
195                         }
196
197                         snapshot_count += snapinfo.count;
198                 } while (snapinfo.head.error == 0 && snapinfo.count);
199         }
200
201 out:
202         if (fd != -1)
203                 close(fd);
204         return snapshot_count;
205 }