]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libhandle/handle.c
Merge whitespace changes over
[thirdparty/xfsprogs-dev.git] / libhandle / handle.c
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 <libxfs.h>
35
36 /* attributes.h (purposefully) unavailable to xfsprogs, make do */
37 struct attrlist_cursor { __u32 opaque[4]; };
38
39 #include <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
54 typedef union {
55 int fd;
56 char *path;
57 } comarg_t;
58
59 static int
60 obj_to_handle (
61 char *fspath,
62 int fsfd,
63 unsigned int opcode,
64 comarg_t obj,
65 void **hanp,
66 size_t *hlen);
67
68 static int
69 handle_to_fsfd (
70 void *hanp,
71 char **path);
72
73
74 /*
75 * Filesystem Handle -> Open File Descriptor Cache
76 *
77 * Maps filesystem handles to a corresponding open file descriptor for that
78 * filesystem. We need this because we're doing handle operations via xfsctl
79 * and we need to remember the open file descriptor for each filesystem.
80 */
81
82 struct fdhash {
83 int fsfd;
84 char fsh[FSIDSIZE];
85 struct fdhash *fnxt;
86 char fspath[MAXPATHLEN];
87 };
88
89 static struct fdhash *fdhash_head = NULL;
90
91 int
92 path_to_fshandle (
93 char *path, /* input, path to convert */
94 void **hanp, /* output, pointer to data */
95 size_t *hlen) /* output, size of returned data */
96 {
97 int result;
98 int fd;
99 comarg_t obj;
100 struct fdhash *fdhp;
101
102 fd = open(path, O_RDONLY);
103
104 if (fd < 0) {
105 perror(path);
106 exit(1);
107 }
108
109 obj.path = path;
110
111 result = obj_to_handle(path, fd, XFS_IOC_PATH_TO_FSHANDLE,
112 obj, hanp, hlen);
113
114 if (result >= 0) {
115 fdhp = malloc(sizeof(struct fdhash));
116 if (fdhp == NULL) {
117 errno = ENOMEM;
118 return -1;
119 }
120
121 fdhp->fsfd = fd;
122 fdhp->fnxt = NULL;
123 strncpy(fdhp->fspath, path, sizeof(fdhp->fspath));
124 memcpy(fdhp->fsh, *hanp, FSIDSIZE);
125
126 if (fdhash_head)
127 fdhash_head->fnxt = fdhp;
128 else
129 fdhash_head = fdhp;
130 }
131
132 return result;
133 }
134
135
136 int
137 path_to_handle (
138 char *path, /* input, path to convert */
139 void **hanp, /* output, pointer to data */
140 size_t *hlen) /* output, size of returned data */
141 {
142 int fd;
143 int result;
144 comarg_t obj;
145
146 fd = open(path, O_RDONLY);
147
148 if (fd < 0) {
149 perror(path);
150 exit(1);
151 }
152
153 obj.path = path;
154
155 result = obj_to_handle (path, fd, XFS_IOC_PATH_TO_HANDLE, obj, hanp, hlen);
156
157 close(fd);
158
159 return result;
160 }
161
162
163 int
164 handle_to_fshandle (
165 void *hanp,
166 size_t hlen,
167 void **fshanp,
168 size_t *fshlen)
169 {
170 if (hlen < FSIDSIZE)
171 return EINVAL;
172
173 *fshanp = malloc (FSIDSIZE);
174
175 if (*fshanp == NULL)
176 return ENOMEM;
177
178 *fshlen = FSIDSIZE;
179
180 memcpy(*fshanp, hanp, FSIDSIZE);
181
182 return 0;
183 }
184
185
186 static int
187 handle_to_fsfd(void *hanp, char **path)
188 {
189 struct fdhash *fdhp;
190
191 for (fdhp = fdhash_head; fdhp != NULL; fdhp = fdhp->fnxt) {
192 if (memcmp(fdhp->fsh, hanp, FSIDSIZE) == 0) {
193 *path = fdhp->fspath;
194 return fdhp->fsfd;
195 }
196 }
197 return -1;
198 }
199
200
201 static int
202 obj_to_handle (
203 char *fspath,
204 int fsfd,
205 unsigned int opcode,
206 comarg_t obj,
207 void **hanp,
208 size_t *hlen)
209 {
210 char hbuf [MAXHANSIZ];
211 int ret;
212 xfs_fsop_handlereq_t hreq;
213
214 if (opcode == XFS_IOC_FD_TO_HANDLE) {
215 hreq.fd = obj.fd;
216 hreq.path = NULL;
217 } else {
218 hreq.fd = 0;
219 hreq.path = obj.path;
220 }
221
222 hreq.oflags = O_LARGEFILE;
223 hreq.ihandle = NULL;
224 hreq.ihandlen = 0;
225 hreq.ohandle = hbuf;
226 hreq.ohandlen = (__u32 *)hlen;
227
228 ret = xfsctl(fspath, fsfd, opcode, &hreq);
229 if (ret)
230 return ret;
231
232 *hanp = malloc(*hlen);
233 if (*hanp == NULL) {
234 errno = ENOMEM;
235 return -1;
236 }
237
238 memcpy(*hanp, hbuf, (int) *hlen);
239
240 return 0;
241 }
242
243
244 int
245 open_by_handle (
246 void *hanp,
247 size_t hlen,
248 int rw)
249 {
250 int fd;
251 char *path;
252 xfs_fsop_handlereq_t hreq;
253
254 if ((fd = handle_to_fsfd(hanp, &path)) < 0) {
255 errno = EBADF;
256 return -1;
257 }
258
259 hreq.fd = 0;
260 hreq.path = NULL;
261 hreq.oflags = rw | O_LARGEFILE;
262 hreq.ihandle = hanp;
263 hreq.ihandlen = hlen;
264 hreq.ohandle = NULL;
265 hreq.ohandlen = NULL;
266
267 return xfsctl(path, fd, XFS_IOC_OPEN_BY_HANDLE, &hreq);
268 }
269
270 int
271 readlink_by_handle (
272 void *hanp,
273 size_t hlen,
274 void *buf,
275 size_t bufsiz)
276 {
277 int fd;
278 char *path;
279 xfs_fsop_handlereq_t hreq;
280
281
282 if ((fd = handle_to_fsfd(hanp, &path)) < 0) {
283 errno = EBADF;
284 return -1;
285 }
286
287 hreq.fd = 0;
288 hreq.path = NULL;
289 hreq.oflags = O_LARGEFILE;
290 hreq.ihandle = hanp;
291 hreq.ihandlen = hlen;
292 hreq.ohandle = buf;
293 hreq.ohandlen = (__u32 *)&bufsiz;
294
295 return xfsctl(path, fd, XFS_IOC_READLINK_BY_HANDLE, &hreq);
296 }
297
298 int
299 attr_multi_by_handle(
300 void *hanp,
301 size_t hlen,
302 void *buf,
303 int rtrvcnt,
304 int flags)
305 {
306 int fd;
307 char *path;
308 xfs_fsop_attrmulti_handlereq_t amhreq;
309
310 if ((fd = handle_to_fsfd(hanp, &path)) < 0) {
311 errno = EBADF;
312 return -1;
313 }
314
315 amhreq.hreq.fd = 0;
316 amhreq.hreq.path = NULL;
317 amhreq.hreq.oflags = O_LARGEFILE;
318 amhreq.hreq.ihandle = hanp;
319 amhreq.hreq.ihandlen = hlen;
320 amhreq.hreq.ohandle = NULL;
321 amhreq.hreq.ohandlen = NULL;
322
323 amhreq.opcount = rtrvcnt;
324 amhreq.ops = buf;
325
326 return xfsctl(path, fd, XFS_IOC_ATTRMULTI_BY_HANDLE, &amhreq);
327 }
328
329 int
330 attr_list_by_handle(
331 void *hanp,
332 size_t hlen,
333 void *buf,
334 size_t bufsize,
335 int flags,
336 struct attrlist_cursor *cursor)
337 {
338 int fd;
339 char *path;
340 xfs_fsop_attrlist_handlereq_t alhreq;
341
342 if ((fd = handle_to_fsfd(hanp, &path)) < 0) {
343 errno = EBADF;
344 return -1;
345 }
346
347 alhreq.hreq.fd = 0;
348 alhreq.hreq.path = NULL;
349 alhreq.hreq.oflags = O_LARGEFILE;
350 alhreq.hreq.ihandle = hanp;
351 alhreq.hreq.ihandlen = hlen;
352 alhreq.hreq.ohandle = NULL;
353 alhreq.hreq.ohandlen = NULL;
354
355 memcpy(&alhreq.pos, cursor, sizeof(alhreq.pos));
356 alhreq.flags = flags;
357 alhreq.buflen = bufsize;
358 alhreq.buffer = buf;
359
360 return xfsctl(path, fd, XFS_IOC_ATTRLIST_BY_HANDLE, &alhreq);
361 }
362
363 int
364 fssetdm_by_handle (
365 void *hanp,
366 size_t hlen,
367 struct fsdmidata *fsdmidata)
368 {
369 int fd;
370 char *path;
371 xfs_fsop_setdm_handlereq_t dmhreq;
372
373
374 if ((fd = handle_to_fsfd(hanp, &path)) < 0) {
375 errno = EBADF;
376 return -1;
377 }
378
379 dmhreq.hreq.fd = 0;
380 dmhreq.hreq.path = NULL;
381 dmhreq.hreq.oflags = O_LARGEFILE;
382 dmhreq.hreq.ihandle = hanp;
383 dmhreq.hreq.ihandlen = hlen;
384 dmhreq.hreq.ohandle = NULL;
385 dmhreq.hreq.ohandlen = NULL;
386
387 dmhreq.data = fsdmidata;
388
389 return xfsctl(path, fd, XFS_IOC_FSSETDM_BY_HANDLE, &dmhreq);
390 }
391
392 /*ARGSUSED*/
393 void
394 free_handle (
395 void *hanp,
396 size_t hlen)
397 {
398 free (hanp);
399 }