fd-remove-tree.dhover×191all
#!/usr/bin/env dub
/+ dub.sdl:
    name "fd_remove_tree"
    platforms "posix"
    targetPath "build"
    buildType "checked" {
        buildOptions "optimize" "inline" "debugInfo"
    }
+/
/**
 * The `rm -r` shape that Rust's CVE-2022-21658 fix, CPython's `rmtree`
 * (`avoids_symlink_attacks`) and gnulib's `fts` (`FTS_CWDFD`) converged on:
 * recursive deletion through directory *handles*, never through paths.
 *
 * Each directory is opened relative to its parent with `O_NOFOLLOW`, listed
 * with `fdopendir`, and every entry removed with `unlinkat` relative to that
 * handle (`AT_REMOVEDIR` for a subdirectory once it is empty). A symlink is a
 * name to unlink, never a directory to descend — so the demonstration plants
 * a symlink to a directory *outside* the tree and shows that directory's
 * contents survive the removal.
 *
 * Companion to docs/research/safe-path-traversal/rust-std.md
 * § "Dimension 7 — enumeration and deletion".
 *
 * Run with: `dub run --single fd-remove-tree.d`
 */
module 
(module) fd_remove_tree

The rm -r shape that Rust's CVE-2022-21658 fix, CPython's rmtree (avoids_symlink_attacks) and gnulib's fts (FTS_CWDFD) converged on: recursive deletion through directory handles, never through paths.

Each directory is opened relative to its parent with O_NOFOLLOW, listed with fdopendir, and every entry removed with unlinkat relative to that handle (AT_REMOVEDIR for a subdirectory once it is empty). A symlink is a name to unlink, never a directory to descend — so the demonstration plants a symlink to a directory outside the tree and shows that directory's contents survive the removal.

Companion to docs/research/safe-path-traversal/rust-std.md § "Dimension 7 — enumeration and deletion".

Run with: dub run --single fd-remove-tree.d

fd_remove_tree
;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.errno

D header file for C99.

pubs.opengroup.org/onlinepubs/009695399/basedefs/errno.h.html, errno.h

Source

core/stdc/errno.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly, Alex Rønne Petersen@standardsISO/IEC 9899:1999 (E)
errno
:
(alias) fd_remove_tree.errno = int core.stdc.errno.__errno_location() nothrow @nogc ref @trusted
errno
;
import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.posix
posix
.
(module) core.sys.posix.dirent

D header file for POSIX.

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseBoost License 1.0.@authorsSean Kelly, Alex Rønne Petersn@standardsThe Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
dirent
:
(struct) core.sys.posix.dirent.DIR
DIR
,
(alias) fd_remove_tree.closedir = int core.sys.posix.dirent.closedir(core.sys.posix.dirent.DIR*) nothrow @nogc
closedir
,
(struct) core.sys.posix.dirent.dirent
dirent
, readdir;
import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.posix
posix
.
(module) core.sys.posix.fcntl

D header file for POSIX.

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseBoost License 1.0.@authorsSean Kelly, Alex Rønne Petersen@standardsThe Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
fcntl
:
(alias constant) fd_remove_tree.O_RDONLY = int core.sys.posix.fcntl.O_RDONLY = 0
O_RDONLY
,
(alias constant) fd_remove_tree.O_NOFOLLOW = int core.sys.posix.fcntl.O_NOFOLLOW = 131072
O_NOFOLLOW
, open, openat;
// Darwin's druntime `core.sys.posix.fcntl` declares neither; the values are // XNU's `bsd/sys/fcntl.h`. version (
OSX
OSX
)
{ enum O_DIRECTORY = 0x100000; enum O_CLOEXEC = 0x1000000; } else import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.posix
posix
.
(module) core.sys.posix.fcntl

D header file for POSIX.

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseBoost License 1.0.@authorsSean Kelly, Alex Rønne Petersen@standardsThe Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
fcntl
:
(alias constant) fd_remove_tree.O_DIRECTORY = int core.sys.posix.fcntl.O_DIRECTORY = 65536
O_DIRECTORY
,
(alias constant) fd_remove_tree.O_CLOEXEC = int core.sys.posix.fcntl.O_CLOEXEC = 524288
O_CLOEXEC
;
import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.posix
posix
.
(module) core.sys.posix.unistd

D header file for POSIX.

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseBoost License 1.0.@authorsSean Kelly@standardsThe Open Group Base Specifications Issue 8, IEEE Std 1003.1, 2024 Edition
unistd
:
(alias) fd_remove_tree.close = int core.sys.posix.unistd.close(int) nothrow @nogc @trusted
close
;
import
(package) std
std
.
(module) std.conv

A one-stop shop for converting values from one type to another.

Category Functions
Generic asOriginalType castFrom parse to toChars bitCast
Strings text wtext dtext writeText writeWText writeDText hexString
Numeric octal roundTo signed unsigned
Exceptions ConvException ConvOverflowException

Source

std/conv.d

@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Shin Fujishiro, Adam D. Ruppe, Kenji Hara
conv
:
(alias template) fd_remove_tree.text = std.conv.text(T...)(T args) if (T.length > 0)

Convenience functions for converting one or more arguments of any type into text (the three character widths).

text
;
import
(package) std
std
.
(module) std.exception

This module defines functions related to exceptions and general error handling. It also defines functions intended to aid in unit testing.

Category Functions
Assumptions assertNotThrown assertThrown assumeUnique assumeWontThrow mayPointTo
Enforce doesPointTo enforce errnoEnforce
Handlers collectException collectExceptionMsg ifThrown handle
Other basicExceptionCtors emptyExceptionMsg ErrnoException RangePrimitive

Source

std/exception.d

Examples

Synopis

import core.stdc.stdlib : malloc, free;
import std.algorithm.comparison : equal;
import std.algorithm.iteration : map, splitter;
import std.algorithm.searching : endsWith;
import std.conv : ConvException, to;
import std.range : front, retro;

// use enforce like assert
int a = 3;
enforce(a > 2, "a needs to be higher than 2.");

// enforce can throw a custom exception
enforce!ConvException(a > 2, "a needs to be higher than 2.");

// enforce will return it's input
enum size = 42;
auto memory = enforce(malloc(size), "malloc failed")[0 .. size];
scope(exit) free(memory.ptr);

// collectException can be used to test for exceptions
Exception e = collectException("abc".to!int);
assert(e.file.endsWith("conv.d"));

// and just for the exception message
string msg = collectExceptionMsg("abc".to!int);
assert(msg == "Unexpected 'a' when converting from type string to type int");

// assertThrown can be used to assert that an exception is thrown
assertThrown!ConvException("abc".to!int);

// ifThrown can be used to provide a default value if an exception is thrown
assert("x".to!int().ifThrown(0) == 0);

// handle is a more advanced version of ifThrown for ranges
auto r = "12,1337z32,54".splitter(',').map!(a => to!int(a));
auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
assert(h.equal([12, 0, 54]));
assertThrown!ConvException(h.retro.equal([54, 0, 12]));

// basicExceptionCtors avoids the boilerplate when creating custom exceptions
static class MeaCulpa : Exception
{
    mixin basicExceptionCtors;
}
e = collectException((){throw new MeaCulpa("diagnostic message");}());
assert(e.msg == "diagnostic message");
assert(e.file == __FILE__);
assert(e.line == __LINE__ - 3);

// assumeWontThrow can be used to cast throwing code into `nothrow`
void exceptionFreeCode() nothrow
{
    // auto-decoding only throws if an invalid UTF char is given
    assumeWontThrow("abc".front);
}

// assumeUnique can be used to cast mutable instance to an `immutable` one
// use with care
char[] str = "  mutable".dup;
str[0 .. 2] = "im";
immutable res = assumeUnique(str);
assert(res == "immutable");
@copyrightCopyright Andrei Alexandrescu 2008-, Jonathan M Davis 2011-.@licenseBoost License 1.0@authorsAndrei Alexandrescu and Jonathan M Davis
exception
:
(alias template) fd_remove_tree.enforce = std.exception.enforce(E : Throwable = Exception) if (is(typeof(new E("", string.init, size_t.init)) : Throwable) || is(typeof(new E(string.init, size_t.init)) : Throwable))

Enforces that the given value is true. If the given value is false, an exception is thrown. The

  • msg - error message as a string

  • dg - custom delegate that return a string and is only called if an exception occurred

  • ex - custom exception to be thrown. It is lazy and is only created if an exception occurred

@paramvalue The value to test.@paramE Exception type to throw if the value evaluates to false.@parammsg The error message to put in the exception if it is thrown.@paramdg The delegate to be called if the value evaluates to false.@paramex The exception to throw if the value evaluates to false.@paramfile The source file of the caller.@paramline The line number of the caller.@returns

value, if cast(bool) value is true. Otherwise, depending on the chosen overload, new Exception(msg), dg() or ex is thrown.

enforce is used to throw exceptions and is therefore intended to aid in error handling. It is not intended for verifying the logic of your program - that is what assert is for.

Do not use enforce inside of contracts (i.e. inside of in and out blocks and invariants), because contracts are compiled out when compiling with -release.

If a delegate is passed, the safety and purity of this function are inferred from Dg's safety and purity.

enforce
;
import
(package) std
std
.
(module) std.file

Utilities for manipulating files and scanning directories. Functions in this module handle files as a unit, e.g., read or write one file at a time. For opening files and manipulating them via handles refer to module std.stdio.

Category Functions
General exists isDir isFile isSymlink rename thisExePath
Directories chdir dirEntries getcwd mkdir mkdirRecurse rmdir rmdirRecurse tempDir
Files append copy read readText remove slurp write
Symlinks symlink readLink
Attributes attrIsDir attrIsFile attrIsSymlink getAttributes getLinkAttributes getSize setAttributes
Timestamp getTimes getTimesWin setTimes timeLastModified timeLastAccessed timeStatusChanged
Other DirEntry FileException PreserveAttributes SpanMode getAvailableDiskSpace

Source

std/file.d

@copyrightCopyright The D Language Foundation 2007 - 2011.@seeThe official tutorial for an introduction to working with files in D, module std.stdio for opening files and manipulating them via handles, and module std.path for manipulating path strings.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Jonathan M Davis
file
:
(alias template) fd_remove_tree.dirEntries = std.file.dirEntries(bool useDIP1000 = dip1000Enabled)(string path, SpanMode mode, bool followSymlink = true)

Returns an input range of DirEntry that lazily iterates a given directory, also provides two ways of foreach iteration. The iteration variable can be of type string if only the name is needed, or DirEntry if additional details are needed. The span mode dictates how the directory is traversed. The name of each iterated directory entry contains the absolute or relative path (depending on pathname).

Note

The order of returned directory entries is as it is provided by the operating system / filesystem, and may not follow any particular sorting.

Example

// Iterate a directory in depth
foreach (string name; dirEntries("destroy/me", SpanMode.depth))
{
    remove(name);
}

// Iterate the current directory in breadth
foreach (string name; dirEntries("", SpanMode.breadth))
{
    writeln(name);
}

// Iterate a directory and get detailed info about it
foreach (DirEntry e; dirEntries("dmd-testing", SpanMode.breadth))
{
    writeln(e.name, "\t", e.size);
}

// Iterate over all *.d files in current directory and all its subdirectories
auto dFiles = dirEntries("", SpanMode.depth).filter!(f => f.name.endsWith(".d"));
foreach (d; dFiles)
    writeln(d.name);

// Hook it up with std.parallelism to compile them all in parallel:
foreach (d; parallel(dFiles, 1)) //passes by 1 file to each thread
{
    string cmd = "dmd -c "  ~ d.name;
    writeln(cmd);
    std.process.executeShell(cmd);
}

// Iterate over all D source files in current directory and all its
// subdirectories
auto dFiles = dirEntries("","*.{d,di}",SpanMode.depth);
foreach (d; dFiles)
    writeln(d.name);

To handle subdirectories with denied read permission, use SpanMode.shallow:

void scan(string path)
{
    foreach (DirEntry entry; dirEntries(path, SpanMode.shallow))
    {
        try
        {
            writeln(entry.name);
            if (entry.isDir)
                scan(entry.name);
        }
        catch (FileException fe) { continue; } // ignore
    }
}

scan("");
@paramuseDIP1000 used to instantiate this function separately for code with and without -preview=dip1000 compiler switch, because it affects the ABI of this function. Set automatically - don't touch.@parampath The directory to iterate over. If empty, the current directory will be iterated.@parampattern Optional string with wildcards, such as "*.d". When present, it is used to filter the results by their file name. The supported wildcard strings are described under globMatch.@parammode Whether the directory's sub-directories should be iterated in depth-first post-order (depth), depth-first pre-order (breadth), or not at all (shallow).@paramfollowSymlink Whether symbolic links which point to directories should be treated as directories and their contents iterated over.@returnsAn input range of DirEntry.@throws
  • FileException if the path directory does not exist or read permission is denied.

  • FileException if mode is not shallow and a subdirectory cannot be read.

dirEntries
,
(alias template) fd_remove_tree.exists = std.file.exists(R)(R name) if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R)

Determine whether the given file (or directory) exists.

@paramname string or range of characters representing the file name@returnstrue if the file name specified as input exists
exists
,
(alias) fd_remove_tree.mkdirRecurse = void std.file.mkdirRecurse(scope const(char)[] pathname) @safe

Make directory and all parent directories as needed.

Does nothing if the directory specified by pathname already exists.

@parampathname the full path of the directory to create@throwsFileException on error.
mkdirRecurse
,
(alias) fd_remove_tree.rmdirRecurse = void std.file.rmdirRecurse(scope const(char)[] pathname) @safe

Remove directory and all of its content and subdirectories, recursively.

@parampathname the path of the directory to completely remove@paramde The DirEntry to remove@throwsFileException if there is an error (including if the given file is not a directory).
rmdirRecurse
,
(enum) std.file.SpanMode

Dictates directory spanning policy for dirEntries (see below).

Examples

import std.algorithm.comparison : equal;
import std.algorithm.iteration : map;
import std.algorithm.sorting : sort;
import std.array : array;
import std.path : buildPath, relativePath;

auto root = deleteme ~ "root";
scope(exit) root.rmdirRecurse;
root.mkdir;

root.buildPath("animals").mkdir;
root.buildPath("animals", "cat").mkdir;

alias removeRoot = (return scope e) => e.relativePath(root);

assert(root.dirEntries(SpanMode.depth).map!removeRoot.equal(
    [buildPath("animals", "cat"), "animals"]));

assert(root.dirEntries(SpanMode.breadth).map!removeRoot.equal(
    ["animals", buildPath("animals", "cat")]));

root.buildPath("plants").mkdir;

assert(root.dirEntries(SpanMode.shallow).array.sort.map!removeRoot.equal(
    ["animals", "plants"]));
SpanMode
,
(alias template) fd_remove_tree.symlink = std.file.symlink(RO, RL)(RO original, RL link) if ((isSomeFiniteCharInputRange!RO || isConvertibleToString!RO) && (isSomeFiniteCharInputRange!RL || isConvertibleToString!RL))

This function is POSIX-Only.

Creates a symbolic link (symlink).

@paramoriginal The file that is being linked. This is the target path that's stored in the symlink. A relative path is relative to the created symlink.@paramlink The symlink to create. A relative path is relative to the current working directory.@throwsFileException on error (which includes if the symlink already exists).
symlink
,
(alias) fd_remove_tree.tempDir = string std.file.tempDir() @trusted

Returns the path to a directory for temporary files. On POSIX platforms, it searches through the following list of directories and returns the first one which is found to exist:

  1. The directory given by the TMPDIR environment variable.

  2. The directory given by the TEMP environment variable.

  3. The directory given by the TMP environment variable.

  4. /tmp/

  5. /var/tmp/

  6. /usr/tmp/

On all platforms, tempDir returns the current working directory on failure.

The return value of the function is cached, so the procedures described below will only be performed the first time the function is called. All subsequent runs will return the same string, regardless of whether environment variables and directory structures have changed in the meantime.

The POSIX tempDir algorithm is inspired by Python's tempfile.tempdir.

@returns

On Windows, this function returns the result of calling the Windows API function GetTempPath.

On POSIX platforms, it searches through the following list of directories and returns the first one which is found to exist:

  1. The directory given by the TMPDIR environment variable.

  2. The directory given by the TEMP environment variable.

  3. The directory given by the TMP environment variable.

  4. /tmp

  5. /var/tmp

  6. /usr/tmp

On all platforms, tempDir returns "." on failure, representing the current working directory.

tempDir
,
(alias template) fd_remove_tree.write = std.file.write(R)(R name, const void[] buffer) if ((isSomeFiniteCharInputRange!R || isSomeString!R) && !isConvertibleToString!R)

Write buffer to file name.

Creates the file if it does not already exist.

@paramname string or range of characters representing the file name@parambuffer data to be written to file@throwsFileException on error.@seetoFile
write
;
import
(package) std
std
.
(module) std.path

This module is used to manipulate path strings.

All functions, with the exception of expandTilde (and in some cases absolutePath and relativePath), are pure string manipulation functions; they don't depend on any state outside the program, nor do they perform any actual file system actions. This has the consequence that the module does not make any distinction between a path that points to a directory and a path that points to a file, and it does not know whether or not the object pointed to by the path actually exists in the file system. To differentiate between these cases, use isDir and exists.

Note that on Windows, both the backslash (\) and the slash (/) are in principle valid directory separators. This module treats them both on equal footing, but in cases where a new separator is added, a backslash will be used. Furthermore, the buildNormalizedPath function will replace all slashes with backslashes on that platform.

In general, the functions in this module assume that the input paths are well-formed. (That is, they should not contain invalid characters, they should follow the file system's path format, etc.) The result of calling a function on an ill-formed path is undefined. When there is a chance that a path or a file name is invalid (for instance, when it has been input by the user), it may sometimes be desirable to use the isValidFilename and isValidPath functions to check this.

Most functions do not perform any memory allocations, and if a string is returned, it is usually a slice of an input string. If a function allocates, this is explicitly mentioned in the documentation.

Category Functions
Normalization absolutePath asAbsolutePath asNormalizedPath asRelativePath buildNormalizedPath buildPath chainPath expandTilde
Partitioning baseName dirName dirSeparator driveName pathSeparator pathSplitter relativePath rootName stripDrive
Validation isAbsolute isDirSeparator isRooted isValidFilename isValidPath
Extension defaultExtension extension setExtension stripExtension withDefaultExtension withExtension
Other filenameCharCmp filenameCmp globMatch CaseSensitive

Source

std/path.d

@authorsLars Tandle Kyllingstad, Walter Bright, Grzegorz Adam Hankiewicz, Thomas Khne, Andrei Alexandrescu@copyrightCopyright (c) 2000-2014, the authors. All rights reserved.@licenseBoost License 1.0
path
:
(alias template) fd_remove_tree.buildPath = std.path.buildPath(Range)(scope Range segments) if (isInputRange!Range && !isInfinite!Range && isSomeString!(ElementType!Range))

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
;
import
(package) std
std
.
(module) std.stdio
Category Symbols
File handles _popen File isFileHandle openNetwork stderr stdin stdout
Reading chunks lines readf readfln readln
Writing toFile write writef writefln writeln
Misc KeepTerminator LockType StdioException

Standard I/O functions that extend core.stdc.stdio. core.stdc.stdio is publically imported when importing std.stdio.

There are three layers of I/O:

  1. The lowest layer is the operating system layer. The two main schemes are Windows and Posix.

  2. C's stdio.h which unifies the two operating system schemes.

  3. std.stdio, this module, unifies the various stdio.h implementations into a high level package for D programs.

Source

std/stdio.d

@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Alex Rønne Petersen
stdio
:
(alias template) fd_remove_tree.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))

Equivalent to writef(fmt, args, '\n').

writefln
,
(alias template) fd_remove_tree.writeln = std.stdio.writeln(T...)(T args)

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
;
import
(package) std
std
.
(module) std.string

String handling functions.

Category Functions
Searching
column
indexOf
indexOfAny
indexOfNeither
lastIndexOf
lastIndexOfAny
lastIndexOfNeither
Comparison
isNumeric
Mutation
capitalize
Pruning and Filling
center
chomp
chompPrefix
chop
detabber
detab
entab
entabber
leftJustify
outdent
rightJustify
strip
stripLeft
stripRight
wrap
Substitution
abbrev
soundex
soundexer
succ
tr
translate
Miscellaneous
assumeUTF
fromStringz
lineSplitter
representation
splitLines
toStringz
Objects of types string, wstring, and dstring are value types
and cannot be mutated element-by-element. For using mutation during building
strings, use char[], wchar[], or dchar[]. The xxxstring
types are preferable because they don't exhibit undesired aliasing, thus
making code more robust.

The following functions are publicly imported:

Module Functions
Publicly imported functions
std.algorithm
cmp, std,algorithm,comparison
count, std,algorithm,searching
endsWith, std,algorithm,searching
startsWith, std,algorithm,searching
std.array
join, std,array
replace, std,array
replaceInPlace, std,array
split, std,array
empty, std,array
std.format
format, std,format
sformat, std,format
std.uni
icmp, std,uni
toLower, std,uni
toLowerInPlace, std,uni
toUpper, std,uni
toUpperInPlace, std,uni
There is a rich set of functions for string handling defined in other modules.
Functions related to Unicode and ASCII are found in std.uni
and std.ascii, respectively. Other functions that have a
wider generality than just strings can be found in std.algorithm
and std.range.

Source

std/string.d

@seestd.algorithm and std.range for generic range algorithms , std.ascii for functions that work with ASCII strings , std.uni for functions that work with unicode strings@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Jonathan M Davis, and David L. 'SpottedTiger' Davis
string
:
(alias template) fd_remove_tree.fromStringz = std.string.fromStringz(Char)(return scope inout(Char)* cString) if (isSomeChar!Char)
@paramcString A null-terminated c-style string.@returns

A D-style array of char, wchar or dchar referencing the same string. The returned array will retain the same type qualifiers as the input.

Important Note: The returned array is a slice of the original buffer. The original data is not changed and not copied.

fromStringz
,
(alias) fd_remove_tree.toStringz = immutable(char)* std.string.toStringz(scope const(char)[] s) pure nothrow @trusted
@params A D-style string.@returns

A C-style null-terminated string equivalent to s. s must not contain embedded '\0''s as any C function will treat the first '\0' that it sees as the end of the string. If s.empty is true, then a string containing only '\0' is returned.

Important Note: When passing a char* to a C function, and the C function keeps it around for any reason, make sure that you keep a reference to it in your D code. Otherwise, it may become invalid during a garbage collection cycle and cause a nasty bug when the C code tries to use it.

toStringz
;
// Neither is in druntime's core.sys.posix as of LDC 1.42. extern (C) nothrow @nogc {
(struct) core.sys.posix.dirent.DIR
DIR
*
core.sys.posix.dirent.DIR* fd_remove_tree.fdopendir(int fd) nothrow @nogc
fdopendir
(int
(parameter) int fd
fd
);
int
int fd_remove_tree.unlinkat(int dirfd, const(char*) path, int flags) nothrow @nogc
unlinkat
(int
(parameter) int dirfd
dirfd
, const char*
(parameter) const(char*) path
path
, int
(parameter) int flags
flags
);
} // `AT_REMOVEDIR` differs per platform — the price of a portable `*at` layer. version (
linux
linux
)
enum
(constant) int fd_remove_tree.AT_REMOVEDIR = 512
AT_REMOVEDIR
= 0x200;
else version (OSX) enum AT_REMOVEDIR = 0x080; else version (FreeBSD) enum AT_REMOVEDIR = 0x800; else static assert(0, "AT_REMOVEDIR for this platform"); /// Removes everything inside the directory open at `dirfd`; the caller removes /// the directory itself. `depth` bounds recursion so a pathological tree /// cannot exhaust the stack or the fd table. void
void fd_remove_tree.removeContents(int dirfd, uint depth, ref uint removed)

Removes everything inside the directory open at dirfd; the caller removes the directory itself. depth bounds recursion so a pathological tree cannot exhaust the stack or the fd table.

removeContents
(int
(parameter) int dirfd
dirfd
, uint
(parameter) uint depth
depth
, ref uint
(parameter) uint removed
removed
)
{
bool std.exception.enforce!().enforce!bool(bool value, lazy const(char)[] msg = null, string file = __FILE__, ulong line = cast(ulong)__LINE__) pure @safe

Enforces that the given value is true. If the given value is false, an exception is thrown. The

  • msg - error message as a string

  • dg - custom delegate that return a string and is only called if an exception occurred

  • ex - custom exception to be thrown. It is lazy and is only created if an exception occurred

@paramvalue The value to test.@paramE Exception type to throw if the value evaluates to false.@parammsg The error message to put in the exception if it is thrown.@paramdg The delegate to be called if the value evaluates to false.@paramex The exception to throw if the value evaluates to false.@paramfile The source file of the caller.@paramline The line number of the caller.@returns

value, if cast(bool) value`` is true. Otherwise, depending on the chosen overload, new Exception(msg), dg() or ex is thrown.

enforce is used to throw exceptions and is therefore intended to aid in error handling. It is not intended for verifying the logic of your program - that is what assert is for.

Do not use enforce inside of contracts (i.e. inside of in and out blocks and invariants), because contracts are compiled out when compiling with -release.

If a delegate is passed, the safety and purity of this function are inferred from Dg's safety and purity.

enforce
(
(parameter) uint depth
depth
< 64, "tree too deep");
// `fdopendir` takes ownership of the fd it is given — and of its *file // description*, whose offset `readdir` then moves. A `dup` would share that // description with our own `dirfd`, so rustix re-opens the directory // through the handle instead (`openat(fd, ".")`): a fresh description that // still cannot be redirected, because `.` is resolved relative to the // handle, not to a path. const
(local variable) const(int) listfd
listfd
= openat(
int core.sys.posix.fcntl.openat64(int, scope const(char*), int, ...) nothrow @nogc
dirfd
, ".",
(constant) int core.sys.posix.fcntl.O_RDONLY = 0
O_RDONLY
|
(constant) int core.sys.posix.fcntl.O_DIRECTORY = 65536
O_DIRECTORY
|
(constant) int core.sys.posix.fcntl.O_NOFOLLOW = 131072
O_NOFOLLOW
|
(constant) int core.sys.posix.fcntl.O_CLOEXEC = 524288
O_CLOEXEC
);
bool std.exception.enforce!().enforce!bool(bool value, lazy const(char)[] msg = null, string file = __FILE__, ulong line = cast(ulong)__LINE__) pure @safe

Enforces that the given value is true. If the given value is false, an exception is thrown. The

  • msg - error message as a string

  • dg - custom delegate that return a string and is only called if an exception occurred

  • ex - custom exception to be thrown. It is lazy and is only created if an exception occurred

@paramvalue The value to test.@paramE Exception type to throw if the value evaluates to false.@parammsg The error message to put in the exception if it is thrown.@paramdg The delegate to be called if the value evaluates to false.@paramex The exception to throw if the value evaluates to false.@paramfile The source file of the caller.@paramline The line number of the caller.@returns

value, if cast(bool) value`` is true. Otherwise, depending on the chosen overload, new Exception(msg), dg() or ex is thrown.

enforce is used to throw exceptions and is therefore intended to aid in error handling. It is not intended for verifying the logic of your program - that is what assert is for.

Do not use enforce inside of contracts (i.e. inside of in and out blocks and invariants), because contracts are compiled out when compiling with -release.

If a delegate is passed, the safety and purity of this function are inferred from Dg's safety and purity.

enforce
(
(local variable) const(int) listfd
listfd
>= 0, "reopen for listing failed");
(struct) core.sys.posix.dirent.DIR
DIR
*
(local variable) core.sys.posix.dirent.DIR* d
d
=
core.sys.posix.dirent.DIR* fd_remove_tree.fdopendir(int fd) nothrow @nogc
fdopendir
(
(local variable) const(int) listfd
listfd
);
bool std.exception.enforce!().enforce!bool(bool value, lazy const(char)[] msg = null, string file = __FILE__, ulong line = cast(ulong)__LINE__) pure @safe

Enforces that the given value is true. If the given value is false, an exception is thrown. The

  • msg - error message as a string

  • dg - custom delegate that return a string and is only called if an exception occurred

  • ex - custom exception to be thrown. It is lazy and is only created if an exception occurred

@paramvalue The value to test.@paramE Exception type to throw if the value evaluates to false.@parammsg The error message to put in the exception if it is thrown.@paramdg The delegate to be called if the value evaluates to false.@paramex The exception to throw if the value evaluates to false.@paramfile The source file of the caller.@paramline The line number of the caller.@returns

value, if cast(bool) value`` is true. Otherwise, depending on the chosen overload, new Exception(msg), dg() or ex is thrown.

enforce is used to throw exceptions and is therefore intended to aid in error handling. It is not intended for verifying the logic of your program - that is what assert is for.

Do not use enforce inside of contracts (i.e. inside of in and out blocks and invariants), because contracts are compiled out when compiling with -release.

If a delegate is passed, the safety and purity of this function are inferred from Dg's safety and purity.

enforce
(
(local variable) core.sys.posix.dirent.DIR* d
d
!is null, "fdopendir failed");
scope (exit)
int core.sys.posix.dirent.closedir(core.sys.posix.dirent.DIR*) nothrow @nogc
closedir
(
(local variable) core.sys.posix.dirent.DIR* d
d
);
while (true) {
int core.stdc.errno.__errno_location() nothrow @nogc ref @trusted
errno
= 0;
(struct) core.sys.posix.dirent.dirent
dirent
*
(local variable) core.sys.posix.dirent.dirent* e
e
= readdir(
core.sys.posix.dirent.dirent* core.sys.posix.dirent.readdir64(core.sys.posix.dirent.DIR*) nothrow @nogc
d
);
if (
(local variable) core.sys.posix.dirent.dirent* e
e
is null)
break; const
(local variable) const(char[]) name
name
=
(local variable) core.sys.posix.dirent.dirent* e
e
.
(field) char[256] core.sys.posix.dirent.dirent.d_name
d_name
.
(constant) char* char[256].ptr = &(*e).d_name
ptr
.
inout(char)[] std.string.fromStringz!char(return scope inout(char)* cString) pure nothrow @nogc @system
@paramcString A null-terminated c-style string.@returns

A D-style array of char, wchar or dchar referencing the same string. The returned array will retain the same type qualifiers as the input.

Important Note: The returned array is a slice of the original buffer. The original data is not changed and not copied.

fromStringz
;
if (
(local variable) const(char[]) name
name
== "." ||
(local variable) const(char[]) name
name
== "..")
continue; // Try as a directory first, WITHOUT following: a symlink to a // directory fails here (`ENOTDIR` on Linux, `ELOOP` on older kernels // and other systems — Rust std accepts both) and is unlinked below. const
(local variable) const(int) child
child
= openat(
int core.sys.posix.fcntl.openat64(int, scope const(char*), int, ...) nothrow @nogc
dirfd
,
(local variable) const(char[]) name
name
.
immutable(char)* std.string.toStringz(scope const(char)[] s) pure nothrow @trusted

Examples

import core.stdc.string : strlen;
import std.conv : to;

auto p = toStringz("foo");
assert(strlen(p) == 3);
const(char)[] foo = "abbzxyzzy";
p = toStringz(foo[3 .. 5]);
assert(strlen(p) == 2);

string test = "";
p = toStringz(test);
assert(*p == 0);

test = "\0";
p = toStringz(test);
assert(*p == 0);

test = "foo\0";
p = toStringz(test);
assert(p[0] == 'f' && p[1] == 'o' && p[2] == 'o' && p[3] == 0);

const string test2 = "";
p = toStringz(test2);
assert(*p == 0);

assert(toStringz([]) is toStringz(""));
@params A D-style string.@returns

A C-style null-terminated string equivalent to s. s must not contain embedded '\0''s as any C function will treat the first '\0' that it sees as the end of the string. If ``s.empty is true, then a string containing only '\0' is returned.

Important Note: When passing a char* to a C function, and the C function keeps it around for any reason, make sure that you keep a reference to it in your D code. Otherwise, it may become invalid during a garbage collection cycle and cause a nasty bug when the C code tries to use it.

toStringz
,
(constant) int core.sys.posix.fcntl.O_RDONLY = 0
O_RDONLY
|
(constant) int core.sys.posix.fcntl.O_DIRECTORY = 65536
O_DIRECTORY
|
(constant) int core.sys.posix.fcntl.O_NOFOLLOW = 131072
O_NOFOLLOW
|
(constant) int core.sys.posix.fcntl.O_CLOEXEC = 524288
O_CLOEXEC
);
if (
(local variable) const(int) child
child
>= 0)
{
void fd_remove_tree.removeContents(int dirfd, uint depth, ref uint removed)

Removes everything inside the directory open at dirfd; the caller removes the directory itself. depth bounds recursion so a pathological tree cannot exhaust the stack or the fd table.

removeContents
(
(local variable) const(int) child
child
,
(parameter) uint depth
depth
+ 1,
(parameter) uint removed
removed
);
int core.sys.posix.unistd.close(int) nothrow @nogc @trusted
close
(
(local variable) const(int) child
child
);
bool std.exception.enforce!().enforce!bool(bool value, lazy const(char)[] msg = null, string file = __FILE__, ulong line = cast(ulong)__LINE__) pure @safe

Enforces that the given value is true. If the given value is false, an exception is thrown. The

  • msg - error message as a string

  • dg - custom delegate that return a string and is only called if an exception occurred

  • ex - custom exception to be thrown. It is lazy and is only created if an exception occurred

@paramvalue The value to test.@paramE Exception type to throw if the value evaluates to false.@parammsg The error message to put in the exception if it is thrown.@paramdg The delegate to be called if the value evaluates to false.@paramex The exception to throw if the value evaluates to false.@paramfile The source file of the caller.@paramline The line number of the caller.@returns

value, if cast(bool) value`` is true. Otherwise, depending on the chosen overload, new Exception(msg), dg() or ex is thrown.

enforce is used to throw exceptions and is therefore intended to aid in error handling. It is not intended for verifying the logic of your program - that is what assert is for.

Do not use enforce inside of contracts (i.e. inside of in and out blocks and invariants), because contracts are compiled out when compiling with -release.

If a delegate is passed, the safety and purity of this function are inferred from Dg's safety and purity.

enforce
(
int fd_remove_tree.unlinkat(int dirfd, const(char*) path, int flags) nothrow @nogc
unlinkat
(
(parameter) int dirfd
dirfd
,
(local variable) const(char[]) name
name
.
immutable(char)* std.string.toStringz(scope const(char)[] s) pure nothrow @trusted

Examples

import core.stdc.string : strlen;
import std.conv : to;

auto p = toStringz("foo");
assert(strlen(p) == 3);
const(char)[] foo = "abbzxyzzy";
p = toStringz(foo[3 .. 5]);
assert(strlen(p) == 2);

string test = "";
p = toStringz(test);
assert(*p == 0);

test = "\0";
p = toStringz(test);
assert(*p == 0);

test = "foo\0";
p = toStringz(test);
assert(p[0] == 'f' && p[1] == 'o' && p[2] == 'o' && p[3] == 0);

const string test2 = "";
p = toStringz(test2);
assert(*p == 0);

assert(toStringz([]) is toStringz(""));
@params A D-style string.@returns

A C-style null-terminated string equivalent to s. s must not contain embedded '\0''s as any C function will treat the first '\0' that it sees as the end of the string. If ``s.empty is true, then a string containing only '\0' is returned.

Important Note: When passing a char* to a C function, and the C function keeps it around for any reason, make sure that you keep a reference to it in your D code. Otherwise, it may become invalid during a garbage collection cycle and cause a nasty bug when the C code tries to use it.

toStringz
,
(constant) int fd_remove_tree.AT_REMOVEDIR = 512
AT_REMOVEDIR
) == 0,
string std.conv.text!(string, const(char)[])(string __param_0, const(char)[] __param_1) pure nothrow @safe

Convenience functions for converting one or more arguments of any type into text (the three character widths).

text
("rmdir ",
(local variable) const(char[]) name
name
));
} else
bool std.exception.enforce!().enforce!bool(bool value, lazy const(char)[] msg = null, string file = __FILE__, ulong line = cast(ulong)__LINE__) pure @safe

Enforces that the given value is true. If the given value is false, an exception is thrown. The

  • msg - error message as a string

  • dg - custom delegate that return a string and is only called if an exception occurred

  • ex - custom exception to be thrown. It is lazy and is only created if an exception occurred

@paramvalue The value to test.@paramE Exception type to throw if the value evaluates to false.@parammsg The error message to put in the exception if it is thrown.@paramdg The delegate to be called if the value evaluates to false.@paramex The exception to throw if the value evaluates to false.@paramfile The source file of the caller.@paramline The line number of the caller.@returns

value, if cast(bool) value`` is true. Otherwise, depending on the chosen overload, new Exception(msg), dg() or ex is thrown.

enforce is used to throw exceptions and is therefore intended to aid in error handling. It is not intended for verifying the logic of your program - that is what assert is for.

Do not use enforce inside of contracts (i.e. inside of in and out blocks and invariants), because contracts are compiled out when compiling with -release.

If a delegate is passed, the safety and purity of this function are inferred from Dg's safety and purity.

enforce
(
int fd_remove_tree.unlinkat(int dirfd, const(char*) path, int flags) nothrow @nogc
unlinkat
(
(parameter) int dirfd
dirfd
,
(local variable) const(char[]) name
name
.
immutable(char)* std.string.toStringz(scope const(char)[] s) pure nothrow @trusted

Examples

import core.stdc.string : strlen;
import std.conv : to;

auto p = toStringz("foo");
assert(strlen(p) == 3);
const(char)[] foo = "abbzxyzzy";
p = toStringz(foo[3 .. 5]);
assert(strlen(p) == 2);

string test = "";
p = toStringz(test);
assert(*p == 0);

test = "\0";
p = toStringz(test);
assert(*p == 0);

test = "foo\0";
p = toStringz(test);
assert(p[0] == 'f' && p[1] == 'o' && p[2] == 'o' && p[3] == 0);

const string test2 = "";
p = toStringz(test2);
assert(*p == 0);

assert(toStringz([]) is toStringz(""));
@params A D-style string.@returns

A C-style null-terminated string equivalent to s. s must not contain embedded '\0''s as any C function will treat the first '\0' that it sees as the end of the string. If ``s.empty is true, then a string containing only '\0' is returned.

Important Note: When passing a char* to a C function, and the C function keeps it around for any reason, make sure that you keep a reference to it in your D code. Otherwise, it may become invalid during a garbage collection cycle and cause a nasty bug when the C code tries to use it.

toStringz
, 0) == 0,
string std.conv.text!(string, const(char)[])(string __param_0, const(char)[] __param_1) pure nothrow @safe

Convenience functions for converting one or more arguments of any type into text (the three character widths).

text
("unlink ",
(local variable) const(char[]) name
name
));
(parameter) uint removed
removed
++;
} } int
int D main()
main
()
{ const
(local variable) const(string) base
base
=
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
string std.file.tempDir() @trusted

Returns the path to a directory for temporary files. On POSIX platforms, it searches through the following list of directories and returns the first one which is found to exist:

  1. The directory given by the TMPDIR environment variable.

  2. The directory given by the TEMP environment variable.

  3. The directory given by the TMP environment variable.

  4. /tmp/

  5. /var/tmp/

  6. /usr/tmp/

On all platforms, tempDir returns the current working directory on failure.

The return value of the function is cached, so the procedures described below will only be performed the first time the function is called. All subsequent runs will return the same string, regardless of whether environment variables and directory structures have changed in the meantime.

The POSIX tempDir algorithm is inspired by Python's tempfile.tempdir.

Examples

import std.ascii : letters;
import std.conv : to;
import std.path : buildPath;
import std.random : randomSample;
import std.utf : byCodeUnit;

// random id with 20 letters
auto id = letters.byCodeUnit.randomSample(20).to!string;
auto myFile = tempDir.buildPath(id ~ "my_tmp_file");
scope(exit) myFile.remove;

myFile.write("hello");
assert(myFile.readText == "hello");
@returns

On Windows, this function returns the result of calling the Windows API function GetTempPath.

On POSIX platforms, it searches through the following list of directories and returns the first one which is found to exist:

  1. The directory given by the TMPDIR environment variable.

  2. The directory given by the TEMP environment variable.

  3. The directory given by the TMP environment variable.

  4. /tmp

  5. /var/tmp

  6. /usr/tmp

On all platforms, tempDir returns "." on failure, representing the current working directory.

tempDir
, "fd-remove-tree-demo");
if (
(local variable) const(string) base
base
.
bool std.file.exists!string(string name) nothrow @nogc @safe

Determine whether the given file (or directory) exists.

@paramname string or range of characters representing the file name@returnstrue if the file name specified as input exists
exists
)
void std.file.rmdirRecurse(scope const(char)[] pathname) @safe

Remove directory and all of its content and subdirectories, recursively.

@parampathname the path of the directory to completely remove@paramde The DirEntry to remove@throwsFileException if there is an error (including if the given file is not a directory).
rmdirRecurse
(
(local variable) const(string) base
base
);
scope (exit)
void std.file.rmdirRecurse(scope const(char)[] pathname) @safe

Remove directory and all of its content and subdirectories, recursively.

@parampathname the path of the directory to completely remove@paramde The DirEntry to remove@throwsFileException if there is an error (including if the given file is not a directory).
rmdirRecurse
(
(local variable) const(string) base
base
);
const
(local variable) const(string) outside
outside
=
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) const(string) base
base
, "outside");
const
(local variable) const(string) victim
victim
=
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) const(string) base
base
, "victim");
void std.file.mkdirRecurse(scope const(char)[] pathname) @safe

Make directory and all parent directories as needed.

Does nothing if the directory specified by pathname already exists.

Examples

import std.path : buildPath;

auto dir = deleteme ~ "dir";
scope(exit) dir.rmdirRecurse;

dir.mkdir;
assert(dir.exists);
dir.mkdirRecurse; // does nothing

// creates all parent directories as needed
auto nested = dir.buildPath("a", "b", "c");
nested.mkdirRecurse;
assert(nested.exists);
import std.exception : assertThrown;

scope(exit) deleteme.remove;
deleteme.write("a");

// cannot make directory as it's already a file
assertThrown!FileException(deleteme.mkdirRecurse);
@parampathname the full path of the directory to create@throwsFileException on error.
mkdirRecurse
(
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) const(string) outside
outside
));
void std.file.write!string(string name, const(void[]) buffer) @safe

Write buffer to file name.

Creates the file if it does not already exist.

Examples

scope(exit)
{
    assert(exists(deleteme));
    remove(deleteme);
}

int[] a = [ 0, 1, 1, 2, 3, 5, 8 ];
write(deleteme, a); // deleteme is the name of a temporary file
const bytes = read(deleteme);
const fileInts = () @trusted { return cast(int[]) bytes; }();
assert(fileInts == a);
@paramname string or range of characters representing the file name@parambuffer data to be written to file@throwsFileException on error.@seetoFile
write
(
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) const(string) outside
outside
, "precious.txt"), "keep me");
void std.file.mkdirRecurse(scope const(char)[] pathname) @safe

Make directory and all parent directories as needed.

Does nothing if the directory specified by pathname already exists.

Examples

import std.path : buildPath;

auto dir = deleteme ~ "dir";
scope(exit) dir.rmdirRecurse;

dir.mkdir;
assert(dir.exists);
dir.mkdirRecurse; // does nothing

// creates all parent directories as needed
auto nested = dir.buildPath("a", "b", "c");
nested.mkdirRecurse;
assert(nested.exists);
import std.exception : assertThrown;

scope(exit) deleteme.remove;
deleteme.write("a");

// cannot make directory as it's already a file
assertThrown!FileException(deleteme.mkdirRecurse);
@parampathname the full path of the directory to create@throwsFileException on error.
mkdirRecurse
(
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) const(string) victim
victim
, "sub", "deeper"));
void std.file.write!string(string name, const(void[]) buffer) @safe

Write buffer to file name.

Creates the file if it does not already exist.

Examples

scope(exit)
{
    assert(exists(deleteme));
    remove(deleteme);
}

int[] a = [ 0, 1, 1, 2, 3, 5, 8 ];
write(deleteme, a); // deleteme is the name of a temporary file
const bytes = read(deleteme);
const fileInts = () @trusted { return cast(int[]) bytes; }();
assert(fileInts == a);
@paramname string or range of characters representing the file name@parambuffer data to be written to file@throwsFileException on error.@seetoFile
write
(
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) const(string) victim
victim
, "top.txt"), "x");
void std.file.write!string(string name, const(void[]) buffer) @safe

Write buffer to file name.

Creates the file if it does not already exist.

Examples

scope(exit)
{
    assert(exists(deleteme));
    remove(deleteme);
}

int[] a = [ 0, 1, 1, 2, 3, 5, 8 ];
write(deleteme, a); // deleteme is the name of a temporary file
const bytes = read(deleteme);
const fileInts = () @trusted { return cast(int[]) bytes; }();
assert(fileInts == a);
@paramname string or range of characters representing the file name@parambuffer data to be written to file@throwsFileException on error.@seetoFile
write
(
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) const(string) victim
victim
, "sub", "deeper", "leaf.txt"), "x");
void std.file.symlink!(string, string)(string original, string link) @safe

This function is POSIX-Only.

Creates a symbolic link (symlink).

@paramoriginal The file that is being linked. This is the target path that's stored in the symlink. A relative path is relative to the created symlink.@paramlink The symlink to create. A relative path is relative to the current working directory.@throwsFileException on error (which includes if the symlink already exists).
symlink
(
(local variable) const(string) outside
outside
,
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) const(string) victim
victim
, "sub", "escape")); // the trap
const
(local variable) const(int) fd
fd
= open(
int core.sys.posix.fcntl.open64(scope const(char*), int, ...) nothrow @nogc
victim
.
immutable(char)* std.string.toStringz(scope const(char)[] s) pure nothrow @trusted

Examples

import core.stdc.string : strlen;
import std.conv : to;

auto p = toStringz("foo");
assert(strlen(p) == 3);
const(char)[] foo = "abbzxyzzy";
p = toStringz(foo[3 .. 5]);
assert(strlen(p) == 2);

string test = "";
p = toStringz(test);
assert(*p == 0);

test = "\0";
p = toStringz(test);
assert(*p == 0);

test = "foo\0";
p = toStringz(test);
assert(p[0] == 'f' && p[1] == 'o' && p[2] == 'o' && p[3] == 0);

const string test2 = "";
p = toStringz(test2);
assert(*p == 0);

assert(toStringz([]) is toStringz(""));
@params A D-style string.@returns

A C-style null-terminated string equivalent to s. s must not contain embedded '\0''s as any C function will treat the first '\0' that it sees as the end of the string. If ``s.empty is true, then a string containing only '\0' is returned.

Important Note: When passing a char* to a C function, and the C function keeps it around for any reason, make sure that you keep a reference to it in your D code. Otherwise, it may become invalid during a garbage collection cycle and cause a nasty bug when the C code tries to use it.

toStringz
,
(constant) int core.sys.posix.fcntl.O_RDONLY = 0
O_RDONLY
|
(constant) int core.sys.posix.fcntl.O_DIRECTORY = 65536
O_DIRECTORY
|
(constant) int core.sys.posix.fcntl.O_NOFOLLOW = 131072
O_NOFOLLOW
|
(constant) int core.sys.posix.fcntl.O_CLOEXEC = 524288
O_CLOEXEC
);
assert(
(local variable) const(int) fd
fd
>= 0);
uint
(local variable) uint removed
removed
;
void fd_remove_tree.removeContents(int dirfd, uint depth, ref uint removed)

Removes everything inside the directory open at dirfd; the caller removes the directory itself. depth bounds recursion so a pathological tree cannot exhaust the stack or the fd table.

removeContents
(
(local variable) const(int) fd
fd
, 0,
(local variable) uint removed
removed
);
int core.sys.posix.unistd.close(int) nothrow @nogc @trusted
close
(
(local variable) const(int) fd
fd
);
void std.file.rmdirRecurse(scope const(char)[] pathname) @safe

Remove directory and all of its content and subdirectories, recursively.

@parampathname the path of the directory to completely remove@paramde The DirEntry to remove@throwsFileException if there is an error (including if the given file is not a directory).
rmdirRecurse
(
(local variable) const(string) victim
victim
); // the now-empty root, by path — it is ours
void std.stdio.writefln!(char, uint)(in char[] fmt, uint __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("removed %d entries beneath victim/",
(local variable) uint removed
removed
);
void std.stdio.writefln!(char, bool)(in char[] fmt, bool __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("victim/ exists afterwards: %s",
(local variable) const(string) victim
victim
.
bool std.file.exists!string(string name) nothrow @nogc @safe

Determine whether the given file (or directory) exists.

@paramname string or range of characters representing the file name@returnstrue if the file name specified as input exists
exists
);
void std.stdio.writefln!(char, bool)(in char[] fmt, bool __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("outside/precious.txt survived: %s",
string std.path.buildPath!char(const(char)[][] paths...) pure nothrow @safe

Combines one or more path segments.

This function takes a set of path segments, given as an input range of string elements or as a set of string arguments, and concatenates them with each other. Directory separators are inserted between segments if necessary. If any of the path segments are absolute (as defined by isAbsolute), the preceding segments will be dropped.

On Windows, if one of the path segments are rooted, but not absolute (e.g. \foo), all preceding path segments down to the previous root will be dropped. (See below for an example.)

This function always allocates memory to hold the resulting path. The variadic overload is guaranteed to only perform a single allocation, as is the range version if paths is a forward range.

Examples

version (Posix)
{
    assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
    assert(buildPath("/foo/", "bar/baz")  == "/foo/bar/baz");
    assert(buildPath("/foo", "/bar")      == "/bar");
}

version (Windows)
{
    assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
    assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
    assert(buildPath("foo", `d:\bar`)     == `d:\bar`);
    assert(buildPath("foo", `\bar`)       == `\bar`);
    assert(buildPath(`c:\foo`, `\bar`)    == `c:\bar`);
}
@paramsegments An input range of segments to assemble the path from.@returnsThe assembled path.
buildPath
(
(local variable) const(string) outside
outside
, "precious.txt").
bool std.file.exists!string(string name) nothrow @nogc @safe

Determine whether the given file (or directory) exists.

@paramname string or range of characters representing the file name@returnstrue if the file name specified as input exists
exists
);
return 0; }