Skip to content

Move fails with EPERM when destination is in root of drive #819

Closed
@ZudoB

Description

@ZudoB
  • Operating System: Windows 10 1909
  • Node.js version: 14.2.0
  • fs-extra version: 9.0.1

Moving a file or directory where the destination is in the root of a drive (e.g. D:\filename) causes the operation to fail, as the move function attempts to mkdir the root of the drive.

const fs = require("fs-extra");
fs.moveSync("D:\\Source.txt", "D:\\Destination\\SomeFolder"); // succeeds
fs.moveSync("D:\\Source.txt", "D:\\Destination"); // fails

Error is as follows:

Uncaught Error: EPERM: operation not permitted, mkdir 'D:\'
    at Object.mkdirSync (fs.js:940:3)
    at module.exports.makeDirSync (---\node_modules\fs-extra\lib\mkdirs\make-dir.js:101:15)
    at Object.moveSync (---\node_modules\fs-extra\lib\move-sync\move-sync.js:16:3) {
  errno: -4048,
  syscall: 'mkdir',
  code: 'EPERM',
  path: 'D:\\'
}

Activity

RyanZim

RyanZim commented on Jul 3, 2020

@RyanZim
Collaborator

Huh, that's a bug; looks like we need to either check if the parent is root, or else have proper handling of an EPERM error here:

mkdirp(path.dirname(dest), err => {

@manidlou what's your preference?

manidlou

manidlou commented on Jul 5, 2020

@manidlou
Collaborator

That's actually documented (https://nodejs.org/api/fs.html#fs_fs_mkdir_path_options_callback). I would say we check the error, but if anyone thinks checking if parent is root is a better approach because of specific reasons, I am open to that!

RyanZim

RyanZim commented on Jul 6, 2020

@RyanZim
Collaborator

We will need to check for root either way most likely, because we can't consider all EPERM errors to be as a result of root. The question is whether we pre-emptively check for root, or check after we get EPERM. As for the choice between those two, if we need to hit the FS to check root, do it after we get the error, to keep it fast for all other cases; if we can just do a static path check, perhaps we can check before calling mkdirp.

To be perfectly clear here, I'm not in favor of changing the way mkdirp works here, I just think move should handle this better.

RyanZim

RyanZim commented on Jul 6, 2020

@RyanZim
Collaborator

Interestingly enough, copy doesn't have this problem, because it does an explicit pathExists call before calling mkdirs:

function checkParentDir (destStat, src, dest, opts, cb) {
const destParent = path.dirname(dest)
pathExists(destParent, (err, dirExists) => {
if (err) return cb(err)
if (dirExists) return startCopy(destStat, src, dest, opts, cb)
mkdirs(destParent, err => {
if (err) return cb(err)
return startCopy(destStat, src, dest, opts, cb)
})
})
}

Not sure if that's ideal, though. Anytime you use pathExists, you have race condition potential.

added this to the 10.0.0 milestone on Jul 29, 2020
manidlou

manidlou commented on Oct 30, 2020

@manidlou
Collaborator

Is it enough to use path.parse() to get the root and check if that's the same as the parent?

RyanZim

RyanZim commented on Oct 30, 2020

@RyanZim
Collaborator

@manidlou That's a good idea! It should work, though I'm not sure, we might need to do some slash normalization.

self-assigned this
on Feb 17, 2021
manidlou

manidlou commented on Feb 17, 2021

@manidlou
Collaborator

hmm.. I actually just remembered that moving to the root would basically fail because of permission error (unless you run it with sudo) at least on unix like systems, but I guess things are different in windows! That makes writing tests for this a bit tricky!

RyanZim

RyanZim commented on Apr 2, 2021

@RyanZim
Collaborator

@manidlou it'd be perfectly fine to write a test that's skipped on all platforms other than Windows for this. Any progress here?

RyanZim

RyanZim commented on Apr 21, 2021

@RyanZim
Collaborator

@manidlou what's the status here?

RyanZim

RyanZim commented on May 1, 2021

@RyanZim
Collaborator

I'd like to ship v10 next week, looks like this will need to be pushed back.

manidlou

manidlou commented on May 1, 2021

@manidlou
Collaborator

Sorry @RyanZim! been super busy! I plan to wrap this up this weekend. If I cannot manage to do that, we will leave it for v11.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

Relationships

None yet

    Development

    Participants

    @ZudoB@manidlou@RyanZim

    Issue actions

      Move fails with EPERM when destination is in root of drive · Issue #819 · jprichardson/node-fs-extra