/******************************************************************************* * Copyright 2019 UChicago Argonne, LLC. * (c.f. AUTHORS, LICENSE) * * This file is part of the Argo containers project. * For more info, see https://xgitlab.cels.anl.gov/argo/containers * * SPDX-License-Identifier: BSD-3-Clause *******************************************************************************/ #include "resource_locker.hpp" #include "utils.hpp" #include "common.hpp" #include "ilogger.hpp" #include #include #include #include #include #include #include "trace.hpp" Resource_locker::Resource_locker(const string& filename, const string& path): _locked(false), _pid(getpid()) { ACTIVATE_TRACE_MASK(RESOURCE_LOCKER_MASK); elevate_privileges(); int status = mkdir(path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IWOTH); if(status !=0 && errno != EEXIST) { argo_exit(EXIT_FAILURE, "Failure to create " + path); } string fname = path; if(fname[fname.size() - 1] != '/') fname += '/'; fname += filename; TRACE_LOC_ON_MASK(RESOURCE_LOCKER_MASK, "euid = %d; ruid = %d\n", geteuid(), getuid()); _fd = open(fname.c_str(), O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); if(_fd == -1) { argo_exit(EXIT_FAILURE, "Failure to open " + filename); } lower_privileges(); } Resource_locker::~Resource_locker() { unlock(); close(_fd); } void Resource_locker::lock() { elevate_privileges(); TRACE_LOC_ON_MASK(RESOURCE_LOCKER_MASK, "[%d] About to lock\n", _pid); if(flock(_fd, LOCK_EX)) { argo_exit(EXIT_FAILURE, "flock failed"); } _locked = true; TRACE_LOC_ON_MASK(RESOURCE_LOCKER_MASK, "[%d] Got lock\n", _pid); lower_privileges(); } void Resource_locker::unlock() { TRACE_LOC_ON_MASK(RESOURCE_LOCKER_MASK, "[%d] About to unlock\n", _pid); if(!_locked) { TRACE_LOC_ON_MASK(RESOURCE_LOCKER_MASK, "[%d] Did not unlock because the lock was not held\n", _pid); return; } elevate_privileges(); if(flock(_fd, LOCK_UN) != 0) { argo_exit(EXIT_FAILURE, "flock failed"); } lower_privileges(); _locked = false; TRACE_LOC_ON_MASK(RESOURCE_LOCKER_MASK, "[%d] Unlocked\n", _pid); } bool Resource_locker::trylock() { elevate_privileges(); TRACE_LOC_ON_MASK(RESOURCE_LOCKER_MASK, "[%d] About to try locking\n", _pid); int status = flock(_fd, LOCK_EX|LOCK_NB); lower_privileges(); if(status == 0) { _locked = true; TRACE_LOC_ON_MASK(RESOURCE_LOCKER_MASK, "[%d] Got lock\n", _pid); return true; } else if(errno == EWOULDBLOCK) { TRACE_LOC_ON_MASK(RESOURCE_LOCKER_MASK, "[%d] Couldn't got lock\n", _pid); return false; } else { argo_exit(EXIT_FAILURE, "flock failed"); } return false; //will never reach here }