From dce91754672985b1807d00f064973a75c75ad8ee Mon Sep 17 00:00:00 2001 From: anonymous Date: Wed, 3 Feb 2016 15:17:22 +0100 Subject: [PATCH 1/3] rangify readLink and symlink Removing @safe from the signatures so that attribute inference takes care of things. There are @safe unittests already, ensuring that the functions themselves don't do anything unsafe. Replacing @trusted declarations with @trusted function literals. This way it's more clear that the specific call is @trusted, not the called function. --- changelog.dd | 2 + std/file.d | 101 +++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 80 insertions(+), 23 deletions(-) diff --git a/changelog.dd b/changelog.dd index 1a95f395ca0..10eed4b3b8d 100644 --- a/changelog.dd +++ b/changelog.dd @@ -23,6 +23,8 @@ $(BUGSTITLE Library Changes, of the type being iterated) $(LI $(XREF algorithm, sorting, isStrictlyMonotonic) which doesn't allow equal values was added.) + $(LI $(REF readLink, std,file) and $(REF symlink, std,file) have been + rangified.) ) $(BUGSTITLE Library Changes, diff --git a/std/file.d b/std/file.d index ccb82ba7d38..691f23d7d41 100644 --- a/std/file.d +++ b/std/file.d @@ -2310,15 +2310,31 @@ unittest $(D FileException) on error (which includes if the _symlink already exists). +/ -version(StdDdoc) void symlink(C1, C2)(const(C1)[] original, const(C2)[] link) @safe; -else version(Posix) void symlink(C1, C2)(const(C1)[] original, const(C2)[] link) @safe -{ - static auto trustedSymlink(const(C1)[] path1, const(C2)[] path2) @trusted +version(StdDdoc) void symlink(RO, RL)(RO original, RL link) + if ((isInputRange!RO && isSomeChar!(ElementType!RO) || + isConvertibleToString!RO) && + (isInputRange!RL && isSomeChar!(ElementType!RL) || + isConvertibleToString!RL)); +else version(Posix) void symlink(RO, RL)(RO original, RL link) + if ((isInputRange!RO && isSomeChar!(ElementType!RO) || + isConvertibleToString!RO) && + (isInputRange!RL && isSomeChar!(ElementType!RL) || + isConvertibleToString!RL)) +{ + static if (isConvertibleToString!RO || isConvertibleToString!RL) + { + import std.meta : staticMap; + alias Types = staticMap!(convertToString, RO, RL); + symlink!Types(original, link); + } + else { - return core.sys.posix.unistd.symlink(path1.tempCString(), - path2.tempCString()); + auto oz = original.tempCString(); + auto lz = link.tempCString(); + alias posixSymlink = core.sys.posix.unistd.symlink; + immutable int result = () @trusted {return posixSymlink(oz, lz);} (); + cenforce(result == 0, text(link)); } - cenforce(trustedSymlink(original, link) == 0, link); } version(Posix) @safe unittest @@ -2364,6 +2380,12 @@ version(Posix) @safe unittest } } +version(Posix) unittest +{ + static assert(__traits(compiles, + symlink(TestAliasedString(null), TestAliasedString(null)))); +} + /++ $(BLUE This function is Posix-Only.) @@ -2376,23 +2398,22 @@ version(Posix) @safe unittest Throws: $(D FileException) on error. +/ -version(StdDdoc) string readLink(C)(const(C)[] link) @safe; -else version(Posix) string readLink(C)(const(C)[] link) @safe +version(StdDdoc) string readLink(R)(R link) + if (isInputRange!R && isSomeChar!(ElementEncodingType!R) && + !isConvertibleToString!R); +else version(Posix) string readLink(R)(R link) + if (isInputRange!R && isSomeChar!(ElementEncodingType!R) && + !isConvertibleToString!R) { - static auto trustedReadlink(const(C)[] path, char[] buf) @trusted - { - return core.sys.posix.unistd.readlink(path.tempCString(), buf.ptr, buf.length); - } - static auto trustedAssumeUnique(ref C[] array) @trusted - { - return assumeUnique(array); - } - + alias posixReadlink = core.sys.posix.unistd.readlink; enum bufferLen = 2048; enum maxCodeUnits = 6; char[bufferLen] buffer; - auto size = trustedReadlink(link, buffer); - cenforce(size != -1, link); + const linkz = link.tempCString(); + auto size = () @trusted { + return posixReadlink(linkz, buffer.ptr, buffer.length); + } (); + cenforce(size != -1, to!string(link)); if(size <= bufferLen - maxCodeUnits) return to!string(buffer[0 .. size]); @@ -2401,13 +2422,17 @@ else version(Posix) string readLink(C)(const(C)[] link) @safe foreach(i; 0 .. 10) { - size = trustedReadlink(link, dynamicBuffer); - cenforce(size != -1, link); + size = () @trusted { + return posixReadlink(linkz, dynamicBuffer.ptr, dynamicBuffer.length); + } (); + cenforce(size != -1, to!string(link)); if(size <= dynamicBuffer.length - maxCodeUnits) { dynamicBuffer.length = size; - return trustedAssumeUnique(dynamicBuffer); + return () @trusted { + return assumeUnique(dynamicBuffer); + } (); } dynamicBuffer.length = dynamicBuffer.length * 3 / 2; @@ -2416,6 +2441,15 @@ else version(Posix) string readLink(C)(const(C)[] link) @safe throw new FileException(to!string(link), "Path is too long to read."); } +/// ditto +version(StdDdoc) string readLink(R)(R link) + if (isConvertibleToString!R); +else version(Posix) string readLink(R)(R link) + if (isConvertibleToString!R) +{ + return readLink!(StringTypeOf!R)(link); +} + version(Posix) @safe unittest { import std.string; @@ -2434,6 +2468,27 @@ version(Posix) @safe unittest assertThrown!FileException(readLink("/doesnotexist")); } +version(Posix) @safe unittest +{ + static assert(__traits(compiles, readLink(TestAliasedString("foo")))); +} + +version(Posix) unittest // input range of dchars +{ + mkdirRecurse(deleteme); + scope(exit) if(deleteme.exists) rmdirRecurse(deleteme); + write(deleteme ~ "/f", ""); + import std.range.interfaces: InputRange, inputRangeObject; + import std.utf: byChar; + immutable string link = deleteme ~ "/l"; + symlink("f", link); + InputRange!dchar linkr = inputRangeObject(link); + alias R = typeof(linkr); + static assert(isInputRange!R); + static assert(!isForwardRange!R); + assert(readLink(linkr) == "f"); +} + /**************************************************** * Get the current working directory. From 831ddccdaeab90c80857e31af6284303be9aff74 Mon Sep 17 00:00:00 2001 From: anonymous Date: Fri, 5 Feb 2016 15:51:38 +0100 Subject: [PATCH 2/3] code formattting --- std/file.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/file.d b/std/file.d index 691f23d7d41..0e207f2624a 100644 --- a/std/file.d +++ b/std/file.d @@ -2332,7 +2332,7 @@ else version(Posix) void symlink(RO, RL)(RO original, RL link) auto oz = original.tempCString(); auto lz = link.tempCString(); alias posixSymlink = core.sys.posix.unistd.symlink; - immutable int result = () @trusted {return posixSymlink(oz, lz);} (); + immutable int result = () @trusted { return posixSymlink(oz, lz); } (); cenforce(result == 0, text(link)); } } From 863b251162548b7528ef4afb26ac388ba185aa98 Mon Sep 17 00:00:00 2001 From: anonymous Date: Fri, 5 Feb 2016 16:13:56 +0100 Subject: [PATCH 3/3] smoothen out differences between readLink and symlink ElementType -> ElementEncodingType template constraints -> static if --- std/file.d | 83 +++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/std/file.d b/std/file.d index 0e207f2624a..3c7b38ee7e3 100644 --- a/std/file.d +++ b/std/file.d @@ -2311,14 +2311,14 @@ unittest exists). +/ version(StdDdoc) void symlink(RO, RL)(RO original, RL link) - if ((isInputRange!RO && isSomeChar!(ElementType!RO) || + if ((isInputRange!RO && isSomeChar!(ElementEncodingType!RO) || isConvertibleToString!RO) && - (isInputRange!RL && isSomeChar!(ElementType!RL) || + (isInputRange!RL && isSomeChar!(ElementEncodingType!RL) || isConvertibleToString!RL)); else version(Posix) void symlink(RO, RL)(RO original, RL link) - if ((isInputRange!RO && isSomeChar!(ElementType!RO) || + if ((isInputRange!RO && isSomeChar!(ElementEncodingType!RO) || isConvertibleToString!RO) && - (isInputRange!RL && isSomeChar!(ElementType!RL) || + (isInputRange!RL && isSomeChar!(ElementEncodingType!RL) || isConvertibleToString!RL)) { static if (isConvertibleToString!RO || isConvertibleToString!RL) @@ -2399,55 +2399,54 @@ version(Posix) unittest $(D FileException) on error. +/ version(StdDdoc) string readLink(R)(R link) - if (isInputRange!R && isSomeChar!(ElementEncodingType!R) && - !isConvertibleToString!R); + if (isInputRange!R && isSomeChar!(ElementEncodingType!R) || + isConvertibleToString!R); else version(Posix) string readLink(R)(R link) - if (isInputRange!R && isSomeChar!(ElementEncodingType!R) && - !isConvertibleToString!R) + if (isInputRange!R && isSomeChar!(ElementEncodingType!R) || + isConvertibleToString!R) { - alias posixReadlink = core.sys.posix.unistd.readlink; - enum bufferLen = 2048; - enum maxCodeUnits = 6; - char[bufferLen] buffer; - const linkz = link.tempCString(); - auto size = () @trusted { - return posixReadlink(linkz, buffer.ptr, buffer.length); - } (); - cenforce(size != -1, to!string(link)); - - if(size <= bufferLen - maxCodeUnits) - return to!string(buffer[0 .. size]); - - auto dynamicBuffer = new char[](bufferLen * 3 / 2); - - foreach(i; 0 .. 10) + static if (isConvertibleToString!R) { - size = () @trusted { - return posixReadlink(linkz, dynamicBuffer.ptr, dynamicBuffer.length); + return readLink!(convertToString!R)(link); + } + else + { + alias posixReadlink = core.sys.posix.unistd.readlink; + enum bufferLen = 2048; + enum maxCodeUnits = 6; + char[bufferLen] buffer; + const linkz = link.tempCString(); + auto size = () @trusted { + return posixReadlink(linkz, buffer.ptr, buffer.length); } (); cenforce(size != -1, to!string(link)); - if(size <= dynamicBuffer.length - maxCodeUnits) + if(size <= bufferLen - maxCodeUnits) + return to!string(buffer[0 .. size]); + + auto dynamicBuffer = new char[](bufferLen * 3 / 2); + + foreach(i; 0 .. 10) { - dynamicBuffer.length = size; - return () @trusted { - return assumeUnique(dynamicBuffer); + size = () @trusted { + return posixReadlink(linkz, dynamicBuffer.ptr, + dynamicBuffer.length); } (); - } + cenforce(size != -1, to!string(link)); - dynamicBuffer.length = dynamicBuffer.length * 3 / 2; - } + if(size <= dynamicBuffer.length - maxCodeUnits) + { + dynamicBuffer.length = size; + return () @trusted { + return assumeUnique(dynamicBuffer); + } (); + } - throw new FileException(to!string(link), "Path is too long to read."); -} + dynamicBuffer.length = dynamicBuffer.length * 3 / 2; + } -/// ditto -version(StdDdoc) string readLink(R)(R link) - if (isConvertibleToString!R); -else version(Posix) string readLink(R)(R link) - if (isConvertibleToString!R) -{ - return readLink!(StringTypeOf!R)(link); + throw new FileException(to!string(link), "Path is too long to read."); + } } version(Posix) @safe unittest