]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame_incremental - 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
1/*
2 * Copyright (c) 1995, 2001-2003 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2.1 of the GNU Lesser General Public License
6 * as published by the Free Software Foundation.
7 *
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.
11 *
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.
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 *
24 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
25 * Mountain View, CA 94043, or:
26 *
27 * http://www.sgi.com
28 *
29 * For further information regarding this notice, see:
30 *
31 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
32 */
33
34#include <xfs/libxfs.h>
35
36/* attributes.h (purposefully) unavailable to xfsprogs, make do */
37struct attrlist_cursor { __u32 opaque[4]; };
38
39#include <xfs/handle.h>
40
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
59static int obj_to_handle(char *, int, unsigned int, comarg_t, void**, size_t*);
60static int handle_to_fsfd(void *, char **);
61
62
63/*
64 * Filesystem Handle -> Open File Descriptor Cache
65 *
66 * Maps filesystem handles to a corresponding open file descriptor for that
67 * filesystem. We need this because we're doing handle operations via xfsctl
68 * and we need to remember the open file descriptor for each filesystem.
69 */
70
71struct fdhash {
72 int fsfd;
73 char fsh[FSIDSIZE];
74 struct fdhash *fnxt;
75 char fspath[MAXPATHLEN];
76};
77
78static struct fdhash *fdhash_head = NULL;
79
80int
81path_to_fshandle(
82 char *path, /* input, path to convert */
83 void **fshanp, /* output, pointer to data */
84 size_t *fshlen) /* output, size of returned data */
85{
86 int result;
87 int fd;
88 comarg_t obj;
89 struct fdhash *fdhp;
90 char *tmppath;
91
92 fd = open(path, O_RDONLY);
93 if (fd < 0)
94 return -1;
95
96 obj.path = path;
97 result = obj_to_handle(path, fd, XFS_IOC_PATH_TO_FSHANDLE,
98 obj, fshanp, fshlen);
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 */
109 fdhp = malloc(sizeof(struct fdhash));
110 if (fdhp == NULL) {
111 errno = ENOMEM;
112 return -1;
113 }
114
115 fdhp->fsfd = fd;
116 strncpy(fdhp->fspath, path, sizeof(fdhp->fspath));
117 memcpy(fdhp->fsh, *fshanp, FSIDSIZE);
118
119 fdhp->fnxt = fdhash_head;
120 fdhash_head = fdhp;
121 }
122
123 return result;
124}
125
126int
127path_to_handle(
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);
137 if (fd < 0)
138 return -1;
139
140 obj.path = path;
141 result = obj_to_handle(path, fd, XFS_IOC_PATH_TO_HANDLE,
142 obj, hanp, hlen);
143 close(fd);
144 return result;
145}
146
147int
148handle_to_fshandle(
149 void *hanp,
150 size_t hlen,
151 void **fshanp,
152 size_t *fshlen)
153{
154 if (hlen < FSIDSIZE) {
155 errno = EINVAL;
156 return -1;
157 }
158 *fshanp = malloc(FSIDSIZE);
159 if (*fshanp == NULL) {
160 errno = ENOMEM;
161 return -1;
162 }
163 *fshlen = FSIDSIZE;
164 memcpy(*fshanp, hanp, FSIDSIZE);
165 return 0;
166}
167
168static int
169handle_to_fsfd(void *hanp, char **path)
170{
171 struct fdhash *fdhp;
172
173 for (fdhp = fdhash_head; fdhp != NULL; fdhp = fdhp->fnxt) {
174 if (memcmp(fdhp->fsh, hanp, FSIDSIZE) == 0) {
175 *path = fdhp->fspath;
176 return fdhp->fsfd;
177 }
178 }
179 errno = EBADF;
180 return -1;
181}
182
183static int
184obj_to_handle(
185 char *fspath,
186 int fsfd,
187 unsigned int opcode,
188 comarg_t obj,
189 void **hanp,
190 size_t *hlen)
191{
192 char hbuf [MAXHANSIZ];
193 int ret;
194 __uint32_t handlen;
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
205 hreq.oflags = O_LARGEFILE;
206 hreq.ihandle = NULL;
207 hreq.ihandlen = 0;
208 hreq.ohandle = hbuf;
209 hreq.ohandlen = &handlen;
210
211 ret = xfsctl(fspath, fsfd, opcode, &hreq);
212 if (ret)
213 return ret;
214
215 *hanp = malloc(handlen);
216 if (*hanp == NULL) {
217 errno = ENOMEM;
218 return -1;
219 }
220
221 memcpy(*hanp, hbuf, handlen);
222 *hlen = handlen;
223 return 0;
224}
225
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
250int
251open_by_handle(
252 void *hanp,
253 size_t hlen,
254 int rw)
255{
256 int fsfd;
257 char *path;
258 void *fshanp;
259 size_t fshlen;
260 xfs_fsop_handlereq_t hreq;
261
262 if (handle_to_fshandle(hanp, hlen, &fshanp, &fshlen) != 0)
263 return -1;
264
265 if ((fsfd = handle_to_fsfd(fshanp, &path)) < 0)
266 return -1;
267
268 hreq.fd = 0;
269 hreq.path = NULL;
270 hreq.oflags = rw | O_LARGEFILE;
271 hreq.ihandle = hanp;
272 hreq.ihandlen = hlen;
273 hreq.ohandle = NULL;
274 hreq.ohandlen = NULL;
275
276 return xfsctl(path, fsfd, XFS_IOC_OPEN_BY_HANDLE, &hreq);
277}
278
279int
280readlink_by_handle(
281 void *hanp,
282 size_t hlen,
283 void *buf,
284 size_t bufsiz)
285{
286 int fd;
287 char *path;
288 xfs_fsop_handlereq_t hreq;
289
290 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
291 return -1;
292
293 hreq.fd = 0;
294 hreq.path = NULL;
295 hreq.oflags = O_LARGEFILE;
296 hreq.ihandle = hanp;
297 hreq.ihandlen = hlen;
298 hreq.ohandle = buf;
299 hreq.ohandlen = (__u32 *)&bufsiz;
300
301 return xfsctl(path, fd, XFS_IOC_READLINK_BY_HANDLE, &hreq);
302}
303
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;
313 char *path;
314 xfs_fsop_attrmulti_handlereq_t amhreq;
315
316 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
317 return -1;
318
319 amhreq.hreq.fd = 0;
320 amhreq.hreq.path = NULL;
321 amhreq.hreq.oflags = O_LARGEFILE;
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
330 return xfsctl(path, fd, XFS_IOC_ATTRMULTI_BY_HANDLE, &amhreq);
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;
343 char *path;
344 xfs_fsop_attrlist_handlereq_t alhreq;
345
346 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
347 return -1;
348
349 alhreq.hreq.fd = 0;
350 alhreq.hreq.path = NULL;
351 alhreq.hreq.oflags = O_LARGEFILE;
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
362 return xfsctl(path, fd, XFS_IOC_ATTRLIST_BY_HANDLE, &alhreq);
363}
364
365int
366fssetdm_by_handle(
367 void *hanp,
368 size_t hlen,
369 struct fsdmidata *fsdmidata)
370{
371 int fd;
372 char *path;
373 xfs_fsop_setdm_handlereq_t dmhreq;
374
375 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
376 return -1;
377
378 dmhreq.hreq.fd = 0;
379 dmhreq.hreq.path = NULL;
380 dmhreq.hreq.oflags = O_LARGEFILE;
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
388 return xfsctl(path, fd, XFS_IOC_FSSETDM_BY_HANDLE, &dmhreq);
389}
390
391void
392free_handle(
393 void *hanp,
394 size_t hlen)
395{
396 free(hanp);
397}