1 #include "git-compat-util.h"
2 #include "fsmonitor-ll.h"
3 #include "fsmonitor-path-utils.h"
10 #include <sys/mount.h>
12 int fsmonitor__get_fs_info(const char *path
, struct fs_info
*fs_info
)
15 if (statfs(path
, &fs
) == -1) {
16 int saved_errno
= errno
;
17 trace_printf_key(&trace_fsmonitor
, "statfs('%s') failed: %s",
18 path
, strerror(saved_errno
));
23 trace_printf_key(&trace_fsmonitor
,
24 "statfs('%s') [type 0x%08x][flags 0x%08x] '%s'",
25 path
, fs
.f_type
, fs
.f_flags
, fs
.f_fstypename
);
27 if (!(fs
.f_flags
& MNT_LOCAL
))
28 fs_info
->is_remote
= 1;
30 fs_info
->is_remote
= 0;
32 fs_info
->typename
= xstrdup(fs
.f_fstypename
);
34 trace_printf_key(&trace_fsmonitor
,
36 path
, fs_info
->is_remote
);
40 int fsmonitor__is_fs_remote(const char *path
)
43 if (fsmonitor__get_fs_info(path
, &fs
))
52 * Scan the root directory for synthetic firmlinks that when resolved
53 * are a prefix of the path, stopping at the first one found.
55 * Some information about firmlinks and synthetic firmlinks:
56 * https://eclecticlight.co/2020/01/23/catalina-boot-volumes/
58 * macOS no longer allows symlinks in the root directory; any link found
59 * there is therefore a synthetic firmlink.
61 * If this function gets called often, will want to cache all the firmlink
62 * information, but for now there is only one caller of this function.
64 * If there is more than one alias for the path, that is another
67 int fsmonitor__get_alias(const char *path
, struct alias_info
*info
)
71 const char *const root
= "/";
75 struct strbuf points_to
= STRBUF_INIT
;
79 return error_errno(_("opendir('%s') failed"), root
);
81 strbuf_init(&alias
, 256);
83 while ((de
= readdir(dir
)) != NULL
) {
85 strbuf_addf(&alias
, "%s%s", root
, de
->d_name
);
87 if (lstat(alias
.buf
, &st
) < 0) {
88 error_errno(_("lstat('%s') failed"), alias
.buf
);
92 if (!S_ISLNK(st
.st_mode
))
95 if (strbuf_readlink(&points_to
, alias
.buf
, st
.st_size
) < 0) {
96 error_errno(_("strbuf_readlink('%s') failed"), alias
.buf
);
100 if (!strncmp(points_to
.buf
, path
, points_to
.len
) &&
101 (path
[points_to
.len
] == '/')) {
102 strbuf_addbuf(&info
->alias
, &alias
);
103 strbuf_addbuf(&info
->points_to
, &points_to
);
104 trace_printf_key(&trace_fsmonitor
,
105 "Found alias for '%s' : '%s' -> '%s'",
106 path
, info
->alias
.buf
, info
->points_to
.buf
);
111 retval
= 0; /* no alias */
114 strbuf_release(&alias
);
115 strbuf_release(&points_to
);
116 if (closedir(dir
) < 0)
117 return error_errno(_("closedir('%s') failed"), root
);
121 char *fsmonitor__resolve_alias(const char *path
,
122 const struct alias_info
*info
)
124 if (!info
->alias
.len
)
127 if ((!strncmp(info
->alias
.buf
, path
, info
->alias
.len
))
128 && path
[info
->alias
.len
] == '/') {
129 struct strbuf tmp
= STRBUF_INIT
;
130 const char *remainder
= path
+ info
->alias
.len
;
132 strbuf_addbuf(&tmp
, &info
->points_to
);
133 strbuf_add(&tmp
, remainder
, strlen(remainder
));
134 return strbuf_detach(&tmp
, NULL
);