Files
rtorrent/src/utils/lockfile.cc
T
Bryant Eadon 00ef7d4be2 cleanup of personal information
Given the change to the README I thought it might be a good idea to also update the copyright notices which had an address too.
2025-09-02 20:10:38 +02:00

163 lines
3.9 KiB
C++

// rTorrent - BitTorrent client
// Copyright (C) 2005-2011, Jari Sundell
//
// 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 2 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, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations
// including the two.
//
// You must obey the GNU General Public License in all respects for
// all of the code used other than OpenSSL. If you modify file(s)
// with this exception, you may extend this exception to your version
// of the file(s), but you are not obligated to do so. If you do not
// wish to do so, delete this exception statement from your version.
// If you delete this exception statement from all source files in the
// program, then also delete it here.
//
// Contact: Jari Sundell <sundell.software@gmail.com>
#include "config.h"
#include <algorithm>
#include <cctype>
#include <cerrno>
#include <cstring>
#include <cstdio>
#include <sstream>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "lockfile.h"
namespace utils {
struct lockfile_valid_char {
bool operator () (char c) {
return !std::isgraph(c);
}
};
struct lockfile_valid_hostname {
bool operator () (char c) {
return !std::isgraph(c) || c == ':';
}
};
bool
Lockfile::is_stale() {
process_type process = locked_by();
char buf[256];
if (process.second <= 0 ||
::gethostname(buf, 255) != 0 || buf != process.first)
return false;
return ::kill(process.second, 0) != 0 && errno != EPERM;
}
bool
Lockfile::try_lock() {
if (m_path.empty()) {
m_locked = true;
return true;
}
if (is_stale())
::unlink(m_path.c_str());
// Just do a simple locking for now that isn't safe for network
// devices.
int fd = ::open(m_path.c_str(), O_RDWR | O_CREAT | O_EXCL, 0444);
if (fd == -1)
return false;
char buf[256];
int pos = ::gethostname(buf, 255);
if (pos == 0) {
ssize_t len = std::strlen(buf);
::snprintf(buf + len, 255 - len, ":+%i\n", ::getpid());
[[maybe_unused]] int result = ::write(fd, buf, std::strlen(buf));
}
::close(fd);
m_locked = true;
return true;
}
bool
Lockfile::unlock() {
m_locked = false;
if (m_path.empty())
return true;
else
return ::unlink(m_path.c_str()) != -1;
}
Lockfile::process_type
Lockfile::locked_by() const {
int fd = ::open(m_path.c_str(), O_RDONLY);
if (fd < 0)
return process_type(std::string(), 0);
char first[256];
char* last = first + std::max<ssize_t>(read(fd, first, 255), 0);
*last = '\0';
::close(fd);
char* endHostname = std::find_if(first, last, lockfile_valid_hostname());
char* beginPid = endHostname;
char* endPid;
long long int pid;
if (beginPid + 2 >= last ||
*(beginPid++) != ':' ||
*(beginPid++) != '+' ||
(pid = strtoll(beginPid, &endPid, 10)) == 0 ||
endPid == NULL)
return process_type(std::string(), 0);
return process_type(std::string(first, endHostname), pid);
}
std::string
Lockfile::locked_by_as_string() const {
process_type p = locked_by();
if (p.first.empty())
return "<error>";
std::stringstream str;
str << p.first << ":+" << p.second;
return str.str();
}
}