~ubuntu-branches/ubuntu/raring/autofs5/raring

« back to all changes in this revision

Viewing changes to lib/dev-ioctl-lib.c

  • Committer: Bazaar Package Importer
  • Author(s): Jan Christoph Nordholz
  • Date: 2009-03-09 01:16:48 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090309011648-gjynlid883f0s2c4
Tags: 5.0.4-1
* New upstream version (5.0.4 plus patchset as of 2009/03/09).
  * Closes: #518728.
  * Remove dpatch 14, applied upstream.
* New dpatch 14 to avoid using the relatively young SOCK_CLOEXEC
  feature.
* Only invoke 'make clean' on clean target so ./configure isn't
  purged.
* Fix a typo in the postinst regarding the ucf conffile handling.
* Add 'set -e' to package maintenance scripts.
* Drop unnecessary /var/run/autofs from package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ----------------------------------------------------------------------- *
 
2
 *
 
3
 *  ctl-dev-lib.c - module for Linux automount mount table lookup functions
 
4
 *
 
5
 *  Copyright 2008 Red Hat, Inc. All rights reserved.
 
6
 *  Copyright 2008 Ian Kent <raven@themaw.net> - All Rights Reserved
 
7
 *
 
8
 *  This program is free software; you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU General Public License as published by
 
10
 *  the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
 
11
 *  USA; either version 2 of the License, or (at your option) any later
 
12
 *  version; incorporated herein by reference.
 
13
 *
 
14
 * ----------------------------------------------------------------------- */
 
15
 
 
16
#include <stdio.h>
 
17
#include <stdlib.h>
 
18
#include <string.h>
 
19
#include <errno.h>
 
20
#include <limits.h>
 
21
#include <sys/types.h>
 
22
#include <sys/stat.h>
 
23
#include <sys/ioctl.h>
 
24
#include <fcntl.h>
 
25
#include <mntent.h>
 
26
#include <sys/vfs.h>
 
27
 
 
28
#include "automount.h"
 
29
 
 
30
/* ioctld control function interface */
 
31
static struct ioctl_ctl ctl = { -1, NULL };
 
32
 
 
33
#ifndef AUTOFS_SUPER_MAGIC
 
34
#define AUTOFS_SUPER_MAGIC      0x0187
 
35
#endif
 
36
 
 
37
/*
 
38
 * Define functions for autofs ioctl control.
 
39
 *
 
40
 * We provide two interfaces. One which routes ioctls via a
 
41
 * miscelaneous device node and can be used to obtain an ioctl
 
42
 * file descriptor for autofs mounts that are covered by an
 
43
 * active mount (eg. active direct or multi-mount offsets).
 
44
 * The other provides the traditional autofs ioctl implementation.
 
45
 *
 
46
 * The miscielaneous device control functions are prefixed with
 
47
 * dev_ctl_ and the traditional ones are prefixed with ioctl_.
 
48
 */
 
49
static int dev_ioctl_version(unsigned int, int, struct autofs_dev_ioctl *);
 
50
static int dev_ioctl_protover(unsigned int, int, unsigned int *);
 
51
static int dev_ioctl_protosubver(unsigned int, int, unsigned int *);
 
52
static int dev_ioctl_mount_device(unsigned int, const char *, unsigned int, dev_t *);
 
53
static int dev_ioctl_open(unsigned int, int *, dev_t, const char *);
 
54
static int dev_ioctl_close(unsigned int, int);
 
55
static int dev_ioctl_send_ready(unsigned int, int, unsigned int);
 
56
static int dev_ioctl_send_fail(unsigned int, int, unsigned int, int);
 
57
static int dev_ioctl_setpipefd(unsigned int, int, int);
 
58
static int dev_ioctl_catatonic(unsigned int, int);
 
59
static int dev_ioctl_timeout(unsigned int, int, time_t *);
 
60
static int dev_ioctl_requestor(unsigned int, int, const char *, uid_t *, gid_t *);
 
61
static int dev_ioctl_expire(unsigned int, int, const char *, unsigned int);
 
62
static int dev_ioctl_askumount(unsigned int, int, unsigned int *);
 
63
static int dev_ioctl_ismountpoint(unsigned int, int, const char *, unsigned int *);
 
64
 
 
65
static int ioctl_protover(unsigned int, int, unsigned int *);
 
66
static int ioctl_protosubver(unsigned int, int, unsigned int *);
 
67
static int ioctl_mount_device(unsigned int, const char *, unsigned int, dev_t *);
 
68
static int ioctl_open(unsigned int, int *, dev_t, const char *);
 
69
static int ioctl_close(unsigned int, int);
 
70
static int ioctl_send_ready(unsigned int, int, unsigned int);
 
71
static int ioctl_send_fail(unsigned int, int, unsigned int, int);
 
72
static int ioctl_catatonic(unsigned int, int);
 
73
static int ioctl_timeout(unsigned int, int, time_t *);
 
74
static int ioctl_expire(unsigned int, int, const char *, unsigned int);
 
75
static int ioctl_askumount(unsigned int, int, unsigned int *);
 
76
 
 
77
static struct ioctl_ops dev_ioctl_ops = {
 
78
        .version        = dev_ioctl_version,
 
79
        .protover       = dev_ioctl_protover,
 
80
        .protosubver    = dev_ioctl_protosubver,
 
81
        .mount_device   = dev_ioctl_mount_device,
 
82
        .open           = dev_ioctl_open,
 
83
        .close          = dev_ioctl_close,
 
84
        .send_ready     = dev_ioctl_send_ready,
 
85
        .send_fail      = dev_ioctl_send_fail,
 
86
        .setpipefd      = dev_ioctl_setpipefd,
 
87
        .catatonic      = dev_ioctl_catatonic,
 
88
        .timeout        = dev_ioctl_timeout,
 
89
        .requestor      = dev_ioctl_requestor,
 
90
        .expire         = dev_ioctl_expire,
 
91
        .askumount      = dev_ioctl_askumount,
 
92
        .ismountpoint   = dev_ioctl_ismountpoint
 
93
};
 
94
 
 
95
static struct ioctl_ops ioctl_ops = {
 
96
        .version        = NULL,
 
97
        .protover       = ioctl_protover,
 
98
        .protosubver    = ioctl_protosubver,
 
99
        .mount_device   = ioctl_mount_device,
 
100
        .open           = ioctl_open,
 
101
        .close          = ioctl_close,
 
102
        .send_ready     = ioctl_send_ready,
 
103
        .send_fail      = ioctl_send_fail,
 
104
        .setpipefd      = NULL,
 
105
        .catatonic      = ioctl_catatonic,
 
106
        .timeout        = ioctl_timeout,
 
107
        .requestor      = NULL,
 
108
        .expire         = ioctl_expire,
 
109
        .askumount      = ioctl_askumount,
 
110
        .ismountpoint   = NULL
 
111
};
 
112
 
 
113
/*
 
114
 * Allocate the control struct that holds the misc device file
 
115
 * descriptor and operation despatcher table.
 
116
 */
 
117
void init_ioctl_ctl(void)
 
118
{
 
119
        int devfd;
 
120
 
 
121
        if (ctl.ops)
 
122
                return;
 
123
 
 
124
        devfd = open(CONTROL_DEVICE, O_RDONLY);
 
125
        if (devfd == -1)
 
126
                ctl.ops = &ioctl_ops;
 
127
        else {
 
128
                struct autofs_dev_ioctl param;
 
129
 
 
130
                int cl_flags = fcntl(devfd, F_GETFD, 0);
 
131
                if (cl_flags != -1) {
 
132
                        cl_flags |= FD_CLOEXEC;
 
133
                        fcntl(devfd, F_SETFD, cl_flags);
 
134
                }
 
135
                /*
 
136
                 * Check compile version against kernel.
 
137
                 * Selinux may allow us to open the device but not
 
138
                 * actually allow us to do anything.
 
139
                 */
 
140
                init_autofs_dev_ioctl(&param);
 
141
                if (ioctl(devfd, AUTOFS_DEV_IOCTL_VERSION, &param) == -1) {
 
142
                        close(devfd);
 
143
                        ctl.ops = &ioctl_ops;
 
144
                } else {
 
145
                        ctl.devfd = devfd;
 
146
                        ctl.ops = &dev_ioctl_ops;
 
147
                }
 
148
        }
 
149
        return;
 
150
}
 
151
 
 
152
void close_ioctl_ctl(void)
 
153
{
 
154
        if (ctl.devfd != -1) {
 
155
                close(ctl.devfd);
 
156
                ctl.devfd = -1;
 
157
        }
 
158
        ctl.ops = NULL;
 
159
        return;
 
160
}
 
161
 
 
162
/* Return a pointer to the operations control struct */
 
163
struct ioctl_ops *get_ioctl_ops(void)
 
164
{
 
165
        if (!ctl.ops)
 
166
                init_ioctl_ctl();
 
167
        return ctl.ops;
 
168
}
 
169
 
 
170
/* Get kenrel version of misc device code */
 
171
static int dev_ioctl_version(unsigned int logopt,
 
172
                             int ioctlfd, struct autofs_dev_ioctl *param)
 
173
{
 
174
        param->ioctlfd = ioctlfd;
 
175
 
 
176
        if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_VERSION, param) == -1)
 
177
                return -1;
 
178
 
 
179
        return 0;
 
180
}
 
181
 
 
182
/* Get major version of autofs kernel module mount protocol */
 
183
static int dev_ioctl_protover(unsigned int logopt,
 
184
                              int ioctlfd, unsigned int *major)
 
185
{
 
186
        struct autofs_dev_ioctl param;
 
187
 
 
188
        init_autofs_dev_ioctl(&param);
 
189
        param.ioctlfd = ioctlfd;
 
190
 
 
191
        if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_PROTOVER, &param) == -1)
 
192
                return -1;
 
193
 
 
194
        *major = param.protover.version;
 
195
 
 
196
        return 0;
 
197
}
 
198
 
 
199
static int ioctl_protover(unsigned int logopt,
 
200
                          int ioctlfd, unsigned int *major)
 
201
{
 
202
        return ioctl(ioctlfd, AUTOFS_IOC_PROTOVER, major);
 
203
}
 
204
 
 
205
/* Get minor version of autofs kernel module mount protocol */
 
206
static int dev_ioctl_protosubver(unsigned int logopt,
 
207
                                 int ioctlfd, unsigned int *minor)
 
208
{
 
209
        struct autofs_dev_ioctl param;
 
210
 
 
211
        init_autofs_dev_ioctl(&param);
 
212
        param.ioctlfd = ioctlfd;
 
213
 
 
214
        if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_PROTOSUBVER, &param) == -1)
 
215
                return -1;
 
216
 
 
217
        *minor = param.protosubver.sub_version;
 
218
 
 
219
        return 0;
 
220
}
 
221
 
 
222
static int ioctl_protosubver(unsigned int logopt,
 
223
                             int ioctlfd, unsigned int *minor)
 
224
{
 
225
        return ioctl(ioctlfd, AUTOFS_IOC_PROTOSUBVER, minor);
 
226
}
 
227
 
 
228
/*
 
229
 * Allocate a parameter struct for misc device ioctl used when
 
230
 * opening an autofs mount point. Attach the path to the end
 
231
 * of the struct. and lookup the device number if not given.
 
232
 * Locating the device number relies on the mount option
 
233
 * "dev=<device number>" being present in the autofs fs mount
 
234
 * options.
 
235
 */
 
236
static struct autofs_dev_ioctl *alloc_dev_ioctl_open(const char *path, dev_t devid)
 
237
{
 
238
        struct autofs_dev_ioctl *ioctl;
 
239
        size_t size, p_len;
 
240
        dev_t devno = devid;
 
241
 
 
242
        if (!path)
 
243
                return NULL;
 
244
 
 
245
        p_len = strlen(path);
 
246
        size = sizeof(struct autofs_dev_ioctl) + p_len + 1;
 
247
        ioctl = malloc(size);
 
248
        if (!ioctl) {
 
249
                errno = ENOMEM;
 
250
                return NULL;
 
251
        }
 
252
 
 
253
        init_autofs_dev_ioctl(ioctl);
 
254
        ioctl->size = size;
 
255
        memcpy(ioctl->path, path, p_len);
 
256
        ioctl->path[p_len] = '\0';
 
257
        ioctl->openmount.devid = devno;
 
258
 
 
259
        return ioctl;
 
260
}
 
261
 
 
262
static void free_dev_ioctl_open(struct autofs_dev_ioctl *ioctl)
 
263
{
 
264
        free(ioctl);
 
265
        return;
 
266
}
 
267
 
 
268
/*
 
269
 * Allocate a parameter struct for misc device ioctl which includes
 
270
 * a path. This is used when getting the last mount requestor uid
 
271
 * and gid and when checking if a path within the autofs filesystem
 
272
 * is a mount point. We add the path to the end of the struct.
 
273
 */
 
274
static struct autofs_dev_ioctl *alloc_dev_ioctl_path(int ioctlfd, const char *path)
 
275
{
 
276
        struct autofs_dev_ioctl *ioctl;
 
277
        size_t size, p_len;
 
278
 
 
279
        if (!path)
 
280
                return NULL;
 
281
 
 
282
        p_len = strlen(path);
 
283
        size = sizeof(struct autofs_dev_ioctl) + p_len + 1;
 
284
        ioctl = malloc(size);
 
285
        if (!ioctl) {
 
286
                errno = ENOMEM;
 
287
                return NULL;
 
288
        }
 
289
 
 
290
        init_autofs_dev_ioctl(ioctl);
 
291
        ioctl->ioctlfd = ioctlfd;
 
292
        ioctl->size = size;
 
293
        memcpy(ioctl->path, path, p_len);
 
294
        ioctl->path[p_len] = '\0';
 
295
 
 
296
        return ioctl;
 
297
}
 
298
 
 
299
static void free_dev_ioctl_path(struct autofs_dev_ioctl *ioctl)
 
300
{
 
301
        free(ioctl);
 
302
        return;
 
303
}
 
304
 
 
305
/*
 
306
 * Find the device number of an autofs mount with given path and
 
307
 * type (eg..AUTOFS_TYPE_DIRECT). The device number is used by
 
308
 * the kernel to identify the autofs super block when searching
 
309
 * for the mount.
 
310
 */
 
311
static int dev_ioctl_mount_device(unsigned int logopt, const char *path, unsigned int type, dev_t *devid)
 
312
{
 
313
        struct autofs_dev_ioctl *param;
 
314
        int err;
 
315
 
 
316
        if (!path) {
 
317
                errno = EINVAL;
 
318
                return -1;
 
319
        }
 
320
 
 
321
        *devid = -1;
 
322
 
 
323
        param = alloc_dev_ioctl_path(-1, path);
 
324
        if (!param)
 
325
                return -1;
 
326
        param->ismountpoint.in.type = type;
 
327
 
 
328
        err = ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_ISMOUNTPOINT, param);
 
329
        if (err == -1) {
 
330
                int save_errno = errno;
 
331
                free_dev_ioctl_path(param);
 
332
                errno = save_errno;
 
333
                return -1;
 
334
        }
 
335
 
 
336
        if (err)
 
337
                *devid = param->ismountpoint.out.devid;
 
338
 
 
339
        free_dev_ioctl_path(param);
 
340
 
 
341
        return err;
 
342
}
 
343
 
 
344
static int ioctl_mount_device(unsigned int logopt,
 
345
                              const char *path, unsigned int type,
 
346
                              dev_t *devid)
 
347
{
 
348
        return -1;
 
349
}
 
350
 
 
351
/* Get a file descriptor for control operations */
 
352
static int dev_ioctl_open(unsigned int logopt,
 
353
                          int *ioctlfd, dev_t devid, const char *path)
 
354
{
 
355
        struct autofs_dev_ioctl *param;
 
356
 
 
357
        *ioctlfd = -1;
 
358
 
 
359
        param = alloc_dev_ioctl_open(path, devid);
 
360
        if (!param)
 
361
                return -1;
 
362
 
 
363
        if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_OPENMOUNT, param) == -1) {
 
364
                int save_errno = errno;
 
365
                free_dev_ioctl_open(param);
 
366
                errno = save_errno;
 
367
                return -1;
 
368
        }
 
369
 
 
370
        *ioctlfd = param->ioctlfd;
 
371
 
 
372
        free_dev_ioctl_open(param);
 
373
 
 
374
        return 0;
 
375
}
 
376
 
 
377
static int ioctl_open(unsigned int logopt,
 
378
                      int *ioctlfd, dev_t devid, const char *path)
 
379
{
 
380
        struct statfs sfs;
 
381
        int save_errno, fd, cl_flags;
 
382
 
 
383
        *ioctlfd = -1;
 
384
 
 
385
        fd = open(path, O_RDONLY);
 
386
        if (fd == -1)
 
387
                return -1;
 
388
 
 
389
        cl_flags = fcntl(fd, F_GETFD, 0);
 
390
        if (cl_flags != -1) {
 
391
                cl_flags |= FD_CLOEXEC;
 
392
                fcntl(fd, F_SETFD, cl_flags);
 
393
        }
 
394
 
 
395
        if (fstatfs(fd, &sfs) == -1) {
 
396
                save_errno = errno;
 
397
                goto err;
 
398
        }
 
399
 
 
400
        if (sfs.f_type != AUTOFS_SUPER_MAGIC) {
 
401
                save_errno = ENOENT;
 
402
                goto err;
 
403
        }
 
404
 
 
405
        *ioctlfd = fd;
 
406
 
 
407
        return 0;
 
408
err:
 
409
        close(fd);
 
410
        errno = save_errno;
 
411
        return -1;
 
412
}
 
413
 
 
414
/* Close */
 
415
static int dev_ioctl_close(unsigned int logopt, int ioctlfd)
 
416
{
 
417
        struct autofs_dev_ioctl param;
 
418
 
 
419
        init_autofs_dev_ioctl(&param);
 
420
        param.ioctlfd = ioctlfd;
 
421
 
 
422
        if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_CLOSEMOUNT, &param) == -1)
 
423
                return -1;
 
424
 
 
425
        return 0;
 
426
}
 
427
 
 
428
static int ioctl_close(unsigned int logopt, int ioctlfd)
 
429
{
 
430
        return close(ioctlfd);
 
431
}
 
432
 
 
433
/* Send ready status for given token */
 
434
static int dev_ioctl_send_ready(unsigned int logopt,
 
435
                                int ioctlfd, unsigned int token)
 
436
{
 
437
        struct autofs_dev_ioctl param;
 
438
 
 
439
        if (token == 0) {
 
440
                errno = EINVAL;
 
441
                return -1;
 
442
        }
 
443
 
 
444
        debug(logopt, "token = %d", token);
 
445
 
 
446
        init_autofs_dev_ioctl(&param);
 
447
        param.ioctlfd = ioctlfd;
 
448
        param.ready.token = token;
 
449
 
 
450
        if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_READY, &param) == -1) {
 
451
                char *estr, buf[MAX_ERR_BUF];
 
452
                int save_errno = errno;
 
453
                estr = strerror_r(errno, buf, MAX_ERR_BUF);
 
454
                logerr("AUTOFS_DEV_IOCTL_READY: error %s", estr);
 
455
                errno = save_errno;
 
456
                return -1;
 
457
        }
 
458
        return 0;
 
459
}
 
460
 
 
461
static int ioctl_send_ready(unsigned int logopt,
 
462
                            int ioctlfd, unsigned int token)
 
463
{
 
464
        if (token == 0) {
 
465
                errno = EINVAL;
 
466
                return -1;
 
467
        }
 
468
 
 
469
        debug(logopt, "token = %d", token);
 
470
 
 
471
        if (ioctl(ioctlfd, AUTOFS_IOC_READY, token) == -1) {
 
472
                char *estr, buf[MAX_ERR_BUF];
 
473
                int save_errno = errno;
 
474
                estr = strerror_r(errno, buf, MAX_ERR_BUF);
 
475
                logerr("AUTOFS_IOC_READY: error %s", estr);
 
476
                errno = save_errno;
 
477
                return -1;
 
478
        }
 
479
        return 0;
 
480
}
 
481
 
 
482
/*
 
483
 * Send ready status for given token.
 
484
 *
 
485
 * The device node ioctl implementation allows for sending a status
 
486
 * of other than ENOENT, unlike the tradional interface.
 
487
 */
 
488
static int dev_ioctl_send_fail(unsigned int logopt,
 
489
                               int ioctlfd, unsigned int token, int status)
 
490
{
 
491
        struct autofs_dev_ioctl param;
 
492
 
 
493
        if (token == 0) {
 
494
                errno = EINVAL;
 
495
                return -1;
 
496
        }
 
497
 
 
498
        debug(logopt, "token = %d", token);
 
499
 
 
500
        init_autofs_dev_ioctl(&param);
 
501
        param.ioctlfd = ioctlfd;
 
502
        param.fail.token = token;
 
503
        param.fail.status = status;
 
504
 
 
505
        if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_FAIL, &param) == -1) {
 
506
                char *estr, buf[MAX_ERR_BUF];
 
507
                int save_errno = errno;
 
508
                estr = strerror_r(errno, buf, MAX_ERR_BUF);
 
509
                logerr("AUTOFS_DEV_IOCTL_FAIL: error %s", estr);
 
510
                errno = save_errno;
 
511
                return -1;
 
512
        }
 
513
        return 0;
 
514
}
 
515
 
 
516
static int ioctl_send_fail(unsigned int logopt,
 
517
                           int ioctlfd, unsigned int token, int status)
 
518
{
 
519
        if (token == 0) {
 
520
                errno = EINVAL;
 
521
                return -1;
 
522
        }
 
523
 
 
524
        debug(logopt, "token = %d", token);
 
525
 
 
526
        if (ioctl(ioctlfd, AUTOFS_IOC_FAIL, token) == -1) {
 
527
                char *estr, buf[MAX_ERR_BUF];
 
528
                int save_errno = errno;
 
529
                estr = strerror_r(errno, buf, MAX_ERR_BUF);
 
530
                logerr("AUTOFS_IOC_FAIL: error %s", estr);
 
531
                errno = save_errno;
 
532
                return -1;
 
533
        }
 
534
        return 0;
 
535
}
 
536
 
 
537
/*
 
538
 * Set the pipe fd for kernel communication.
 
539
 *
 
540
 * Normally this is set at mount using an option but if we
 
541
 * are reconnecting to a busy mount then we need to use this
 
542
 * to tell the autofs kernel module about the new pipe fd. In
 
543
 * order to protect mounts against incorrectly setting the
 
544
 * pipefd we also require that the autofs mount be catatonic.
 
545
 *
 
546
 * If successful this also sets the process group id used to
 
547
 * identify the controlling process to the process group of
 
548
 * the caller.
 
549
 */
 
550
static int dev_ioctl_setpipefd(unsigned int logopt, int ioctlfd, int pipefd)
 
551
{
 
552
        struct autofs_dev_ioctl param;
 
553
 
 
554
        if (pipefd == -1) {
 
555
                errno = EBADF;
 
556
                return -1;
 
557
        }
 
558
 
 
559
        init_autofs_dev_ioctl(&param);
 
560
        param.ioctlfd = ioctlfd;
 
561
        param.setpipefd.pipefd = pipefd;
 
562
 
 
563
        if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_SETPIPEFD, &param) == -1)
 
564
                return -1;
 
565
 
 
566
        return 0;
 
567
}
 
568
 
 
569
/*
 
570
 * Make the autofs mount point catatonic, no longer responsive to
 
571
 * mount requests. Also closes the kernel pipe file descriptor.
 
572
 */
 
573
static int dev_ioctl_catatonic(unsigned int logopt, int ioctlfd)
 
574
{
 
575
        struct autofs_dev_ioctl param;
 
576
 
 
577
        init_autofs_dev_ioctl(&param);
 
578
        param.ioctlfd = ioctlfd;
 
579
 
 
580
        if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_CATATONIC, &param) == -1)
 
581
                return -1;
 
582
 
 
583
        return 0;
 
584
}
 
585
 
 
586
static int ioctl_catatonic(unsigned int logopt, int ioctlfd)
 
587
{
 
588
        return ioctl(ioctlfd, AUTOFS_IOC_CATATONIC, 0);
 
589
}
 
590
 
 
591
/* Set the autofs mount timeout */
 
592
static int dev_ioctl_timeout(unsigned int logopt, int ioctlfd, time_t *timeout)
 
593
{
 
594
        struct autofs_dev_ioctl param;
 
595
 
 
596
        init_autofs_dev_ioctl(&param);
 
597
        param.ioctlfd = ioctlfd;
 
598
        param.timeout.timeout = *timeout;
 
599
 
 
600
        if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_TIMEOUT, &param) == -1)
 
601
                return -1;
 
602
 
 
603
        *timeout = param.timeout.timeout;
 
604
 
 
605
        return 0;
 
606
}
 
607
 
 
608
static int ioctl_timeout(unsigned int logopt, int ioctlfd, time_t *timeout)
 
609
{
 
610
        return ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, timeout);
 
611
}
 
612
 
 
613
/*
 
614
 * Get the uid and gid of the last request for the mountpoint, path.
 
615
 *
 
616
 * When reconstructing an autofs mount tree with active mounts
 
617
 * we need to re-connect to mounts that may have used the original
 
618
 * process uid and gid (or string variations of them) for mount
 
619
 * lookups within the map entry.
 
620
 */
 
621
static int dev_ioctl_requestor(unsigned int logopt,
 
622
                               int ioctlfd, const char *path,
 
623
                               uid_t *uid, gid_t *gid)
 
624
{
 
625
        struct autofs_dev_ioctl *param;
 
626
        int err;
 
627
 
 
628
        if (!path)
 
629
                errno = EINVAL;
 
630
 
 
631
        *uid = -1;
 
632
        *gid = -1;
 
633
 
 
634
 
 
635
        param = alloc_dev_ioctl_path(ioctlfd, path);
 
636
        if (!param)
 
637
                return -1;
 
638
 
 
639
        err = ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_REQUESTER, param);
 
640
        if (err == -1) {
 
641
                int save_errno = errno;
 
642
                free_dev_ioctl_open(param);
 
643
                errno = save_errno;
 
644
                return -1;
 
645
        }
 
646
 
 
647
        *uid = param->requester.uid;
 
648
        *gid = param->requester.gid;
 
649
 
 
650
        free_dev_ioctl_path(param);
 
651
 
 
652
        return 0;
 
653
}
 
654
 
 
655
/*
 
656
 * Call repeatedly until it returns EAGAIN, meaning there's nothing
 
657
 * more that can be done.
 
658
 */
 
659
static int expire(unsigned int logopt,
 
660
                  int cmd, int fd, int ioctlfd, const char *path, void *arg)
 
661
{
 
662
        int ret, retries = EXPIRE_RETRIES;
 
663
        unsigned int may_umount;
 
664
 
 
665
        while (retries--) {
 
666
                struct timespec tm = {0, 100000000};
 
667
 
 
668
                /* Ggenerate expire message for the mount. */
 
669
                ret = ioctl(fd, cmd, arg);
 
670
                if (ret == -1) {
 
671
                        /* Mount has gone away */
 
672
                        if (errno == EBADF || errno == EINVAL)
 
673
                                return 0;
 
674
 
 
675
                        /*
 
676
                         * Other than EAGAIN is an expire error so continue.
 
677
                         * Kernel will try the next mount for indirect maps
 
678
                         * and the same mount again for direct maps, limited
 
679
                         * by retries.
 
680
                         */
 
681
                        if (errno == EAGAIN)
 
682
                                break;
 
683
                }
 
684
                nanosleep(&tm, NULL);
 
685
        }
 
686
 
 
687
        may_umount = 0;
 
688
        if (ctl.ops->askumount(logopt, ioctlfd, &may_umount))
 
689
                return -1;
 
690
 
 
691
        if (!may_umount)
 
692
                return 1;
 
693
 
 
694
        return 0;
 
695
}
 
696
 
 
697
static int dev_ioctl_expire(unsigned int logopt,
 
698
                            int ioctlfd, const char *path, unsigned int when)
 
699
{
 
700
        struct autofs_dev_ioctl param;
 
701
 
 
702
        init_autofs_dev_ioctl(&param);
 
703
        param.ioctlfd = ioctlfd;
 
704
        param.expire.how = when;
 
705
 
 
706
        return expire(logopt, AUTOFS_DEV_IOCTL_EXPIRE,
 
707
                      ctl.devfd, ioctlfd, path, (void *) &param);
 
708
}
 
709
 
 
710
static int ioctl_expire(unsigned int logopt,
 
711
                        int ioctlfd, const char *path, unsigned int when)
 
712
{
 
713
        return expire(logopt, AUTOFS_IOC_EXPIRE_MULTI,
 
714
                      ioctlfd, ioctlfd, path, (void *) &when);
 
715
}
 
716
 
 
717
/* Check if autofs mount point is in use */
 
718
static int dev_ioctl_askumount(unsigned int logopt,
 
719
                               int ioctlfd, unsigned int *busy)
 
720
{
 
721
        struct autofs_dev_ioctl param;
 
722
 
 
723
        init_autofs_dev_ioctl(&param);
 
724
        param.ioctlfd = ioctlfd;
 
725
 
 
726
        if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_ASKUMOUNT, &param) == -1)
 
727
                return -1;
 
728
 
 
729
        *busy = param.askumount.may_umount;
 
730
 
 
731
        return 0;
 
732
}
 
733
 
 
734
static int ioctl_askumount(unsigned int logopt,
 
735
                           int ioctlfd, unsigned int *busy)
 
736
{
 
737
        return ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, busy);
 
738
}
 
739
 
 
740
/*
 
741
 * Check if the given path is a mountpoint.
 
742
 *
 
743
 * The path is considered a mountpoint if it is itself a mountpoint
 
744
 * or contains a mount, such as a multi-mount without a root mount.
 
745
 * In addition, if the path is itself a mountpoint we return whether
 
746
 * the mounted file system is an autofs filesystem or other file
 
747
 * system.
 
748
 */
 
749
static int dev_ioctl_ismountpoint(unsigned int logopt,
 
750
                                  int ioctlfd, const char *path,
 
751
                                  unsigned int *mountpoint)
 
752
{
 
753
        struct autofs_dev_ioctl *param;
 
754
        int err;
 
755
 
 
756
        *mountpoint = 0;
 
757
 
 
758
        if (!path) {
 
759
                errno = EINVAL;
 
760
                return -1;
 
761
        }
 
762
 
 
763
        param = alloc_dev_ioctl_path(ioctlfd, path);
 
764
        if (!param)
 
765
                return -1;
 
766
        set_autofs_type_any(&param->ismountpoint.in.type);
 
767
 
 
768
        err = ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_ISMOUNTPOINT, param);
 
769
        if (err == -1) {
 
770
                int save_errno = errno;
 
771
                free_dev_ioctl_path(param);
 
772
                errno = save_errno;
 
773
                return -1;
 
774
        }
 
775
 
 
776
        if (err) {
 
777
                *mountpoint = DEV_IOCTL_IS_MOUNTED;
 
778
 
 
779
                if (param->ismountpoint.out.magic) {
 
780
                        if (param->ismountpoint.out.magic == AUTOFS_SUPER_MAGIC)
 
781
                                *mountpoint |= DEV_IOCTL_IS_AUTOFS;
 
782
                        else
 
783
                                *mountpoint |= DEV_IOCTL_IS_OTHER;
 
784
                }
 
785
        }
 
786
 
 
787
        free_dev_ioctl_path(param);
 
788
 
 
789
        return 0;
 
790
}