// ----------------------------------------------------------------------
// File: LinuxFds.hh
// Author: Andreas-Joachim Peters - CERN
// ----------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2018 CERN/ASwitzerland *
* *
* 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 .*
************************************************************************/
/**
* @file LinuxFds.hh
*
* @brief Class counting the current filedescriptor usage
*
*/
#ifndef __EOSCOMMON__LINUXFDS__HH
#define __EOSCOMMON__LINUXFDS__HH
#include "common/Namespace.hh"
#include
#include
EOSCOMMONNAMESPACE_BEGIN
/*----------------------------------------------------------------------------*/
//! Static Class to inspect file descriptor usage
//!
//! Example: linux_fds_t fds; GetFdUsage(fds);
//!
/*----------------------------------------------------------------------------*/
class LinuxFds {
public:
typedef struct {
unsigned long long devices,filesystem,sockets,pipes,anon_inode,other,all;
} linux_fds_t;
static bool GetFdUsage(linux_fds_t& result)
{
std::string link_base = "/proc/self/fd/";
const char* fd_path = "/proc/self/fd";
result.devices = result.filesystem = result.sockets =
result.pipes = result. anon_inode, result.other = result.all = 0;
DIR *d = opendir(fd_path);
if (!d) {
perror(fd_path);
return false;
}
struct dirent *dent;
char linkbuffer[4096];
while ((dent = readdir(d)) != NULL) {
std::string link_name = link_base;
link_name += dent->d_name;
ssize_t lsize=0;
if ((lsize = ::readlink(link_name.c_str(), linkbuffer, sizeof(linkbuffer))) > 0) {
result.all++;
std::string target(linkbuffer,lsize);
if (target.substr(0,7) == "socket:") {
result.sockets++;
} else if (target.substr(0,4) == "/dev/") {
result.devices++;
} else if (target.substr(0,1) == "/") {
result.filesystem++;
} else if (target.substr(0,5) == "pipe:") {
result.pipes++;
} else if (target.substr(0,11) == "anon_inode:") {
result.anon_inode++;
} else {
result.other++;
}
} else {
// If we have a forked setuid program, we don't have the permission to resolve symlinks,
// we just count all fds
result.all++;
}
}
closedir(d);
return true;
}
};
EOSCOMMONNAMESPACE_END
#endif