digitalmars.D.learn - errors with filesystem operations
- Hugo Florentino (114/114) Jan 15 2014 Hi,
- Jacob Carlborg (9/17) Jan 15 2014 As of 2.065 (not release yet) you can set file attributes using
- Hugo Florentino (9/13) Jan 15 2014 I am aware of this. However, FAT32 and NTFS (through ntfs-3g) and even
- Kagamin (4/4) Jan 16 2014 Probably because you use ansi api: if filename contains
- Hugo Florentino (25/29) Jan 16 2014 Hmm... that may be true for Linux filesystems, but not necessarily for
- Kagamin (1/1) Jan 16 2014 Does it fail for that one directory only or for any directory?
- Hugo Florentino (9/10) Jan 17 2014 Interesting question. I would have to do more tests with odd names, but
- Kagamin (3/3) Jan 17 2014 I only noticed that rename uses MOVEFILE_REPLACE_EXISTING flag,
- Hugo Florentino (7/10) Jan 17 2014 Well, as a matter of fact I did try to use remove directly and it
- Kagamin (3/3) Jan 18 2014 remove uses DeleteFile, but MSDN says
- Hugo Florentino (7/10) Jan 20 2014 You are correct, so I made a few test using rmdir() with a blank for
- Hugo Florentino (10/10) Jan 20 2014 Update: the combination of both your suggestions worked:
- Kagamin (2/7) Jan 18 2014 In that case try a path with \\?\ prefix (unparsed path).
- Hugo Florentino (26/34) Jan 20 2014 Does not work. I modified the relevant block like this:
Hi, I am trying to make a little application to revert the effect of some viruses on USB memories, and running it from Windows encountered some exceptions that IMHO should not have happened. Maybe I am missing something. Can you please check the commented blocks for errors? Also, is there a way from Linux to remove attributes readonly, system, hidden ? Regards, Hugo import std.stdio; import std.path; import std.regex; import std.file; import std.string; static string info = "CureUSB 0.3 (2014-01-14)"; static string str_moved = "Moved"; static string str_deleted = "Deleted"; static string str_finished = "Done"; static string str_setattrib = "Attributes set"; static string str_safename = "SafeToDelete"; // Expression to match directories with blanks for name static auto re = regex(`^\s+$`); version(Windows) { import core.sys.windows.windows; extern(Windows) uint SetFileAttributesA(LPCSTR, DWORD); } int main() { string ExePath = thisExePath(); string SearchPath = rootName(ExePath); string BlankDirToDelete; version(Windows) SetConsoleOutputCP(65001); writefln(info); foreach(DirEntry d; dirEntries(SearchPath, SpanMode.shallow)) { auto m = matchFirst(baseName(d.name), re); if (m.captures.length > 0) { if (isDir(d.name)) { foreach(DirEntry f; dirEntries(d.name, SpanMode.shallow)) { string origname = buildPath(SearchPath, baseName(f.name)); rename(f.name, origname); writefln(`%s "%s"`, str_moved, origname); } BlankDirToDelete = d.name; } break; } } // The following block does not work; supposedly the process does not have // access to the directory because it is being used by another process, // which does not seem to be the case. Uncomment to try /* if (exists(BlankDirToDelete)) try { string SafeToBeDeleted = buildPath(SearchPath, str_safename) rename(BlankDirToDelete, SafeToBeDeleted); remove(SafeToBeDeleted); } catch (FileException e) writeln(e.msg); */ foreach(DirEntry d; dirEntries(SearchPath, SpanMode.shallow)) { if (d.name != ExePath) { string bname = baseName(d.name); version(Windows) { if ( (bname != "RECYCLER") && (bname != "$Recycle.bin") && (bname != "System Volume Information") && (bname != "Recovery") && (bname != "MSOCache") ) SetFileAttributesA(toStringz(d.name), FILE_ATTRIBUTE_NORMAL + FILE_ATTRIBUTE_ARCHIVE); } // The following block gives a FileException, claiming that the specified file // could not befound. Uncomment to try /* string exten = extension(d.name); if (exten.length > 0) { // writefln(`"%s" "%s"`, d.name, extension(d.name)); //debug line if ( (exten == ".exe") || (exten == ".lnk") || (exten == ".scr") || (exten == ".cpl") || (exten == ".hta") || (exten == ".com") || (exten == ".bat") || (exten == ".vb") || (exten == ".vbs") ) if (isDir(buildPath(SearchPath, stripExtension(baseName(d.name))))) { remove(d.name); writefln(`%s "%s"`, str_deleted, d.name); } } */ } } writefln("%s", str_setattrib); writefln("%s.", str_finished); return 0; }
Jan 15 2014
On 2014-01-15 11:33, Hugo Florentino wrote:Hi, I am trying to make a little application to revert the effect of some viruses on USB memories, and running it from Windows encountered some exceptions that IMHO should not have happened. Maybe I am missing something. Can you please check the commented blocks for errors? Also, is there a way from Linux to remove attributes readonly, system, hidden ?As of 2.065 (not release yet) you can set file attributes using std.file.setAttributes [1]. On Linux, hidden files are all files where the filename starts with a dot. To make it visible you need to rename the file. As far as I know, Linux doesn't have any form of system attribute. [1] https://github.com/D-Programming-Language/phobos/commit/5ab8dae665c27ed45eced244720e23e53ef23457 -- /Jacob Carlborg
Jan 15 2014
On Wed, 15 Jan 2014 13:41:50 +0100, Jacob Carlborg wrote:... On Linux, hidden files are all files where the filename starts with a dot. To make it visible you need to rename the file. As far as I know, Linux doesn't have any form of system attribute.I am aware of this. However, FAT32 and NTFS (through ntfs-3g) and even ExFAT (I do not remember now the name of the project) are supported by Linux, so there should be a way to alter file structure so as to change attributes even if the OS does not natively provide a function for this (why should a user working in Linux be forced to reboot in Windows not even to run an unported application but just to change file attributes in a filesystem the OS supports)? Has anyone attempted it from D?
Jan 15 2014
Probably because you use ansi api: if filename contains non-english character, there could be a problem. A filesystem support is primarily for storing files, attributes can be safely ignored.
Jan 16 2014
On Thu, 16 Jan 2014 15:41:06 +0000, Kagamin wrote:Probably because you use ansi api: if filename contains non-english character, there could be a problem. A filesystem support is primarily for storing files, attributes can be safely ignored.Hmm... that may be true for Linux filesystems, but not necessarily for filesystems used by Windows, where attributes do matter. Probably the majority of people here works from Linux and maybe most have the good fortune that the rest of the users in their organization either works in Linux too, or are computer literate persons. However where I work all users work in Windows (there is a specific application for the management of music rights which has not been ported to Linux AFAIK) and most of them have rather basic computer skills. So these users sometimes bring a USB memory from home, infected with some virus which the company antivirus does disinfect, but the effects (hidden folders or files moved to a directory with a blank name, among others) are not always reversed. So you see, I would prefer distributing an executable which fixes the memory for them rather than having them come into my office and make me reboot to Windows just to remove the hidden attribute from their folders or so on. Besides, if in my application I specifically set console codepage to UTF8 for the Windows version of the executable, and I am calling a D function (supposedly portable) to rename or delete a directory, and yet it does not get deleted, supposedly because it is being used (which I have tried to avoid in my code), I find this rather odd, and since I am new to D, I do not yet know the internals of the language well enough to realize where the problem is. Which is why I am asking for help here :)
Jan 16 2014
Does it fail for that one directory only or for any directory?
Jan 16 2014
On Fri, 17 Jan 2014 07:07:35 +0000, Kagamin wrote:Does it fail for that one directory only or for any directory?Interesting question. I would have to do more tests with odd names, but apparently both remove() and rename() have problems with directories with a blank name. Curiously, moving files or directories from within that blank directory to another directory seems to working correctly, so it's not like the directory is not being detected. I haven't dived in the code for both functions, but I suspect that some validation may be causing the problem.
Jan 17 2014
I only noticed that rename uses MOVEFILE_REPLACE_EXISTING flag, which can't be used with directories. Are you sure remove fails too? If rename throws, remove is not called in your code.
Jan 17 2014
On Fri, 17 Jan 2014 13:10:00 +0000, Kagamin wrote:I only noticed that rename uses MOVEFILE_REPLACE_EXISTING flag, which can't be used with directories. Are you sure remove fails too? If rename throws, remove is not called in your code.Well, as a matter of fact I did try to use remove directly and it failed with the same problem (directory in use by some process) Since subdirectories were being moved just fine, I thought once the content of the problematic directory was moved elsewhere I could rename the directory first and then remove it, but this approach failed too, at least from Windows.
Jan 17 2014
remove uses DeleteFile, but MSDN says To remove an empty directory, use the RemoveDirectory function. so remove probably won't work on directories.
Jan 18 2014
On Sat, 18 Jan 2014 11:51:48 +0000, Kagamin wrote:remove uses DeleteFile, but MSDN says To remove an empty directory, use the RemoveDirectory function. so remove probably won't work on directories.You are correct, so I made a few test using rmdir() with a blank for directory name and now I get: d:\ : Directory is not empty. However, the diretory is certainly empty. Go figure! Note that in Windows I cannot create a directoy with a blank name from D either, so in order to test this, I have to create it elsewhere.
Jan 20 2014
Update: the combination of both your suggestions worked: if (exists(BlankDirToDelete)) { try rmdir(`\\?\` ~ BlankDirToDelete); catch (FileException e) writeln(e.msg); } Thanks! Now I just have to find out why the block of the file extensions is failing.
Jan 20 2014
On Friday, 17 January 2014 at 12:52:09 UTC, Hugo Florentino wrote:On Fri, 17 Jan 2014 07:07:35 +0000, Kagamin wrote:In that case try a path with \\?\ prefix (unparsed path).Does it fail for that one directory only or for any directory?Interesting question. I would have to do more tests with odd names, but apparently both remove() and rename() have problems with directories with a blank name.
Jan 18 2014
On Sat, 18 Jan 2014 11:33:16 +0000, Kagamin wrote:On Friday, 17 January 2014 at 12:52:09 UTC, Hugo Florentino wrote:Does not work. I modified the relevant block like this: if (exists(BlankDirToDelete)) { string SafeToBeDeleted = buildPath(`\\?\`, SearchPath, baseName(BlankDirToDelete)); writefln(`"%s"`, SafeToBeDeleted); try remove(SafeToBeDeleted); catch (FileException e) writeln(e.msg); try remove(`\\?\` ~ SafeToBeDeleted); catch (FileException e) writeln(e.msg); } The result? "d:\ " d:\ : Access denied. \\?\d:\ : Access denied. This happens even while executing the prompt as administrator, so it's not a problem of file privileges. Note that from the Windows explorer I am also having problems renaming or deleting the problematic directory, however with something else like Total Commander, I can both rename and delete with no issues. Regards, HugoOn Fri, 17 Jan 2014 07:07:35 +0000, Kagamin wrote:In that case try a path with \\?\ prefix (unparsed path).Does it fail for that one directory only or for any directory?Interesting question. I would have to do more tests with odd names, but apparently both remove() and rename() have problems with directories with a blank name.
Jan 20 2014