Jump to page: 1 2
Thread overview
errors with filesystem operations
Jan 15, 2014
Hugo Florentino
Jan 15, 2014
Jacob Carlborg
Jan 15, 2014
Hugo Florentino
Jan 16, 2014
Kagamin
Jan 16, 2014
Hugo Florentino
Jan 17, 2014
Kagamin
Jan 17, 2014
Hugo Florentino
Jan 17, 2014
Kagamin
Jan 18, 2014
Hugo Florentino
Jan 18, 2014
Kagamin
Jan 20, 2014
Hugo Florentino
Jan 20, 2014
Hugo Florentino
Jan 18, 2014
Kagamin
Jan 20, 2014
Hugo Florentino
January 15, 2014
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;
}
January 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
January 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?
January 16, 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.
January 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 :)

January 17, 2014
Does it fail for that one directory only or for any directory?
January 17, 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.
January 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.
January 18, 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.
January 18, 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:
>> 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.

In that case try a path with \\?\ prefix (unparsed path).
« First   ‹ Prev
1 2