Hi, I had a customer which had reported that the ksh run into problem if the /tmp partition on his system had no space left due to a process gone wild:
Last login: Tue Oct 23 15:12:00 2012 from ... /etc/profile: line 12: write to 1 failed [No space left on device] /etc/profile: line 41: write to 1 failed [No space left on device] /etc/profile: line 87: write to 1 failed [No space left on device] /etc/profile: line 88: write to 1 failed [No space left on device] /etc/profile: line 91: write to 1 failed [No space left on device] /etc/profile: line 92: write to 1 failed [No space left on device] /etc/profile: line 93: write to 1 failed [No space left on device] /usr/bin/manpath: can't set the locale; make sure $LC_* and $LANG are correct /etc/profile: line 207: write to 1 failed [No space left on device] /etc/profile[324]: .: line 606: write to 4 failed [No space left on device] also the ksh93u-2012-02-29 sometimes crash in src/cmd/ksh93/sh/subshell.c which seems to be fixed in current ksh. Nevertheless IMHO the ksh should check not only if access is allowed in /tmp or /usr/tmp (which points to /var/tmp) but also if there is enough room left. If no space is left on the temporary device it would be perfect to use pipe() as fallback for stdout. See the attached patch for a suggested solution. The change in src/lib/libast/path/pathtemp.c uses statvfs() to check if the device has at least space of the sitze of one page left. The change in src/lib/libast/sfio/sftmp.c use the /dev/shm tmpfs which is used for POSIX shared memory objects. One could use shm_open()/shm_unlink() but the file descriptor then has FD_CLOEXEC set in its flags. Werner -- "Having a smoking section in a restaurant is like having a peeing section in a swimming pool." -- Edward Burr
--- src/lib/libast/path/pathtemp.c +++ src/lib/libast/path/pathtemp.c 2012-10-25 10:35:14.510345073 +0000 @@ -73,15 +73,49 @@ #include <ls.h> #include <tv.h> #include <tm.h> +#include <error.h> #define ATTEMPT 10 #define TMP_ENV "TMPDIR" #define TMP_PATH_ENV "TMPPATH" #define TMP1 "/tmp" -#define TMP2 "/usr/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 ch 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 ch 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) --- src/lib/libast/sfio/sftmp.c +++ src/lib/libast/sfio/sftmp.c 2012-10-25 12:09:18.026344912 +0000 @@ -20,6 +20,14 @@ * * ***********************************************************************/ #include "sfhdr.h" +#if _PACKAGE_ast +# if defined(__linux__) && _lib_statfs +# include <sys/statfs.h> +# 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);
_______________________________________________ ast-developers mailing list ast-developers@research.att.com https://mailman.research.att.com/mailman/listinfo/ast-developers