2 #define _FILE_OFFSET_BITS 64
10 #include <sys/param.h>
12 # include <sys/statvfs.h>
13 # include <sys/ucred.h>
14 # include <sys/mount.h>
23 #pragma GCC diagnostic ignored "-Wformat" // shut warning on '%z'
63 static const char procfs[] =
"/proc/filesystems";
64 FILE *fs = fopen(procfs,
"r");
69 <<
"Cannot read '" << procfs <<
"': "
70 << strerror(nerr) <<
" (error " << nerr <<
")";
83 if ((nread = getdelim(&type, &len,
'\t', fs)) == -1 && ! feof(fs))
85 fprintf(stderr,
"%s:%d: %s (%zd; 1)\n",
86 procfs, line, strerror(errno), nread);
92 if ((nread = getdelim(&fstype, &len,
'\n', fs)) == -1 && ! feof(fs))
94 fprintf(stderr,
"%s:%d: %s (%zd; 2)\n",
95 procfs, line, strerror(errno), nread);
109 if (! strcmp(type,
"nodev\t")
110 || ! strcmp(fstype,
"lustre\n")
111 || ! strncmp(fstype,
"fuse", 4))
143 struct statfs *
m =
static_cast<struct statfs *
>(
arg);
144 size_t infolen =
sizeof(
struct FSInfo);
145 size_t fslen = strlen(m->f_mntfromname) + 1;
146 size_t dirlen = strlen(m->f_mntonname) + 1;
147 size_t typelen = strlen(m->f_fstypename) + 1;
148 size_t totlen = infolen + fslen + dirlen + typelen;
150 char *
p = (
char *) i;
151 i->
fsname = strncpy(p += infolen, m->f_mntfromname, fslen);
152 i->
type = strncpy(p += fslen, m->f_fstypename, typelen);
153 i->
dir = strncpy(p += typelen, m->f_mntonname, dirlen);
154 i->
dev = m->f_fsid.val[0];
161 i->
freespc /= 1024. * 1024. * 1024.;
169 i->
local = ((m->f_flags & MNT_LOCAL) ? 1 : 0);
174 mntent *m =
static_cast<mntent *
>(
arg);
175 size_t infolen =
sizeof(
struct FSInfo);
176 size_t fslen = strlen(m->mnt_fsname) + 1;
177 size_t dirlen = strlen(m->mnt_dir) + 1;
178 size_t typelen = strlen(m->mnt_type) + 1;
179 size_t totlen = infolen + fslen + dirlen + typelen;
181 char *p = (
char *) i;
182 i->
fsname = strncpy(p += infolen, m->mnt_fsname, fslen);
183 i->
type = strncpy(p += fslen, m->mnt_type, typelen);
184 i->
dir = strncpy(p += typelen, m->mnt_dir, dirlen);
210 struct statfs *mtab = 0;
211 if ((rc = getmntinfo(&mtab, MNT_NOWAIT)) < 0)
215 <<
"getmntinfo() failed: " << strerror(nerr)
216 <<
" (error " << nerr <<
")";
221 for (
int ix = 0; ix < rc; ++ix)
227 FILE *mtab = setmntent(_PATH_MOUNTED,
"r");
232 <<
"Cannot read '" << _PATH_MOUNTED <<
"': "
233 << strerror(nerr) <<
" (error " << nerr <<
")";
238 while ((m = getmntent(mtab)))
265 if (lstat(i->
dir, &s) < 0)
268 if (nerr != ENOENT && nerr != EACCES)
270 <<
"Cannot lstat('" << i->
dir <<
"'): "
271 << strerror(nerr) <<
" (error " << nerr <<
")";
275 if (statfs(i->
dir, &sfs) < 0)
279 <<
"Cannot statfs('" << i->
dir <<
"'): "
280 << strerror(nerr) <<
" (error " << nerr <<
")";
290 i->
freespc /= 1024. * 1024. * 1024.;
320 size_t len = strlen(path);
321 for (
size_t i = 0;
i <
fs_.size(); ++
i)
325 size_t fslen = strlen(
fs_[
i]->
dir);
326 if (! strncmp(
fs_[
i]->
dir, path, fslen)
327 && ((fslen == 1 &&
fs_[
i]->
dir[0] ==
'/')
328 || len == fslen || path[fslen] ==
'/')
329 && (! best || fslen > bestlen))
340 if (
fs_[i]->dev != s->st_dev ||
fs_[i]->fstype != sfs->f_type)
369 char *fullpath = realpath(path.c_str(), 0);
372 fullpath = strdup(path.c_str());
374 if (lstat(fullpath, &s) < 0)
378 <<
"Cannot lstat('" << fullpath <<
"' alias '"
379 << path <<
"'): " << strerror(nerr) <<
" (error "
385 if (statfs(fullpath, &sfs) < 0)
389 <<
"Cannot statfs('" << fullpath <<
"' alias '"
390 << path <<
"'): " << strerror(nerr) <<
" (error "
399 return m ? m->
local :
false;
426 for (
size_t i = 0,
e = paths.size();
i <
e; ++
i)
429 const char *inpath = paths[
i].c_str();
430 const char *
path = inpath;
434 char *
p = getenv(path+1);
437 else if (! strcmp(path,
"$TMPDIR"))
441 if (! (fullpath = realpath(path, 0)))
442 fullpath = strdup(path);
446 <<
"Checking if '" << fullpath <<
"', from '"
447 << inpath <<
"' is valid cache path with "
448 << minFreeSpace <<
" free space" << std::endl;
451 if (lstat(fullpath, &s) < 0)
454 if (nerr != ENOENT && nerr != EACCES)
456 <<
"Cannot lstat('" << fullpath <<
"', from '"
457 << inpath <<
"'): " << strerror(nerr) <<
" (error "
463 if (statfs(fullpath, &sfs) < 0)
467 <<
"Cannot statfs('" << fullpath <<
"', from '"
468 << inpath <<
"'): " << strerror(nerr) <<
" (error "
477 <<
"Candidate '" << fullpath <<
"': "
478 <<
"found=" << (m ? 1 : 0)
479 <<
" local=" << (m && m->
local)
480 <<
" free=" << (m ? m->
freespc : 0)
481 <<
" access=" << access(fullpath, W_OK)
488 && access(fullpath, W_OK) == 0)
490 std::string
result(fullpath);
498 return std::string();
514 for (
size_t i = 0,
e =
fs_.size();
i <
e; ++
i)
int statFSInfo(FSInfo *i)
Information about file systems on this node.
FSInfo * findMount(const char *path, struct statfs *sfs, struct stat *s)
std::string findCachePath(const std::vector< std::string > &paths, double minFreeSpace)
bool isLocalPath(const std::string &path)
std::vector< std::string > fstypes_
FSInfo * initFSInfo(void *p)
std::vector< FSInfo * > fs_