cmogstored 1.8.1 - use default system stack size
[cmogstored.git] / fs.c
blobb540ebdc535fedf780b81728f9a4922b760176cc
1 /*
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
16 #ifndef O_NOATIME
17 # define O_NOATIME 0
18 #endif
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
27 * startup.
29 #ifdef O_CLOEXEC
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; \
43 return -1; \
44 } \
45 } while (0)
47 #ifndef HAVE_FSTATAT
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 */
57 #ifdef HAVE_OPENAT
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)
87 int fd;
89 retry:
90 fd = open_read(svc, path);
91 if (fd < 0 && errno != ENOENT && (noatime_flags & O_NOATIME)) {
92 noatime_flags = O_RDONLY;
93 goto retry;
95 return fd;
98 #ifndef HAVE_UNLINKAT
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 */
120 #ifndef HAVE_MKDIRAT
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);
136 if (rc <= 0) {
137 errno = ENAMETOOLONG;
138 return -1;
140 return statvfs(fspath, v);