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

« back to all changes in this revision

Viewing changes to lib/parse_subs.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:
18
18
#include <stdlib.h>
19
19
#include <string.h>
20
20
#include <ctype.h>
21
 
#include <sys/types.h>
22
 
#include <sys/stat.h>
23
21
#include <unistd.h>
24
 
#include <sys/vfs.h>
25
22
#include "automount.h"
26
23
 
27
24
/*
304
301
        return s_path;
305
302
}
306
303
 
307
 
int umount_ent(struct autofs_point *ap, const char *path)
308
 
{
309
 
        struct stat st;
310
 
        struct statfs fs;
311
 
        int sav_errno;
312
 
        int status, is_smbfs = 0;
313
 
        int ret, rv = 1;
314
 
 
315
 
        ret = statfs(path, &fs);
316
 
        if (ret == -1) {
317
 
                warn(ap->logopt, "could not stat fs of %s", path);
318
 
                is_smbfs = 0;
319
 
        } else {
320
 
                int cifsfs = fs.f_type == (__SWORD_TYPE) CIFS_MAGIC_NUMBER;
321
 
                int smbfs = fs.f_type == (__SWORD_TYPE) SMB_SUPER_MAGIC;
322
 
                is_smbfs = (cifsfs | smbfs) ? 1 : 0;
323
 
        }
324
 
 
325
 
        status = lstat(path, &st);
326
 
        sav_errno = errno;
327
 
 
328
 
        if (status < 0)
329
 
                warn(ap->logopt, "lstat of %s failed with %d", path, status);
330
 
 
331
 
        /*
332
 
         * lstat failed and we're an smbfs fs returning an error that is not
333
 
         * EIO or EBADSLT or the lstat failed so it's a bad path. Return
334
 
         * a fail.
335
 
         *
336
 
         * EIO appears to correspond to an smb mount that has gone away
337
 
         * and EBADSLT relates to CD changer not responding.
338
 
         */
339
 
        if (!status && (S_ISDIR(st.st_mode) && st.st_dev != ap->dev)) {
340
 
                rv = spawn_umount(ap->logopt, path, NULL);
341
 
        } else if (is_smbfs && (sav_errno == EIO || sav_errno == EBADSLT)) {
342
 
                rv = spawn_umount(ap->logopt, path, NULL);
343
 
        }
344
 
 
345
 
        /* We are doing a forced shutcwdown down so unlink busy mounts */
346
 
        if (rv && (ap->state == ST_SHUTDOWN_FORCE || ap->state == ST_SHUTDOWN)) {
347
 
                ret = stat(path, &st);
348
 
                if (ret == -1 && errno == ENOENT) {
349
 
                        warn(ap->logopt, "mount point does not exist");
350
 
                        return 0;
351
 
                }
352
 
 
353
 
                if (ret == 0 && !S_ISDIR(st.st_mode)) {
354
 
                        warn(ap->logopt, "mount point is not a directory");
355
 
                        return 0;
356
 
                }
357
 
 
358
 
                if (ap->state == ST_SHUTDOWN_FORCE) {
359
 
                        info(ap->logopt, "forcing umount of %s", path);
360
 
                        rv = spawn_umount(ap->logopt, "-l", path, NULL);
361
 
                }
362
 
 
363
 
                /*
364
 
                 * Verify that we actually unmounted the thing.  This is a
365
 
                 * belt and suspenders approach to not eating user data.
366
 
                 * We have seen cases where umount succeeds, but there is
367
 
                 * still a file system mounted on the mount point.  How
368
 
                 * this happens has not yet been determined, but we want to
369
 
                 * make sure to return failure here, if that is the case,
370
 
                 * so that we do not try to call rmdir_path on the
371
 
                 * directory.
372
 
                 */
373
 
                if (!rv && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
374
 
                        crit(ap->logopt,
375
 
                             "the umount binary reported that %s was "
376
 
                             "unmounted, but there is still something "
377
 
                             "mounted on this path.", path);
378
 
                        rv = -1;
379
 
                }
380
 
        }
381
 
 
382
 
        return rv;
383
 
}
384
 
 
385
 
int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
386
 
{
387
 
        char path[PATH_MAX + 1];
388
 
        char *offset = path;
389
 
        struct mapent *oe;
390
 
        struct list_head *pos = NULL;
391
 
        unsigned int fs_path_len;
392
 
        unsigned int mounted;
393
 
        int start;
394
 
 
395
 
        fs_path_len = strlen(root) + strlen(base);
396
 
        if (fs_path_len > PATH_MAX)
397
 
                return -1;
398
 
 
399
 
        strcpy(path, root);
400
 
        strcat(path, base);
401
 
 
402
 
        mounted = 0;
403
 
        start = strlen(root);
404
 
        offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
405
 
        while (offset) {
406
 
                int plen = fs_path_len + strlen(offset);
407
 
 
408
 
                if (plen > PATH_MAX) {
409
 
                        warn(ap->logopt, "path loo long");
410
 
                        goto cont;
411
 
                }
412
 
 
413
 
                oe = cache_lookup_offset(base, offset, start, &me->multi_list);
414
 
                if (!oe)
415
 
                        goto cont;
416
 
 
417
 
                debug(ap->logopt, "mount offset %s", oe->key);
418
 
 
419
 
                if (mount_autofs_offset(ap, oe) < 0)
420
 
                        warn(ap->logopt, "failed to mount offset");
421
 
                else
422
 
                        mounted++;
423
 
cont:
424
 
                offset = cache_get_offset(base,
425
 
                                offset, start, &me->multi_list, &pos);
426
 
        }
427
 
 
428
 
        return mounted;
429
 
}
430
 
 
431
 
int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
432
 
{
433
 
        char path[PATH_MAX + 1];
434
 
        char *offset;
435
 
        struct mapent *oe;
436
 
        struct list_head *mm_root, *pos;
437
 
        const char o_root[] = "/";
438
 
        const char *mm_base;
439
 
        int left, start;
440
 
 
441
 
        left = 0;
442
 
        start = strlen(root);
443
 
 
444
 
        mm_root = &me->multi->multi_list;
445
 
 
446
 
        if (!base)
447
 
                mm_base = o_root;
448
 
        else
449
 
                mm_base = base;
450
 
 
451
 
        pos = NULL;
452
 
        offset = path;
453
 
 
454
 
        /* Make sure "none" of the offsets have an active mount. */
455
 
        while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
456
 
                char *oe_base;
457
 
 
458
 
                oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
459
 
                /* root offset is a special case */
460
 
                if (!oe || (strlen(oe->key) - start) == 1)
461
 
                        continue;
462
 
 
463
 
                /*
464
 
                 * Check for and umount subtree offsets resulting from
465
 
                 * nonstrict mount fail.
466
 
                 */
467
 
                oe_base = oe->key + strlen(root);
468
 
                left += umount_multi_triggers(ap, root, oe, oe_base);
469
 
 
470
 
                if (oe->ioctlfd != -1)
471
 
                        left++;
472
 
        }
473
 
 
474
 
        if (left)
475
 
                return left;
476
 
 
477
 
        pos = NULL;
478
 
        offset = path;
479
 
 
480
 
        /* Make sure "none" of the offsets have an active mount. */
481
 
        while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
482
 
                oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
483
 
                /* root offset is a special case */
484
 
                if (!oe || (strlen(oe->key) - start) == 1)
485
 
                        continue;
486
 
 
487
 
                debug(ap->logopt, "umount offset %s", oe->key);
488
 
 
489
 
                if (umount_autofs_offset(ap, oe)) {
490
 
                        warn(ap->logopt, "failed to umount offset");
491
 
                        left++;
492
 
                }
493
 
        }
494
 
 
495
 
        if (!left && me->multi == me) {
496
 
                struct mapent_cache *mc = me->mc;
497
 
                int status;
498
 
 
499
 
                /*
500
 
                 * Special case.
501
 
                 * If we can't umount the root container then we can't
502
 
                 * delete the offsets from the cache and we need to put
503
 
                 * the offset triggers back.
504
 
                 */
505
 
                if (is_mounted(_PATH_MOUNTED, root, MNTS_REAL)) {
506
 
                        info(ap->logopt, "unmounting dir = %s", root);
507
 
                        if (umount_ent(ap, root)) {
508
 
                                if (!mount_multi_triggers(ap, root, me, "/"))
509
 
                                        warn(ap->logopt,
510
 
                                             "failed to remount offset triggers");
511
 
                                return left++;
512
 
                        }
513
 
                }
514
 
 
515
 
                /* We're done - clean out the offsets */
516
 
                status = cache_delete_offset_list(mc, me->key);
517
 
                if (status != CHE_OK)
518
 
                        warn(ap->logopt, "couldn't delete offset list");
519
 
        }
520
 
 
521
 
        return left;
522
 
}
523