Bug 7819 – std.file.setTimes throws error on folders
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2012-04-04T05:42:00Z
Last change time
2013-02-13T00:14:10Z
Keywords
pull
Assigned to
andrej.mitrovich
Creator
jayn
Comments
Comment #0 by jayn — 2012-04-04T05:42:30Z
std.file.setTimes threw an error on folder names while it worked ok on regular files. Not sure if it is an error since there is no documentation that it shouldn't work for folders. Should it work, or what is the alternative?
In the lines below, am.time was from std.zip archive entry.
tz was from localTime().
fullPathname is a full path to a windows directory name.
SysTime st = DosFileTimeToSysTime(am.time, tz);
std.file.setTimes(fullPathname, st, st);
Comment #1 by jayn — 2012-04-04T21:27:09Z
It looks like CreateFile requires a special flag, FILE_FLAG_BACKUP_SEMANTICS , in order to get a handle from a directory that can be used with the SetFileTime call. Below is an excerpt from a discussion on the topic.
http://cygwin.com/ml/cygwin/1997-12/msg00350.html
Windows NT: You can obtain a handle to a directory by calling the
CreateFile function with the FILE_FLAG_BACKUP_SEMANTICS flag set, as
follows:
hDir = CreateFile (
DirName,
GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL
);
You can pass a directory handle to the following SetFileTime function.
Comment #2 by jayn — 2012-04-04T22:15:17Z
I tried the mod below in the setTimes code in 2.058 std.file and it now will permit both file and directory timestamp updates with no thrown errors. The only changes are to line 2788 where I added the FILE_ATTRIBUTE_DIRECTORY and FILE_FLAG_BACKUP_SEMANTICS attributes, and a few lines prior adding FILE_SHARE_READ|FILE_SHARE_DELETE, as suggested in the other discussion. I tested using this change to restore timestamps on all files and folders in an unzipped 2GB directory with no issues.
else void setTimes(C)(in C[] name,
SysTime fileAccessTime,
SysTime fileModificationTime)
if(is(Unqual!C == char))
{
version(Windows)
{
const ta = SysTimeToFILETIME(fileAccessTime);
const tm = SysTimeToFILETIME(fileModificationTime);
alias TypeTuple!(GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_DELETE,
null,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_DIRECTORY, HANDLE.init)
Comment #3 by andrej.mitrovich — 2013-02-09T19:21:27Z