2 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
3 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
5 * All path operations we support are relative to mog_svc.docroot.
6 * Absolute path lookups are sometimes more expensive, especially
7 * for deeper directory structures, so we'll favor AT_FILE functions.
9 * However, it's somewhat common for systems to have AT_FILE functions
10 * to be available on the system they're built on, but not available
11 * on the system the code is deployed on. We'll provide fallbacks to
12 * the absolute path variants for everything.
14 #include "cmogstored.h"
15 #define MY_PATHMAX 256
20 static int noatime_flags
= O_RDONLY
| O_NOATIME
;
21 static int put_flags
= O_RDWR
;
24 * Like AT_FILE functions, we may be built on systems with O_CLOEXEC and
25 * run on systems without it. O_CLOEXEC is still too recent and was
26 * broken on some Linux kernels, so we always run cloexec_detect.c at
30 void mog_cloexec_works(void)
32 noatime_flags
|= O_CLOEXEC
;
33 put_flags
|= O_CLOEXEC
;
35 #endif /* O_CLOEXEC */
37 /* we only use real *at syscalls, Gnulib workalikes aren't thread-safe */
39 #define GET_FSPATH(DST,SRC) do { \
40 int rc = snprintf((DST), sizeof(DST), "%s%s", svc->docroot, (SRC)); \
41 if (rc <= 0 || rc >= sizeof(DST)) { \
42 errno = ENAMETOOLONG; \
48 int mog_stat(struct mog_svc
*svc
, const char *path
, struct stat
*sb
)
50 char fspath
[MY_PATHMAX
];
52 GET_FSPATH(fspath
, path
);
53 return stat(fspath
, sb
);
55 #endif /* !HAVE_FSTATAT */
58 static int open_read(struct mog_svc
*svc
, const char *path
)
60 return openat(svc
->docroot_fd
, path
+ 1, noatime_flags
);
63 int mog_open_put(struct mog_svc
*svc
, const char *path
, int flags
)
65 return openat(svc
->docroot_fd
, path
+ 1, flags
| put_flags
, 0600);
67 #else /* !HAVE_OPENAT */
68 MOG_NOINLINE
static int open_read(struct mog_svc
*svc
, const char *path
)
70 char fspath
[MY_PATHMAX
];
72 GET_FSPATH(fspath
, path
);
73 return open(fspath
, noatime_flags
);
76 int mog_open_put(struct mog_svc
*svc
, const char *path
, int flags
)
78 char fspath
[MY_PATHMAX
];
80 GET_FSPATH(fspath
, path
);
81 return open(fspath
, flags
| put_flags
, 0600);
83 #endif /* !HAVE_OPENAT */
85 int mog_open_read(struct mog_svc
*svc
, const char *path
)
90 fd
= open_read(svc
, path
);
91 if (fd
< 0 && errno
!= ENOENT
&& (noatime_flags
& O_NOATIME
)) {
92 noatime_flags
= O_RDONLY
;
99 int mog_unlink(struct mog_svc
*svc
, const char *path
)
101 char fspath
[MY_PATHMAX
];
103 GET_FSPATH(fspath
,path
);
104 return unlink(fspath
);
106 #endif /* !HAVE_UNLINKAT */
108 #ifndef HAVE_RENAMEAT
109 int mog_rename(struct mog_svc
*svc
, const char *old
, const char *new)
111 char fsnew
[MY_PATHMAX
];
112 char fsold
[MY_PATHMAX
];
114 GET_FSPATH(fsold
, old
);
115 GET_FSPATH(fsnew
, new);
116 return rename(fsold
, fsnew
);
118 #endif /* !HAVE_RENAMEAT */
121 int mog_mkdir(struct mog_svc
*svc
, const char *path
, mode_t mode
)
123 char fspath
[MY_PATHMAX
];
125 GET_FSPATH(fspath
, path
);
126 return mkdir(fspath
, mode
);
128 #endif /* !HAVE_MKDIRAT */
130 int mog_statvfs(struct mog_svc
*svc
, struct mog_dev
*dev
, struct statvfs
*v
)
132 char fspath
[MY_PATHMAX
];
133 int rc
= snprintf(fspath
, sizeof(fspath
), "%s/dev%u",
134 svc
->docroot
, dev
->devid
);
137 errno
= ENAMETOOLONG
;
140 return statvfs(fspath
, v
);