1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
|
#include <string.h>
#include "jimiocompat.h"
void Jim_SetResultErrno(Jim_Interp *interp, const char *msg)
{
Jim_SetResultFormatted(interp, "%s: %s", msg, strerror(Jim_Errno()));
}
#if defined(__MINGW32__)
#include <sys/stat.h>
int Jim_Errno(void)
{
switch (GetLastError()) {
case ERROR_FILE_NOT_FOUND: return ENOENT;
case ERROR_PATH_NOT_FOUND: return ENOENT;
case ERROR_TOO_MANY_OPEN_FILES: return EMFILE;
case ERROR_ACCESS_DENIED: return EACCES;
case ERROR_INVALID_HANDLE: return EBADF;
case ERROR_BAD_ENVIRONMENT: return E2BIG;
case ERROR_BAD_FORMAT: return ENOEXEC;
case ERROR_INVALID_ACCESS: return EACCES;
case ERROR_INVALID_DRIVE: return ENOENT;
case ERROR_CURRENT_DIRECTORY: return EACCES;
case ERROR_NOT_SAME_DEVICE: return EXDEV;
case ERROR_NO_MORE_FILES: return ENOENT;
case ERROR_WRITE_PROTECT: return EROFS;
case ERROR_BAD_UNIT: return ENXIO;
case ERROR_NOT_READY: return EBUSY;
case ERROR_BAD_COMMAND: return EIO;
case ERROR_CRC: return EIO;
case ERROR_BAD_LENGTH: return EIO;
case ERROR_SEEK: return EIO;
case ERROR_WRITE_FAULT: return EIO;
case ERROR_READ_FAULT: return EIO;
case ERROR_GEN_FAILURE: return EIO;
case ERROR_SHARING_VIOLATION: return EACCES;
case ERROR_LOCK_VIOLATION: return EACCES;
case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE;
case ERROR_HANDLE_DISK_FULL: return ENOSPC;
case ERROR_NOT_SUPPORTED: return ENODEV;
case ERROR_REM_NOT_LIST: return EBUSY;
case ERROR_DUP_NAME: return EEXIST;
case ERROR_BAD_NETPATH: return ENOENT;
case ERROR_NETWORK_BUSY: return EBUSY;
case ERROR_DEV_NOT_EXIST: return ENODEV;
case ERROR_TOO_MANY_CMDS: return EAGAIN;
case ERROR_ADAP_HDW_ERR: return EIO;
case ERROR_BAD_NET_RESP: return EIO;
case ERROR_UNEXP_NET_ERR: return EIO;
case ERROR_NETNAME_DELETED: return ENOENT;
case ERROR_NETWORK_ACCESS_DENIED: return EACCES;
case ERROR_BAD_DEV_TYPE: return ENODEV;
case ERROR_BAD_NET_NAME: return ENOENT;
case ERROR_TOO_MANY_NAMES: return ENFILE;
case ERROR_TOO_MANY_SESS: return EIO;
case ERROR_SHARING_PAUSED: return EAGAIN;
case ERROR_REDIR_PAUSED: return EAGAIN;
case ERROR_FILE_EXISTS: return EEXIST;
case ERROR_CANNOT_MAKE: return ENOSPC;
case ERROR_OUT_OF_STRUCTURES: return ENFILE;
case ERROR_ALREADY_ASSIGNED: return EEXIST;
case ERROR_INVALID_PASSWORD: return EPERM;
case ERROR_NET_WRITE_FAULT: return EIO;
case ERROR_NO_PROC_SLOTS: return EAGAIN;
case ERROR_DISK_CHANGE: return EXDEV;
case ERROR_BROKEN_PIPE: return EPIPE;
case ERROR_OPEN_FAILED: return ENOENT;
case ERROR_DISK_FULL: return ENOSPC;
case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE;
case ERROR_INVALID_TARGET_HANDLE: return EBADF;
case ERROR_INVALID_NAME: return ENOENT;
case ERROR_PROC_NOT_FOUND: return ESRCH;
case ERROR_WAIT_NO_CHILDREN: return ECHILD;
case ERROR_CHILD_NOT_COMPLETE: return ECHILD;
case ERROR_DIRECT_ACCESS_HANDLE: return EBADF;
case ERROR_SEEK_ON_DEVICE: return ESPIPE;
case ERROR_BUSY_DRIVE: return EAGAIN;
case ERROR_DIR_NOT_EMPTY: return EEXIST;
case ERROR_NOT_LOCKED: return EACCES;
case ERROR_BAD_PATHNAME: return ENOENT;
case ERROR_LOCK_FAILED: return EACCES;
case ERROR_ALREADY_EXISTS: return EEXIST;
case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG;
case ERROR_BAD_PIPE: return EPIPE;
case ERROR_PIPE_BUSY: return EAGAIN;
case ERROR_PIPE_NOT_CONNECTED: return EPIPE;
case ERROR_DIRECTORY: return ENOTDIR;
}
return EINVAL;
}
pidtype waitpid(pidtype pid, int *status, int nohang)
{
DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE);
if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) {
/* WAIT_TIMEOUT can only happend with WNOHANG */
return JIM_BAD_PID;
}
GetExitCodeProcess(pid, &ret);
*status = ret;
CloseHandle(pid);
return pid;
}
int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file)
{
char name[MAX_PATH];
HANDLE handle;
if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, filename_template ? filename_template : "JIM", 0, name)) {
return -1;
}
handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | (unlink_file ? FILE_FLAG_DELETE_ON_CLOSE : 0),
NULL);
if (handle == INVALID_HANDLE_VALUE) {
goto error;
}
Jim_SetResultString(interp, name, -1);
return _open_osfhandle((int)handle, _O_RDWR | _O_TEXT);
error:
Jim_SetResultErrno(interp, name);
DeleteFile(name);
return -1;
}
int Jim_OpenForWrite(const char *filename, int append)
{
if (strcmp(filename, "/dev/null") == 0) {
filename = "nul:";
}
int fd = _open(filename, _O_WRONLY | _O_CREAT | _O_TEXT | (append ? _O_APPEND : _O_TRUNC), _S_IREAD | _S_IWRITE);
if (fd >= 0 && append) {
/* Note that _O_APPEND doesn't actually work. need to do it manually */
_lseek(fd, 0L, SEEK_END);
}
return fd;
}
int Jim_OpenForRead(const char *filename)
{
if (strcmp(filename, "/dev/null") == 0) {
filename = "nul:";
}
return _open(filename, _O_RDONLY | _O_TEXT, 0);
}
#elif defined(HAVE_UNISTD_H)
/* Unix-specific implementation */
int Jim_MakeTempFile(Jim_Interp *interp, const char *filename_template, int unlink_file)
{
int fd;
mode_t mask;
Jim_Obj *filenameObj;
if (filename_template == NULL) {
const char *tmpdir = getenv("TMPDIR");
if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) {
tmpdir = "/tmp/";
}
filenameObj = Jim_NewStringObj(interp, tmpdir, -1);
if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') {
Jim_AppendString(interp, filenameObj, "/", 1);
}
Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1);
}
else {
filenameObj = Jim_NewStringObj(interp, filename_template, -1);
}
/* Update the template name directly with the filename */
mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
#ifdef HAVE_MKSTEMP
fd = mkstemp(filenameObj->bytes);
#else
if (mktemp(filenameObj->bytes) == NULL) {
fd = -1;
}
else {
fd = open(filenameObj->bytes, O_RDWR | O_CREAT | O_TRUNC);
}
#endif
umask(mask);
if (fd < 0) {
Jim_SetResultErrno(interp, Jim_String(filenameObj));
Jim_FreeNewObj(interp, filenameObj);
return -1;
}
if (unlink_file) {
remove(Jim_String(filenameObj));
}
Jim_SetResult(interp, filenameObj);
return fd;
}
int Jim_OpenForWrite(const char *filename, int append)
{
return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666);
}
int Jim_OpenForRead(const char *filename)
{
return open(filename, O_RDONLY, 0);
}
#endif
|