@@ -2,6 +2,7 @@ use napi::bindgen_prelude::*;
22use napi:: Task ;
33use napi_derive:: napi;
44use std:: fs;
5+ use std:: io:: ErrorKind ;
56use std:: path:: Path ;
67
78#[ napi( object) ]
@@ -25,7 +26,13 @@ fn mkdir_impl(path_str: String, options: Option<MkdirOptions>) -> Result<Option<
2526 if recursive {
2627 // Node.js returns the first directory path created, or undefined if it already existed
2728 if path. exists ( ) {
28- return Ok ( None ) ;
29+ if path. is_dir ( ) {
30+ return Ok ( None ) ;
31+ }
32+ return Err ( Error :: from_reason ( format ! (
33+ "EEXIST: file already exists, mkdir '{}'" ,
34+ path. to_string_lossy( )
35+ ) ) ) ;
2936 }
3037
3138 // Find the first ancestor that doesn't exist
@@ -39,9 +46,14 @@ fn mkdir_impl(path_str: String, options: Option<MkdirOptions>) -> Result<Option<
3946 }
4047 }
4148
42- fs:: create_dir_all ( path) . map_err ( |e| {
43- Error :: from_reason ( format ! ( "ENOENT: no such file or directory, mkdir '{}'" , e) )
44- } ) ?;
49+ if current. exists ( ) && !current. is_dir ( ) {
50+ return Err ( Error :: from_reason ( format ! (
51+ "ENOTDIR: not a directory, mkdir '{}'" ,
52+ path. to_string_lossy( )
53+ ) ) ) ;
54+ }
55+
56+ fs:: create_dir_all ( path) . map_err ( |e| mkdir_error ( path, e) ) ?;
4557
4658 #[ cfg( unix) ]
4759 {
@@ -54,21 +66,7 @@ fn mkdir_impl(path_str: String, options: Option<MkdirOptions>) -> Result<Option<
5466 let first_created = ancestors. last ( ) . map ( |p| p. to_string_lossy ( ) . to_string ( ) ) ;
5567 Ok ( first_created)
5668 } else {
57- fs:: create_dir ( path) . map_err ( |e| {
58- if e. kind ( ) == std:: io:: ErrorKind :: NotFound {
59- Error :: from_reason ( format ! (
60- "ENOENT: no such file or directory, mkdir '{}'" ,
61- path. to_string_lossy( )
62- ) )
63- } else if e. kind ( ) == std:: io:: ErrorKind :: AlreadyExists {
64- Error :: from_reason ( format ! (
65- "EEXIST: file already exists, mkdir '{}'" ,
66- path. to_string_lossy( )
67- ) )
68- } else {
69- Error :: from_reason ( format ! ( "{}" , e) )
70- }
71- } ) ?;
69+ fs:: create_dir ( path) . map_err ( |e| mkdir_error ( path, e) ) ?;
7270
7371 #[ cfg( unix) ]
7472 {
@@ -80,6 +78,29 @@ fn mkdir_impl(path_str: String, options: Option<MkdirOptions>) -> Result<Option<
8078 }
8179}
8280
81+ fn mkdir_error ( path : & Path , err : std:: io:: Error ) -> Error {
82+ let path_display = path. to_string_lossy ( ) ;
83+ match err. kind ( ) {
84+ ErrorKind :: NotFound => Error :: from_reason ( format ! (
85+ "ENOENT: no such file or directory, mkdir '{}'" ,
86+ path_display
87+ ) ) ,
88+ ErrorKind :: AlreadyExists => Error :: from_reason ( format ! (
89+ "EEXIST: file already exists, mkdir '{}'" ,
90+ path_display
91+ ) ) ,
92+ ErrorKind :: PermissionDenied => Error :: from_reason ( format ! (
93+ "EACCES: permission denied, mkdir '{}'" ,
94+ path_display
95+ ) ) ,
96+ ErrorKind :: NotADirectory => Error :: from_reason ( format ! (
97+ "ENOTDIR: not a directory, mkdir '{}'" ,
98+ path_display
99+ ) ) ,
100+ _ => Error :: from_reason ( format ! ( "{}, mkdir '{}'" , err, path_display) ) ,
101+ }
102+ }
103+
83104#[ napi( js_name = "mkdirSync" ) ]
84105pub fn mkdir_sync ( path : String , options : Option < MkdirOptions > ) -> Result < Option < String > > {
85106 mkdir_impl ( path, options)
0 commit comments