]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libhandle/handle.c
Fix minor xfs_quota double-reporting issue found by QA testing project quota; bump...
[thirdparty/xfsprogs-dev.git] / libhandle / handle.c
CommitLineData
e9688c1d 1/*
93d9f139 2 * Copyright (c) 1995, 2001-2003 Silicon Graphics, Inc. All Rights Reserved.
7c49c48b 3 *
e9688c1d 4 * This program is free software; you can redistribute it and/or modify it
7c49c48b
DR
5 * under the terms of version 2.1 of the GNU Lesser General Public License
6 * as published by the Free Software Foundation.
7 *
e9688c1d
NS
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7c49c48b 11 *
e9688c1d
NS
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
7c49c48b
DR
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this program; if not, write the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
22 * USA.
23 *
e9688c1d
NS
24 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
25 * Mountain View, CA 94043, or:
7c49c48b
DR
26 *
27 * http://www.sgi.com
28 *
29 * For further information regarding this notice, see:
30 *
e9688c1d
NS
31 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
32 */
33
1d7e80ee 34#include <xfs/libxfs.h>
14290264
NS
35
36/* attributes.h (purposefully) unavailable to xfsprogs, make do */
37struct attrlist_cursor { __u32 opaque[4]; };
38
1d7e80ee 39#include <xfs/handle.h>
e9688c1d 40
e9688c1d
NS
41/* just pick a value we know is more than big enough */
42#define MAXHANSIZ 64
43
44/*
45 * The actual content of a handle is supposed to be opaque here.
46 * But, to do handle_to_fshandle, we need to know what it is. Sigh.
47 * However we can get by with knowing only that the first 8 bytes of
48 * a file handle are the file system ID, and that a file system handle
49 * consists of only those 8 bytes.
50 */
51
52#define FSIDSIZE 8
53
54typedef union {
55 int fd;
56 char *path;
57} comarg_t;
58
3fbbdc85
NS
59static int obj_to_handle(char *, int, unsigned int, comarg_t, void**, size_t*);
60static int handle_to_fsfd(void *, char **);
93d9f139 61
89184fbc
AG
62
63/*
64 * Filesystem Handle -> Open File Descriptor Cache
65 *
66 * Maps filesystem handles to a corresponding open file descriptor for that
93d9f139 67 * filesystem. We need this because we're doing handle operations via xfsctl
89184fbc
AG
68 * and we need to remember the open file descriptor for each filesystem.
69 */
e9688c1d
NS
70
71struct fdhash {
72 int fsfd;
73 char fsh[FSIDSIZE];
74 struct fdhash *fnxt;
93d9f139 75 char fspath[MAXPATHLEN];
e9688c1d
NS
76};
77
dc987226 78static struct fdhash *fdhash_head = NULL;
e9688c1d
NS
79
80int
3fbbdc85 81path_to_fshandle(
e9688c1d 82 char *path, /* input, path to convert */
a3cbe7cd
MK
83 void **fshanp, /* output, pointer to data */
84 size_t *fshlen) /* output, size of returned data */
e9688c1d
NS
85{
86 int result;
87 int fd;
88 comarg_t obj;
89 struct fdhash *fdhp;
dc987226 90 char *tmppath;
e9688c1d
NS
91
92 fd = open(path, O_RDONLY);
3fbbdc85
NS
93 if (fd < 0)
94 return -1;
e9688c1d
NS
95
96 obj.path = path;
93d9f139 97 result = obj_to_handle(path, fd, XFS_IOC_PATH_TO_FSHANDLE,
a3cbe7cd 98 obj, fshanp, fshlen);
dc987226
BK
99 if (result < 0) {
100 close(fd);
101 return result;
102 }
103
104 if (handle_to_fsfd(*fshanp, &tmppath) >= 0) {
105 /* this filesystem is already in the cache */
106 close(fd);
107 } else {
108 /* new filesystem. add it to the cache */
e9688c1d 109 fdhp = malloc(sizeof(struct fdhash));
e9688c1d
NS
110 if (fdhp == NULL) {
111 errno = ENOMEM;
112 return -1;
113 }
114
115 fdhp->fsfd = fd;
93d9f139 116 strncpy(fdhp->fspath, path, sizeof(fdhp->fspath));
a3cbe7cd
MK
117 memcpy(fdhp->fsh, *fshanp, FSIDSIZE);
118
dc987226
BK
119 fdhp->fnxt = fdhash_head;
120 fdhash_head = fdhp;
e9688c1d
NS
121 }
122
123 return result;
124}
125
e9688c1d 126int
3fbbdc85 127path_to_handle(
e9688c1d
NS
128 char *path, /* input, path to convert */
129 void **hanp, /* output, pointer to data */
130 size_t *hlen) /* output, size of returned data */
131{
132 int fd;
133 int result;
134 comarg_t obj;
135
136 fd = open(path, O_RDONLY);
3fbbdc85
NS
137 if (fd < 0)
138 return -1;
e9688c1d
NS
139
140 obj.path = path;
3fbbdc85
NS
141 result = obj_to_handle(path, fd, XFS_IOC_PATH_TO_HANDLE,
142 obj, hanp, hlen);
e9688c1d 143 close(fd);
e9688c1d
NS
144 return result;
145}
146
e9688c1d 147int
3fbbdc85 148handle_to_fshandle(
e9688c1d
NS
149 void *hanp,
150 size_t hlen,
151 void **fshanp,
152 size_t *fshlen)
153{
dc987226
BK
154 if (hlen < FSIDSIZE) {
155 errno = EINVAL;
156 return -1;
157 }
3fbbdc85 158 *fshanp = malloc(FSIDSIZE);
dc987226
BK
159 if (*fshanp == NULL) {
160 errno = ENOMEM;
161 return -1;
162 }
e9688c1d 163 *fshlen = FSIDSIZE;
e9688c1d 164 memcpy(*fshanp, hanp, FSIDSIZE);
e9688c1d
NS
165 return 0;
166}
167
93d9f139
NS
168static int
169handle_to_fsfd(void *hanp, char **path)
89184fbc
AG
170{
171 struct fdhash *fdhp;
172
173 for (fdhp = fdhash_head; fdhp != NULL; fdhp = fdhp->fnxt) {
93d9f139
NS
174 if (memcmp(fdhp->fsh, hanp, FSIDSIZE) == 0) {
175 *path = fdhp->fspath;
89184fbc 176 return fdhp->fsfd;
93d9f139 177 }
89184fbc 178 }
3fbbdc85 179 errno = EBADF;
89184fbc
AG
180 return -1;
181}
182
93d9f139 183static int
3fbbdc85 184obj_to_handle(
93d9f139 185 char *fspath,
e9688c1d 186 int fsfd,
5b64e00a 187 unsigned int opcode,
e9688c1d
NS
188 comarg_t obj,
189 void **hanp,
190 size_t *hlen)
191{
192 char hbuf [MAXHANSIZ];
193 int ret;
ace4c158 194 __uint32_t handlen;
e9688c1d
NS
195 xfs_fsop_handlereq_t hreq;
196
197 if (opcode == XFS_IOC_FD_TO_HANDLE) {
198 hreq.fd = obj.fd;
199 hreq.path = NULL;
200 } else {
201 hreq.fd = 0;
202 hreq.path = obj.path;
203 }
204
489aaf4d 205 hreq.oflags = O_LARGEFILE;
e9688c1d
NS
206 hreq.ihandle = NULL;
207 hreq.ihandlen = 0;
208 hreq.ohandle = hbuf;
ace4c158 209 hreq.ohandlen = &handlen;
fe37ab57 210
93d9f139 211 ret = xfsctl(fspath, fsfd, opcode, &hreq);
e9688c1d
NS
212 if (ret)
213 return ret;
214
ace4c158 215 *hanp = malloc(handlen);
e9688c1d
NS
216 if (*hanp == NULL) {
217 errno = ENOMEM;
218 return -1;
219 }
220
ace4c158
CH
221 memcpy(*hanp, hbuf, handlen);
222 *hlen = handlen;
e9688c1d
NS
223 return 0;
224}
225
a3cbe7cd
MK
226int
227open_by_fshandle(
228 void *fshanp,
229 size_t fshlen,
230 int rw)
231{
232 int fsfd;
233 char *path;
234 xfs_fsop_handlereq_t hreq;
235
236 if ((fsfd = handle_to_fsfd(fshanp, &path)) < 0)
237 return -1;
238
239 hreq.fd = 0;
240 hreq.path = NULL;
241 hreq.oflags = rw | O_LARGEFILE;
242 hreq.ihandle = fshanp;
243 hreq.ihandlen = fshlen;
244 hreq.ohandle = NULL;
245 hreq.ohandlen = NULL;
246
247 return xfsctl(path, fsfd, XFS_IOC_OPEN_BY_HANDLE, &hreq);
248}
249
e9688c1d 250int
3fbbdc85 251open_by_handle(
e9688c1d
NS
252 void *hanp,
253 size_t hlen,
254 int rw)
255{
a3cbe7cd 256 int fsfd;
93d9f139 257 char *path;
a3cbe7cd
MK
258 void *fshanp;
259 size_t fshlen;
e9688c1d
NS
260 xfs_fsop_handlereq_t hreq;
261
a3cbe7cd
MK
262 if (handle_to_fshandle(hanp, hlen, &fshanp, &fshlen) != 0)
263 return -1;
264
265 if ((fsfd = handle_to_fsfd(fshanp, &path)) < 0)
e9688c1d 266 return -1;
e9688c1d
NS
267
268 hreq.fd = 0;
269 hreq.path = NULL;
489aaf4d 270 hreq.oflags = rw | O_LARGEFILE;
e9688c1d
NS
271 hreq.ihandle = hanp;
272 hreq.ihandlen = hlen;
273 hreq.ohandle = NULL;
274 hreq.ohandlen = NULL;
275
a3cbe7cd 276 return xfsctl(path, fsfd, XFS_IOC_OPEN_BY_HANDLE, &hreq);
e9688c1d
NS
277}
278
279int
3fbbdc85 280readlink_by_handle(
e9688c1d
NS
281 void *hanp,
282 size_t hlen,
283 void *buf,
284 size_t bufsiz)
285{
286 int fd;
93d9f139 287 char *path;
e9688c1d
NS
288 xfs_fsop_handlereq_t hreq;
289
3fbbdc85 290 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
e9688c1d 291 return -1;
e9688c1d
NS
292
293 hreq.fd = 0;
294 hreq.path = NULL;
489aaf4d 295 hreq.oflags = O_LARGEFILE;
e9688c1d
NS
296 hreq.ihandle = hanp;
297 hreq.ihandlen = hlen;
298 hreq.ohandle = buf;
5b64e00a 299 hreq.ohandlen = (__u32 *)&bufsiz;
e9688c1d 300
93d9f139 301 return xfsctl(path, fd, XFS_IOC_READLINK_BY_HANDLE, &hreq);
e9688c1d
NS
302}
303
14290264
NS
304int
305attr_multi_by_handle(
306 void *hanp,
307 size_t hlen,
308 void *buf,
309 int rtrvcnt,
310 int flags)
311{
312 int fd;
93d9f139 313 char *path;
14290264
NS
314 xfs_fsop_attrmulti_handlereq_t amhreq;
315
3fbbdc85 316 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
14290264 317 return -1;
14290264
NS
318
319 amhreq.hreq.fd = 0;
320 amhreq.hreq.path = NULL;
489aaf4d 321 amhreq.hreq.oflags = O_LARGEFILE;
14290264
NS
322 amhreq.hreq.ihandle = hanp;
323 amhreq.hreq.ihandlen = hlen;
324 amhreq.hreq.ohandle = NULL;
325 amhreq.hreq.ohandlen = NULL;
326
327 amhreq.opcount = rtrvcnt;
328 amhreq.ops = buf;
329
93d9f139 330 return xfsctl(path, fd, XFS_IOC_ATTRMULTI_BY_HANDLE, &amhreq);
14290264
NS
331}
332
333int
334attr_list_by_handle(
335 void *hanp,
336 size_t hlen,
337 void *buf,
338 size_t bufsize,
339 int flags,
340 struct attrlist_cursor *cursor)
341{
342 int fd;
93d9f139 343 char *path;
14290264
NS
344 xfs_fsop_attrlist_handlereq_t alhreq;
345
3fbbdc85 346 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
14290264 347 return -1;
14290264
NS
348
349 alhreq.hreq.fd = 0;
350 alhreq.hreq.path = NULL;
489aaf4d 351 alhreq.hreq.oflags = O_LARGEFILE;
14290264
NS
352 alhreq.hreq.ihandle = hanp;
353 alhreq.hreq.ihandlen = hlen;
354 alhreq.hreq.ohandle = NULL;
355 alhreq.hreq.ohandlen = NULL;
356
357 memcpy(&alhreq.pos, cursor, sizeof(alhreq.pos));
358 alhreq.flags = flags;
359 alhreq.buflen = bufsize;
360 alhreq.buffer = buf;
361
93d9f139 362 return xfsctl(path, fd, XFS_IOC_ATTRLIST_BY_HANDLE, &alhreq);
14290264
NS
363}
364
e1864286 365int
3fbbdc85 366fssetdm_by_handle(
e1864286
DR
367 void *hanp,
368 size_t hlen,
369 struct fsdmidata *fsdmidata)
370{
371 int fd;
93d9f139 372 char *path;
e1864286
DR
373 xfs_fsop_setdm_handlereq_t dmhreq;
374
3fbbdc85 375 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
e1864286 376 return -1;
e1864286
DR
377
378 dmhreq.hreq.fd = 0;
379 dmhreq.hreq.path = NULL;
489aaf4d 380 dmhreq.hreq.oflags = O_LARGEFILE;
e1864286
DR
381 dmhreq.hreq.ihandle = hanp;
382 dmhreq.hreq.ihandlen = hlen;
383 dmhreq.hreq.ohandle = NULL;
384 dmhreq.hreq.ohandlen = NULL;
385
386 dmhreq.data = fsdmidata;
387
93d9f139 388 return xfsctl(path, fd, XFS_IOC_FSSETDM_BY_HANDLE, &dmhreq);
e1864286
DR
389}
390
e9688c1d 391void
3fbbdc85 392free_handle(
e9688c1d
NS
393 void *hanp,
394 size_t hlen)
395{
3fbbdc85 396 free(hanp);
e9688c1d 397}