*
*********************************************************/
-#ifndef _POSIX_H_
-#define _POSIX_H_
+#ifndef VMWARE_POSIX_H
+#define VMWARE_POSIX_H
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMCORE
int Posix_Lstat(const char *pathName, struct stat *statbuf);
char *Posix_MkTemp(const char *pathName);
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Posix_Free --
+ *
+ * Wrapper around free() that preserves errno.
+ *
+ * C11 (and earlier) does not prohibit free() implementations from
+ * modifying errno. That is undesirable since it can clobber errno along
+ * cleanup paths, and it is expected to be prohibited by a future (as of
+ * January 2017) version of the POSIX standard. See:
+ * <http://stackoverflow.com/a/30571921/179715>
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE void
+Posix_Free(void *p) // IN
+{
+ int err = errno;
+ free(p);
+ errno = err;
+}
+
+
#if !defined(_WIN32)
/*
* These Windows APIs actually work with non-ASCII (MBCS) strings.
#if !defined(__APPLE__) && !defined(__FreeBSD__)
int Posix_Mount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
- const void *data);
+ const void *data);
int Posix_Umount(const char *target);
FILE *Posix_Setmntent(const char *pathName, const char *mode);
struct mntent *Posix_Getmntent(FILE *fp);
char **p;
if (he) {
+ // See Posix_Free.
+ int err = errno;
free(he->h_name);
if (he->h_aliases) {
Util_FreeStringList(he->h_aliases, -1);
}
free(he->h_addr_list);
free(he);
+ errno = err;
}
#else
(void) he;
retval = -1;
WSASetLastError(WSAEFAULT);
}
- free(nameUTF8);
+ Posix_Free(nameUTF8);
}
- free(nameMBCS);
+ Posix_Free(nameMBCS);
return retval;
}
if (nameMBCS != NULL) {
hostentMBCS = gethostbyname(nameMBCS);
- free(nameMBCS);
+ Posix_Free(nameMBCS);
if (hostentMBCS != NULL) {
newhostent = (struct hostent *)Util_SafeMalloc(sizeof *newhostent);
Posix_FreeHostent(struct hostent *he)
{
if (he) {
- free(he->h_name);
+ Posix_Free(he->h_name);
if (he->h_aliases) {
Util_FreeStringList(he->h_aliases, -1);
}
- free(he);
+ Posix_Free(he);
}
}
#endif // defined(_WINSOCKAPI_) || defined(_WINSOCK2API_)
FreeAddrInfoW(resW);
}
- free(nodenameW);
- free(servnameW);
+ Posix_Free(nodenameW);
+ Posix_Free(servnameW);
return retval;
}
{
struct addrinfo *temp;
+ // See Posix_Free.
+ int err = errno;
while (ai) {
temp = ai;
ai = ai->ai_next;
free(temp->ai_addr);
free(temp);
}
+ errno = err;
}
}
exit:
- free(hostW);
- free(servW);
- free(hostUTF8);
- free(servUTF8);
+ Posix_Free(hostW);
+ Posix_Free(servW);
+ Posix_Free(hostUTF8);
+ Posix_Free(servUTF8);
return retval;
}
} // extern "C"
#endif
-#endif // _POSIX_H_
+#endif // VMWARE_POSIX_H
size_t bufSize) // IN
{
if (buf != NULL) {
+ // See Posix_Free.
+ int err = errno;
Util_Zero(buf, bufSize);
free(buf);
+ errno = err;
}
}
Util_ZeroFreeString(char *str) // IN/OUT/OPT
{
if (str != NULL) {
+ // See Posix_Free.
+ int err = errno;
Util_ZeroString(str);
free(str);
+ errno = err;
}
}
Util_ZeroFreeStringW(wchar_t *str) // IN/OUT/OPT
{
if (str != NULL) {
+ // See Posix_Free.
+ int err = errno;
Util_Zero(str, wcslen(str) * sizeof *str);
free(str);
+ errno = err;
}
}
#endif // _WIN32
Util_FreeList(void **list, // IN/OUT/OPT: the list to free
ssize_t length) // IN: the length
{
+ // See Posix_Free.
+ int err;
+
if (list == NULL) {
ASSERT(length <= 0);
return;
}
+ err = errno;
+
if (length >= 0) {
ssize_t i;
}
}
free(list);
+ errno = err;
}
static INLINE void
ret = dlopen(path, flag);
- free(path);
+ Posix_Free(path);
return ret;
}
#endif
}
ht = HashTable_AllocOnce(&htPtr, 128,
- HASH_FLAG_ATOMIC | HASH_FLAG_COPYKEY |
- HASH_STRING_KEY,
+ HASH_FLAG_ATOMIC | HASH_FLAG_COPYKEY |
+ HASH_STRING_KEY,
PosixEnvFree);
/*
*/
if (!HashTable_Lookup(ht, name, (void **) &e)) {
- e = Util_SafeMalloc(sizeof *e);
- Atomic_WritePtr(&e->value, value);
- Atomic_WritePtr(&e->lastValue, NULL);
- if (!HashTable_Insert(ht, name, e)) {
- free(e);
- continue;
- }
- break;
+ e = Util_SafeMalloc(sizeof *e);
+ Atomic_WritePtr(&e->value, value);
+ Atomic_WritePtr(&e->lastValue, NULL);
+ if (!HashTable_Insert(ht, name, e)) {
+ Posix_Free(e);
+ continue;
+ }
+ break;
}
/*
oldValue = Atomic_ReadPtr(&e->value);
if (Str_Strcmp(oldValue, value) == 0) {
- free(value);
- value = oldValue;
- break;
+ Posix_Free(value);
+ value = oldValue;
+ break;
}
/*
*/
if (Atomic_ReadIfEqualWritePtr(&e->value, oldValue, value) == oldValue) {
- oldValue = Atomic_ReadWritePtr(&e->lastValue, oldValue);
- free(oldValue);
- break;
+ oldValue = Atomic_ReadWritePtr(&e->lastValue, oldValue);
+ Posix_Free(oldValue);
+ break;
}
}
fd = open(path, flags, mode);
- free(path);
+ Posix_Free(path);
return fd;
}
stream = fopen(path, mode);
- free(path);
+ Posix_Free(path);
return stream;
}
ret = stat(path, statbuf);
- free(path);
+ Posix_Free(path);
return ret;
}
ret = chmod(path, mode);
- free(path);
+ Posix_Free(path);
return ret;
}
return -1;
}
if (!PosixConvertToCurrent(toPathName, &toPath)) {
- free(fromPath);
+ Posix_Free(fromPath);
return -1;
}
result = rename(fromPath, toPath);
- free(toPath);
- free(fromPath);
+ Posix_Free(toPath);
+ Posix_Free(fromPath);
return result;
}
ret = unlink(path);
- free(path);
+ Posix_Free(path);
return ret;
}
ret = rmdir(path);
- free(path);
+ Posix_Free(path);
return ret;
}
stream = freopen(path, mode, input_stream);
- free(path);
+ Posix_Free(path);
return stream;
}
ret = access(path, mode);
#endif
- free(path);
+ Posix_Free(path);
return ret;
}
ret = euidaccess(path, mode);
- free(path);
+ Posix_Free(path);
return ret;
#else
errno = ENOSYS;
ret = utime(path, times);
- free(path);
+ Posix_Free(path);
return ret;
}
// ignore conversion error silently
perror(tmpstr);
- free(tmpstr);
+ Posix_Free(tmpstr);
}
ret = pathconf(path, name);
- free(path);
+ Posix_Free(path);
return ret;
}
stream = popen(path, mode);
- free(path);
+ Posix_Free(path);
return stream;
}
ret = mknod(path, mode, dev);
- free(path);
+ Posix_Free(path);
return ret;
}
ret = chown(path, owner, group);
- free(path);
+ Posix_Free(path);
return ret;
}
ret = lchown(path, owner, group);
- free(path);
+ Posix_Free(path);
return ret;
}
return -1;
}
if (!PosixConvertToCurrent(pathName2, &path2)) {
- free(path1);
+ Posix_Free(path1);
return -1;
}
ret = link(path1, path2);
- free(path1);
- free(path2);
+ Posix_Free(path1);
+ Posix_Free(path2);
return ret;
}
return -1;
}
if (!PosixConvertToCurrent(pathName2, &path2)) {
- free(path1);
+ Posix_Free(path1);
return -1;
}
ret = symlink(path1, path2);
- free(path1);
- free(path2);
+ Posix_Free(path1);
+ Posix_Free(path2);
return ret;
}
ret = mkfifo(path, mode);
- free(path);
+ Posix_Free(path);
return ret;
}
ret = truncate(path, length);
- free(path);
+ Posix_Free(path);
return ret;
}
ret = utimes(path, times);
- free(path);
+ Posix_Free(path);
return ret;
}
ret = execv(path, argv);
exit:
- if (argv) {
- Util_FreeStringList(argv, -1);
- }
- free(path);
+ Util_FreeStringList(argv, -1);
+ Posix_Free(path);
return ret;
}
ret = execvp(file, argv);
exit:
- if (argv) {
- Util_FreeStringList(argv, -1);
- }
- free(file);
+ Util_FreeStringList(argv, -1);
+ Posix_Free(file);
return ret;
}
ret = execv(path, argv);
exit:
- if (argv) {
- Util_FreeStringList(argv, -1);
- }
- free(path);
+ Util_FreeStringList(argv, -1);
+ Posix_Free(path);
return ret;
}
int
Posix_Execve(const char *pathName, // IN:
- char *const argVal[], // IN:
+ char *const argVal[], // IN:
char *const envPtr[]) // IN:
{
int ret = -1;
ret = execve(path, argv, envp);
exit:
- if (argv) {
- Util_FreeStringList(argv, -1);
- }
- if (envp) {
- Util_FreeStringList(envp, -1);
- }
- free(path);
+ Util_FreeStringList(argv, -1);
+ Util_FreeStringList(envp, -1);
+ Posix_Free(path);
return ret;
}
ret = execvp(file, argv);
exit:
- if (argv) {
- Util_FreeStringList(argv, -1);
- }
- free(file);
+ Util_FreeStringList(argv, -1);
+ Posix_Free(file);
return ret;
}
ret = system(tmpcommand);
- free(tmpcommand);
+ Posix_Free(tmpcommand);
return ret;
}
ret = mkdir(path, mode);
- free(path);
+ Posix_Free(path);
return ret;
}
ret = chdir(path);
- free(path);
+ Posix_Free(path);
return ret;
}
p = realpath(path, rpath);
- free(path);
+ Posix_Free(path);
return p == NULL ? NULL : Unicode_Alloc(rpath, STRING_ENCODING_DEFAULT);
}
ssize_t len = readlink(path, linkPath, size);
if (len == -1) {
- free(linkPath);
+ Posix_Free(linkPath);
break;
}
if (len < size) {
linkPath[len] = '\0'; // Add the missing NUL to path
result = Unicode_Alloc(linkPath, STRING_ENCODING_DEFAULT);
- free(linkPath);
+ Posix_Free(linkPath);
break;
}
- free(linkPath);
+ Posix_Free(linkPath);
size += 1024;
}
}
- free(path);
+ Posix_Free(path);
return result;
}
ret = lstat(path, statbuf);
- free(path);
+ Posix_Free(path);
return ret;
}
ret = opendir(path);
- free(path);
+ Posix_Free(path);
return ret;
}
return NULL;
}
rawValue = getenv(rawName);
- free(rawName);
+ Posix_Free(rawName);
if (rawValue == NULL) {
return NULL;
}
return PosixGetenvHash(name, Unicode_Alloc(rawValue,
- STRING_ENCODING_DEFAULT));
+ STRING_ENCODING_DEFAULT));
}
ret = statfs(path, statfsbuf);
- free(path);
+ Posix_Free(path);
return ret;
}
#endif
exit:
- free(rawName);
- free(rawValue);
+ Posix_Free(rawName);
+ Posix_Free(rawValue);
return ret;
}
#else
unsetenv(rawName);
#endif
- free(rawName);
+ Posix_Free(rawName);
}
ret = mount(tmpsource, tmptarget, filesystemtype, mountflags, data);
exit:
- free(tmpsource);
- free(tmptarget);
+ Posix_Free(tmpsource);
+ Posix_Free(tmptarget);
return ret;
}
ret = umount(tmptarget);
- free(tmptarget);
+ Posix_Free(tmptarget);
return ret;
}
return NULL;
}
stream = setmntent(path, mode);
- free(path);
+ Posix_Free(path);
return stream;
#endif
}
/* Free static structure string pointers before reuse. */
- free(sm.mnt_fsname);
+ Posix_Free(sm.mnt_fsname);
sm.mnt_fsname = NULL;
- free(sm.mnt_dir);
+ Posix_Free(sm.mnt_dir);
sm.mnt_dir = NULL;
- free(sm.mnt_type);
+ Posix_Free(sm.mnt_type);
sm.mnt_type = NULL;
- free(sm.mnt_opts);
+ Posix_Free(sm.mnt_opts);
sm.mnt_opts = NULL;
/* Fill out structure with new values. */
exit:
- free(fsname);
- free(dir);
- free(type);
- free(opts);
+ Posix_Free(fsname);
+ Posix_Free(dir);
+ Posix_Free(type);
+ Posix_Free(opts);
if (ret != 0) {
errno = ret;
}
numChars = printf("%s", outCurr);
- free(output);
- free(outCurr);
+ Posix_Free(output);
+ Posix_Free(outCurr);
return numChars;
}
}
nOutput = fprintf(stream, "%s", outCurr);
- free(output);
- free(outCurr);
+ Posix_Free(output);
+ Posix_Free(outCurr);
return nOutput;
}
ret = getmntent(fp, mp);
if (ret == 0) {
- free(m.mnt_special);
- free(m.mnt_mountp);
- free(m.mnt_fstype);
- free(m.mnt_mntopts);
- free(m.mnt_time);
+ Posix_Free(m.mnt_special);
+ Posix_Free(m.mnt_mountp);
+ Posix_Free(m.mnt_fstype);
+ Posix_Free(m.mnt_mntopts);
+ Posix_Free(m.mnt_time);
m.mnt_special = Unicode_Alloc(mp->mnt_special, STRING_ENCODING_DEFAULT);
m.mnt_mountp = Unicode_Alloc(mp->mnt_mountp, STRING_ENCODING_DEFAULT);
m.mnt_fstype = Unicode_Alloc(mp->mnt_fstype, STRING_ENCODING_DEFAULT);
unlink(path);
result = Unicode_Alloc(path, STRING_ENCODING_DEFAULT);
}
- free(path);
+ Posix_Free(path);
return result;
}
return NULL;
}
pw = getpwnam(tmpname);
- free(tmpname);
+ Posix_Free(tmpname);
return GetpwInternal(pw);
}
}
/* Free static structure string pointers before reuse. */
- free(spw.pw_passwd);
+ Posix_Free(spw.pw_passwd);
spw.pw_passwd = NULL;
- free(spw.pw_dir);
+ Posix_Free(spw.pw_dir);
spw.pw_dir = NULL;
- free(spw.pw_name);
+ Posix_Free(spw.pw_name);
spw.pw_name = NULL;
#if !defined __ANDROID__
- free(spw.pw_gecos);
+ Posix_Free(spw.pw_gecos);
spw.pw_gecos = NULL;
#endif
- free(spw.pw_shell);
+ Posix_Free(spw.pw_shell);
spw.pw_shell = NULL;
#if defined(__FreeBSD__)
- free(spw.pw_class);
+ Posix_Free(spw.pw_class);
spw.pw_class = NULL;
#endif
/*
*----------------------------------------------------------------------
+ *
* Posix_Getpwent --
*
* POSIX getpwent()
ret = EmulateGetpwnam_r(tmpname, pw, buf, size, ppw);
#endif
- free(tmpname);
+ Posix_Free(tmpname);
// ret is errno on failure, *ppw is NULL if no matching entry found.
if (ret != 0 || *ppw == NULL) {
ret = 0;
exit:
- free(passwd);
- free(dir);
- free(pwname);
+ Posix_Free(passwd);
+ Posix_Free(dir);
+ Posix_Free(pwname);
#if !defined __ANDROID__
- free(gecos);
+ Posix_Free(gecos);
#endif
- free(shell);
+ Posix_Free(shell);
return ret;
}
*ngroups = 1;
if (n < 1) {
- return -1;
+ return -1;
}
ASSERT(groups != NULL);
*groups = group;
ret = getgrouplist(tmpuser, group, groups, ngroups);
- free(tmpuser);
+ Posix_Free(tmpuser);
return ret;
}
/*
*----------------------------------------------------------------------
+ *
* Posix_Getgrnam --
*
* POSIX getgrnam()
return NULL;
}
gr = getgrnam(tmpname);
- free(tmpname);
+ Posix_Free(tmpname);
if (!gr) {
return NULL;
}
/* Free static structure string pointers before reuse. */
- free(sgr.gr_name);
+ Posix_Free(sgr.gr_name);
sgr.gr_name = NULL;
- free(sgr.gr_passwd);
+ Posix_Free(sgr.gr_passwd);
sgr.gr_passwd = NULL;
- if (sgr.gr_mem != NULL) {
- Util_FreeStringList(sgr.gr_mem, -1);
- sgr.gr_mem = NULL;
- }
+ Util_FreeStringList(sgr.gr_mem, -1);
+ sgr.gr_mem = NULL;
/* Fill out structure with new values. */
sgr.gr_gid = gr->gr_gid;
#else
ret = EmulateGetgrnam_r(tmpname, gr, buf, size, pgr);
#endif
- free(tmpname);
+ Posix_Free(tmpname);
// ret is errno on failure, *pgr is NULL if no matching entry found.
if (ret != 0 || *pgr == NULL) {
size_t len = strlen(grmem[i]) + 1;
if (n + len > size) {
- goto exit;
+ goto exit;
}
gr->gr_mem[i] = memcpy(buf + n, grmem[i], len);
n += len;
ret = 0;
exit:
- free(grpasswd);
- free(grname);
- if (grmem) {
- Util_FreeStringList(grmem, -1);
- }
+ Posix_Free(grpasswd);
+ Posix_Free(grname);
+ Util_FreeStringList(grmem, -1);
return ret;
}