diff --git a/CMakeLists.txt b/CMakeLists.txt index cd5bf81..dfa88de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,5 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. project(mkdir_r) -add_library(${PROJECT_NAME} STATIC "mkdir_r.c") +set(srcs "mkdir_r.c") + +if(WIN32) + set(${srcs} "${srcs}" "win32.c") +else() + set(${srcs} "${srcs}" "posix.c") +endif() + +add_library(${PROJECT_NAME} STATIC ${srcs}) target_include_directories(${PROJECT_NAME} PUBLIC ".") +target_include_directories(${PROJECT_NAME} PRIVATE "private_include") diff --git a/mkdir_r.c b/mkdir_r.c index 20920e3..b91daae 100644 --- a/mkdir_r.c +++ b/mkdir_r.c @@ -14,13 +14,9 @@ limitations under the License. */ #include "mkdir_r.h" +#include "mkdir_r_private.h" #include #include -#include -#include -#include -#include -#include #include #include @@ -66,19 +62,7 @@ int mkdir_r(const char *const path) if (!*dir) /* Path starting with delimiter character. */ ; - else if (!access(dir, 0)) - { - struct stat sb; - - if (stat(dir, &sb)) - goto exit; - else if (!(sb.st_mode & S_IFDIR)) - { - errno = ENOTDIR; - goto exit; - } - } - else if (mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) + else if (mkdir_r_port(dir)) goto exit; dir = dup; diff --git a/posix.c b/posix.c new file mode 100644 index 0000000..d2d3651 --- /dev/null +++ b/posix.c @@ -0,0 +1,40 @@ +/* + Copyright 2020 Xavier Del Campo Romero + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +#include +#include +#include +#include +#include + +int mkdir_r_port(const char *const dir) +{ + if (!access(dir, 0)) + { + struct stat sb; + + if (stat(dir, &sb)) + return -1; + else if (!(sb.st_mode & S_IFDIR)) + { + errno = ENOTDIR; + return -1; + } + } + else if (mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) + return -1; + + return 0; +} diff --git a/private_include/mkdir_r_private.h b/private_include/mkdir_r_private.h new file mode 100644 index 0000000..12efdbb --- /dev/null +++ b/private_include/mkdir_r_private.h @@ -0,0 +1,28 @@ +/* + Copyright 2020 Xavier Del Campo Romero + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +#ifndef MKDIR_R_PRIVATE_H +#define MKDIR_R_PRIVATE_H + +/** + * Creates a directory using OS-specific API. + * @param dir Directory path. + * @return 0 if successful, -1 otherwise. + * @note Sets @c errno to @c ENOTDIR if one of the elements from @c path is not + * a directory. + */ +int mkdir_r_port(const char *const dir); + +#endif /* MKDIR_R_PRIVATE_H */ diff --git a/win32.c b/win32.c new file mode 100644 index 0000000..eff119b --- /dev/null +++ b/win32.c @@ -0,0 +1,35 @@ +/* + Copyright 2020 Xavier Del Campo Romero + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +#include +#include +#include + +int mkdir_r_port(const char *const dir) +{ + if (!CreateDirectoryA(dir, NULL)) + { + switch (GetLastError()) + { + case ERROR_ALREADY_EXISTS: + break; + + default: + return -1; + } + } + + return 0; +}