mirror of
https://github.com/NixOS/nix.git
synced 2025-11-12 05:26:02 +01:00
Instead of running the builds under
`$TMPDIR/{unique-build-directory-owned-by-the-build-user}`, run them
under `$TMPDIR/{unique-build-directory-owned-by-the-daemon}/{subdir-owned-by-the-build-user}`
where the build directory is only readable and traversable by the daemon user.
This achieves two things:
1. It prevents builders from making their build directory world-readable
(or even writeable), which would allow the outside world to interact
with them.
2. It prevents external processes running as the build user (either
because that somehow leaked, maybe as a consequence of 1., or because
`build-users` isn't in use) from gaining access to the build
directory.
(cherry picked from commit 1d3696f0fb)
273 lines
6.5 KiB
C++
273 lines
6.5 KiB
C++
#pragma once
|
|
/**
|
|
* @file
|
|
*
|
|
* Utiltities for working with the file sytem and file paths.
|
|
*/
|
|
|
|
#include "types.hh"
|
|
#include "error.hh"
|
|
#include "logging.hh"
|
|
#include "file-descriptor.hh"
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <dirent.h>
|
|
#include <unistd.h>
|
|
#ifdef _WIN32
|
|
# include <windef.h>
|
|
#endif
|
|
#include <signal.h>
|
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
#include <atomic>
|
|
#include <functional>
|
|
#include <map>
|
|
#include <sstream>
|
|
#include <optional>
|
|
|
|
#ifndef HAVE_STRUCT_DIRENT_D_TYPE
|
|
#define DT_UNKNOWN 0
|
|
#define DT_REG 1
|
|
#define DT_LNK 2
|
|
#define DT_DIR 3
|
|
#endif
|
|
|
|
/**
|
|
* Polyfill for MinGW
|
|
*
|
|
* Windows does in fact support symlinks, but the C runtime interfaces predate this.
|
|
*
|
|
* @todo get rid of this, and stop using `stat` when we want `lstat` too.
|
|
*/
|
|
#ifndef S_ISLNK
|
|
# define S_ISLNK(m) false
|
|
#endif
|
|
|
|
namespace nix {
|
|
|
|
struct Sink;
|
|
struct Source;
|
|
|
|
/**
|
|
* @return An absolutized path, resolving paths relative to the
|
|
* specified directory, or the current directory otherwise. The path
|
|
* is also canonicalised.
|
|
*/
|
|
Path absPath(PathView path,
|
|
std::optional<PathView> dir = {},
|
|
bool resolveSymlinks = false);
|
|
|
|
/**
|
|
* Canonicalise a path by removing all `.` or `..` components and
|
|
* double or trailing slashes. Optionally resolves all symlink
|
|
* components such that each component of the resulting path is *not*
|
|
* a symbolic link.
|
|
*/
|
|
Path canonPath(PathView path, bool resolveSymlinks = false);
|
|
|
|
/**
|
|
* @return The directory part of the given canonical path, i.e.,
|
|
* everything before the final `/`. If the path is the root or an
|
|
* immediate child thereof (e.g., `/foo`), this means `/`
|
|
* is returned.
|
|
*/
|
|
Path dirOf(const PathView path);
|
|
|
|
/**
|
|
* @return the base name of the given canonical path, i.e., everything
|
|
* following the final `/` (trailing slashes are removed).
|
|
*/
|
|
std::string_view baseNameOf(std::string_view path);
|
|
|
|
/**
|
|
* Check whether 'path' is a descendant of 'dir'. Both paths must be
|
|
* canonicalized.
|
|
*/
|
|
bool isInDir(std::string_view path, std::string_view dir);
|
|
|
|
/**
|
|
* Check whether 'path' is equal to 'dir' or a descendant of
|
|
* 'dir'. Both paths must be canonicalized.
|
|
*/
|
|
bool isDirOrInDir(std::string_view path, std::string_view dir);
|
|
|
|
/**
|
|
* Get status of `path`.
|
|
*/
|
|
struct stat stat(const Path & path);
|
|
struct stat lstat(const Path & path);
|
|
/**
|
|
* `lstat` the given path if it exists.
|
|
* @return std::nullopt if the path doesn't exist, or an optional containing the result of `lstat` otherwise
|
|
*/
|
|
std::optional<struct stat> maybeLstat(const Path & path);
|
|
|
|
/**
|
|
* @return true iff the given path exists.
|
|
*/
|
|
bool pathExists(const Path & path);
|
|
|
|
/**
|
|
* A version of pathExists that returns false on a permission error.
|
|
* Useful for inferring default paths across directories that might not
|
|
* be readable.
|
|
* @return true iff the given path can be accessed and exists
|
|
*/
|
|
bool pathAccessible(const Path & path);
|
|
|
|
/**
|
|
* Read the contents (target) of a symbolic link. The result is not
|
|
* in any way canonicalised.
|
|
*/
|
|
Path readLink(const Path & path);
|
|
|
|
bool isLink(const Path & path);
|
|
|
|
/**
|
|
* Read the contents of a directory. The entries `.` and `..` are
|
|
* removed.
|
|
*/
|
|
struct DirEntry
|
|
{
|
|
std::string name;
|
|
ino_t ino;
|
|
/**
|
|
* one of DT_*
|
|
*/
|
|
unsigned char type;
|
|
DirEntry(std::string name, ino_t ino, unsigned char type)
|
|
: name(std::move(name)), ino(ino), type(type) { }
|
|
};
|
|
|
|
typedef std::vector<DirEntry> DirEntries;
|
|
|
|
DirEntries readDirectory(const Path & path);
|
|
|
|
unsigned char getFileType(const Path & path);
|
|
|
|
/**
|
|
* Read the contents of a file into a string.
|
|
*/
|
|
std::string readFile(const Path & path);
|
|
void readFile(const Path & path, Sink & sink);
|
|
|
|
/**
|
|
* Write a string to a file.
|
|
*/
|
|
void writeFile(const Path & path, std::string_view s, mode_t mode = 0666, bool sync = false);
|
|
|
|
void writeFile(const Path & path, Source & source, mode_t mode = 0666, bool sync = false);
|
|
|
|
/**
|
|
* Flush a file's parent directory to disk
|
|
*/
|
|
void syncParent(const Path & path);
|
|
|
|
/**
|
|
* Delete a path; i.e., in the case of a directory, it is deleted
|
|
* recursively. It's not an error if the path does not exist. The
|
|
* second variant returns the number of bytes and blocks freed.
|
|
*/
|
|
void deletePath(const Path & path);
|
|
|
|
void deletePath(const Path & path, uint64_t & bytesFreed);
|
|
|
|
/**
|
|
* Create a directory and all its parents, if necessary. Returns the
|
|
* list of created directories, in order of creation.
|
|
*/
|
|
Paths createDirs(const Path & path);
|
|
inline Paths createDirs(PathView path)
|
|
{
|
|
return createDirs(Path(path));
|
|
}
|
|
|
|
/**
|
|
* Create a single directory.
|
|
*/
|
|
void createDir(const Path & path, mode_t mode = 0755);
|
|
|
|
/**
|
|
* Create a symlink.
|
|
*/
|
|
void createSymlink(const Path & target, const Path & link);
|
|
|
|
/**
|
|
* Atomically create or replace a symlink.
|
|
*/
|
|
void replaceSymlink(const Path & target, const Path & link);
|
|
|
|
void renameFile(const Path & src, const Path & dst);
|
|
|
|
/**
|
|
* Similar to 'renameFile', but fallback to a copy+remove if `src` and `dst`
|
|
* are on a different filesystem.
|
|
*
|
|
* Beware that this might not be atomic because of the copy that happens behind
|
|
* the scenes
|
|
*/
|
|
void moveFile(const Path & src, const Path & dst);
|
|
|
|
/**
|
|
* Recursively copy the content of `oldPath` to `newPath`. If `andDelete` is
|
|
* `true`, then also remove `oldPath` (making this equivalent to `moveFile`, but
|
|
* with the guaranty that the destination will be “fresh”, with no stale inode
|
|
* or file descriptor pointing to it).
|
|
*/
|
|
void copyFile(const Path & oldPath, const Path & newPath, bool andDelete);
|
|
|
|
/**
|
|
* Automatic cleanup of resources.
|
|
*/
|
|
class AutoDelete
|
|
{
|
|
Path path;
|
|
bool del;
|
|
bool recursive;
|
|
public:
|
|
AutoDelete();
|
|
AutoDelete(const Path & p, bool recursive = true);
|
|
~AutoDelete();
|
|
void cancel();
|
|
void reset(const Path & p, bool recursive = true);
|
|
operator Path() const { return path; }
|
|
operator PathView() const { return path; }
|
|
};
|
|
|
|
|
|
struct DIRDeleter
|
|
{
|
|
void operator()(DIR * dir) const {
|
|
closedir(dir);
|
|
}
|
|
};
|
|
|
|
typedef std::unique_ptr<DIR, DIRDeleter> AutoCloseDir;
|
|
|
|
|
|
/**
|
|
* Create a temporary directory.
|
|
*/
|
|
Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
|
|
bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755);
|
|
|
|
/**
|
|
* Create a temporary file, returning a file handle and its path.
|
|
*/
|
|
std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix = "nix");
|
|
|
|
/**
|
|
* Return `TMPDIR`, or the default temporary directory if unset or empty.
|
|
*/
|
|
Path defaultTempDir();
|
|
|
|
/**
|
|
* Used in various places.
|
|
*/
|
|
typedef std::function<bool(const Path & path)> PathFilter;
|
|
|
|
extern PathFilter defaultPathFilter;
|
|
|
|
}
|