/* * os_mkstemp -- generate a unique temporary filename from template */ int os_mkstemp(char *temp) { unsigned rnd; wchar_t *utemp = util_toUTF16(temp); if (utemp == NULL) return -1; wchar_t *path = _wmktemp(utemp); if (path == NULL) { util_free_UTF16(utemp); return -1; } wchar_t *npath = Malloc(sizeof(*npath) * wcslen(path) + _MAX_FNAME); if (npath == NULL) { util_free_UTF16(utemp); return -1; } wcscpy(npath, path); util_free_UTF16(utemp); /* * Use rand_s to generate more unique tmp file name than _mktemp do. * In case with multiple threads and multiple files even after close() * file name conflicts occurred. * It resolved issue with synchronous removing * multiples files by system. */ rand_s(&rnd); int ret = _snwprintf(npath + wcslen(npath), _MAX_FNAME, L"%u", rnd); if (ret < 0) goto out; /* * Use O_TEMPORARY flag to make sure the file is deleted when * the last file descriptor is closed. Also, it prevents opening * this file from another process. */ ret = _wopen(npath, O_RDWR | O_CREAT | O_EXCL | O_TEMPORARY, S_IWRITE | S_IREAD); out: Free(npath); return ret; }
int os_execv(const char *path, char *const argv[]) { wchar_t *wpath = util_toUTF16(path); if (wpath == NULL) return -1; int argc = 0; while (argv[argc]) argc++; int ret; wchar_t **wargv = Zalloc((argc + 1) * sizeof(wargv[0])); if (!wargv) { ret = -1; goto wargv_alloc_failed; } for (int i = 0; i < argc; ++i) { wargv[i] = util_toUTF16(argv[i]); if (!wargv[i]) { ret = -1; goto end; } } intptr_t iret = _wexecv(wpath, wargv); if (iret == 0) ret = 0; else ret = -1; end: for (int i = 0; i < argc; ++i) util_free_UTF16(wargv[i]); Free(wargv); wargv_alloc_failed: util_free_UTF16(wpath); return ret; }
/* * os_chmod -- chmod abstraction layer */ int os_chmod(const char *pathname, mode_t mode) { wchar_t *path = util_toUTF16(pathname); if (path == NULL) return -1; int ret = _wchmod(path, mode); util_free_UTF16(path); return ret; }
/* * os_access -- access abstraction layer */ int os_access(const char *pathname, int mode) { wchar_t *path = util_toUTF16(pathname); if (path == NULL) return -1; int ret = _waccess(path, mode); util_free_UTF16(path); return ret; }
/* * os_unlink -- unlink abstraction layer */ int os_unlink(const char *pathname) { wchar_t *path = util_toUTF16(pathname); if (path == NULL) return -1; int ret = _wunlink(path); util_free_UTF16(path); return ret; }
/* * os_stat -- stat abstraction layer */ int os_stat(const char *pathname, os_stat_t *buf) { wchar_t *path = util_toUTF16(pathname); if (path == NULL) return -1; int ret = _wstat64(path, buf); util_free_UTF16(path); return ret; }
/* * os_fopen -- fopen abstraction layer */ FILE * os_fopen(const char *pathname, const char *mode) { wchar_t *path = util_toUTF16(pathname); if (path == NULL) return NULL; wchar_t *wmode = util_toUTF16(mode); if (path == NULL) { util_free_UTF16(path); return NULL; } FILE *ret = _wfopen(path, wmode); util_free_UTF16(path); util_free_UTF16(wmode); os_skipBOM(ret); return ret; }
/* * os_open -- open abstraction layer */ int os_open(const char *pathname, int flags, ...) { wchar_t *path = util_toUTF16(pathname); if (path == NULL) return -1; int ret; if (flags & O_CREAT) { va_list arg; va_start(arg, flags); mode_t mode = va_arg(arg, mode_t); va_end(arg); ret = _wopen(path, flags, mode); } else { ret = _wopen(path, flags); } util_free_UTF16(path); /* BOM skipping should not modify errno */ int orig_errno = errno; /* * text files on windows can contain BOM. As we open files * in binary mode we have to detect bom and skip it */ if (ret != -1) { char bom[3]; if (_read(ret, bom, sizeof(bom)) != 3 || memcmp(bom, UTF8_BOM, 3) != 0) { /* UTF-8 bom not found - reset file to the beginning */ lseek(ret, 0, SEEK_SET); } } errno = orig_errno; return ret; }