Remove unused files linux.cc/.h and linuxfdwalk.c/.h.
BUG=none Review-Url: https://codereview.webrtc.org/2508803011 Cr-Commit-Position: refs/heads/master@{#15159}
This commit is contained in:
parent
2184155782
commit
3898944d32
@ -468,13 +468,7 @@ if (rtc_include_tests) {
|
||||
]
|
||||
|
||||
if (is_linux) {
|
||||
sources += [
|
||||
"base/latebindingsymboltable_unittest.cc",
|
||||
|
||||
# TODO(ronghuawu): Reenable this test.
|
||||
# "linux_unittest.cc",
|
||||
"base/linuxfdwalk_unittest.cc",
|
||||
]
|
||||
sources += [ "base/latebindingsymboltable_unittest.cc" ]
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
|
||||
@ -559,13 +559,6 @@ rtc_static_library("rtc_base") {
|
||||
"window.h",
|
||||
]
|
||||
|
||||
if (is_linux) {
|
||||
sources += [
|
||||
"linuxfdwalk.c",
|
||||
"linuxfdwalk.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_posix) {
|
||||
sources += [
|
||||
"latebindingsymboltable.cc",
|
||||
@ -699,13 +692,6 @@ rtc_static_library("rtc_base") {
|
||||
}
|
||||
}
|
||||
|
||||
if (is_linux || is_android) {
|
||||
sources += [
|
||||
"linux.cc",
|
||||
"linux.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_nacl) {
|
||||
deps += [ "//native_client_sdk/src/libraries/nacl_io" ]
|
||||
defines += [ "timezone=_timezone" ]
|
||||
|
||||
@ -1,264 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#if defined(WEBRTC_LINUX)
|
||||
#include "webrtc/base/linux.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <set>
|
||||
|
||||
#include "webrtc/base/stringencode.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
static const char kCpuInfoFile[] = "/proc/cpuinfo";
|
||||
static const char kCpuMaxFreqFile[] =
|
||||
"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
|
||||
|
||||
ProcCpuInfo::ProcCpuInfo() {
|
||||
}
|
||||
|
||||
ProcCpuInfo::~ProcCpuInfo() {
|
||||
}
|
||||
|
||||
bool ProcCpuInfo::LoadFromSystem() {
|
||||
ConfigParser procfs;
|
||||
if (!procfs.Open(kCpuInfoFile)) {
|
||||
return false;
|
||||
}
|
||||
return procfs.Parse(§ions_);
|
||||
};
|
||||
|
||||
bool ProcCpuInfo::GetSectionCount(size_t* count) {
|
||||
if (sections_.empty()) {
|
||||
return false;
|
||||
}
|
||||
if (count) {
|
||||
*count = sections_.size();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProcCpuInfo::GetNumCpus(int* num) {
|
||||
if (sections_.empty()) {
|
||||
return false;
|
||||
}
|
||||
int total_cpus = 0;
|
||||
#if defined(__arm__)
|
||||
// Count the number of blocks that have a "processor" key defined. On ARM,
|
||||
// there may be extra blocks of information that aren't per-processor.
|
||||
size_t section_count = sections_.size();
|
||||
for (size_t i = 0; i < section_count; ++i) {
|
||||
int processor_id;
|
||||
if (GetSectionIntValue(i, "processor", &processor_id)) {
|
||||
++total_cpus;
|
||||
}
|
||||
}
|
||||
// Single core ARM systems don't include "processor" keys at all, so return
|
||||
// that we have a single core if we didn't find any explicitly above.
|
||||
if (total_cpus == 0) {
|
||||
total_cpus = 1;
|
||||
}
|
||||
#else
|
||||
// On X86, there is exactly one info section per processor.
|
||||
total_cpus = static_cast<int>(sections_.size());
|
||||
#endif
|
||||
if (num) {
|
||||
*num = total_cpus;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProcCpuInfo::GetNumPhysicalCpus(int* num) {
|
||||
if (sections_.empty()) {
|
||||
return false;
|
||||
}
|
||||
// TODO: /proc/cpuinfo only reports cores that are currently
|
||||
// _online_, so this may underreport the number of physical cores.
|
||||
#if defined(__arm__)
|
||||
// ARM (currently) has no hyperthreading, so just return the same value
|
||||
// as GetNumCpus.
|
||||
return GetNumCpus(num);
|
||||
#else
|
||||
int total_cores = 0;
|
||||
std::set<int> physical_ids;
|
||||
size_t section_count = sections_.size();
|
||||
for (size_t i = 0; i < section_count; ++i) {
|
||||
int physical_id;
|
||||
int cores;
|
||||
// Count the cores for the physical id only if we have not counted the id.
|
||||
if (GetSectionIntValue(i, "physical id", &physical_id) &&
|
||||
GetSectionIntValue(i, "cpu cores", &cores) &&
|
||||
physical_ids.find(physical_id) == physical_ids.end()) {
|
||||
physical_ids.insert(physical_id);
|
||||
total_cores += cores;
|
||||
}
|
||||
}
|
||||
|
||||
if (num) {
|
||||
*num = total_cores;
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ProcCpuInfo::GetCpuFamily(int* id) {
|
||||
int cpu_family = 0;
|
||||
|
||||
#if defined(__arm__)
|
||||
// On some ARM platforms, there is no 'cpu family' in '/proc/cpuinfo'. But
|
||||
// there is 'CPU Architecture' which can be used as 'cpu family'.
|
||||
// See http://en.wikipedia.org/wiki/ARM_architecture for a good list of
|
||||
// ARM cpu families, architectures, and their mappings.
|
||||
// There may be multiple sessions that aren't per-processor. We need to scan
|
||||
// through each session until we find the first 'CPU architecture'.
|
||||
size_t section_count = sections_.size();
|
||||
for (size_t i = 0; i < section_count; ++i) {
|
||||
if (GetSectionIntValue(i, "CPU architecture", &cpu_family)) {
|
||||
// We returns the first one (if there are multiple entries).
|
||||
break;
|
||||
};
|
||||
}
|
||||
#else
|
||||
GetSectionIntValue(0, "cpu family", &cpu_family);
|
||||
#endif
|
||||
if (id) {
|
||||
*id = cpu_family;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProcCpuInfo::GetSectionStringValue(size_t section_num,
|
||||
const std::string& key,
|
||||
std::string* result) {
|
||||
if (section_num >= sections_.size()) {
|
||||
return false;
|
||||
}
|
||||
ConfigParser::SimpleMap::iterator iter = sections_[section_num].find(key);
|
||||
if (iter == sections_[section_num].end()) {
|
||||
return false;
|
||||
}
|
||||
*result = iter->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProcCpuInfo::GetSectionIntValue(size_t section_num,
|
||||
const std::string& key,
|
||||
int* result) {
|
||||
if (section_num >= sections_.size()) {
|
||||
return false;
|
||||
}
|
||||
ConfigParser::SimpleMap::iterator iter = sections_[section_num].find(key);
|
||||
if (iter == sections_[section_num].end()) {
|
||||
return false;
|
||||
}
|
||||
return FromString(iter->second, result);
|
||||
}
|
||||
|
||||
ConfigParser::ConfigParser() {}
|
||||
|
||||
ConfigParser::~ConfigParser() {}
|
||||
|
||||
bool ConfigParser::Open(const std::string& filename) {
|
||||
FileStream* fs = new FileStream();
|
||||
if (!fs->Open(filename, "r", NULL)) {
|
||||
return false;
|
||||
}
|
||||
instream_.reset(fs);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConfigParser::Attach(StreamInterface* stream) {
|
||||
instream_.reset(stream);
|
||||
}
|
||||
|
||||
bool ConfigParser::Parse(MapVector* key_val_pairs) {
|
||||
// Parses the file and places the found key-value pairs into key_val_pairs.
|
||||
SimpleMap section;
|
||||
while (ParseSection(§ion)) {
|
||||
key_val_pairs->push_back(section);
|
||||
section.clear();
|
||||
}
|
||||
return (!key_val_pairs->empty());
|
||||
}
|
||||
|
||||
bool ConfigParser::ParseSection(SimpleMap* key_val_pair) {
|
||||
// Parses the next section in the filestream and places the found key-value
|
||||
// pairs into key_val_pair.
|
||||
std::string key, value;
|
||||
while (ParseLine(&key, &value)) {
|
||||
(*key_val_pair)[key] = value;
|
||||
}
|
||||
return (!key_val_pair->empty());
|
||||
}
|
||||
|
||||
bool ConfigParser::ParseLine(std::string* key, std::string* value) {
|
||||
// Parses the next line in the filestream and places the found key-value
|
||||
// pair into key and val.
|
||||
std::string line;
|
||||
if ((instream_->ReadLine(&line)) == SR_EOS) {
|
||||
return false;
|
||||
}
|
||||
std::vector<std::string> tokens;
|
||||
if (2 != split(line, ':', &tokens)) {
|
||||
return false;
|
||||
}
|
||||
// Removes whitespace at the end of Key name
|
||||
size_t pos = tokens[0].length() - 1;
|
||||
while ((pos > 0) && isspace(tokens[0][pos])) {
|
||||
pos--;
|
||||
}
|
||||
tokens[0].erase(pos + 1);
|
||||
// Removes whitespace at the start of value
|
||||
pos = 0;
|
||||
while (pos < tokens[1].length() && isspace(tokens[1][pos])) {
|
||||
pos++;
|
||||
}
|
||||
tokens[1].erase(0, pos);
|
||||
*key = tokens[0];
|
||||
*value = tokens[1];
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string ReadLinuxUname() {
|
||||
struct utsname buf;
|
||||
if (uname(&buf) < 0) {
|
||||
LOG_ERR(LS_ERROR) << "Can't call uname()";
|
||||
return std::string();
|
||||
}
|
||||
std::ostringstream sstr;
|
||||
sstr << buf.sysname << " "
|
||||
<< buf.release << " "
|
||||
<< buf.version << " "
|
||||
<< buf.machine;
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
int ReadCpuMaxFreq() {
|
||||
FileStream fs;
|
||||
std::string str;
|
||||
int freq = -1;
|
||||
if (!fs.Open(kCpuMaxFreqFile, "r", NULL) ||
|
||||
SR_SUCCESS != fs.ReadLine(&str) ||
|
||||
!FromString(str, &freq)) {
|
||||
return -1;
|
||||
}
|
||||
return freq;
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // defined(WEBRTC_LINUX)
|
||||
@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_LINUX_H_
|
||||
#define WEBRTC_BASE_LINUX_H_
|
||||
|
||||
#if defined(WEBRTC_LINUX)
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/stream.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// ConfigParser parses a FileStream of an ".ini."-type format into a map.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Sample Usage:
|
||||
// ConfigParser parser;
|
||||
// ConfigParser::MapVector key_val_pairs;
|
||||
// if (parser.Open(inifile) && parser.Parse(&key_val_pairs)) {
|
||||
// for (int section_num=0; i < key_val_pairs.size(); ++section_num) {
|
||||
// std::string val1 = key_val_pairs[section_num][key1];
|
||||
// std::string val2 = key_val_pairs[section_num][key2];
|
||||
// // Do something with valn;
|
||||
// }
|
||||
// }
|
||||
|
||||
class ConfigParser {
|
||||
public:
|
||||
typedef std::map<std::string, std::string> SimpleMap;
|
||||
typedef std::vector<SimpleMap> MapVector;
|
||||
|
||||
ConfigParser();
|
||||
virtual ~ConfigParser();
|
||||
|
||||
virtual bool Open(const std::string& filename);
|
||||
virtual void Attach(StreamInterface* stream);
|
||||
virtual bool Parse(MapVector* key_val_pairs);
|
||||
virtual bool ParseSection(SimpleMap* key_val_pair);
|
||||
virtual bool ParseLine(std::string* key, std::string* value);
|
||||
|
||||
private:
|
||||
std::unique_ptr<StreamInterface> instream_;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// ProcCpuInfo reads CPU info from the /proc subsystem on any *NIX platform.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Sample Usage:
|
||||
// ProcCpuInfo proc_info;
|
||||
// int no_of_cpu;
|
||||
// if (proc_info.LoadFromSystem()) {
|
||||
// std::string out_str;
|
||||
// proc_info.GetNumCpus(&no_of_cpu);
|
||||
// proc_info.GetCpuStringValue(0, "vendor_id", &out_str);
|
||||
// }
|
||||
// }
|
||||
|
||||
class ProcCpuInfo {
|
||||
public:
|
||||
ProcCpuInfo();
|
||||
virtual ~ProcCpuInfo();
|
||||
|
||||
// Reads the proc subsystem's cpu info into memory. If this fails, this
|
||||
// returns false; if it succeeds, it returns true.
|
||||
virtual bool LoadFromSystem();
|
||||
|
||||
// Obtains the number of logical CPU threads and places the value num.
|
||||
virtual bool GetNumCpus(int* num);
|
||||
|
||||
// Obtains the number of physical CPU cores and places the value num.
|
||||
virtual bool GetNumPhysicalCpus(int* num);
|
||||
|
||||
// Obtains the CPU family id.
|
||||
virtual bool GetCpuFamily(int* id);
|
||||
|
||||
// Obtains the number of sections in /proc/cpuinfo, which may be greater
|
||||
// than the number of CPUs (e.g. on ARM)
|
||||
virtual bool GetSectionCount(size_t* count);
|
||||
|
||||
// Looks for the CPU proc item with the given name for the given section
|
||||
// number and places the string value in result.
|
||||
virtual bool GetSectionStringValue(size_t section_num, const std::string& key,
|
||||
std::string* result);
|
||||
|
||||
// Looks for the CPU proc item with the given name for the given section
|
||||
// number and places the int value in result.
|
||||
virtual bool GetSectionIntValue(size_t section_num, const std::string& key,
|
||||
int* result);
|
||||
|
||||
private:
|
||||
ConfigParser::MapVector sections_;
|
||||
};
|
||||
|
||||
// Returns the output of "uname".
|
||||
std::string ReadLinuxUname();
|
||||
|
||||
// Returns the content (int) of
|
||||
// /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
|
||||
// Returns -1 on error.
|
||||
int ReadCpuMaxFreq();
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // defined(WEBRTC_LINUX)
|
||||
#endif // WEBRTC_BASE_LINUX_H_
|
||||
@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "webrtc/base/linux.h"
|
||||
#include "webrtc/base/fileutils.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/base/gunit.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// These tests running on ARM are fairly specific to the output of the tegra2
|
||||
// ARM processor, and so may fail on other ARM-based systems.
|
||||
TEST(ProcCpuInfo, GetProcInfo) {
|
||||
ProcCpuInfo proc_info;
|
||||
EXPECT_TRUE(proc_info.LoadFromSystem());
|
||||
|
||||
int out_cpus = 0;
|
||||
EXPECT_TRUE(proc_info.GetNumCpus(&out_cpus));
|
||||
LOG(LS_INFO) << "GetNumCpus: " << out_cpus;
|
||||
EXPECT_GT(out_cpus, 0);
|
||||
|
||||
int out_cpus_phys = 0;
|
||||
EXPECT_TRUE(proc_info.GetNumPhysicalCpus(&out_cpus_phys));
|
||||
LOG(LS_INFO) << "GetNumPhysicalCpus: " << out_cpus_phys;
|
||||
EXPECT_GT(out_cpus_phys, 0);
|
||||
EXPECT_LE(out_cpus_phys, out_cpus);
|
||||
|
||||
int out_family = 0;
|
||||
EXPECT_TRUE(proc_info.GetCpuFamily(&out_family));
|
||||
LOG(LS_INFO) << "cpu family: " << out_family;
|
||||
EXPECT_GE(out_family, 4);
|
||||
|
||||
#if defined(__arm__)
|
||||
std::string out_processor;
|
||||
EXPECT_TRUE(proc_info.GetSectionStringValue(0, "Processor", &out_processor));
|
||||
LOG(LS_INFO) << "Processor: " << out_processor;
|
||||
EXPECT_NE(std::string::npos, out_processor.find("ARM"));
|
||||
|
||||
// Most other info, such as model, stepping, vendor, etc.
|
||||
// is missing on ARM systems.
|
||||
#else
|
||||
int out_model = 0;
|
||||
EXPECT_TRUE(proc_info.GetSectionIntValue(0, "model", &out_model));
|
||||
LOG(LS_INFO) << "model: " << out_model;
|
||||
|
||||
int out_stepping = 0;
|
||||
EXPECT_TRUE(proc_info.GetSectionIntValue(0, "stepping", &out_stepping));
|
||||
LOG(LS_INFO) << "stepping: " << out_stepping;
|
||||
|
||||
int out_processor = 0;
|
||||
EXPECT_TRUE(proc_info.GetSectionIntValue(0, "processor", &out_processor));
|
||||
LOG(LS_INFO) << "processor: " << out_processor;
|
||||
EXPECT_EQ(0, out_processor);
|
||||
|
||||
std::string out_str;
|
||||
EXPECT_TRUE(proc_info.GetSectionStringValue(0, "vendor_id", &out_str));
|
||||
LOG(LS_INFO) << "vendor_id: " << out_str;
|
||||
EXPECT_FALSE(out_str.empty());
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(ConfigParser, ParseConfig) {
|
||||
ConfigParser parser;
|
||||
MemoryStream *test_stream = new MemoryStream(
|
||||
"Key1: Value1\n"
|
||||
"Key2\t: Value2\n"
|
||||
"Key3:Value3\n"
|
||||
"\n"
|
||||
"Key1:Value1\n");
|
||||
ConfigParser::MapVector key_val_pairs;
|
||||
parser.Attach(test_stream);
|
||||
EXPECT_EQ(true, parser.Parse(&key_val_pairs));
|
||||
EXPECT_EQ(2U, key_val_pairs.size());
|
||||
EXPECT_EQ("Value1", key_val_pairs[0]["Key1"]);
|
||||
EXPECT_EQ("Value2", key_val_pairs[0]["Key2"]);
|
||||
EXPECT_EQ("Value3", key_val_pairs[0]["Key3"]);
|
||||
EXPECT_EQ("Value1", key_val_pairs[1]["Key1"]);
|
||||
key_val_pairs.clear();
|
||||
EXPECT_EQ(true, parser.Open("/proc/cpuinfo"));
|
||||
EXPECT_EQ(true, parser.Parse(&key_val_pairs));
|
||||
}
|
||||
|
||||
TEST(ReadLinuxUname, ReturnsSomething) {
|
||||
std::string str = ReadLinuxUname();
|
||||
EXPECT_FALSE(str.empty());
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "webrtc/base/linuxfdwalk.h"
|
||||
|
||||
// Parses a file descriptor number in base 10, requiring the strict format used
|
||||
// in /proc/*/fd. Returns the value, or -1 if not a valid string.
|
||||
static int parse_fd(const char *s) {
|
||||
if (!*s) {
|
||||
// Empty string is invalid.
|
||||
return -1;
|
||||
}
|
||||
int val = 0;
|
||||
do {
|
||||
if (*s < '0' || *s > '9') {
|
||||
// Non-numeric characters anywhere are invalid.
|
||||
return -1;
|
||||
}
|
||||
int digit = *s++ - '0';
|
||||
val = val * 10 + digit;
|
||||
} while (*s);
|
||||
return val;
|
||||
}
|
||||
|
||||
int fdwalk(void (*func)(void *, int), void *opaque) {
|
||||
DIR *dir = opendir("/proc/self/fd");
|
||||
if (!dir) {
|
||||
return -1;
|
||||
}
|
||||
int opendirfd = dirfd(dir);
|
||||
int parse_errors = 0;
|
||||
struct dirent *ent;
|
||||
// Have to clear errno to distinguish readdir() completion from failure.
|
||||
while (errno = 0, (ent = readdir(dir)) != NULL) {
|
||||
if (strcmp(ent->d_name, ".") == 0 ||
|
||||
strcmp(ent->d_name, "..") == 0) {
|
||||
continue;
|
||||
}
|
||||
// We avoid atoi or strtol because those are part of libc and they involve
|
||||
// locale stuff, which is probably not safe from a post-fork context in a
|
||||
// multi-threaded app.
|
||||
int fd = parse_fd(ent->d_name);
|
||||
if (fd < 0) {
|
||||
parse_errors = 1;
|
||||
continue;
|
||||
}
|
||||
if (fd != opendirfd) {
|
||||
(*func)(opaque, fd);
|
||||
}
|
||||
}
|
||||
int saved_errno = errno;
|
||||
if (closedir(dir) < 0) {
|
||||
if (!saved_errno) {
|
||||
// Return the closedir error.
|
||||
return -1;
|
||||
}
|
||||
// Else ignore it because we have a more relevant error to return.
|
||||
}
|
||||
if (saved_errno) {
|
||||
errno = saved_errno;
|
||||
return -1;
|
||||
} else if (parse_errors) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_BASE_LINUXFDWALK_H_
|
||||
#define WEBRTC_BASE_LINUXFDWALK_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Linux port of SunOS's fdwalk(3) call. It loops over all open file descriptors
|
||||
// and calls func on each one. Additionally, it is safe to use from the child
|
||||
// of a fork that hasn't exec'ed yet, so you can use it to close all open file
|
||||
// descriptors prior to exec'ing a daemon.
|
||||
// The return value is 0 if successful, or else -1 and errno is set. The
|
||||
// possible errors include any error that can be returned by opendir(),
|
||||
// readdir(), or closedir(), plus EBADF if there are problems parsing the
|
||||
// contents of /proc/self/fd.
|
||||
// The file descriptors that are enumerated will not include the file descriptor
|
||||
// used for the enumeration itself.
|
||||
int fdwalk(void (*func)(void *, int), void *opaque);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // WEBRTC_BASE_LINUXFDWALK_H_
|
||||
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
#include "webrtc/base/gunit.h"
|
||||
#include "webrtc/base/linuxfdwalk.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const int kArbitraryLargeFdNumber = 424;
|
||||
|
||||
static void FdCheckVisitor(void *data, int fd) {
|
||||
std::set<int> *fds = static_cast<std::set<int> *>(data);
|
||||
EXPECT_EQ(1U, fds->erase(fd));
|
||||
}
|
||||
|
||||
static void FdEnumVisitor(void *data, int fd) {
|
||||
std::set<int> *fds = static_cast<std::set<int> *>(data);
|
||||
EXPECT_TRUE(fds->insert(fd).second);
|
||||
}
|
||||
|
||||
// Checks that the set of open fds is exactly the given list.
|
||||
static void CheckOpenFdList(std::set<int> fds) {
|
||||
EXPECT_EQ(0, fdwalk(&FdCheckVisitor, &fds));
|
||||
EXPECT_EQ(0U, fds.size());
|
||||
}
|
||||
|
||||
static void GetOpenFdList(std::set<int> *fds) {
|
||||
fds->clear();
|
||||
EXPECT_EQ(0, fdwalk(&FdEnumVisitor, fds));
|
||||
}
|
||||
|
||||
TEST(LinuxFdWalk, TestFdWalk) {
|
||||
std::set<int> fds;
|
||||
GetOpenFdList(&fds);
|
||||
std::ostringstream str;
|
||||
// I have observed that the open set when starting a test is [0, 6]. Leaked
|
||||
// fds would change that, but so can (e.g.) running under a debugger, so we
|
||||
// can't really do an EXPECT. :(
|
||||
str << "File descriptors open in test executable:";
|
||||
for (std::set<int>::const_iterator i = fds.begin(); i != fds.end(); ++i) {
|
||||
str << " " << *i;
|
||||
}
|
||||
LOG(LS_INFO) << str.str();
|
||||
// Open some files.
|
||||
int fd1 = open("/dev/null", O_RDONLY);
|
||||
EXPECT_LE(0, fd1);
|
||||
int fd2 = open("/dev/null", O_WRONLY);
|
||||
EXPECT_LE(0, fd2);
|
||||
int fd3 = open("/dev/null", O_RDWR);
|
||||
EXPECT_LE(0, fd3);
|
||||
int fd4 = dup2(fd3, kArbitraryLargeFdNumber);
|
||||
EXPECT_LE(0, fd4);
|
||||
EXPECT_TRUE(fds.insert(fd1).second);
|
||||
EXPECT_TRUE(fds.insert(fd2).second);
|
||||
EXPECT_TRUE(fds.insert(fd3).second);
|
||||
EXPECT_TRUE(fds.insert(fd4).second);
|
||||
CheckOpenFdList(fds);
|
||||
EXPECT_EQ(0, close(fd1));
|
||||
EXPECT_EQ(0, close(fd2));
|
||||
EXPECT_EQ(0, close(fd3));
|
||||
EXPECT_EQ(0, close(fd4));
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user