Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8355663

Files::delete throws exception for read-only files on DOS file systems

XMLWordPrintable

    • generic
    • windows

      A DESCRIPTION OF THE PROBLEM :
      On DOS file systems, if the `dos:readonly` attribute is set to true for a given file `p`, `Files.delete(p)` fails with `java.nio.file.AccessDeniedException`.

      This is inconsistent with the following, both of which delete the file successfully:
      * `p.toFile().delete()`
      * `Files.delete(q)`, where `q` denotes a read-only file on a POSIX file system (i.e., a file for which `Files.getPosixFilePermissions(p)` only returns `*_READ` permissions)

      Given these inconsistencies and the fact that the API does not provide an elegant way to forcefully delete such read-only files (e.g., by providing a `DeleteOption` interface, analogous to the `OpenOption` and `CopyOption` interfaces), I believe this is a bug, rather than intended behavior.

      As a workaround, one could use something like the provided code (see `Test Case Code`), but that code is problematic:
      * it is unable to do the unsetting of the attribute and the deletion in a single atomic operation
      * the unsetting is always attempted, even for files that are not affected (and removing the `unsetDosReadOnly(p);` from the try-block might have the opposite effect, where the code constantly falls into the catch-block)

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      * create a read-only file, named `readonly.txt`, on a DOS file system (e.g., NTFS partition on a Windows PC)
      * run `jshell` in the directory that contains the file
      * run `Files.delete(Path.of("readonly.txt"))`

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      the file is deleted
      ACTUAL -
      the following exception is thrown:

      | Exception java.nio.file.AccessDeniedException: readonly.txt
      | at WindowsException.translateToIOException (WindowsException.java:89)
      | at WindowsException.rethrowAsIOException (WindowsException.java:103)
      | at WindowsException.rethrowAsIOException (WindowsException.java:108)
      | at WindowsFileSystemProvider.implDelete (WindowsFileSystemProvider.java:269)
      | at AbstractFileSystemProvider.delete (AbstractFileSystemProvider.java:105)
      | at Files.delete (Files.java:1052)
      | at (#4:1)


      ---------- BEGIN SOURCE ----------
      void delete(Path p) throws IOException {
          try {
              unsetDosReadOnly(p);
              Files.delete(p);
          } catch(AccessDeniedException e) {
              unsetDosReadOnly(p);
              Files.delete(p);
          }
      }

      void unsetDosReadOnly(Path p) throws IOException {
          var attrs = Files.getFileAttributeView(p, java.nio.file.attribute.DosFileAttributeView.class);
          if(attrs != null) {
              attrs.setReadOnly(false);
          }
      }

      ---------- END SOURCE ----------

            bpb Brian Burkhalter
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: