Skip to content

Commit 8e54c98

Browse files
committed
mex: symlink reuse code
1 parent 4ecb5f5 commit 8e54c98

File tree

5 files changed

+91
-90
lines changed

5 files changed

+91
-90
lines changed

private/get_mex_sources.m

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@
1010

1111
mac = fullfile(top, "src/macos.cpp");
1212

13+
sym = fullfile(top, "src/symlink_fs.cpp");
14+
1315
srcs = {fullfile(top, "src/is_char_device.cpp"), ...
1416
fullfile(top, "src/set_permissions.cpp"), ...
15-
fullfile(top, "src/create_symlink.cpp"), ...
1617
[fullfile(top, "src/is_rosetta.cpp"), mac], ...
1718
[fullfile(top, "src/windows_shortname.cpp"), win]
1819
};
1920

20-
%% isSymbolicLink() new in R2024b
21-
if ~isMATLABReleaseOlderThan("R2024b")
22-
srcs{end+1} = [fullfile(top, "src/is_symlink.cpp"), win];
21+
%% new in R2024b
22+
if isMATLABReleaseOlderThan("R2024b")
23+
srcs{end+1} = [fullfile(top, "src/is_symlink.cpp"), win, sym];
24+
srcs{end+1} = [fullfile(top, "src/create_symlink.cpp"), win, sym];
2325
end
2426

2527
end

src/create_symlink.cpp

Lines changed: 1 addition & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -7,63 +7,7 @@
77
#include <vector>
88
#include <memory>
99

10-
#if defined(_WIN32)
11-
# define WIN32_LEAN_AND_MEAN
12-
# include <windows.h>
13-
#else
14-
# include <unistd.h> // for symlink()
15-
#endif
16-
17-
#if __has_include(<filesystem>)
18-
# include <filesystem>
19-
# include <system_error>
20-
#endif
21-
22-
23-
bool fs_create_symlink(std::string target, std::string link)
24-
{
25-
// confusing program errors if target is "" -- we'd never make such a symlink in real use.
26-
if(target.empty())
27-
return false;
28-
29-
// macOS needs empty check to avoid SIGABRT
30-
if(link.empty())
31-
return false;
32-
33-
#if defined(__MINGW32__) || (defined(_WIN32) && !defined(__cpp_lib_filesystem))
34-
35-
const DWORD attr = GetFileAttributesA(target.data());
36-
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileattributesa
37-
// https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
38-
39-
if (attr == INVALID_FILE_ATTRIBUTES)
40-
return false;
41-
42-
DWORD p = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
43-
if(attr & FILE_ATTRIBUTE_DIRECTORY)
44-
p |= SYMBOLIC_LINK_FLAG_DIRECTORY;
45-
46-
return CreateSymbolicLinkA(link.data(), target.data(), p);
47-
#elif defined(__cpp_lib_filesystem)
48-
std::error_code ec;
49-
std::filesystem::path t(target);
50-
51-
bool isdir = std::filesystem::is_directory(t, ec);
52-
if (ec)
53-
return false;
54-
55-
isdir
56-
? std::filesystem::create_directory_symlink(t, link, ec)
57-
: std::filesystem::create_symlink(t, link, ec);
58-
59-
return !ec;
60-
#else
61-
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/symlink.2.html
62-
// https://linux.die.net/man/3/symlink
63-
return symlink(target.data(), link.data()) == 0;
64-
#endif
65-
66-
}
10+
#include "symlink_fs.h"
6711

6812

6913
class MexFunction : public matlab::mex::Function {

src/is_symlink.cpp

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,7 @@
1010
#include <vector>
1111
#include <memory>
1212

13-
#if defined(_WIN32)
14-
# include "win32_fs.h"
15-
#endif
16-
17-
#if __has_include(<filesystem>)
18-
# include <filesystem>
19-
# include <system_error>
20-
#endif
21-
22-
#include <sys/types.h>
23-
#include <sys/stat.h>
24-
25-
26-
static bool fs_is_symlink(std::string path)
27-
{
28-
29-
#if defined(__MINGW32__) || (defined(_WIN32) && !defined(__cpp_lib_filesystem))
30-
return fs_win32_is_symlink(path);
31-
#elif defined(__cpp_lib_filesystem)
32-
// std::filesystem::symlink_status doesn't detect symlinks on MinGW
33-
std::error_code ec;
34-
const auto s = std::filesystem::symlink_status(path, ec);
35-
return !ec && std::filesystem::is_symlink(s);
36-
#else
37-
struct stat s;
38-
return lstat(path.data(), &s) == 0 && S_ISLNK(s.st_mode);
39-
#endif
40-
}
41-
13+
#include "symlink_fs.h"
4214

4315
class MexFunction : public matlab::mex::Function {
4416
public:

src/symlink_fs.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#if defined(_WIN32)
2+
# include "win32_fs.h"
3+
#else
4+
# include "unistd.h" // for symlink()
5+
#endif
6+
7+
#include <string>
8+
9+
#if __has_include(<filesystem>)
10+
# include <filesystem>
11+
# include <system_error>
12+
#endif
13+
14+
#include <sys/types.h>
15+
#include <sys/stat.h>
16+
17+
#include "symlink_fs.h"
18+
19+
20+
bool fs_create_symlink(std::string target, std::string link)
21+
{
22+
// confusing program errors if target is "" -- we'd never make such a symlink in real use.
23+
if(target.empty())
24+
return false;
25+
26+
// macOS needs empty check to avoid SIGABRT
27+
if(link.empty())
28+
return false;
29+
30+
#if defined(__MINGW32__) || (defined(_WIN32) && !defined(__cpp_lib_filesystem))
31+
32+
const DWORD attr = GetFileAttributesA(target.data());
33+
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileattributesa
34+
// https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
35+
36+
if (attr == INVALID_FILE_ATTRIBUTES)
37+
return false;
38+
39+
DWORD p = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
40+
if(attr & FILE_ATTRIBUTE_DIRECTORY)
41+
p |= SYMBOLIC_LINK_FLAG_DIRECTORY;
42+
43+
return CreateSymbolicLinkA(link.data(), target.data(), p);
44+
#elif defined(__cpp_lib_filesystem)
45+
std::error_code ec;
46+
std::filesystem::path t(target);
47+
48+
bool isdir = std::filesystem::is_directory(t, ec);
49+
if (ec)
50+
return false;
51+
52+
isdir
53+
? std::filesystem::create_directory_symlink(t, link, ec)
54+
: std::filesystem::create_symlink(t, link, ec);
55+
56+
return !ec;
57+
#else
58+
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/symlink.2.html
59+
// https://linux.die.net/man/3/symlink
60+
return symlink(target.data(), link.data()) == 0;
61+
#endif
62+
}
63+
64+
65+
bool fs_is_symlink(std::string path)
66+
{
67+
68+
#if defined(__MINGW32__) || (defined(_WIN32) && !defined(__cpp_lib_filesystem))
69+
return fs_win32_is_symlink(path);
70+
#elif defined(__cpp_lib_filesystem)
71+
// std::filesystem::symlink_status doesn't detect symlinks on MinGW
72+
std::error_code ec;
73+
const auto s = std::filesystem::symlink_status(path, ec);
74+
return !ec && std::filesystem::is_symlink(s);
75+
#else
76+
struct stat s;
77+
return lstat(path.data(), &s) == 0 && S_ISLNK(s.st_mode);
78+
#endif
79+
}

src/symlink_fs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#include <string>
2+
3+
bool fs_is_symlink(std::string);
4+
bool fs_create_symlink(std::string, std::string);

0 commit comments

Comments
 (0)