// ---------------------------------------------------------------------- // File: com_quota.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 "common/StringTokenizer.hh" #include "console/ConsoleMain.hh" #include #include //------------------------------------------------------------------------------ // Quota System listing, configuration and manipulation //------------------------------------------------------------------------------ int com_quota(char* arg1) { // Split subcommands eos::common::StringTokenizer subtokenizer(arg1); subtokenizer.GetLine(); XrdOucString subcommand = subtokenizer.GetToken(); XrdOucString arg = subtokenizer.GetToken(); bool highlighting = true; if (subcommand == "-m") { subcommand = ""; arg = "-m"; } if (subcommand == "" || subcommand.beginswith("/")) { XrdOucString in = "mgm.cmd=quota&mgm.subcmd=lsuser"; if (subcommand == "") { subcommand = DefaultRoute().c_str(); } if (subcommand.beginswith("/")) { in += "&mgm.quota.space="; in += subcommand; } if (arg == "-m") { in += "&mgm.quota.format=m"; } global_retc = output_result(client_command(in)); return (0); } bool has_space = false; if (wants_help(arg1)) { goto com_quota_usage; } if (subcommand == "ls") { XrdOucString in = "mgm.cmd=quota&mgm.subcmd=ls"; if (arg.length()) do { if ((arg == "--uid") || (arg == "-u")) { XrdOucString uid = subtokenizer.GetToken(); if (!uid.length()) { goto com_quota_usage; } in += "&mgm.quota.uid="; in += uid; arg = subtokenizer.GetToken(); } else if ((arg == "--gid") || (arg == "-g")) { XrdOucString gid = subtokenizer.GetToken(); if (!gid.length()) { goto com_quota_usage; } in += "&mgm.quota.gid="; in += gid; arg = subtokenizer.GetToken(); } else if ((arg == "--path") || (arg == "-p")) { if (has_space) { goto com_quota_usage; } XrdOucString space = subtokenizer.GetToken(); if (space.c_str()) { in += "&mgm.quota.space="; in += space; arg = subtokenizer.GetToken(); has_space = true; } } else if ((arg == "-m")) { in += "&mgm.quota.format=m"; arg = subtokenizer.GetToken(); highlighting = false; } else if ((arg == "-n")) { in += "&mgm.quota.printid=n"; arg = subtokenizer.GetToken(); } else { if ((arg.beginswith("/")) && (!has_space)) { in += "&mgm.quota.space="; in += arg; has_space = true; arg = subtokenizer.GetToken(); } else { goto com_quota_usage; } } } while (arg.length()); global_retc = output_result(client_command(in), highlighting); return (0); } if (subcommand == "set") { XrdOucString in = "mgm.cmd=quota&mgm.subcmd=set"; XrdOucString space = "default"; do { if ((arg == "--uid") || (arg == "-u")) { XrdOucString uid = subtokenizer.GetToken(); if (!uid.length()) { goto com_quota_usage; } in += "&mgm.quota.uid="; in += uid; arg = subtokenizer.GetToken(); } else if ((arg == "--gid") || (arg == "-g")) { XrdOucString gid = subtokenizer.GetToken(); if (!gid.length()) { goto com_quota_usage; } in += "&mgm.quota.gid="; in += gid; arg = subtokenizer.GetToken(); } else if ((arg == "--path") || (arg == "-p")) { if (has_space) { goto com_quota_usage; } space = subtokenizer.GetToken(); if (!space.length()) { goto com_quota_usage; } in += "&mgm.quota.space="; in += space; arg = subtokenizer.GetToken(); has_space = true; } else if ((arg == "--volume") || (arg == "-v")) { XrdOucString bytes = subtokenizer.GetToken(); if (!bytes.length()) { goto com_quota_usage; } in += "&mgm.quota.maxbytes="; in += bytes; arg = subtokenizer.GetToken(); } else if ((arg == "--inodes") || (arg == "-i")) { XrdOucString inodes = subtokenizer.GetToken(); if (!inodes.length()) { goto com_quota_usage; } in += "&mgm.quota.maxinodes="; in += inodes; arg = subtokenizer.GetToken(); } else { if ((arg.beginswith("/")) && (!has_space)) { in += "&mgm.quota.space="; in += arg; has_space = true; arg = subtokenizer.GetToken(); } else { goto com_quota_usage; } } } while (arg.length()); global_retc = output_result(client_command(in)); return (0); } if (subcommand == "rm") { XrdOucString in = "mgm.cmd=quota&mgm.subcmd=rm"; do { if ((arg == "--uid") || (arg == "-u")) { XrdOucString uid = subtokenizer.GetToken(); if (!uid.length()) { goto com_quota_usage; } in += "&mgm.quota.uid="; in += uid; arg = subtokenizer.GetToken(); } else if ((arg == "--gid") || (arg == "-g")) { XrdOucString gid = subtokenizer.GetToken(); if (!gid.length()) { goto com_quota_usage; } in += "&mgm.quota.gid="; in += gid; arg = subtokenizer.GetToken(); } else if ((arg == "--path") || (arg == "-p")) { if (has_space) { goto com_quota_usage; } XrdOucString space = subtokenizer.GetToken(); if (!space.length()) { goto com_quota_usage; } in += "&mgm.quota.space="; in += space; arg = subtokenizer.GetToken(); has_space = true; } else if ((arg == "--inode") || (arg == "-i")) { in += "&mgm.quota.type=inode"; arg = subtokenizer.GetToken(); } else if ((arg == "--volume") || (arg == "-v")) { in += "&mgm.quota.type=volume"; arg = subtokenizer.GetToken(); } else { if ((arg.beginswith("/")) && (!has_space)) { in += "&mgm.quota.space="; in += arg; has_space = true; arg = subtokenizer.GetToken(); } else { goto com_quota_usage; } } } while (arg.length()); global_retc = output_result(client_command(in)); return (0); } if (subcommand == "rmnode") { XrdOucString in = "mgm.cmd=quota&mgm.subcmd=rmnode"; XrdOucString space = ""; bool dontask = false; do { if (arg == "--really-want") { fprintf(stderr,"arg: %s\n", arg.c_str()); arg = subtokenizer.GetToken(); fprintf(stderr,"arg: %s\n", arg.c_str()); dontask = true; continue; } if ((arg == "--path") || (arg == "-p")) { space = subtokenizer.GetToken(); if (!space.length()) { goto com_quota_usage; } in += "&mgm.quota.space="; in += space; arg = subtokenizer.GetToken(); } else { goto com_quota_usage; } } while (arg.length()); if (!space.length()) { goto com_quota_usage; } std::string s; std::string sconfirmation; if (!dontask) { fprintf(stdout, "Do you really want to delete the quota node under path %s?\n", space.c_str()); fprintf(stdout, "Confirm the deletion by typing => "); XrdOucString confirmation = ""; for (int i = 0; i < 10; i++) { // coverity[DC.WEAK_CRYPTO] confirmation += (int)(9.0 * rand() / RAND_MAX); } fprintf(stdout, "%s\n", confirmation.c_str()); fprintf(stdout, " => "); getline(std::cin, s); sconfirmation = confirmation.c_str(); } if (s == sconfirmation) { fprintf(stdout, "\nSending deletion request to server ...\n"); global_retc = output_result(client_command(in, true)); } else { fprintf(stdout, "\nDeletion aborted!\n"); global_retc = -1; } return 0; } com_quota_usage: std::ostringstream oss; std::vector col_size = {0, 0}; std::map map_cmds = { { "quota []", ": show personal quota for all or only the quota node responsible for " }, { "quota ls [-n] [-m] [-u ] [-g ] [ [-p] ]", ": list configured quota and quota node(s)" }, { "quota set -u |-g [-v ] [-i ] [-p] ", ": set volume and/or inode quota by uid or gid" }, { "quota rm -u |-g [-v] [-i] [-p] ", ": remove configured quota type(s) for uid/gid in path" }, { "quota rmnode -p ", ": remove quota node and every defined quota on that node" } }; // Compute max width for command and description table for (auto it = map_cmds.begin(); it != map_cmds.end(); ++it) { if (col_size[0] < it->first.length()) { col_size[0] = it->first.length() + 1; } if (col_size[1] < it->second.length()) { col_size[1] = it->second.length() + 1; } } std::int8_t tab_size = 2; std::string usage_txt = "Usage:"; std::string opt_txt = "General options:"; std::string notes_txt = "Notes:"; oss << usage_txt << std::endl; // Print the command and their description for (auto it = map_cmds.begin(); it != map_cmds.end(); ++it) { oss << std::setw(usage_txt.length()) << "" << std::setw(col_size[0]) << std::setiosflags(std::ios_base::left) << it->first << std::setw(col_size[1]) << std::setiosflags(std::ios_base::left) << it->second << std::endl; } std::uint32_t indent_len = usage_txt.length() + tab_size; // Print general options oss << std::endl << std::setw(usage_txt.length()) << "" << opt_txt << std::endl << std::setw(indent_len) << "" << "-m : print information in monitoring = format" << std::endl << std::setw(indent_len) << "" << "-n : don't translate ids, print uid and gid number" << std::endl << std::setw(indent_len) << "" << "-u/--uid : print information only for uid " << std::endl << std::setw(indent_len) << "" << "-g/--gid : print information only for gid " << std::endl << std::setw(indent_len) << "" << "-p/--path : print information only for path - this " << "can also be given without -p or --path" << std::endl << std::setw(indent_len) << "" << "-v/--volume : refer to volume limit in " << std::endl << std::setw(indent_len) << "" << "-i/--inodes : refer to inode limit in number of " << std::endl; indent_len = usage_txt.length() + tab_size; // Print extra notes oss << std::endl << std::setw(usage_txt.length()) << "" << notes_txt << std::endl << std::setw(indent_len) << "" << "=> you have to specify either the user or the group identified by the " << "unix id or the user/group name" << std::endl << std::setw(indent_len) << "" << "=> the space argument is by default assumed as 'default'" << std::endl << std::setw(indent_len) << "" << "=> you have to specify at least a volume or an inode limit to set quota" << std::endl << std::setw(indent_len) << "" << "=> for convenience all commands can just use as last argument " << "ommitting the -p|--path e.g. quota ls /eos/ ..." << std::endl << std::setw(indent_len) << "" << "=> if is not terminated with a '/' it is assumed to be a file " << "so it won't match the quota node with / !" << std::endl; fprintf(stdout, "%s", oss.str().c_str()); global_retc = EINVAL; return 0; }