17aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley/* mountpoint.c - Check if a directory is a mountpoint.
28ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwer *
38ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwer * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
48ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwer
5a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob LandleyUSE_MOUNTPOINT(NEWTOY(mountpoint, "<1qdx[-dx]", TOYFLAG_BIN))
68ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwer
78ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwerconfig MOUNTPOINT
87aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  bool "mountpoint"
97aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  default y
107aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  help
117aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    usage: mountpoint [-q] [-d] directory
127aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley           mountpoint [-q] [-x] device
137aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley
147aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    -q	Be quiet, return zero if directory is a mountpoint
157aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    -d	Print major/minor device number of the directory
167aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    -x	Print major/minor device number of the block device
178ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwer*/
188ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwer
19c0e56edaf256adb6c60c5a052525a1ffbb927901Rob Landley#define FOR_mountpoint
208ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwer#include "toys.h"
218ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwer
22afd712aabc1b5bb6782489e01b8228b9021232f0Rob Landleystatic void die(char *gripe)
23afd712aabc1b5bb6782489e01b8228b9021232f0Rob Landley{
24afd712aabc1b5bb6782489e01b8228b9021232f0Rob Landley  if (!(toys.optflags & FLAG_q)) printf("%s: not a %s\n", *toys.optargs, gripe);
25afd712aabc1b5bb6782489e01b8228b9021232f0Rob Landley
26afd712aabc1b5bb6782489e01b8228b9021232f0Rob Landley  toys.exitval++;
27afd712aabc1b5bb6782489e01b8228b9021232f0Rob Landley  xexit();
28afd712aabc1b5bb6782489e01b8228b9021232f0Rob Landley}
29afd712aabc1b5bb6782489e01b8228b9021232f0Rob Landley
308ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwervoid mountpoint_main(void)
318ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwer{
327aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  struct stat st1, st2;
33a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley  char *arg = *toys.optargs;
347aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  int quiet = toys.optflags & FLAG_q;
358ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwer
36d3a435e53c94ec25b4ae5fa2614f49ef8884e08aRob Landley  if (lstat(arg, &st1)) perror_exit_raw(arg);
37a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley
38a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley  if (toys.optflags & FLAG_x) {
397aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    if (S_ISBLK(st1.st_mode)) {
407aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley      if (!quiet) printf("%u:%u\n", major(st1.st_rdev), minor(st1.st_rdev));
41afd712aabc1b5bb6782489e01b8228b9021232f0Rob Landley
427aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley      return;
437aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    }
44afd712aabc1b5bb6782489e01b8228b9021232f0Rob Landley    die("block device");
457aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  }
468ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwer
47afd712aabc1b5bb6782489e01b8228b9021232f0Rob Landley  // TODO: Ignore the fact a file can be a mountpoint for --bind mounts.
48afd712aabc1b5bb6782489e01b8228b9021232f0Rob Landley  if (!S_ISDIR(st1.st_mode)) die("directory");
49a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley
50a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley  arg = xmprintf("%s/..", arg);
51a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley  xstat(arg, &st2);
52a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley  if (CFG_TOYBOX_FREE) free(arg);
53a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley
54a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley  // If the device is different, it's a mount point. If the device _and_
55a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley  // inode are the same, it's probably "/". This misses --bind mounts from
56a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley  // elsewhere in the same filesystem, but so does the other one and in the
57a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley  // absence of a spec I guess that's the expected behavior?
58a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley  toys.exitval = !(st1.st_dev != st2.st_dev || st1.st_ino == st2.st_ino);
597aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  if (toys.optflags & FLAG_d)
607aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    printf("%u:%u\n", major(st1.st_dev), minor(st1.st_dev));
61a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley  else if (!quiet)
62a92f4e1e2097fac6a5d35fc519861e92b39fbc8bRob Landley    printf("%s is %sa mountpoint\n", *toys.optargs, toys.exitval ? "not " : "");
638ad2a7d440d6ace7dc0b0deac1f2b4c8e5cc3a97Elie De Brauwer}
64