diff --git a/src/lib/libast/path/pathtemp.c b/src/lib/libast/path/pathtemp.c index 9ace96189..e9d252336 100644 --- a/src/lib/libast/path/pathtemp.c +++ b/src/lib/libast/path/pathtemp.c @@ -73,6 +73,7 @@ #include #include #include +#include #define ATTEMPT 10 @@ -81,7 +82,40 @@ #define TMP1 "/tmp" #define TMP2 "/var/tmp" -#define VALID(d) (*(d)&&!eaccess(d,W_OK|X_OK)) +static inline int xaccess(const char *path, int mode) +{ + static size_t pgsz; + struct statvfs vfs; + int ret; + + if (!pgsz) + pgsz = strtoul(astconf("PAGESIZE",NiL,NiL),NiL,0); + + if (!path || !*path) + { + errno = EFAULT; + goto err; + } + + do + ret = statvfs(path, &vfs); + while (ret < 0 && errno == EINTR); + + if (ret < 0) + goto err; + + if (vfs.f_frsize*vfs.f_bavail < pgsz) + { + errno = ENOSPC; + goto err; + } + + return eaccess(path, mode); +err: + return -1; +} + +#define VALID(d) (*(d)&&!xaccess(d,W_OK|X_OK)) static struct { @@ -182,7 +216,7 @@ pathtemp(char* buf, size_t len, const char* dir, const char* pfx, int* fdp) tv.tv_nsec = 0; else tvgettime(&tv); - if (!(d = (char*)dir) || *d && eaccess(d, W_OK|X_OK)) + if (!(d = (char*)dir) || (*d && xaccess(d, W_OK|X_OK))) { if (!tmp.vec) { @@ -227,7 +261,7 @@ pathtemp(char* buf, size_t len, const char* dir, const char* pfx, int* fdp) tmp.dir = tmp.vec; d = *tmp.dir++; } - if (!d && (!*(d = astconf("TMP", NiL, NiL)) || eaccess(d, W_OK|X_OK)) && eaccess(d = TMP1, W_OK|X_OK) && eaccess(d = TMP2, W_OK|X_OK)) + if (!d && (!*(d = astconf("TMP", NiL, NiL)) || xaccess(d, W_OK|X_OK)) && xaccess(d = TMP1, W_OK|X_OK) && xaccess(d = TMP2, W_OK|X_OK)) return 0; } if (!len) diff --git a/src/lib/libast/sfio/sftmp.c b/src/lib/libast/sfio/sftmp.c index cdbfa4cd5..051314f9b 100644 --- a/src/lib/libast/sfio/sftmp.c +++ b/src/lib/libast/sfio/sftmp.c @@ -20,6 +20,14 @@ * * ***********************************************************************/ #include "sfhdr.h" +#if _PACKAGE_ast +# if defined(__linux__) && _lib_statfs +# include +# ifndef TMPFS_MAGIC +# define TMPFS_MAGIC 0x01021994 +# endif +# endif +#endif /* Create a temporary stream for read/write. ** The stream is originally created as a memory-resident stream. @@ -207,7 +215,24 @@ Sfio_t* f; int fd; #if _PACKAGE_ast +# if defined(__linux__) && _lib_statfs + /* + * Use the area of POSIX shared memory objects for the new temporary file descriptor + * that is do not access HD or SSD but only the memory based tmpfs of the POSIX SHM + */ + static int doshm; + static char *shm = "/dev/shm"; + if (!doshm) + { + struct statfs fs; + if (statfs(shm, &fs) < 0 || fs.f_type != TMPFS_MAGIC || eaccess(shm, W_OK|X_OK)) + shm = NiL; + doshm++; + } + if(!(file = pathtemp(NiL,PATH_MAX,shm,"sf",&fd))) +# else if(!(file = pathtemp(NiL,PATH_MAX,NiL,"sf",&fd))) +# endif return -1; _rmtmp(f, file); free(file);