217 lines
6.5 KiB
C
217 lines
6.5 KiB
C
/* umount_davfs.c: unmount the davfs file system.
|
|
Copyright (C) 2006, 2007, 2008, 2009 Werner Baumann
|
|
|
|
This file is part of davfs2.
|
|
|
|
davfs2 is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
davfs2 is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with davfs2; if not, write to the Free Software Foundation,
|
|
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include <error.h>
|
|
#include <errno.h>
|
|
#include <getopt.h>
|
|
#ifdef HAVE_LIBINTL_H
|
|
#include <libintl.h>
|
|
#endif
|
|
#ifdef HAVE_LOCALE_H
|
|
#include <locale.h>
|
|
#endif
|
|
#include <stdio.h>
|
|
#ifdef HAVE_STDLIB_H
|
|
#include <stdlib.h>
|
|
#endif
|
|
#ifdef HAVE_STRING_H
|
|
#include <string.h>
|
|
#endif
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include "xalloc.h"
|
|
#include "xvasprintf.h"
|
|
|
|
#include "defaults.h"
|
|
#include "canonicalize.h"
|
|
|
|
#ifdef ENABLE_NLS
|
|
#define _(String) gettext(String)
|
|
#else
|
|
#define _(String) String
|
|
#define textdomain(Domainname)
|
|
#define bindtextdomain(Domainname, Dirname)
|
|
#endif
|
|
|
|
|
|
/* This is lazy programming. All the dirty work is left to the real umount
|
|
program, while we just sit and wait for mount.davfs to terminate.
|
|
umount.davfs is a umount helper. It is usually called by umount and makes
|
|
sure, that umount will not return until mount.davfs has synchronized all
|
|
files.
|
|
It first reads the pid-file and identifies the mount.davfs process. Then
|
|
it calls mount again, with option -i (to not be called again), to do the
|
|
real unmounting. In a loop it will watch the process list. When the
|
|
mount.davfs process terminates, it will return.
|
|
If it can't identify the mount.davfs process, it will call umount -i anyway,
|
|
but warn the user. */
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
setuid(getuid());
|
|
setgid(getgid());
|
|
|
|
setlocale(LC_ALL, "");
|
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
textdomain(PACKAGE);
|
|
|
|
char *short_options = "Vhflnrv";
|
|
static const struct option options[] = {
|
|
{"version", no_argument, NULL, 'V'},
|
|
{"help", no_argument, NULL, 'h'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
int o;
|
|
o = getopt_long(argc, argv, short_options, options, NULL);
|
|
while (o != -1) {
|
|
switch (o) {
|
|
case 'V':
|
|
printf("%s <%s>\n\n", PACKAGE_STRING, PACKAGE_BUGREPORT);
|
|
printf(_("This is free software; see the source for copying "
|
|
"conditions. There is NO\n"
|
|
"warranty; not even for MERCHANTABILITY or FITNESS "
|
|
"FOR A PARTICULAR PURPOSE.\n"));
|
|
exit(EXIT_SUCCESS);
|
|
case 'h':
|
|
printf(_("Usage:\n"
|
|
" u%s -V,--version : print version string\n"
|
|
" u%s -h,--help : print this message\n\n"),
|
|
PROGRAM_NAME, PROGRAM_NAME);
|
|
printf(_("To umount a WebDAV-resource don't call u%s directly, "
|
|
"but use\n"
|
|
"`umount' instead.\n"), PROGRAM_NAME);
|
|
printf(_(" umount <mountpoint> : umount the WebDAV-resource as "
|
|
"specified in\n"
|
|
" /etc/fstab.\n"));
|
|
exit(EXIT_SUCCESS);
|
|
case 'f':
|
|
case 'l':
|
|
case 'n':
|
|
case 'r':
|
|
case 'v':
|
|
case '?':
|
|
break;
|
|
default:
|
|
error(EXIT_FAILURE, 0, _("unknown error parsing arguments"));
|
|
}
|
|
o = getopt_long(argc, argv, short_options, options, NULL);
|
|
}
|
|
|
|
if (optind > (argc - 1))
|
|
error(EXIT_FAILURE, 0, _("missing argument"));
|
|
if (optind < (argc - 1))
|
|
error(EXIT_FAILURE, 0, _("too many arguments"));
|
|
|
|
char *mpoint = canonicalize_file_name(argv[optind]);
|
|
if (!mpoint)
|
|
mpoint = argv[optind];
|
|
if (!mpoint || *mpoint != '/')
|
|
error(EXIT_FAILURE, 0, _("can't determine mount point"));
|
|
|
|
char *m = mpoint;
|
|
while (*m == '/')
|
|
m++;
|
|
char *mp = xstrdup(m);
|
|
m = strchr(mp, '/');
|
|
while (m) {
|
|
*m = '-';
|
|
m = strchr(mp, '/');
|
|
}
|
|
char *pidfile = xasprintf("%s/%s.pid", DAV_SYS_RUN, mp);
|
|
free(mp);
|
|
|
|
char *umount_command = xasprintf("umount -i '%s'", mpoint);
|
|
|
|
char pid[32];
|
|
FILE *file = fopen(pidfile, "r");
|
|
if (!file || fscanf(file, "%30[0-9]", pid) < 1) {
|
|
error(0, 0,
|
|
_("\n"
|
|
" can't read PID from file %s;\n"
|
|
" trying to unmount anyway;\n"
|
|
" please wait for %s to terminate"), pidfile, PROGRAM_NAME);
|
|
return system(umount_command);
|
|
}
|
|
fclose(file);
|
|
|
|
char *ps_command = xasprintf("ps -p %s", pid);
|
|
FILE *ps_in = popen(ps_command, "r");
|
|
if (!ps_in) {
|
|
error(0, 0,
|
|
_("\n"
|
|
" can't read process list;\n"
|
|
" trying to unmount anyway;\n"
|
|
" please wait for %s to terminate"), PROGRAM_NAME);
|
|
return system(umount_command);
|
|
}
|
|
|
|
int found = 0;
|
|
size_t n = 0;
|
|
char *ps_line = NULL;
|
|
while (!found && getline(&ps_line, &n, ps_in) > 0)
|
|
found = (strstr(ps_line, pid) && strstr(ps_line, PROGRAM_NAME));
|
|
pclose(ps_in);
|
|
|
|
if (!found) {
|
|
error(0, 0,
|
|
_("\n"
|
|
" can't find %s-process with pid %s;\n"
|
|
" trying to unmount anyway.\n"
|
|
" you propably have to remove %s manually"),
|
|
PROGRAM_NAME, pid, pidfile);
|
|
return system(umount_command);
|
|
}
|
|
|
|
if (system(umount_command) != 0)
|
|
exit(EXIT_FAILURE);
|
|
|
|
printf(_("%s: waiting while %s (pid %s) synchronizes the cache ."),
|
|
argv[0], PROGRAM_NAME, pid);
|
|
fflush(stdout);
|
|
|
|
while (found) {
|
|
|
|
sleep(3);
|
|
printf(".");
|
|
fflush(stdout);
|
|
|
|
ps_in = popen(ps_command, "r");
|
|
if (!ps_in) {
|
|
printf("\n");
|
|
error(EXIT_FAILURE, 0, _("an error occured while waiting; "
|
|
"please wait for %s to terminate"), PROGRAM_NAME);
|
|
}
|
|
|
|
found = 0;
|
|
while (!found && getline(&ps_line, &n, ps_in) > 0)
|
|
found = (strstr(ps_line, pid) && strstr(ps_line, PROGRAM_NAME));
|
|
|
|
pclose(ps_in);
|
|
}
|
|
printf(" OK\n");
|
|
|
|
return 0;
|
|
}
|