Skip to content

Commit

Permalink
Fix #2751: Files#delete now throws DirectoryNotEmptyException (#2753)
Browse files Browse the repository at this point in the history
  • Loading branch information
LeeTibbert committed Aug 4, 2022
1 parent f3b776d commit 62e6302
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 8 deletions.
28 changes: 26 additions & 2 deletions javalib/src/main/scala/java/nio/file/Files.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import scalanative.unsafe._
import scalanative.libc._
import scalanative.posix.{dirent, fcntl, limits, unistd}
import dirent._
import scalanative.posix.errno.{EEXIST, ENOTEMPTY}

import java.nio.file.StandardCopyOption.{COPY_ATTRIBUTES, REPLACE_EXISTING}
import scalanative.nio.fs.unix.UnixException
import scalanative.posix.sys.stat
Expand Down Expand Up @@ -331,12 +333,34 @@ object Files {
): Path =
createTempFile(null: File, prefix, suffix, attrs)

private def windowsDeletePath(path: Path): Unit = {
// Optimize for delete() success. Spend cycles fixing up only on failure.
if (!path.toFile().delete()) {
val targetFile = path.toFile()
if (targetFile.isDirectory() && !targetFile.list().isEmpty) {
throw new DirectoryNotEmptyException(targetFile.getAbsolutePath())
} else {
throw new IOException(s"Failed to remove $path")
}
}
}

private def unixDeletePath(path: Path): Unit = Zone { implicit z =>
val ps = path.toString
if (stdio.remove(toCString(ps)) == -1) {
// For historical reasons, some systems report ENOTEMPTY as EEXIST
val fixedErrno = if (errno.errno == EEXIST) ENOTEMPTY else errno.errno
throw PosixException(ps, fixedErrno)
}
}

def delete(path: Path): Unit = {
if (!exists(path, Array.empty)) {
throw new NoSuchFileException(path.toString)
} else if (isWindows) {
windowsDeletePath(path)
} else {
if (path.toFile().delete()) ()
else throw new IOException(s"Failed to remove $path")
unixDeletePath(path) // give more information on unanticipated failure
}
}

Expand Down
11 changes: 6 additions & 5 deletions javalib/src/main/scala/java/nio/file/PosixException.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import scalanative.unsafe.{CInt, fromCString}

object PosixException {
def apply(file: String, errno: CInt): IOException = errno match {
case e if e == ENOTDIR => new NotDirectoryException(file)
case e if e == EACCES => new AccessDeniedException(file)
case e if e == ENOENT => new NoSuchFileException(file)
case e if e == EEXIST => new FileAlreadyExistsException(file)
case e => new IOException(fromCString(string.strerror(e)))
case e if e == EACCES => new AccessDeniedException(file)
case e if e == EEXIST => new FileAlreadyExistsException(file)
case e if e == ENOENT => new NoSuchFileException(file)
case e if e == ENOTDIR => new NotDirectoryException(file)
case e if e == ENOTEMPTY => new DirectoryNotEmptyException(file)
case e => new IOException(fromCString(string.strerror(e)))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,8 @@ class FilesTest {
Files.createFile(file)
assertTrue("a1", Files.exists(subdir))
assertTrue("a2", Files.isDirectory(subdir))
assertThrows(classOf[IOException], Files.delete(subdir))

assertThrows(classOf[DirectoryNotEmptyException], Files.delete(subdir))
}
}

Expand Down

0 comments on commit 62e6302

Please sign in to comment.