// ----------------------------------------------------------------------
// File: com_fuse.cc
// Author: Andreas-Joachim Peters - CERN
// ----------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright(C) 2011 CERN/Switzerland *
* *
* This program 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. *
* *
* This program 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 this program. If not, see .*
************************************************************************/
/*----------------------------------------------------------------------------*/
#include "console/ConsoleMain.hh"
#include "common/StringTokenizer.hh"
/*----------------------------------------------------------------------------*/
#include
#include
#include
#include
extern XrdOucString serveruri;
/* mount/umount via fuse */
int
com_fuse(char* arg1)
{
if (interactive) {
fprintf(stderr,
"error: don't call from an interactive shell - call via 'eos fuse ...'!\n");
global_retc = -1;
return 0;
}
// split subcommands
XrdOucString mountpoint = "";
eos::common::StringTokenizer subtokenizer(arg1);
subtokenizer.GetLine();
XrdOucString cmd = subtokenizer.GetToken();
XrdOucString option = "";
XrdOucString logfile = "";
XrdCl::URL url(serveruri.c_str());
XrdOucString params = "fsname=";
if (url.GetHostName() == "localhost") {
params += "localhost.localdomain";
} else {
params += url.GetHostName().c_str();
}
params += ":";
params += url.GetPath().c_str();
if (wants_help(arg1)) {
goto com_fuse_usage;
}
if ((cmd != "mount") && (cmd != "umount")) {
goto com_fuse_usage;
}
do {
option = subtokenizer.GetToken();
if (!option.length()) {
break;
}
if (option.beginswith("-o")) {
params = subtokenizer.GetToken();
if (!params.length()) {
goto com_fuse_usage;
}
} else {
break;
}
} while (1);
mountpoint = option;
if (!mountpoint.length()) {
goto com_fuse_usage;
}
if (mountpoint.beginswith("-")) {
goto com_fuse_usage;
}
if (!mountpoint.beginswith("/")) {
fprintf(stderr,
"warning: assuming you gave a relative path with respect to current working directory => mountpoint=%s\n",
mountpoint.c_str());
XrdOucString pwd = getenv("PWD");
if (!pwd.endswith("/")) {
pwd += "/";
}
mountpoint.insert(pwd.c_str(), 0);
}
if (cmd == "mount") {
struct stat buf;
struct stat buf2;
if (stat(mountpoint.c_str(), &buf)) {
XrdOucString createdir = "mkdir -p ";
createdir += mountpoint;
createdir += " >& /dev/null";
fprintf(stderr, ".... trying to create ... %s\n", mountpoint.c_str());
int rc = system(createdir.c_str());
if (WEXITSTATUS(rc)) {
fprintf(stderr, "error: creation of mountpoint failed");
}
}
if (stat(mountpoint.c_str(), &buf)) {
fprintf(stderr, "error: cannot create mountpoint %s !\n", mountpoint.c_str());
exit(-1);
} else {
if (buf.st_dev == 19) {
fprintf(stderr, "error: already/still mounted on %s !\n", mountpoint.c_str());
exit(EBUSY);
}
}
#ifdef __APPLE__
params += " -onoappledouble,allow_root,defer_permissions,volname=EOS,iosize=65536,fsname=eos@cern.ch";
#endif
fprintf(stderr, "===> Mountpoint : %s\n", mountpoint.c_str());
fprintf(stderr, "===> Fuse-Options : %s\n", params.c_str());
XrdOucString mount;
mount = "eosxd ";
mount += mountpoint.c_str();
mount += " -o";
mount += params;
fprintf(stderr, "running %s\n", mount.c_str());
#ifdef __APPLE__
mount += " >& /dev/null";
#else
mount += " >& /dev/null";
#endif
int rc = system(mount.c_str());
if (WEXITSTATUS(rc)) {
fprintf(stderr, "error: failed mount, maybe still mounted? Check with "
"df and eventually 'killall eosd'\n");
exit(-1);
}
#ifdef __APPLE__
int cnt = 5;
for (cnt = 5; cnt > 0; cnt--) {
fprintf(stderr, "\r[wait] %i seconds ...", cnt);
fflush(stderr);
sleep(1);
}
fprintf(stderr, "\n");
#endif
bool mountok = false;
// Keep checking for 5 seconds
for (size_t i = 0; i < 50; i++) {
if (stat(mountpoint.c_str(), &buf2) || (buf2.st_ino == buf.st_ino)) {
usleep(100000);
if (i && (!(i % 10))) {
fprintf(stderr, "[check] %zu. time for mount ...\n", i / 10);
}
} else {
mountok = true;
break;
}
}
if (!mountok) {
fprintf(stderr, "error: failed mount, maybe still mounted? Check with "
"df and eventually 'killall eosd'\n");
exit(-1);
} else {
fprintf(stderr, "info: successfully mounted EOS [%s] under %s\n",
serveruri.c_str(), mountpoint.c_str());
}
}
if (cmd == "umount") {
struct stat buf2;
#ifndef __APPLE__
struct stat buf1;
XrdOucString pmount = mountpoint;
if (pmount.endswith("/")) {
pmount.erase(pmount.length() - 1);
}
pmount.erase(pmount.rfind('/'));
int r1 = stat(mountpoint.c_str(), &buf1);
int r2 = stat(pmount.c_str(), &buf2);
if ((r1 || r2) || (buf1.st_dev == buf2.st_dev)) {
fprintf(stderr, "error: there is no eos mount at %s\n", mountpoint.c_str());
exit(-1);
}
#endif
XrdOucString umount;
#ifdef __APPLE__
umount = "umount -f ";
umount += mountpoint.c_str();
umount += " >& /dev/null";
#else
umount = "fusermount -z -u ";
umount += mountpoint.c_str();
#endif
int rc = system(umount.c_str());
if (WEXITSTATUS(rc)) {
fprintf(stderr, "error: umount failed - maybe wasn't mounted?\n");
}
if ((stat(mountpoint.c_str(), &buf2))) {
fprintf(stderr, "error: mount directory disappeared from %s\n",
mountpoint.c_str());
exit(-1);
}
#ifndef __APPLE__
if (buf1.st_ino == buf2.st_ino) {
fprintf(stderr, "error: umount didn't work\n");
exit(-1);
}
#endif
}
exit(0);
com_fuse_usage:
fprintf(stdout,
"usage: fuse mount : mount connected eos instance on \n");
fprintf(stdout,
" fuse umount : unmount eos pool from \n");
exit(-1);
}