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