#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
- if (src.wide)
- result = MoveFileExW(src.wide, dst.wide, flags);
+ if (src->wide)
+ result = CreateHardLinkW(dst->wide, src->wide, NULL);
else
- result = MoveFileExA(src.narrow, dst.narrow, flags);
+ result = CreateHardLinkA(dst->narrow, src->narrow, NULL);
Py_END_ALLOW_THREADS
- if (!result) {
- return_value = path_error2(&src, &dst);
- goto exit;
- }
-
+ if (!result)
+ return path_error2(src, dst);
#else
Py_BEGIN_ALLOW_THREADS
-#ifdef HAVE_RENAMEAT
- if (dir_fd_specified)
- result = renameat(src_dir_fd, src.narrow, dst_dir_fd, dst.narrow);
+#ifdef HAVE_LINKAT
+ if ((src_dir_fd != DEFAULT_DIR_FD) ||
+ (dst_dir_fd != DEFAULT_DIR_FD) ||
+ (!follow_symlinks))
+ result = linkat(src_dir_fd, src->narrow,
+ dst_dir_fd, dst->narrow,
+ follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
else
#endif
- result = rename(src.narrow, dst.narrow);
+ result = link(src->narrow, dst->narrow);
Py_END_ALLOW_THREADS
- if (result) {
- return_value = path_error2(&src, &dst);
- goto exit;
- }
+ if (result)
+ return path_error2(src, dst);
#endif
- Py_INCREF(Py_None);
- return_value = Py_None;
-exit:
- path_cleanup(&src);
- path_cleanup(&dst);
- return return_value;
+ Py_RETURN_NONE;
}
+#endif
-PyDoc_STRVAR(posix_rename__doc__,
-"rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n\n\
-Rename a file or directory.\n\
-\n\
-If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
- descriptor open to a directory, and the respective path string (src or dst)\n\
- should be relative; the path will then be relative to that directory.\n\
-src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n\
- If they are unavailable, using them will raise a NotImplementedError.");
+#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
static PyObject *
-posix_rename(PyObject *self, PyObject *args, PyObject *kwargs)
+_listdir_windows_no_opendir(path_t *path, PyObject *list)
{
- return internal_rename(args, kwargs, 0);
-}
-
-PyDoc_STRVAR(posix_replace__doc__,
-"replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n\n\
-Rename a file or directory, overwriting the destination.\n\
-\n\
-If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
- descriptor open to a directory, and the respective path string (src or dst)\n\
- should be relative; the path will then be relative to that directory.\n\
-src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n\
- If they are unavailable, using them will raise a NotImplementedError.");
+ PyObject *v;
+ HANDLE hFindFile = INVALID_HANDLE_VALUE;
+ BOOL result;
+ WIN32_FIND_DATA FileData;
+ char namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
+ char *bufptr = namebuf;
+ /* only claim to have space for MAX_PATH */
+ Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
+ PyObject *po = NULL;
+ wchar_t *wnamebuf = NULL;
-static PyObject *
-posix_replace(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- return internal_rename(args, kwargs, 1);
-}
+ if (!path->narrow) {
+ WIN32_FIND_DATAW wFileData;
+ wchar_t *po_wchars;
-PyDoc_STRVAR(posix_rmdir__doc__,
-"rmdir(path, *, dir_fd=None)\n\n\
-Remove a directory.\n\
-\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-dir_fd may not be implemented on your platform.\n\
- If it is unavailable, using it will raise a NotImplementedError.");
+ if (!path->wide) { /* Default arg: "." */
+ po_wchars = L".";
+ len = 1;
+ } else {
+ po_wchars = path->wide;
+ len = wcslen(path->wide);
+ }
+ /* The +5 is so we can append "\\*.*\0" */
- wnamebuf = PyMem_Malloc((len + 5) * sizeof(wchar_t));
++ wnamebuf = PyMem_New(wchar_t, len + 5);
+ if (!wnamebuf) {
+ PyErr_NoMemory();
+ goto exit;
+ }
+ wcscpy(wnamebuf, po_wchars);
+ if (len > 0) {
+ wchar_t wch = wnamebuf[len-1];
+ if (wch != SEP && wch != ALTSEP && wch != L':')
+ wnamebuf[len++] = SEP;
+ wcscpy(wnamebuf + len, L"*.*");
+ }
+ if ((list = PyList_New(0)) == NULL) {
+ goto exit;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ hFindFile = FindFirstFileW(wnamebuf, &wFileData);
+ Py_END_ALLOW_THREADS
+ if (hFindFile == INVALID_HANDLE_VALUE) {
+ int error = GetLastError();
+ if (error == ERROR_FILE_NOT_FOUND)
+ goto exit;
+ Py_DECREF(list);
+ list = path_error(path);
+ goto exit;
+ }
+ do {
+ /* Skip over . and .. */
+ if (wcscmp(wFileData.cFileName, L".") != 0 &&
+ wcscmp(wFileData.cFileName, L"..") != 0) {
+ v = PyUnicode_FromWideChar(wFileData.cFileName,
+ wcslen(wFileData.cFileName));
+ if (v == NULL) {
+ Py_DECREF(list);
+ list = NULL;
+ break;
+ }
+ if (PyList_Append(list, v) != 0) {
+ Py_DECREF(v);
+ Py_DECREF(list);
+ list = NULL;
+ break;
+ }
+ Py_DECREF(v);
+ }
+ Py_BEGIN_ALLOW_THREADS
+ result = FindNextFileW(hFindFile, &wFileData);
+ Py_END_ALLOW_THREADS
+ /* FindNextFile sets error to ERROR_NO_MORE_FILES if
+ it got to the end of the directory. */
+ if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
+ Py_DECREF(list);
+ list = path_error(path);
+ goto exit;
+ }
+ } while (result == TRUE);
-static PyObject *
-posix_rmdir(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- path_t path;
- int dir_fd = DEFAULT_DIR_FD;
- static char *keywords[] = {"path", "dir_fd", NULL};
- int result;
- PyObject *return_value = NULL;
+ goto exit;
+ }
+ strcpy(namebuf, path->narrow);
+ len = path->length;
+ if (len > 0) {
+ char ch = namebuf[len-1];
+ if (ch != '\\' && ch != '/' && ch != ':')
+ namebuf[len++] = '\\';
+ strcpy(namebuf + len, "*.*");
+ }
- memset(&path, 0, sizeof(path));
- path.function_name = "rmdir";
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:rmdir", keywords,
- path_converter, &path,
-#ifdef HAVE_UNLINKAT
- dir_fd_converter, &dir_fd
-#else
- dir_fd_unavailable, &dir_fd
-#endif
- ))
+ if ((list = PyList_New(0)) == NULL)
return NULL;
Py_BEGIN_ALLOW_THREADS
return return_value;
}
+static PyObject *
+os_listdir_impl(PyModuleDef *module, path_t *path)
+/*[clinic end generated code: output=e159bd9be6909018 input=09e300416e3cd729]*/
+{
+#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
+ return _listdir_windows_no_opendir(path, NULL);
+#else
+ return _posix_listdir(path, NULL);
+#endif
+}
-PyDoc_STRVAR(posix_uname__doc__,
-"uname() -> uname_result\n\n\
-Return an object identifying the current operating system.\n\
-The object behaves like a named tuple with the following fields:\n\
- (sysname, nodename, release, version, machine)");
-
-static PyStructSequence_Field uname_result_fields[] = {
- {"sysname", "operating system name"},
- {"nodename", "name of machine on network (implementation-defined)"},
- {"release", "operating system release"},
- {"version", "operating system version"},
- {"machine", "hardware identifier"},
- {NULL}
-};
-
-PyDoc_STRVAR(uname_result__doc__,
-"uname_result: Result from os.uname().\n\n\
-This object may be accessed either as a tuple of\n\
- (sysname, nodename, release, version, machine),\n\
-or via the attributes sysname, nodename, release, version, and machine.\n\
-\n\
-See os.uname for more information.");
-
-static PyStructSequence_Desc uname_result_desc = {
- "uname_result", /* name */
- uname_result__doc__, /* doc */
- uname_result_fields,
- 5
-};
-
-static PyTypeObject UnameResultType;
-
-
-#ifdef HAVE_UNAME
+#ifdef MS_WINDOWS
+/* A helper function for abspath on win32 */
+/* AC 3.5: probably just convert to using path converter */
static PyObject *
-posix_uname(PyObject *self, PyObject *noargs)
+posix__getfullpathname(PyObject *self, PyObject *args)
{
- struct utsname u;
- int res;
- PyObject *value;
+ const char *path;
+ char outbuf[MAX_PATH];
+ char *temp;
+ PyObject *po;
- Py_BEGIN_ALLOW_THREADS
- res = uname(&u);
- Py_END_ALLOW_THREADS
- if (res < 0)
- return posix_error();
+ if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po))
+ {
+ wchar_t *wpath;
+ wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
+ wchar_t *wtemp;
+ DWORD result;
+ PyObject *v;
- value = PyStructSequence_New(&UnameResultType);
- if (value == NULL)
+ wpath = PyUnicode_AsUnicode(po);
+ if (wpath == NULL)
+ return NULL;
+ result = GetFullPathNameW(wpath,
+ Py_ARRAY_LENGTH(woutbuf),
+ woutbuf, &wtemp);
+ if (result > Py_ARRAY_LENGTH(woutbuf)) {
- woutbufp = PyMem_Malloc(result * sizeof(wchar_t));
++ woutbufp = PyMem_New(wchar_t, result);
+ if (!woutbufp)
+ return PyErr_NoMemory();
+ result = GetFullPathNameW(wpath, result, woutbufp, &wtemp);
+ }
+ if (result)
+ v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp));
+ else
+ v = win32_error_object("GetFullPathNameW", po);
+ if (woutbufp != woutbuf)
+ PyMem_Free(woutbufp);
+ return v;
+ }
+ /* Drop the argument parsing error as narrow strings
+ are also valid. */
+ PyErr_Clear();
+
+ if (!PyArg_ParseTuple (args, "y:_getfullpathname",
+ &path))
+ return NULL;
+ if (win32_warn_bytes_api())
+ return NULL;
+ if (!GetFullPathName(path, Py_ARRAY_LENGTH(outbuf),
+ outbuf, &temp)) {
+ win32_error("GetFullPathName", path);
return NULL;
+ }
+ if (PyUnicode_Check(PyTuple_GetItem(args, 0))) {
+ return PyUnicode_Decode(outbuf, strlen(outbuf),
+ Py_FileSystemDefaultEncoding, NULL);
+ }
+ return PyBytes_FromString(outbuf);
+}
-#define SET(i, field) \
- { \
- PyObject *o = PyUnicode_DecodeFSDefault(field); \
- if (!o) { \
- Py_DECREF(value); \
- return NULL; \
- } \
- PyStructSequence_SET_ITEM(value, i, o); \
- } \
- SET(0, u.sysname);
- SET(1, u.nodename);
- SET(2, u.release);
- SET(3, u.version);
- SET(4, u.machine);
+/*[clinic input]
+os._getfinalpathname
-#undef SET
+ path: unicode
+ /
- return value;
-}
-#endif /* HAVE_UNAME */
+A helper function for samepath on windows.
+[clinic start generated code]*/
+PyDoc_STRVAR(os__getfinalpathname__doc__,
+"_getfinalpathname($module, path, /)\n"
+"--\n"
+"\n"
+"A helper function for samepath on windows.");
-PyDoc_STRVAR(posix_utime__doc__,
-"utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True)\n\
-Set the access and modified time of path.\n\
-\n\
-path may always be specified as a string.\n\
-On some platforms, path may also be specified as an open file descriptor.\n\
- If this functionality is unavailable, using it raises an exception.\n\
-\n\
-If times is not None, it must be a tuple (atime, mtime);\n\
- atime and mtime should be expressed as float seconds since the epoch.\n\
-If ns is not None, it must be a tuple (atime_ns, mtime_ns);\n\
- atime_ns and mtime_ns should be expressed as integer nanoseconds\n\
- since the epoch.\n\
-If both times and ns are None, utime uses the current time.\n\
-Specifying tuples for both times and ns is an error.\n\
-\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-If follow_symlinks is False, and the last element of the path is a symbolic\n\
- link, utime will modify the symbolic link itself instead of the file the\n\
- link points to.\n\
-It is an error to use dir_fd or follow_symlinks when specifying path\n\
- as an open file descriptor.\n\
-dir_fd and follow_symlinks may not be available on your platform.\n\
- If they are unavailable, using them will raise a NotImplementedError.");
+#define OS__GETFINALPATHNAME_METHODDEF \
+ {"_getfinalpathname", (PyCFunction)os__getfinalpathname, METH_VARARGS, os__getfinalpathname__doc__},
-typedef struct {
- int now;
- time_t atime_s;
- long atime_ns;
- time_t mtime_s;
- long mtime_ns;
-} utime_t;
+static PyObject *
+os__getfinalpathname_impl(PyModuleDef *module, PyObject *path);
-/*
- * these macros assume that "ut" is a pointer to a utime_t
- * they also intentionally leak the declaration of a pointer named "time"
- */
-#define UTIME_TO_TIMESPEC \
- struct timespec ts[2]; \
- struct timespec *time; \
- if (ut->now) \
- time = NULL; \
- else { \
- ts[0].tv_sec = ut->atime_s; \
- ts[0].tv_nsec = ut->atime_ns; \
- ts[1].tv_sec = ut->mtime_s; \
- ts[1].tv_nsec = ut->mtime_ns; \
- time = ts; \
- } \
+static PyObject *
+os__getfinalpathname(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *path;
-#define UTIME_TO_TIMEVAL \
- struct timeval tv[2]; \
- struct timeval *time; \
- if (ut->now) \
- time = NULL; \
- else { \
- tv[0].tv_sec = ut->atime_s; \
- tv[0].tv_usec = ut->atime_ns / 1000; \
- tv[1].tv_sec = ut->mtime_s; \
- tv[1].tv_usec = ut->mtime_ns / 1000; \
- time = tv; \
- } \
+ if (!PyArg_ParseTuple(args,
+ "U:_getfinalpathname",
+ &path))
+ goto exit;
+ return_value = os__getfinalpathname_impl(module, path);
-#define UTIME_TO_UTIMBUF \
- struct utimbuf u; \
- struct utimbuf *time; \
- if (ut->now) \
- time = NULL; \
- else { \
- u.actime = ut->atime_s; \
- u.modtime = ut->mtime_s; \
- time = &u; \
- }
+exit:
+ return return_value;
+}
-#define UTIME_TO_TIME_T \
- time_t timet[2]; \
- time_t *time; \
- if (ut->now) \
- time = NULL; \
- else { \
- timet[0] = ut->atime_s; \
- timet[1] = ut->mtime_s; \
- time = timet; \
- } \
+static PyObject *
+os__getfinalpathname_impl(PyModuleDef *module, PyObject *path)
+/*[clinic end generated code: output=4563c6eacf1b0881 input=71d5e89334891bf4]*/
+{
+ HANDLE hFile;
+ int buf_size;
+ wchar_t *target_path;
+ int result_length;
+ PyObject *result;
+ wchar_t *path_wchar;
+ path_wchar = PyUnicode_AsUnicode(path);
+ if (path_wchar == NULL)
+ return NULL;
-#define UTIME_HAVE_DIR_FD (defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT))
+ if(!check_GetFinalPathNameByHandle()) {
+ /* If the OS doesn't have GetFinalPathNameByHandle, return a
+ NotImplementedError. */
+ return PyErr_Format(PyExc_NotImplementedError,
+ "GetFinalPathNameByHandle not available on this platform");
+ }
-#if UTIME_HAVE_DIR_FD
+ hFile = CreateFileW(
+ path_wchar,
+ 0, /* desired access */
+ 0, /* share mode */
+ NULL, /* security attributes */
+ OPEN_EXISTING,
+ /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
-static int
-utime_dir_fd(utime_t *ut, int dir_fd, char *path, int follow_symlinks)
-{
-#ifdef HAVE_UTIMENSAT
- int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
- UTIME_TO_TIMESPEC;
- return utimensat(dir_fd, path, time, flags);
-#elif defined(HAVE_FUTIMESAT)
- UTIME_TO_TIMEVAL;
- /*
- * follow_symlinks will never be false here;
- * we only allow !follow_symlinks and dir_fd together
- * if we have utimensat()
- */
- assert(follow_symlinks);
- return futimesat(dir_fd, path, time);
-#endif
-}
+ if(hFile == INVALID_HANDLE_VALUE)
+ return win32_error_object("CreateFileW", path);
-#endif
+ /* We have a good handle to the target, use it to determine the
+ target path name. */
+ buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT);
-#define UTIME_HAVE_FD (defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS))
+ if(!buf_size)
+ return win32_error_object("GetFinalPathNameByHandle", path);
- target_path = (wchar_t *)PyMem_Malloc((buf_size+1)*sizeof(wchar_t));
-#if UTIME_HAVE_FD
++ target_path = PyMem_New(wchar_t, buf_size+1);
+ if(!target_path)
+ return PyErr_NoMemory();
-static int
-utime_fd(utime_t *ut, int fd)
-{
-#ifdef HAVE_FUTIMENS
- UTIME_TO_TIMESPEC;
- return futimens(fd, time);
-#else
- UTIME_TO_TIMEVAL;
- return futimes(fd, time);
-#endif
+ result_length = Py_GetFinalPathNameByHandleW(hFile, target_path,
+ buf_size, VOLUME_NAME_DOS);
+ if(!result_length)
+ return win32_error_object("GetFinalPathNamyByHandle", path);
+
+ if(!CloseHandle(hFile))
+ return win32_error_object("CloseHandle", path);
+
+ target_path[result_length] = 0;
+ result = PyUnicode_FromWideChar(target_path, result_length);
+ PyMem_Free(target_path);
+ return result;
}
-#endif
+PyDoc_STRVAR(posix__isdir__doc__,
+"Return true if the pathname refers to an existing directory.");
+/* AC 3.5: convert using path converter */
+static PyObject *
+posix__isdir(PyObject *self, PyObject *args)
+{
+ const char *path;
+ PyObject *po;
+ DWORD attributes;
-#define UTIME_HAVE_NOFOLLOW_SYMLINKS \
- (defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES))
+ if (PyArg_ParseTuple(args, "U|:_isdir", &po)) {
+ wchar_t *wpath = PyUnicode_AsUnicode(po);
+ if (wpath == NULL)
+ return NULL;
-#if UTIME_HAVE_NOFOLLOW_SYMLINKS
+ attributes = GetFileAttributesW(wpath);
+ if (attributes == INVALID_FILE_ATTRIBUTES)
+ Py_RETURN_FALSE;
+ goto check;
+ }
+ /* Drop the argument parsing error as narrow strings
+ are also valid. */
+ PyErr_Clear();
-static int
-utime_nofollow_symlinks(utime_t *ut, char *path)
-{
-#ifdef HAVE_UTIMENSAT
- UTIME_TO_TIMESPEC;
- return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
-#else
- UTIME_TO_TIMEVAL;
- return lutimes(path, time);
-#endif
+ if (!PyArg_ParseTuple(args, "y:_isdir", &path))
+ return NULL;
+ if (win32_warn_bytes_api())
+ return NULL;
+ attributes = GetFileAttributesA(path);
+ if (attributes == INVALID_FILE_ATTRIBUTES)
+ Py_RETURN_FALSE;
+
+check:
+ if (attributes & FILE_ATTRIBUTE_DIRECTORY)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
}
-#endif
-#ifndef MS_WINDOWS
+/*[clinic input]
+os._getvolumepathname
-static int
-utime_default(utime_t *ut, char *path)
-{
-#ifdef HAVE_UTIMENSAT
- UTIME_TO_TIMESPEC;
- return utimensat(DEFAULT_DIR_FD, path, time, 0);
-#elif defined(HAVE_UTIMES)
- UTIME_TO_TIMEVAL;
- return utimes(path, time);
-#elif defined(HAVE_UTIME_H)
- UTIME_TO_UTIMBUF;
- return utime(path, time);
-#else
- UTIME_TO_TIME_T;
- return utime(path, time);
-#endif
-}
+ path: unicode
-#endif
+A helper function for ismount on Win32.
+[clinic start generated code]*/
-static int
-split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns)
+PyDoc_STRVAR(os__getvolumepathname__doc__,
+"_getvolumepathname($module, /, path)\n"
+"--\n"
+"\n"
+"A helper function for ismount on Win32.");
+
+#define OS__GETVOLUMEPATHNAME_METHODDEF \
+ {"_getvolumepathname", (PyCFunction)os__getvolumepathname, METH_VARARGS|METH_KEYWORDS, os__getvolumepathname__doc__},
+
+static PyObject *
+os__getvolumepathname_impl(PyModuleDef *module, PyObject *path);
+
+static PyObject *
+os__getvolumepathname(PyModuleDef *module, PyObject *args, PyObject *kwargs)
{
- int result = 0;
- PyObject *divmod;
- divmod = PyNumber_Divmod(py_long, billion);
- if (!divmod)
- goto exit;
- *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
- if ((*s == -1) && PyErr_Occurred())
- goto exit;
- *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
- if ((*ns == -1) && PyErr_Occurred())
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"path", NULL};
+ PyObject *path;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "U:_getvolumepathname", _keywords,
+ &path))
goto exit;
+ return_value = os__getvolumepathname_impl(module, path);
- result = 1;
exit:
- Py_XDECREF(divmod);
- return result;
+ return return_value;
}
static PyObject *
-posix_utime(PyObject *self, PyObject *args, PyObject *kwargs)
+os__getvolumepathname_impl(PyModuleDef *module, PyObject *path)
+/*[clinic end generated code: output=ac0833b6d6da7657 input=7eacadc40acbda6b]*/
{
- path_t path;
- PyObject *times = NULL;
- PyObject *ns = NULL;
- int dir_fd = DEFAULT_DIR_FD;
- int follow_symlinks = 1;
- char *keywords[] = {"path", "times", "ns", "dir_fd",
- "follow_symlinks", NULL};
-
- utime_t utime;
+ PyObject *result;
+ wchar_t *path_wchar, *mountpath=NULL;
+ size_t buflen;
+ BOOL ret;
-#ifdef MS_WINDOWS
- HANDLE hFile;
- FILETIME atime, mtime;
-#else
- int result;
-#endif
+ path_wchar = PyUnicode_AsUnicodeAndSize(path, &buflen);
+ if (path_wchar == NULL)
+ return NULL;
+ buflen += 1;
- PyObject *return_value = NULL;
+ /* Volume path should be shorter than entire path */
+ buflen = Py_MAX(buflen, MAX_PATH);
- memset(&path, 0, sizeof(path));
- path.function_name = "utime";
- memset(&utime, 0, sizeof(utime_t));
-#if UTIME_HAVE_FD
- path.allow_fd = 1;
-#endif
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "O&|O$OO&p:utime", keywords,
- path_converter, &path,
- ×, &ns,
-#if UTIME_HAVE_DIR_FD
- dir_fd_converter, &dir_fd,
-#else
- dir_fd_unavailable, &dir_fd,
-#endif
- &follow_symlinks
- ))
+ if (buflen > DWORD_MAX) {
+ PyErr_SetString(PyExc_OverflowError, "path too long");
return NULL;
+ }
- mountpath = (wchar_t *)PyMem_Malloc(buflen * sizeof(wchar_t));
- if (times && (times != Py_None) && ns) {
- PyErr_SetString(PyExc_ValueError,
- "utime: you may specify either 'times'"
- " or 'ns' but not both");
++ mountpath = PyMem_New(wchar_t, buflen);
+ if (mountpath == NULL)
+ return PyErr_NoMemory();
+
+ Py_BEGIN_ALLOW_THREADS
+ ret = GetVolumePathNameW(path_wchar, mountpath,
+ Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
+ Py_END_ALLOW_THREADS
+
+ if (!ret) {
+ result = win32_error_object("_getvolumepathname", path);
goto exit;
}
+ result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
- if (times && (times != Py_None)) {
- time_t a_sec, m_sec;
- long a_nsec, m_nsec;
- if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
- PyErr_SetString(PyExc_TypeError,
- "utime: 'times' must be either"
- " a tuple of two ints or None");
- goto exit;
- }
- utime.now = 0;
- if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
- &a_sec, &a_nsec, _PyTime_ROUND_DOWN) == -1 ||
- _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
- &m_sec, &m_nsec, _PyTime_ROUND_DOWN) == -1) {
- goto exit;
- }
- utime.atime_s = a_sec;
- utime.atime_ns = a_nsec;
- utime.mtime_s = m_sec;
- utime.mtime_ns = m_nsec;
- }
- else if (ns) {
- if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
- PyErr_SetString(PyExc_TypeError,
- "utime: 'ns' must be a tuple of two ints");
- goto exit;
- }
- utime.now = 0;
- if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),
- &utime.atime_s, &utime.atime_ns) ||
- !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),
- &utime.mtime_s, &utime.mtime_ns)) {
- goto exit;
- }
- }
- else {
- /* times and ns are both None/unspecified. use "now". */
- utime.now = 1;
- }
+exit:
+ PyMem_Free(mountpath);
+ return result;
+}
-#if !UTIME_HAVE_NOFOLLOW_SYMLINKS
- if (follow_symlinks_specified("utime", follow_symlinks))
- goto exit;
-#endif
+#endif /* MS_WINDOWS */
- if (path_and_dir_fd_invalid("utime", &path, dir_fd) ||
- dir_fd_and_fd_invalid("utime", dir_fd, path.fd) ||
- fd_and_follow_symlinks_invalid("utime", path.fd, follow_symlinks))
- goto exit;
-#if !defined(HAVE_UTIMENSAT)
- if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
- PyErr_SetString(PyExc_ValueError,
- "utime: cannot use dir_fd and follow_symlinks "
- "together on this platform");
+/*[clinic input]
+os.mkdir
+
+ path : path_t
+
+ mode: int = 0o777
+
+ *
+
+ dir_fd : dir_fd(requires='mkdirat') = None
+
+# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
+
+Create a directory.
+
+If dir_fd is not None, it should be a file descriptor open to a directory,
+ and path should be relative; path will then be relative to that directory.
+dir_fd may not be implemented on your platform.
+ If it is unavailable, using it will raise a NotImplementedError.
+
+The mode argument is ignored on Windows.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_mkdir__doc__,
+"mkdir($module, /, path, mode=511, *, dir_fd=None)\n"
+"--\n"
+"\n"
+"Create a directory.\n"
+"\n"
+"If dir_fd is not None, it should be a file descriptor open to a directory,\n"
+" and path should be relative; path will then be relative to that directory.\n"
+"dir_fd may not be implemented on your platform.\n"
+" If it is unavailable, using it will raise a NotImplementedError.\n"
+"\n"
+"The mode argument is ignored on Windows.");
+
+#define OS_MKDIR_METHODDEF \
+ {"mkdir", (PyCFunction)os_mkdir, METH_VARARGS|METH_KEYWORDS, os_mkdir__doc__},
+
+static PyObject *
+os_mkdir_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd);
+
+static PyObject *
+os_mkdir(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"path", "mode", "dir_fd", NULL};
+ path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0);
+ int mode = 511;
+ int dir_fd = DEFAULT_DIR_FD;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O&|i$O&:mkdir", _keywords,
+ path_converter, &path, &mode, MKDIRAT_DIR_FD_CONVERTER, &dir_fd))
goto exit;
- }
-#endif
+ return_value = os_mkdir_impl(module, &path, mode, dir_fd);
+
+exit:
+ /* Cleanup for path */
+ path_cleanup(&path);
+
+ return return_value;
+}
+
+static PyObject *
+os_mkdir_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd)
+/*[clinic end generated code: output=55c6ef2bc1b207e6 input=e965f68377e9b1ce]*/
+{
+ int result;
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
}
-PyDoc_STRVAR(posix_dup2__doc__,
-"dup2(old_fd, new_fd)\n\n\
-Duplicate file descriptor.");
+/*[clinic input]
+os.sched_setparam
+ pid: pid_t
+ param: sched_param
+ /
-static PyObject *
-posix_dup2(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- static char *keywords[] = {"fd", "fd2", "inheritable", NULL};
- int fd, fd2;
- int inheritable = 1;
- int res;
-#if defined(HAVE_DUP3) && \
- !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
- /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
- int dup3_works = -1;
-#endif
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i:dup2", keywords,
- &fd, &fd2, &inheritable))
- return NULL;
-
- if (!_PyVerify_fd_dup2(fd, fd2))
- return posix_error();
-
-#ifdef MS_WINDOWS
- Py_BEGIN_ALLOW_THREADS
- res = dup2(fd, fd2);
- Py_END_ALLOW_THREADS
- if (res < 0)
- return posix_error();
-
- /* Character files like console cannot be make non-inheritable */
- if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
- close(fd2);
- return NULL;
- }
+Set scheduling parameters for the process identified by pid.
-#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
- Py_BEGIN_ALLOW_THREADS
- if (!inheritable)
- res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
- else
- res = dup2(fd, fd2);
- Py_END_ALLOW_THREADS
- if (res < 0)
- return posix_error();
+If pid is 0, sets parameters for the calling process.
+param should be an instance of sched_param.
+[clinic start generated code]*/
-#else
+PyDoc_STRVAR(os_sched_setparam__doc__,
+"sched_setparam($module, pid, param, /)\n"
+"--\n"
+"\n"
+"Set scheduling parameters for the process identified by pid.\n"
+"\n"
+"If pid is 0, sets parameters for the calling process.\n"
+"param should be an instance of sched_param.");
-#ifdef HAVE_DUP3
- if (!inheritable && dup3_works != 0) {
- Py_BEGIN_ALLOW_THREADS
- res = dup3(fd, fd2, O_CLOEXEC);
- Py_END_ALLOW_THREADS
- if (res < 0) {
- if (dup3_works == -1)
- dup3_works = (errno != ENOSYS);
- if (dup3_works)
- return posix_error();
- }
- }
+#define OS_SCHED_SETPARAM_METHODDEF \
+ {"sched_setparam", (PyCFunction)os_sched_setparam, METH_VARARGS, os_sched_setparam__doc__},
- if (inheritable || dup3_works == 0)
- {
-#endif
- Py_BEGIN_ALLOW_THREADS
- res = dup2(fd, fd2);
- Py_END_ALLOW_THREADS
- if (res < 0)
- return posix_error();
+static PyObject *
+os_sched_setparam_impl(PyModuleDef *module, pid_t pid, struct sched_param *param);
- if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
- close(fd2);
- return NULL;
- }
-#ifdef HAVE_DUP3
- }
-#endif
+static PyObject *
+os_sched_setparam(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ pid_t pid;
+ struct sched_param param;
-#endif
+ if (!PyArg_ParseTuple(args,
+ "" _Py_PARSE_PID "O&:sched_setparam",
+ &pid, convert_sched_param, ¶m))
+ goto exit;
+ return_value = os_sched_setparam_impl(module, pid, ¶m);
- Py_INCREF(Py_None);
- return Py_None;
+exit:
+ return return_value;
}
-#ifdef HAVE_LOCKF
-PyDoc_STRVAR(posix_lockf__doc__,
-"lockf(fd, cmd, len)\n\n\
-Apply, test or remove a POSIX lock on an open file descriptor.\n\n\
-fd is an open file descriptor.\n\
-cmd specifies the command to use - one of F_LOCK, F_TLOCK, F_ULOCK or\n\
-F_TEST.\n\
-len specifies the section of the file to lock.");
-
static PyObject *
-posix_lockf(PyObject *self, PyObject *args)
+os_sched_setparam_impl(PyModuleDef *module, pid_t pid, struct sched_param *param)
+/*[clinic end generated code: output=488bdf5bcbe0d4e8 input=6b8d6dfcecdc21bd]*/
{
- int fd, cmd, res;
- off_t len;
- if (!PyArg_ParseTuple(args, "iiO&:lockf",
- &fd, &cmd, _parse_off_t, &len))
- return NULL;
-
- Py_BEGIN_ALLOW_THREADS
- res = lockf(fd, cmd, len);
- Py_END_ALLOW_THREADS
-
- if (res < 0)
+ if (sched_setparam(pid, param))
return posix_error();
-
Py_RETURN_NONE;
}
-#endif
-
+#endif /* HAVE_SCHED_SETPARAM */
-PyDoc_STRVAR(posix_lseek__doc__,
-"lseek(fd, pos, how) -> newpos\n\n\
-Set the current position of a file descriptor.\n\
-Return the new cursor position in bytes, starting from the beginning.");
-static PyObject *
-posix_lseek(PyObject *self, PyObject *args)
-{
- int fd, how;
-#ifdef MS_WINDOWS
- PY_LONG_LONG pos, res;
-#else
- off_t pos, res;
-#endif
- PyObject *posobj;
- if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
- return NULL;
-#ifdef SEEK_SET
- /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
- switch (how) {
- case 0: how = SEEK_SET; break;
- case 1: how = SEEK_CUR; break;
- case 2: how = SEEK_END; break;
- }
-#endif /* SEEK_END */
+#ifdef HAVE_SCHED_RR_GET_INTERVAL
+/*[clinic input]
+os.sched_rr_get_interval -> double
+ pid: pid_t
+ /
-#if !defined(HAVE_LARGEFILE_SUPPORT)
- pos = PyLong_AsLong(posobj);
-#else
- pos = PyLong_AsLongLong(posobj);
-#endif
- if (PyErr_Occurred())
- return NULL;
+Return the round-robin quantum for the process identified by pid, in seconds.
- if (!_PyVerify_fd(fd))
- return posix_error();
- Py_BEGIN_ALLOW_THREADS
-#ifdef MS_WINDOWS
- res = _lseeki64(fd, pos, how);
-#else
- res = lseek(fd, pos, how);
-#endif
- Py_END_ALLOW_THREADS
- if (res < 0)
- return posix_error();
+Value returned is a float.
+[clinic start generated code]*/
-#if !defined(HAVE_LARGEFILE_SUPPORT)
- return PyLong_FromLong(res);
-#else
- return PyLong_FromLongLong(res);
-#endif
-}
+PyDoc_STRVAR(os_sched_rr_get_interval__doc__,
+"sched_rr_get_interval($module, pid, /)\n"
+"--\n"
+"\n"
+"Return the round-robin quantum for the process identified by pid, in seconds.\n"
+"\n"
+"Value returned is a float.");
+#define OS_SCHED_RR_GET_INTERVAL_METHODDEF \
+ {"sched_rr_get_interval", (PyCFunction)os_sched_rr_get_interval, METH_VARARGS, os_sched_rr_get_interval__doc__},
-PyDoc_STRVAR(posix_read__doc__,
-"read(fd, buffersize) -> bytes\n\n\
-Read a file descriptor.");
+static double
+os_sched_rr_get_interval_impl(PyModuleDef *module, pid_t pid);
static PyObject *
-posix_read(PyObject *self, PyObject *args)
+os_sched_rr_get_interval(PyModuleDef *module, PyObject *args)
{
- int fd, size;
- Py_ssize_t n;
- PyObject *buffer;
- if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
- return NULL;
- if (size < 0) {
- errno = EINVAL;
- return posix_error();
- }
- buffer = PyBytes_FromStringAndSize((char *)NULL, size);
- if (buffer == NULL)
- return NULL;
- if (!_PyVerify_fd(fd)) {
- Py_DECREF(buffer);
- return posix_error();
- }
- Py_BEGIN_ALLOW_THREADS
- n = read(fd, PyBytes_AS_STRING(buffer), size);
- Py_END_ALLOW_THREADS
- if (n < 0) {
- Py_DECREF(buffer);
- return posix_error();
- }
- if (n != size)
- _PyBytes_Resize(&buffer, n);
- return buffer;
+ PyObject *return_value = NULL;
+ pid_t pid;
+ double _return_value;
+
+ if (!PyArg_ParseTuple(args,
+ "" _Py_PARSE_PID ":sched_rr_get_interval",
+ &pid))
+ goto exit;
+ _return_value = os_sched_rr_get_interval_impl(module, pid);
+ if ((_return_value == -1.0) && PyErr_Occurred())
+ goto exit;
+ return_value = PyFloat_FromDouble(_return_value);
+
+exit:
+ return return_value;
}
-#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
- || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV)
-static Py_ssize_t
-iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type)
+static double
+os_sched_rr_get_interval_impl(PyModuleDef *module, pid_t pid)
+/*[clinic end generated code: output=5b3b8d1f27fb2c0a input=2a973da15cca6fae]*/
{
- int i, j;
- Py_ssize_t blen, total = 0;
-
- *iov = PyMem_New(struct iovec, cnt);
- if (*iov == NULL) {
- PyErr_NoMemory();
- return -1;
+ struct timespec interval;
+ if (sched_rr_get_interval(pid, &interval)) {
+ posix_error();
+ return -1.0;
}
+ return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
+}
+#endif /* HAVE_SCHED_RR_GET_INTERVAL */
- *buf = PyMem_New(Py_buffer, cnt);
- if (*buf == NULL) {
- PyMem_Del(*iov);
- PyErr_NoMemory();
- return -1;
- }
- for (i = 0; i < cnt; i++) {
- PyObject *item = PySequence_GetItem(seq, i);
- if (item == NULL)
- goto fail;
- if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
- Py_DECREF(item);
- goto fail;
- }
- Py_DECREF(item);
- (*iov)[i].iov_base = (*buf)[i].buf;
- blen = (*buf)[i].len;
- (*iov)[i].iov_len = blen;
- total += blen;
- }
- return total;
+/*[clinic input]
+os.sched_yield
-fail:
- PyMem_Del(*iov);
- for (j = 0; j < i; j++) {
- PyBuffer_Release(&(*buf)[j]);
- }
- PyMem_Del(*buf);
- return -1;
-}
+Voluntarily relinquish the CPU.
+[clinic start generated code]*/
-static void
-iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
+PyDoc_STRVAR(os_sched_yield__doc__,
+"sched_yield($module, /)\n"
+"--\n"
+"\n"
+"Voluntarily relinquish the CPU.");
+
+#define OS_SCHED_YIELD_METHODDEF \
+ {"sched_yield", (PyCFunction)os_sched_yield, METH_NOARGS, os_sched_yield__doc__},
+
+static PyObject *
+os_sched_yield_impl(PyModuleDef *module);
+
+static PyObject *
+os_sched_yield(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
{
- int i;
- PyMem_Del(iov);
- for (i = 0; i < cnt; i++) {
- PyBuffer_Release(&buf[i]);
- }
- PyMem_Del(buf);
+ return os_sched_yield_impl(module);
}
-#endif
-
-#ifdef HAVE_READV
-PyDoc_STRVAR(posix_readv__doc__,
-"readv(fd, buffers) -> bytesread\n\n\
-Read from a file descriptor fd into a number of mutable, bytes-like\n\
-objects (\"buffers\"). readv will transfer data into each buffer\n\
-until it is full and then move on to the next buffer in the sequence\n\
-to hold the rest of the data.\n\n\
-readv returns the total number of bytes read (which may be less than\n\
-the total capacity of all the buffers.");
static PyObject *
-posix_readv(PyObject *self, PyObject *args)
+os_sched_yield_impl(PyModuleDef *module)
+/*[clinic end generated code: output=9d2e5f29f1370324 input=e54d6f98189391d4]*/
{
- int fd, cnt;
- Py_ssize_t n;
- PyObject *seq;
- struct iovec *iov;
- Py_buffer *buf;
+ if (sched_yield())
+ return posix_error();
+ Py_RETURN_NONE;
+}
- if (!PyArg_ParseTuple(args, "iO:readv", &fd, &seq))
- return NULL;
- if (!PySequence_Check(seq)) {
- PyErr_SetString(PyExc_TypeError,
- "readv() arg 2 must be a sequence");
- return NULL;
- }
- cnt = PySequence_Size(seq);
+#ifdef HAVE_SCHED_SETAFFINITY
+/* The minimum number of CPUs allocated in a cpu_set_t */
+static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
- if (iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE) < 0)
- return NULL;
+/*[clinic input]
+os.sched_setaffinity
+ pid: pid_t
+ mask : object
+ /
- Py_BEGIN_ALLOW_THREADS
- n = readv(fd, iov, cnt);
- Py_END_ALLOW_THREADS
+Set the CPU affinity of the process identified by pid to mask.
- iov_cleanup(iov, buf, cnt);
- if (n < 0)
- return posix_error();
+mask should be an iterable of integers identifying CPUs.
+[clinic start generated code]*/
- return PyLong_FromSsize_t(n);
-}
-#endif
+PyDoc_STRVAR(os_sched_setaffinity__doc__,
+"sched_setaffinity($module, pid, mask, /)\n"
+"--\n"
+"\n"
+"Set the CPU affinity of the process identified by pid to mask.\n"
+"\n"
+"mask should be an iterable of integers identifying CPUs.");
-#ifdef HAVE_PREAD
-PyDoc_STRVAR(posix_pread__doc__,
-"pread(fd, buffersize, offset) -> string\n\n\
-Read from a file descriptor, fd, at a position of offset. It will read up\n\
-to buffersize number of bytes. The file offset remains unchanged.");
+#define OS_SCHED_SETAFFINITY_METHODDEF \
+ {"sched_setaffinity", (PyCFunction)os_sched_setaffinity, METH_VARARGS, os_sched_setaffinity__doc__},
static PyObject *
-posix_pread(PyObject *self, PyObject *args)
-{
- int fd, size;
- off_t offset;
- Py_ssize_t n;
- PyObject *buffer;
- if (!PyArg_ParseTuple(args, "iiO&:pread", &fd, &size, _parse_off_t, &offset))
- return NULL;
-
- if (size < 0) {
- errno = EINVAL;
- return posix_error();
- }
- buffer = PyBytes_FromStringAndSize((char *)NULL, size);
- if (buffer == NULL)
- return NULL;
- if (!_PyVerify_fd(fd)) {
- Py_DECREF(buffer);
- return posix_error();
- }
- Py_BEGIN_ALLOW_THREADS
- n = pread(fd, PyBytes_AS_STRING(buffer), size, offset);
- Py_END_ALLOW_THREADS
- if (n < 0) {
- Py_DECREF(buffer);
- return posix_error();
- }
- if (n != size)
- _PyBytes_Resize(&buffer, n);
- return buffer;
-}
-#endif
-
-PyDoc_STRVAR(posix_write__doc__,
-"write(fd, data) -> byteswritten\n\n\
-Write bytes to a file descriptor.");
+os_sched_setaffinity_impl(PyModuleDef *module, pid_t pid, PyObject *mask);
static PyObject *
-posix_write(PyObject *self, PyObject *args)
+os_sched_setaffinity(PyModuleDef *module, PyObject *args)
{
- Py_buffer pbuf;
- int fd;
- Py_ssize_t size, len;
+ PyObject *return_value = NULL;
+ pid_t pid;
+ PyObject *mask;
- if (!PyArg_ParseTuple(args, "iy*:write", &fd, &pbuf))
- return NULL;
- if (!_PyVerify_fd(fd)) {
- PyBuffer_Release(&pbuf);
- return posix_error();
- }
- len = pbuf.len;
- Py_BEGIN_ALLOW_THREADS
-#ifdef MS_WINDOWS
- if (len > INT_MAX)
- len = INT_MAX;
- size = write(fd, pbuf.buf, (int)len);
-#else
- size = write(fd, pbuf.buf, len);
-#endif
- Py_END_ALLOW_THREADS
- PyBuffer_Release(&pbuf);
- if (size < 0)
- return posix_error();
- return PyLong_FromSsize_t(size);
-}
+ if (!PyArg_ParseTuple(args,
+ "" _Py_PARSE_PID "O:sched_setaffinity",
+ &pid, &mask))
+ goto exit;
+ return_value = os_sched_setaffinity_impl(module, pid, mask);
-#ifdef HAVE_SENDFILE
-PyDoc_STRVAR(posix_sendfile__doc__,
-"sendfile(out, in, offset, nbytes) -> byteswritten\n\
-sendfile(out, in, offset, nbytes, headers=None, trailers=None, flags=0)\n\
- -> byteswritten\n\
-Copy nbytes bytes from file descriptor in to file descriptor out.");
+exit:
+ return return_value;
+}
static PyObject *
-posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
+os_sched_setaffinity_impl(PyModuleDef *module, pid_t pid, PyObject *mask)
+/*[clinic end generated code: output=5199929738130196 input=a0791a597c7085ba]*/
{
- int in, out;
- Py_ssize_t ret;
- off_t offset;
+ int ncpus;
+ size_t setsize;
+ cpu_set_t *cpu_set = NULL;
+ PyObject *iterator = NULL, *item;
-#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
-#ifndef __APPLE__
- Py_ssize_t len;
-#endif
- PyObject *headers = NULL, *trailers = NULL;
- Py_buffer *hbuf, *tbuf;
- off_t sbytes;
- struct sf_hdtr sf;
- int flags = 0;
- static char *keywords[] = {"out", "in",
- "offset", "count",
- "headers", "trailers", "flags", NULL};
+ iterator = PyObject_GetIter(mask);
+ if (iterator == NULL)
+ return NULL;
- sf.headers = NULL;
- sf.trailers = NULL;
+ ncpus = NCPUS_START;
+ setsize = CPU_ALLOC_SIZE(ncpus);
+ cpu_set = CPU_ALLOC(ncpus);
+ if (cpu_set == NULL) {
+ PyErr_NoMemory();
+ goto error;
+ }
+ CPU_ZERO_S(setsize, cpu_set);
-#ifdef __APPLE__
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
- keywords, &out, &in, _parse_off_t, &offset, _parse_off_t, &sbytes,
-#else
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
- keywords, &out, &in, _parse_off_t, &offset, &len,
-#endif
- &headers, &trailers, &flags))
- return NULL;
- if (headers != NULL) {
- if (!PySequence_Check(headers)) {
- PyErr_SetString(PyExc_TypeError,
- "sendfile() headers must be a sequence or None");
- return NULL;
- } else {
- Py_ssize_t i = 0; /* Avoid uninitialized warning */
- sf.hdr_cnt = PySequence_Size(headers);
- if (sf.hdr_cnt > 0 &&
- (i = iov_setup(&(sf.headers), &hbuf,
- headers, sf.hdr_cnt, PyBUF_SIMPLE)) < 0)
- return NULL;
-#ifdef __APPLE__
- sbytes += i;
-#endif
+ while ((item = PyIter_Next(iterator))) {
+ long cpu;
+ if (!PyLong_Check(item)) {
+ PyErr_Format(PyExc_TypeError,
+ "expected an iterator of ints, "
+ "but iterator yielded %R",
+ Py_TYPE(item));
+ Py_DECREF(item);
+ goto error;
}
- }
- if (trailers != NULL) {
- if (!PySequence_Check(trailers)) {
- PyErr_SetString(PyExc_TypeError,
- "sendfile() trailers must be a sequence or None");
- return NULL;
- } else {
- Py_ssize_t i = 0; /* Avoid uninitialized warning */
- sf.trl_cnt = PySequence_Size(trailers);
- if (sf.trl_cnt > 0 &&
- (i = iov_setup(&(sf.trailers), &tbuf,
- trailers, sf.trl_cnt, PyBUF_SIMPLE)) < 0)
- return NULL;
-#ifdef __APPLE__
- sbytes += i;
-#endif
+ cpu = PyLong_AsLong(item);
+ Py_DECREF(item);
+ if (cpu < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_ValueError, "negative CPU number");
+ goto error;
}
- }
-
- Py_BEGIN_ALLOW_THREADS
-#ifdef __APPLE__
- ret = sendfile(in, out, offset, &sbytes, &sf, flags);
-#else
- ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
-#endif
- Py_END_ALLOW_THREADS
-
- if (sf.headers != NULL)
- iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
- if (sf.trailers != NULL)
- iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
-
- if (ret < 0) {
- if ((errno == EAGAIN) || (errno == EBUSY)) {
- if (sbytes != 0) {
- // some data has been sent
- goto done;
+ if (cpu > INT_MAX - 1) {
+ PyErr_SetString(PyExc_OverflowError, "CPU number too large");
+ goto error;
+ }
+ if (cpu >= ncpus) {
+ /* Grow CPU mask to fit the CPU number */
+ int newncpus = ncpus;
+ cpu_set_t *newmask;
+ size_t newsetsize;
+ while (newncpus <= cpu) {
+ if (newncpus > INT_MAX / 2)
+ newncpus = cpu + 1;
+ else
+ newncpus = newncpus * 2;
}
- else {
- // no data has been sent; upper application is supposed
- // to retry on EAGAIN or EBUSY
- return posix_error();
+ newmask = CPU_ALLOC(newncpus);
+ if (newmask == NULL) {
+ PyErr_NoMemory();
+ goto error;
}
+ newsetsize = CPU_ALLOC_SIZE(newncpus);
+ CPU_ZERO_S(newsetsize, newmask);
+ memcpy(newmask, cpu_set, setsize);
+ CPU_FREE(cpu_set);
+ setsize = newsetsize;
+ cpu_set = newmask;
+ ncpus = newncpus;
}
- return posix_error();
+ CPU_SET_S(cpu, setsize, cpu_set);
}
- goto done;
-
-done:
- #if !defined(HAVE_LARGEFILE_SUPPORT)
- return Py_BuildValue("l", sbytes);
- #else
- return Py_BuildValue("L", sbytes);
- #endif
+ Py_CLEAR(iterator);
-#else
- Py_ssize_t count;
- PyObject *offobj;
- static char *keywords[] = {"out", "in",
- "offset", "count", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
- keywords, &out, &in, &offobj, &count))
- return NULL;
-#ifdef linux
- if (offobj == Py_None) {
- Py_BEGIN_ALLOW_THREADS
- ret = sendfile(out, in, NULL, count);
- Py_END_ALLOW_THREADS
- if (ret < 0)
- return posix_error();
- return Py_BuildValue("n", ret);
+ if (sched_setaffinity(pid, setsize, cpu_set)) {
+ posix_error();
+ goto error;
}
-#endif
- if (!_parse_off_t(offobj, &offset))
- return NULL;
- Py_BEGIN_ALLOW_THREADS
- ret = sendfile(out, in, &offset, count);
- Py_END_ALLOW_THREADS
- if (ret < 0)
- return posix_error();
- return Py_BuildValue("n", ret);
-#endif
+ CPU_FREE(cpu_set);
+ Py_RETURN_NONE;
+
+error:
+ if (cpu_set)
+ CPU_FREE(cpu_set);
+ Py_XDECREF(iterator);
+ return NULL;
}
-#endif
-PyDoc_STRVAR(posix_fstat__doc__,
-"fstat(fd) -> stat result\n\n\
-Like stat(), but for an open file descriptor.\n\
-Equivalent to stat(fd=fd).");
-static PyObject *
-posix_fstat(PyObject *self, PyObject *args)
-{
- int fd;
- STRUCT_STAT st;
- int res;
- if (!PyArg_ParseTuple(args, "i:fstat", &fd))
- return NULL;
- Py_BEGIN_ALLOW_THREADS
- res = FSTAT(fd, &st);
- Py_END_ALLOW_THREADS
- if (res != 0) {
-#ifdef MS_WINDOWS
- return PyErr_SetFromWindowsErr(0);
-#else
- return posix_error();
-#endif
- }
+/*[clinic input]
+os.sched_getaffinity
+ pid: pid_t
+ /
- return _pystat_fromstructstat(&st);
-}
+Return the affinity of the process identified by pid.
+
+The affinity is returned as a set of CPU identifiers.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_sched_getaffinity__doc__,
+"sched_getaffinity($module, pid, /)\n"
+"--\n"
+"\n"
+"Return the affinity of the process identified by pid.\n"
+"\n"
+"The affinity is returned as a set of CPU identifiers.");
+
+#define OS_SCHED_GETAFFINITY_METHODDEF \
+ {"sched_getaffinity", (PyCFunction)os_sched_getaffinity, METH_VARARGS, os_sched_getaffinity__doc__},
-PyDoc_STRVAR(posix_isatty__doc__,
-"isatty(fd) -> bool\n\n\
-Return True if the file descriptor 'fd' is an open file descriptor\n\
-connected to the slave end of a terminal.");
+static PyObject *
+os_sched_getaffinity_impl(PyModuleDef *module, pid_t pid);
static PyObject *
-posix_isatty(PyObject *self, PyObject *args)
+os_sched_getaffinity(PyModuleDef *module, PyObject *args)
{
- int fd;
- if (!PyArg_ParseTuple(args, "i:isatty", &fd))
- return NULL;
- if (!_PyVerify_fd(fd))
- return PyBool_FromLong(0);
- return PyBool_FromLong(isatty(fd));
-}
+ PyObject *return_value = NULL;
+ pid_t pid;
-#ifdef HAVE_PIPE
-PyDoc_STRVAR(posix_pipe__doc__,
-"pipe() -> (read_end, write_end)\n\n\
-Create a pipe.");
+ if (!PyArg_ParseTuple(args,
+ "" _Py_PARSE_PID ":sched_getaffinity",
+ &pid))
+ goto exit;
+ return_value = os_sched_getaffinity_impl(module, pid);
+
+exit:
+ return return_value;
+}
static PyObject *
-posix_pipe(PyObject *self, PyObject *noargs)
+os_sched_getaffinity_impl(PyModuleDef *module, pid_t pid)
+/*[clinic end generated code: output=7b273b0fca9830f0 input=eaf161936874b8a1]*/
{
- int fds[2];
-#ifdef MS_WINDOWS
- HANDLE read, write;
- SECURITY_ATTRIBUTES attr;
- BOOL ok;
-#else
- int res;
-#endif
-
-#ifdef MS_WINDOWS
- attr.nLength = sizeof(attr);
- attr.lpSecurityDescriptor = NULL;
- attr.bInheritHandle = FALSE;
+ int cpu, ncpus, count;
+ size_t setsize;
+ cpu_set_t *mask = NULL;
+ PyObject *res = NULL;
- Py_BEGIN_ALLOW_THREADS
- ok = CreatePipe(&read, &write, &attr, 0);
- if (ok) {
- fds[0] = _open_osfhandle((Py_intptr_t)read, _O_RDONLY);
- fds[1] = _open_osfhandle((Py_intptr_t)write, _O_WRONLY);
- if (fds[0] == -1 || fds[1] == -1) {
- CloseHandle(read);
- CloseHandle(write);
- ok = 0;
+ ncpus = NCPUS_START;
+ while (1) {
+ setsize = CPU_ALLOC_SIZE(ncpus);
+ mask = CPU_ALLOC(ncpus);
+ if (mask == NULL)
+ return PyErr_NoMemory();
+ if (sched_getaffinity(pid, setsize, mask) == 0)
+ break;
+ CPU_FREE(mask);
+ if (errno != EINVAL)
+ return posix_error();
+ if (ncpus > INT_MAX / 2) {
+ PyErr_SetString(PyExc_OverflowError, "could not allocate "
+ "a large enough CPU set");
+ return NULL;
}
+ ncpus = ncpus * 2;
}
- Py_END_ALLOW_THREADS
-
- if (!ok)
- return PyErr_SetFromWindowsErr(0);
-#else
-
-#ifdef HAVE_PIPE2
- Py_BEGIN_ALLOW_THREADS
- res = pipe2(fds, O_CLOEXEC);
- Py_END_ALLOW_THREADS
- if (res != 0 && errno == ENOSYS)
- {
-#endif
- Py_BEGIN_ALLOW_THREADS
- res = pipe(fds);
- Py_END_ALLOW_THREADS
-
- if (res == 0) {
- if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
- close(fds[0]);
- close(fds[1]);
- return NULL;
- }
- if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
- close(fds[0]);
- close(fds[1]);
- return NULL;
+ res = PySet_New(NULL);
+ if (res == NULL)
+ goto error;
+ for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
+ if (CPU_ISSET_S(cpu, setsize, mask)) {
+ PyObject *cpu_num = PyLong_FromLong(cpu);
+ --count;
+ if (cpu_num == NULL)
+ goto error;
+ if (PySet_Add(res, cpu_num)) {
+ Py_DECREF(cpu_num);
+ goto error;
}
+ Py_DECREF(cpu_num);
}
-#ifdef HAVE_PIPE2
}
-#endif
+ CPU_FREE(mask);
+ return res;
- if (res != 0)
- return PyErr_SetFromErrno(PyExc_OSError);
-#endif /* !MS_WINDOWS */
- return Py_BuildValue("(ii)", fds[0], fds[1]);
+error:
+ if (mask)
+ CPU_FREE(mask);
+ Py_XDECREF(res);
+ return NULL;
}
-#endif /* HAVE_PIPE */
-
-#ifdef HAVE_PIPE2
-PyDoc_STRVAR(posix_pipe2__doc__,
-"pipe2(flags) -> (read_end, write_end)\n\n\
-Create a pipe with flags set atomically.\n\
-flags can be constructed by ORing together one or more of these values:\n\
-O_NONBLOCK, O_CLOEXEC.\n\
-");
-
-static PyObject *
-posix_pipe2(PyObject *self, PyObject *arg)
-{
- int flags;
- int fds[2];
- int res;
- flags = _PyLong_AsInt(arg);
- if (flags == -1 && PyErr_Occurred())
- return NULL;
-
- res = pipe2(fds, flags);
- if (res != 0)
- return posix_error();
- return Py_BuildValue("(ii)", fds[0], fds[1]);
-}
-#endif /* HAVE_PIPE2 */
+#endif /* HAVE_SCHED_SETAFFINITY */
-#ifdef HAVE_WRITEV
-PyDoc_STRVAR(posix_writev__doc__,
-"writev(fd, buffers) -> byteswritten\n\n\
-Write the contents of *buffers* to file descriptor *fd*. *buffers*\n\
-must be a sequence of bytes-like objects.\n\n\
-writev writes the contents of each object to the file descriptor\n\
-and returns the total number of bytes written.");
+#endif /* HAVE_SCHED_H */
-static PyObject *
-posix_writev(PyObject *self, PyObject *args)
-{
- int fd, cnt;
- Py_ssize_t res;
- PyObject *seq;
- struct iovec *iov;
- Py_buffer *buf;
- if (!PyArg_ParseTuple(args, "iO:writev", &fd, &seq))
- return NULL;
- if (!PySequence_Check(seq)) {
- PyErr_SetString(PyExc_TypeError,
- "writev() arg 2 must be a sequence");
- return NULL;
- }
- cnt = PySequence_Size(seq);
+#ifndef OS_SCHED_GET_PRIORITY_MAX_METHODDEF
+#define OS_SCHED_GET_PRIORITY_MAX_METHODDEF
+#endif /* OS_SCHED_GET_PRIORITY_MAX_METHODDEF */
- if (iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE) < 0) {
- return NULL;
- }
+#ifndef OS_SCHED_GET_PRIORITY_MIN_METHODDEF
+#define OS_SCHED_GET_PRIORITY_MIN_METHODDEF
+#endif /* OS_SCHED_GET_PRIORITY_MIN_METHODDEF */
- Py_BEGIN_ALLOW_THREADS
- res = writev(fd, iov, cnt);
- Py_END_ALLOW_THREADS
+#ifndef OS_SCHED_GETSCHEDULER_METHODDEF
+#define OS_SCHED_GETSCHEDULER_METHODDEF
+#endif /* OS_SCHED_GETSCHEDULER_METHODDEF */
- iov_cleanup(iov, buf, cnt);
- if (res < 0)
- return posix_error();
+#ifndef OS_SCHED_SETSCHEDULER_METHODDEF
+#define OS_SCHED_SETSCHEDULER_METHODDEF
+#endif /* OS_SCHED_SETSCHEDULER_METHODDEF */
- return PyLong_FromSsize_t(res);
-}
-#endif
+#ifndef OS_SCHED_GETPARAM_METHODDEF
+#define OS_SCHED_GETPARAM_METHODDEF
+#endif /* OS_SCHED_GETPARAM_METHODDEF */
-#ifdef HAVE_PWRITE
-PyDoc_STRVAR(posix_pwrite__doc__,
-"pwrite(fd, string, offset) -> byteswritten\n\n\
-Write string to a file descriptor, fd, from offset, leaving the file\n\
-offset unchanged.");
+#ifndef OS_SCHED_SETPARAM_METHODDEF
+#define OS_SCHED_SETPARAM_METHODDEF
+#endif /* OS_SCHED_SETPARAM_METHODDEF */
-static PyObject *
-posix_pwrite(PyObject *self, PyObject *args)
-{
- Py_buffer pbuf;
- int fd;
- off_t offset;
- Py_ssize_t size;
+#ifndef OS_SCHED_RR_GET_INTERVAL_METHODDEF
+#define OS_SCHED_RR_GET_INTERVAL_METHODDEF
+#endif /* OS_SCHED_RR_GET_INTERVAL_METHODDEF */
- if (!PyArg_ParseTuple(args, "iy*O&:pwrite", &fd, &pbuf, _parse_off_t, &offset))
- return NULL;
+#ifndef OS_SCHED_YIELD_METHODDEF
+#define OS_SCHED_YIELD_METHODDEF
+#endif /* OS_SCHED_YIELD_METHODDEF */
- if (!_PyVerify_fd(fd)) {
- PyBuffer_Release(&pbuf);
- return posix_error();
- }
- Py_BEGIN_ALLOW_THREADS
- size = pwrite(fd, pbuf.buf, (size_t)pbuf.len, offset);
- Py_END_ALLOW_THREADS
- PyBuffer_Release(&pbuf);
- if (size < 0)
- return posix_error();
- return PyLong_FromSsize_t(size);
-}
-#endif
+#ifndef OS_SCHED_SETAFFINITY_METHODDEF
+#define OS_SCHED_SETAFFINITY_METHODDEF
+#endif /* OS_SCHED_SETAFFINITY_METHODDEF */
-#ifdef HAVE_MKFIFO
-PyDoc_STRVAR(posix_mkfifo__doc__,
-"mkfifo(path, mode=0o666, *, dir_fd=None)\n\n\
-Create a FIFO (a POSIX named pipe).\n\
-\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-dir_fd may not be implemented on your platform.\n\
- If it is unavailable, using it will raise a NotImplementedError.");
+#ifndef OS_SCHED_GETAFFINITY_METHODDEF
+#define OS_SCHED_GETAFFINITY_METHODDEF
+#endif /* OS_SCHED_GETAFFINITY_METHODDEF */
-static PyObject *
-posix_mkfifo(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- path_t path;
- int mode = 0666;
- int dir_fd = DEFAULT_DIR_FD;
- int result;
- PyObject *return_value = NULL;
- static char *keywords[] = {"path", "mode", "dir_fd", NULL};
- memset(&path, 0, sizeof(path));
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkfifo", keywords,
- path_converter, &path,
- &mode,
-#ifdef HAVE_MKFIFOAT
- dir_fd_converter, &dir_fd
+/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
+/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
+#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
+#define DEV_PTY_FILE "/dev/ptc"
+#define HAVE_DEV_PTMX
#else
- dir_fd_unavailable, &dir_fd
-#endif
- ))
- return NULL;
-
- Py_BEGIN_ALLOW_THREADS
-#ifdef HAVE_MKFIFOAT
- if (dir_fd != DEFAULT_DIR_FD)
- result = mkfifoat(dir_fd, path.narrow, mode);
- else
-#endif
- result = mkfifo(path.narrow, mode);
- Py_END_ALLOW_THREADS
-
- if (result < 0) {
- return_value = posix_error();
- goto exit;
- }
-
- return_value = Py_None;
- Py_INCREF(Py_None);
-
-exit:
- path_cleanup(&path);
- return return_value;
-}
+#define DEV_PTY_FILE "/dev/ptmx"
#endif
-#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
-PyDoc_STRVAR(posix_mknod__doc__,
-"mknod(filename, mode=0o600, device=0, *, dir_fd=None)\n\n\
-Create a filesystem node (file, device special file or named pipe)\n\
-named filename. mode specifies both the permissions to use and the\n\
-type of node to be created, being combined (bitwise OR) with one of\n\
-S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
-device defines the newly created device special file (probably using\n\
-os.makedev()), otherwise it is ignored.\n\
-\n\
-If dir_fd is not None, it should be a file descriptor open to a directory,\n\
- and path should be relative; path will then be relative to that directory.\n\
-dir_fd may not be implemented on your platform.\n\
- If it is unavailable, using it will raise a NotImplementedError.");
-
-
-static PyObject *
-posix_mknod(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- path_t path;
- int mode = 0666;
- dev_t device = 0;
- int dir_fd = DEFAULT_DIR_FD;
- int result;
- PyObject *return_value = NULL;
- static char *keywords[] = {"path", "mode", "device", "dir_fd", NULL};
-
- memset(&path, 0, sizeof(path));
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|iO&$O&:mknod", keywords,
- path_converter, &path,
- &mode, _Py_Dev_Converter, &device,
-#ifdef HAVE_MKNODAT
- dir_fd_converter, &dir_fd
+#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
+#ifdef HAVE_PTY_H
+#include <pty.h>
#else
- dir_fd_unavailable, &dir_fd
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#else
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif /* HAVE_UTIL_H */
+#endif /* HAVE_LIBUTIL_H */
+#endif /* HAVE_PTY_H */
+#ifdef HAVE_STROPTS_H
+#include <stropts.h>
#endif
- ))
- return NULL;
+#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
- Py_BEGIN_ALLOW_THREADS
-#ifdef HAVE_MKNODAT
- if (dir_fd != DEFAULT_DIR_FD)
- result = mknodat(dir_fd, path.narrow, mode, device);
- else
-#endif
- result = mknod(path.narrow, mode, device);
- Py_END_ALLOW_THREADS
- if (result < 0) {
- return_value = posix_error();
- goto exit;
- }
+#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
+/*[clinic input]
+os.openpty
- return_value = Py_None;
- Py_INCREF(Py_None);
+Open a pseudo-terminal.
-exit:
- path_cleanup(&path);
- return return_value;
-}
-#endif
+Return a tuple of (master_fd, slave_fd) containing open file descriptors
+for both the master and slave ends.
+[clinic start generated code]*/
-#ifdef HAVE_DEVICE_MACROS
-PyDoc_STRVAR(posix_major__doc__,
-"major(device) -> major number\n\
-Extracts a device major number from a raw device number.");
+PyDoc_STRVAR(os_openpty__doc__,
+"openpty($module, /)\n"
+"--\n"
+"\n"
+"Open a pseudo-terminal.\n"
+"\n"
+"Return a tuple of (master_fd, slave_fd) containing open file descriptors\n"
+"for both the master and slave ends.");
-static PyObject *
-posix_major(PyObject *self, PyObject *args)
-{
- dev_t device;
- if (!PyArg_ParseTuple(args, "O&:major", _Py_Dev_Converter, &device))
- return NULL;
- return PyLong_FromLong((long)major(device));
-}
+#define OS_OPENPTY_METHODDEF \
+ {"openpty", (PyCFunction)os_openpty, METH_NOARGS, os_openpty__doc__},
-PyDoc_STRVAR(posix_minor__doc__,
-"minor(device) -> minor number\n\
-Extracts a device minor number from a raw device number.");
+static PyObject *
+os_openpty_impl(PyModuleDef *module);
static PyObject *
-posix_minor(PyObject *self, PyObject *args)
+os_openpty(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
{
- dev_t device;
- if (!PyArg_ParseTuple(args, "O&:minor", _Py_Dev_Converter, &device))
- return NULL;
- return PyLong_FromLong((long)minor(device));
+ return os_openpty_impl(module);
}
-PyDoc_STRVAR(posix_makedev__doc__,
-"makedev(major, minor) -> device number\n\
-Composes a raw device number from the major and minor device numbers.");
-
static PyObject *
-posix_makedev(PyObject *self, PyObject *args)
+os_openpty_impl(PyModuleDef *module)
+/*[clinic end generated code: output=b12d3c1735468464 input=f3d99fd99e762907]*/
{
- int major, minor;
- if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
- return NULL;
- return _PyLong_FromDev(makedev(major, minor));
-}
-#endif /* device macros */
-
+ int master_fd = -1, slave_fd = -1;
+#ifndef HAVE_OPENPTY
+ char * slave_name;
+#endif
+#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
+ PyOS_sighandler_t sig_saved;
+#ifdef sun
+ extern char *ptsname(int fildes);
+#endif
+#endif
-#ifdef HAVE_FTRUNCATE
-PyDoc_STRVAR(posix_ftruncate__doc__,
-"ftruncate(fd, length)\n\n\
-Truncate a file to a specified length.");
+#ifdef HAVE_OPENPTY
+ if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
+ goto posix_error;
-static PyObject *
-posix_ftruncate(PyObject *self, PyObject *args)
-{
- int fd;
- off_t length;
- int res;
+ if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
+ goto error;
+ if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
+ goto error;
- if (!PyArg_ParseTuple(args, "iO&:ftruncate", &fd, _parse_off_t, &length))
- return NULL;
+#elif defined(HAVE__GETPTY)
+ slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
+ if (slave_name == NULL)
+ goto posix_error;
+ if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
+ goto error;
- Py_BEGIN_ALLOW_THREADS
- res = ftruncate(fd, length);
- Py_END_ALLOW_THREADS
- if (res < 0)
- return posix_error();
- Py_INCREF(Py_None);
- return Py_None;
-}
-#endif
+ slave_fd = _Py_open(slave_name, O_RDWR);
+ if (slave_fd < 0)
+ goto posix_error;
-#ifdef HAVE_TRUNCATE
-PyDoc_STRVAR(posix_truncate__doc__,
-"truncate(path, length)\n\n\
-Truncate the file given by path to length bytes.\n\
-On some platforms, path may also be specified as an open file descriptor.\n\
- If this functionality is unavailable, using it raises an exception.");
+#else
+ master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
+ if (master_fd < 0)
+ goto posix_error;
-static PyObject *
-posix_truncate(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- path_t path;
- off_t length;
- int res;
- PyObject *result = NULL;
- static char *keywords[] = {"path", "length", NULL};
+ sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
- memset(&path, 0, sizeof(path));
- path.function_name = "truncate";
-#ifdef HAVE_FTRUNCATE
- path.allow_fd = 1;
-#endif
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:truncate", keywords,
- path_converter, &path,
- _parse_off_t, &length))
- return NULL;
+ /* change permission of slave */
+ if (grantpt(master_fd) < 0) {
+ PyOS_setsig(SIGCHLD, sig_saved);
+ goto posix_error;
+ }
- Py_BEGIN_ALLOW_THREADS
-#ifdef HAVE_FTRUNCATE
- if (path.fd != -1)
- res = ftruncate(path.fd, length);
- else
-#endif
- res = truncate(path.narrow, length);
- Py_END_ALLOW_THREADS
- if (res < 0)
- result = path_error(&path);
- else {
- Py_INCREF(Py_None);
- result = Py_None;
+ /* unlock slave */
+ if (unlockpt(master_fd) < 0) {
+ PyOS_setsig(SIGCHLD, sig_saved);
+ goto posix_error;
}
- path_cleanup(&path);
- return result;
-}
-#endif
-/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
- and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
- defined, which is the case in Python on AIX. AIX bug report:
- http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
-#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
-# define POSIX_FADVISE_AIX_BUG
-#endif
+ PyOS_setsig(SIGCHLD, sig_saved);
-#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
-PyDoc_STRVAR(posix_posix_fallocate__doc__,
-"posix_fallocate(fd, offset, len)\n\n\
-Ensures that enough disk space is allocated for the file specified by fd\n\
-starting from offset and continuing for len bytes.");
+ slave_name = ptsname(master_fd); /* get name of slave */
+ if (slave_name == NULL)
+ goto posix_error;
-static PyObject *
-posix_posix_fallocate(PyObject *self, PyObject *args)
-{
- off_t len, offset;
- int res, fd;
+ slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
+ if (slave_fd < 0)
+ goto posix_error;
- if (!PyArg_ParseTuple(args, "iO&O&:posix_fallocate",
- &fd, _parse_off_t, &offset, _parse_off_t, &len))
- return NULL;
+ if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
+ goto posix_error;
- Py_BEGIN_ALLOW_THREADS
- res = posix_fallocate(fd, offset, len);
- Py_END_ALLOW_THREADS
- if (res != 0) {
- errno = res;
- return posix_error();
- }
- Py_RETURN_NONE;
-}
+#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC)
+ ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
+ ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
+#ifndef __hpux
+ ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
+#endif /* __hpux */
+#endif /* HAVE_CYGWIN */
+#endif /* HAVE_OPENPTY */
+
+ return Py_BuildValue("(ii)", master_fd, slave_fd);
+
+posix_error:
+ posix_error();
+#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY)
+error:
#endif
+ if (master_fd != -1)
+ close(master_fd);
+ if (slave_fd != -1)
+ close(slave_fd);
+ return NULL;
+}
+#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
-#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
-PyDoc_STRVAR(posix_posix_fadvise__doc__,
-"posix_fadvise(fd, offset, len, advice)\n\n\
-Announces an intention to access data in a specific pattern thus allowing\n\
-the kernel to make optimizations.\n\
-The advice applies to the region of the file specified by fd starting at\n\
-offset and continuing for len bytes.\n\
-advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n\
-POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED or\n\
-POSIX_FADV_DONTNEED.");
-static PyObject *
-posix_posix_fadvise(PyObject *self, PyObject *args)
-{
- off_t len, offset;
- int res, fd, advice;
+#ifdef HAVE_FORKPTY
+/*[clinic input]
+os.forkpty
- if (!PyArg_ParseTuple(args, "iO&O&i:posix_fadvise",
- &fd, _parse_off_t, &offset, _parse_off_t, &len, &advice))
- return NULL;
+Fork a new process with a new pseudo-terminal as controlling tty.
- Py_BEGIN_ALLOW_THREADS
- res = posix_fadvise(fd, offset, len, advice);
- Py_END_ALLOW_THREADS
- if (res != 0) {
- errno = res;
- return posix_error();
- }
- Py_RETURN_NONE;
-}
-#endif
+Returns a tuple of (pid, master_fd).
+Like fork(), return pid of 0 to the child process,
+and pid of child to the parent process.
+To both, return fd of newly opened pseudo-terminal.
+[clinic start generated code]*/
-#ifdef HAVE_PUTENV
-PyDoc_STRVAR(posix_putenv__doc__,
-"putenv(key, value)\n\n\
-Change or add an environment variable.");
+PyDoc_STRVAR(os_forkpty__doc__,
+"forkpty($module, /)\n"
+"--\n"
+"\n"
+"Fork a new process with a new pseudo-terminal as controlling tty.\n"
+"\n"
+"Returns a tuple of (pid, master_fd).\n"
+"Like fork(), return pid of 0 to the child process,\n"
+"and pid of child to the parent process.\n"
+"To both, return fd of newly opened pseudo-terminal.");
-/* Save putenv() parameters as values here, so we can collect them when they
- * get re-set with another call for the same key. */
-static PyObject *posix_putenv_garbage;
+#define OS_FORKPTY_METHODDEF \
+ {"forkpty", (PyCFunction)os_forkpty, METH_NOARGS, os_forkpty__doc__},
static PyObject *
-posix_putenv(PyObject *self, PyObject *args)
+os_forkpty_impl(PyModuleDef *module);
+
+static PyObject *
+os_forkpty(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
{
- PyObject *newstr = NULL;
-#ifdef MS_WINDOWS
- PyObject *os1, *os2;
- wchar_t *newenv;
+ return os_forkpty_impl(module);
+}
- if (!PyArg_ParseTuple(args,
- "UU:putenv",
- &os1, &os2))
- return NULL;
+static PyObject *
+os_forkpty_impl(PyModuleDef *module)
+/*[clinic end generated code: output=d4f82958d2ed5cad input=f1f7f4bae3966010]*/
+{
+ int master_fd = -1, result = 0;
+ pid_t pid;
- newstr = PyUnicode_FromFormat("%U=%U", os1, os2);
- if (newstr == NULL) {
- PyErr_NoMemory();
- goto error;
+ _PyImport_AcquireLock();
+ pid = forkpty(&master_fd, NULL, NULL, NULL);
+ if (pid == 0) {
+ /* child: this clobbers and resets the import lock. */
+ PyOS_AfterFork();
+ } else {
+ /* parent: release the import lock. */
+ result = _PyImport_ReleaseLock();
}
- if (_MAX_ENV < PyUnicode_GET_LENGTH(newstr)) {
- PyErr_Format(PyExc_ValueError,
- "the environment variable is longer than %u characters",
- _MAX_ENV);
- goto error;
+ if (pid == -1)
+ return posix_error();
+ if (result < 0) {
+ /* Don't clobber the OSError if the fork failed. */
+ PyErr_SetString(PyExc_RuntimeError,
+ "not holding the import lock");
+ return NULL;
}
+ return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
+}
+#endif /* HAVE_FORKPTY */
- newenv = PyUnicode_AsUnicode(newstr);
- if (newenv == NULL)
- goto error;
- if (_wputenv(newenv)) {
- posix_error();
- goto error;
- }
-#else
- PyObject *os1, *os2;
- char *s1, *s2;
- char *newenv;
- if (!PyArg_ParseTuple(args,
- "O&O&:putenv",
- PyUnicode_FSConverter, &os1,
- PyUnicode_FSConverter, &os2))
- return NULL;
- s1 = PyBytes_AsString(os1);
- s2 = PyBytes_AsString(os2);
+#ifdef HAVE_GETEGID
+/*[clinic input]
+os.getegid
- newstr = PyBytes_FromFormat("%s=%s", s1, s2);
- if (newstr == NULL) {
- PyErr_NoMemory();
- goto error;
- }
+Return the current process's effective group id.
+[clinic start generated code]*/
- newenv = PyBytes_AS_STRING(newstr);
- if (putenv(newenv)) {
- posix_error();
- goto error;
- }
-#endif
+PyDoc_STRVAR(os_getegid__doc__,
+"getegid($module, /)\n"
+"--\n"
+"\n"
+"Return the current process\'s effective group id.");
- /* Install the first arg and newstr in posix_putenv_garbage;
- * this will cause previous value to be collected. This has to
- * happen after the real putenv() call because the old value
- * was still accessible until then. */
- if (PyDict_SetItem(posix_putenv_garbage, os1, newstr)) {
- /* really not much we can do; just leak */
- PyErr_Clear();
- }
- else {
- Py_DECREF(newstr);
- }
+#define OS_GETEGID_METHODDEF \
+ {"getegid", (PyCFunction)os_getegid, METH_NOARGS, os_getegid__doc__},
-#ifndef MS_WINDOWS
- Py_DECREF(os1);
- Py_DECREF(os2);
-#endif
- Py_RETURN_NONE;
+static PyObject *
+os_getegid_impl(PyModuleDef *module);
-error:
-#ifndef MS_WINDOWS
- Py_DECREF(os1);
- Py_DECREF(os2);
-#endif
- Py_XDECREF(newstr);
- return NULL;
+static PyObject *
+os_getegid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
+{
+ return os_getegid_impl(module);
}
-#endif /* putenv */
-
-#ifdef HAVE_UNSETENV
-PyDoc_STRVAR(posix_unsetenv__doc__,
-"unsetenv(key)\n\n\
-Delete an environment variable.");
static PyObject *
-posix_unsetenv(PyObject *self, PyObject *args)
+os_getegid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=fd12c346fa41cccb input=1596f79ad1107d5d]*/
{
- PyObject *name;
-#ifndef HAVE_BROKEN_UNSETENV
- int err;
-#endif
+ return _PyLong_FromGid(getegid());
+}
+#endif /* HAVE_GETEGID */
- if (!PyArg_ParseTuple(args, "O&:unsetenv",
- PyUnicode_FSConverter, &name))
- return NULL;
+#ifdef HAVE_GETEUID
+/*[clinic input]
+os.geteuid
-#ifdef HAVE_BROKEN_UNSETENV
- unsetenv(PyBytes_AS_STRING(name));
-#else
- err = unsetenv(PyBytes_AS_STRING(name));
- if (err) {
- Py_DECREF(name);
- return posix_error();
- }
-#endif
+Return the current process's effective user id.
+[clinic start generated code]*/
- /* Remove the key from posix_putenv_garbage;
- * this will cause it to be collected. This has to
- * happen after the real unsetenv() call because the
- * old value was still accessible until then.
- */
- if (PyDict_DelItem(posix_putenv_garbage, name)) {
- /* really not much we can do; just leak */
- PyErr_Clear();
- }
- Py_DECREF(name);
- Py_RETURN_NONE;
-}
-#endif /* unsetenv */
+PyDoc_STRVAR(os_geteuid__doc__,
+"geteuid($module, /)\n"
+"--\n"
+"\n"
+"Return the current process\'s effective user id.");
+
+#define OS_GETEUID_METHODDEF \
+ {"geteuid", (PyCFunction)os_geteuid, METH_NOARGS, os_geteuid__doc__},
-PyDoc_STRVAR(posix_strerror__doc__,
-"strerror(code) -> string\n\n\
-Translate an error code to a message string.");
+static PyObject *
+os_geteuid_impl(PyModuleDef *module);
static PyObject *
-posix_strerror(PyObject *self, PyObject *args)
+os_geteuid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
{
- int code;
- char *message;
- if (!PyArg_ParseTuple(args, "i:strerror", &code))
- return NULL;
- message = strerror(code);
- if (message == NULL) {
- PyErr_SetString(PyExc_ValueError,
- "strerror() argument out of range");
- return NULL;
- }
- return PyUnicode_DecodeLocale(message, "surrogateescape");
+ return os_geteuid_impl(module);
}
-
-#ifdef HAVE_SYS_WAIT_H
-
-#ifdef WCOREDUMP
-PyDoc_STRVAR(posix_WCOREDUMP__doc__,
-"WCOREDUMP(status) -> bool\n\n\
-Return True if the process returning 'status' was dumped to a core file.");
-
static PyObject *
-posix_WCOREDUMP(PyObject *self, PyObject *args)
+os_geteuid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=03d98e07f4bc03d4 input=4644c662d3bd9f19]*/
{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
-
- if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
- return NULL;
-
- return PyBool_FromLong(WCOREDUMP(status));
+ return _PyLong_FromUid(geteuid());
}
-#endif /* WCOREDUMP */
+#endif /* HAVE_GETEUID */
-#ifdef WIFCONTINUED
-PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
-"WIFCONTINUED(status) -> bool\n\n\
-Return True if the process returning 'status' was continued from a\n\
-job control stop.");
-static PyObject *
-posix_WIFCONTINUED(PyObject *self, PyObject *args)
-{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
+#ifdef HAVE_GETGID
+/*[clinic input]
+os.getgid
- if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
- return NULL;
+Return the current process's group id.
+[clinic start generated code]*/
- return PyBool_FromLong(WIFCONTINUED(status));
-}
-#endif /* WIFCONTINUED */
+PyDoc_STRVAR(os_getgid__doc__,
+"getgid($module, /)\n"
+"--\n"
+"\n"
+"Return the current process\'s group id.");
-#ifdef WIFSTOPPED
-PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
-"WIFSTOPPED(status) -> bool\n\n\
-Return True if the process returning 'status' was stopped.");
+#define OS_GETGID_METHODDEF \
+ {"getgid", (PyCFunction)os_getgid, METH_NOARGS, os_getgid__doc__},
static PyObject *
-posix_WIFSTOPPED(PyObject *self, PyObject *args)
-{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
-
- if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
- return NULL;
+os_getgid_impl(PyModuleDef *module);
- return PyBool_FromLong(WIFSTOPPED(status));
+static PyObject *
+os_getgid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
+{
+ return os_getgid_impl(module);
}
-#endif /* WIFSTOPPED */
-
-#ifdef WIFSIGNALED
-PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
-"WIFSIGNALED(status) -> bool\n\n\
-Return True if the process returning 'status' was terminated by a signal.");
static PyObject *
-posix_WIFSIGNALED(PyObject *self, PyObject *args)
+os_getgid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=07b0356121b8098d input=58796344cd87c0f6]*/
{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
-
- if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
- return NULL;
-
- return PyBool_FromLong(WIFSIGNALED(status));
+ return _PyLong_FromGid(getgid());
}
-#endif /* WIFSIGNALED */
+#endif /* HAVE_GETGID */
-#ifdef WIFEXITED
-PyDoc_STRVAR(posix_WIFEXITED__doc__,
-"WIFEXITED(status) -> bool\n\n\
-Return true if the process returning 'status' exited using the exit()\n\
-system call.");
-static PyObject *
-posix_WIFEXITED(PyObject *self, PyObject *args)
-{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
+/*[clinic input]
+os.getpid
- if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
- return NULL;
+Return the current process id.
+[clinic start generated code]*/
- return PyBool_FromLong(WIFEXITED(status));
-}
-#endif /* WIFEXITED */
+PyDoc_STRVAR(os_getpid__doc__,
+"getpid($module, /)\n"
+"--\n"
+"\n"
+"Return the current process id.");
-#ifdef WEXITSTATUS
-PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
-"WEXITSTATUS(status) -> integer\n\n\
-Return the process return code from 'status'.");
+#define OS_GETPID_METHODDEF \
+ {"getpid", (PyCFunction)os_getpid, METH_NOARGS, os_getpid__doc__},
static PyObject *
-posix_WEXITSTATUS(PyObject *self, PyObject *args)
-{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
+os_getpid_impl(PyModuleDef *module);
- if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
- return NULL;
-
- return Py_BuildValue("i", WEXITSTATUS(status));
+static PyObject *
+os_getpid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
+{
+ return os_getpid_impl(module);
}
-#endif /* WEXITSTATUS */
-
-#ifdef WTERMSIG
-PyDoc_STRVAR(posix_WTERMSIG__doc__,
-"WTERMSIG(status) -> integer\n\n\
-Return the signal that terminated the process that provided the 'status'\n\
-value.");
static PyObject *
-posix_WTERMSIG(PyObject *self, PyObject *args)
+os_getpid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=d63a01a3cebc573d input=5a9a00f0ab68aa00]*/
{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
-
- if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
- return NULL;
-
- return Py_BuildValue("i", WTERMSIG(status));
+ return PyLong_FromPid(getpid());
}
-#endif /* WTERMSIG */
-#ifdef WSTOPSIG
-PyDoc_STRVAR(posix_WSTOPSIG__doc__,
-"WSTOPSIG(status) -> integer\n\n\
-Return the signal that stopped the process that provided\n\
-the 'status' value.");
+#ifdef HAVE_GETGROUPLIST
+
+/* AC 3.5: funny apple logic below */
+PyDoc_STRVAR(posix_getgrouplist__doc__,
+"getgrouplist(user, group) -> list of groups to which a user belongs\n\n\
+Returns a list of groups to which a user belongs.\n\n\
+ user: username to lookup\n\
+ group: base group id of the user");
static PyObject *
-posix_WSTOPSIG(PyObject *self, PyObject *args)
+posix_getgrouplist(PyObject *self, PyObject *args)
{
- WAIT_TYPE status;
- WAIT_STATUS_INT(status) = 0;
-
- if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
- return NULL;
-
- return Py_BuildValue("i", WSTOPSIG(status));
-}
-#endif /* WSTOPSIG */
+#ifdef NGROUPS_MAX
+#define MAX_GROUPS NGROUPS_MAX
+#else
+ /* defined to be 16 on Solaris7, so this should be a small number */
+#define MAX_GROUPS 64
+#endif
-#endif /* HAVE_SYS_WAIT_H */
+ const char *user;
+ int i, ngroups;
+ PyObject *list;
+#ifdef __APPLE__
+ int *groups, basegid;
+#else
+ gid_t *groups, basegid;
+#endif
+ ngroups = MAX_GROUPS;
+#ifdef __APPLE__
+ if (!PyArg_ParseTuple(args, "si:getgrouplist", &user, &basegid))
+ return NULL;
+#else
+ if (!PyArg_ParseTuple(args, "sO&:getgrouplist", &user,
+ _Py_Gid_Converter, &basegid))
+ return NULL;
+#endif
-#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
-#ifdef _SCO_DS
-/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
- needed definitions in sys/statvfs.h */
-#define _SVID3
+#ifdef __APPLE__
- groups = PyMem_Malloc(ngroups * sizeof(int));
++ groups = PyMem_New(int, ngroups);
+#else
- groups = PyMem_Malloc(ngroups * sizeof(gid_t));
++ groups = PyMem_New(gid_t, ngroups);
#endif
-#include <sys/statvfs.h>
+ if (groups == NULL)
+ return PyErr_NoMemory();
-static PyObject*
-_pystatvfs_fromstructstatvfs(struct statvfs st) {
- PyObject *v = PyStructSequence_New(&StatVFSResultType);
- if (v == NULL)
+ if (getgrouplist(user, basegid, groups, &ngroups) == -1) {
+ PyMem_Del(groups);
+ return posix_error();
+ }
+
+ list = PyList_New(ngroups);
+ if (list == NULL) {
+ PyMem_Del(groups);
return NULL;
+ }
-#if !defined(HAVE_LARGEFILE_SUPPORT)
- PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
- PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
- PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
- PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
- PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
- PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
- PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
- PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
- PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
- PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
+ for (i = 0; i < ngroups; i++) {
+#ifdef __APPLE__
+ PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
#else
- PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
- PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
- PyStructSequence_SET_ITEM(v, 2,
- PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
- PyStructSequence_SET_ITEM(v, 3,
- PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
- PyStructSequence_SET_ITEM(v, 4,
- PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
- PyStructSequence_SET_ITEM(v, 5,
- PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
- PyStructSequence_SET_ITEM(v, 6,
- PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
- PyStructSequence_SET_ITEM(v, 7,
- PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
- PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
- PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
+ PyObject *o = _PyLong_FromGid(groups[i]);
#endif
- if (PyErr_Occurred()) {
- Py_DECREF(v);
- return NULL;
+ if (o == NULL) {
+ Py_DECREF(list);
+ PyMem_Del(groups);
+ return NULL;
+ }
+ PyList_SET_ITEM(list, i, o);
}
- return v;
-}
+ PyMem_Del(groups);
-PyDoc_STRVAR(posix_fstatvfs__doc__,
-"fstatvfs(fd) -> statvfs result\n\n\
-Perform an fstatvfs system call on the given fd.\n\
-Equivalent to statvfs(fd).");
+ return list;
+}
+#endif /* HAVE_GETGROUPLIST */
-static PyObject *
-posix_fstatvfs(PyObject *self, PyObject *args)
-{
- int fd, res;
- struct statvfs st;
- if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
- return NULL;
- Py_BEGIN_ALLOW_THREADS
- res = fstatvfs(fd, &st);
- Py_END_ALLOW_THREADS
- if (res != 0)
- return posix_error();
+#ifdef HAVE_GETGROUPS
+/*[clinic input]
+os.getgroups
- return _pystatvfs_fromstructstatvfs(st);
-}
-#endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
+Return list of supplemental group IDs for the process.
+[clinic start generated code]*/
+PyDoc_STRVAR(os_getgroups__doc__,
+"getgroups($module, /)\n"
+"--\n"
+"\n"
+"Return list of supplemental group IDs for the process.");
-#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
-#include <sys/statvfs.h>
+#define OS_GETGROUPS_METHODDEF \
+ {"getgroups", (PyCFunction)os_getgroups, METH_NOARGS, os_getgroups__doc__},
-PyDoc_STRVAR(posix_statvfs__doc__,
-"statvfs(path)\n\n\
-Perform a statvfs system call on the given path.\n\
-\n\
-path may always be specified as a string.\n\
-On some platforms, path may also be specified as an open file descriptor.\n\
- If this functionality is unavailable, using it raises an exception.");
+static PyObject *
+os_getgroups_impl(PyModuleDef *module);
static PyObject *
-posix_statvfs(PyObject *self, PyObject *args, PyObject *kwargs)
+os_getgroups(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
{
- static char *keywords[] = {"path", NULL};
- path_t path;
- int result;
- PyObject *return_value = NULL;
- struct statvfs st;
-
- memset(&path, 0, sizeof(path));
- path.function_name = "statvfs";
-#ifdef HAVE_FSTATVFS
- path.allow_fd = 1;
-#endif
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:statvfs", keywords,
- path_converter, &path
- ))
- return NULL;
-
- Py_BEGIN_ALLOW_THREADS
-#ifdef HAVE_FSTATVFS
- if (path.fd != -1) {
-#ifdef __APPLE__
- /* handle weak-linking on Mac OS X 10.3 */
- if (fstatvfs == NULL) {
- fd_specified("statvfs", path.fd);
- goto exit;
- }
-#endif
- result = fstatvfs(path.fd, &st);
- }
- else
-#endif
- result = statvfs(path.narrow, &st);
- Py_END_ALLOW_THREADS
-
- if (result) {
- return_value = path_error(&path);
- goto exit;
- }
-
- return_value = _pystatvfs_fromstructstatvfs(st);
-
-exit:
- path_cleanup(&path);
- return return_value;
+ return os_getgroups_impl(module);
}
-#endif /* HAVE_STATVFS */
-
-#ifdef MS_WINDOWS
-PyDoc_STRVAR(win32__getdiskusage__doc__,
-"_getdiskusage(path) -> (total, free)\n\n\
-Return disk usage statistics about the given path as (total, free) tuple.");
static PyObject *
-win32__getdiskusage(PyObject *self, PyObject *args)
+os_getgroups_impl(PyModuleDef *module)
+/*[clinic end generated code: output=d9a3559b2e6f4ab8 input=d3f109412e6a155c]*/
{
- BOOL retval;
- ULARGE_INTEGER _, total, free;
- const wchar_t *path;
+ PyObject *result = NULL;
- if (! PyArg_ParseTuple(args, "u", &path))
- return NULL;
+#ifdef NGROUPS_MAX
+#define MAX_GROUPS NGROUPS_MAX
+#else
+ /* defined to be 16 on Solaris7, so this should be a small number */
+#define MAX_GROUPS 64
+#endif
+ gid_t grouplist[MAX_GROUPS];
- Py_BEGIN_ALLOW_THREADS
- retval = GetDiskFreeSpaceExW(path, &_, &total, &free);
- Py_END_ALLOW_THREADS
- if (retval == 0)
- return PyErr_SetFromWindowsErr(0);
-
- return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
-}
-#endif
-
-
-/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
- * It maps strings representing configuration variable names to
- * integer values, allowing those functions to be called with the
- * magic names instead of polluting the module's namespace with tons of
- * rarely-used constants. There are three separate tables that use
- * these definitions.
- *
- * This code is always included, even if none of the interfaces that
- * need it are included. The #if hackery needed to avoid it would be
- * sufficiently pervasive that it's not worth the loss of readability.
- */
-struct constdef {
- char *name;
- long value;
-};
+ /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
+ * This is a helper variable to store the intermediate result when
+ * that happens.
+ *
+ * To keep the code readable the OSX behaviour is unconditional,
+ * according to the POSIX spec this should be safe on all unix-y
+ * systems.
+ */
+ gid_t* alt_grouplist = grouplist;
+ int n;
-static int
-conv_confname(PyObject *arg, int *valuep, struct constdef *table,
- size_t tablesize)
-{
- if (PyLong_Check(arg)) {
- *valuep = PyLong_AS_LONG(arg);
- return 1;
+#ifdef __APPLE__
+ /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
+ * there are more groups than can fit in grouplist. Therefore, on OS X
+ * always first call getgroups with length 0 to get the actual number
+ * of groups.
+ */
+ n = getgroups(0, NULL);
+ if (n < 0) {
+ return posix_error();
+ } else if (n <= MAX_GROUPS) {
+ /* groups will fit in existing array */
+ alt_grouplist = grouplist;
+ } else {
- alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
++ alt_grouplist = PyMem_New(gid_t, n);
+ if (alt_grouplist == NULL) {
+ errno = EINVAL;
+ return posix_error();
+ }
}
- else {
- /* look up the value in the table using a binary search */
- size_t lo = 0;
- size_t mid;
- size_t hi = tablesize;
- int cmp;
- const char *confname;
- if (!PyUnicode_Check(arg)) {
- PyErr_SetString(PyExc_TypeError,
- "configuration names must be strings or integers");
- return 0;
+
+ n = getgroups(n, alt_grouplist);
+ if (n == -1) {
+ if (alt_grouplist != grouplist) {
+ PyMem_Free(alt_grouplist);
}
- confname = _PyUnicode_AsString(arg);
- if (confname == NULL)
- return 0;
- while (lo < hi) {
- mid = (lo + hi) / 2;
- cmp = strcmp(confname, table[mid].name);
- if (cmp < 0)
- hi = mid;
- else if (cmp > 0)
- lo = mid + 1;
- else {
- *valuep = table[mid].value;
- return 1;
+ return posix_error();
+ }
+#else
+ n = getgroups(MAX_GROUPS, grouplist);
+ if (n < 0) {
+ if (errno == EINVAL) {
+ n = getgroups(0, NULL);
+ if (n == -1) {
+ return posix_error();
+ }
+ if (n == 0) {
+ /* Avoid malloc(0) */
+ alt_grouplist = grouplist;
+ } else {
- alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
++ alt_grouplist = PyMem_New(gid_t, n);
+ if (alt_grouplist == NULL) {
+ errno = EINVAL;
+ return posix_error();
+ }
+ n = getgroups(n, alt_grouplist);
+ if (n == -1) {
+ PyMem_Free(alt_grouplist);
+ return posix_error();
+ }
}
+ } else {
+ return posix_error();
}
- PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
- return 0;
}
-}
-
-
-#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
-static struct constdef posix_constants_pathconf[] = {
-#ifdef _PC_ABI_AIO_XFER_MAX
- {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
-#endif
-#ifdef _PC_ABI_ASYNC_IO
- {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
-#endif
-#ifdef _PC_ASYNC_IO
- {"PC_ASYNC_IO", _PC_ASYNC_IO},
-#endif
-#ifdef _PC_CHOWN_RESTRICTED
- {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
-#endif
-#ifdef _PC_FILESIZEBITS
- {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
-#endif
-#ifdef _PC_LAST
- {"PC_LAST", _PC_LAST},
-#endif
-#ifdef _PC_LINK_MAX
- {"PC_LINK_MAX", _PC_LINK_MAX},
-#endif
-#ifdef _PC_MAX_CANON
- {"PC_MAX_CANON", _PC_MAX_CANON},
-#endif
-#ifdef _PC_MAX_INPUT
- {"PC_MAX_INPUT", _PC_MAX_INPUT},
-#endif
-#ifdef _PC_NAME_MAX
- {"PC_NAME_MAX", _PC_NAME_MAX},
-#endif
-#ifdef _PC_NO_TRUNC
- {"PC_NO_TRUNC", _PC_NO_TRUNC},
-#endif
-#ifdef _PC_PATH_MAX
- {"PC_PATH_MAX", _PC_PATH_MAX},
-#endif
-#ifdef _PC_PIPE_BUF
- {"PC_PIPE_BUF", _PC_PIPE_BUF},
-#endif
-#ifdef _PC_PRIO_IO
- {"PC_PRIO_IO", _PC_PRIO_IO},
-#endif
-#ifdef _PC_SOCK_MAXBUF
- {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
-#endif
-#ifdef _PC_SYNC_IO
- {"PC_SYNC_IO", _PC_SYNC_IO},
-#endif
-#ifdef _PC_VDISABLE
- {"PC_VDISABLE", _PC_VDISABLE},
-#endif
-#ifdef _PC_ACL_ENABLED
- {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
-#endif
-#ifdef _PC_MIN_HOLE_SIZE
- {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
-#endif
-#ifdef _PC_ALLOC_SIZE_MIN
- {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
-#endif
-#ifdef _PC_REC_INCR_XFER_SIZE
- {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
-#endif
-#ifdef _PC_REC_MAX_XFER_SIZE
- {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
-#endif
-#ifdef _PC_REC_MIN_XFER_SIZE
- {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
-#endif
-#ifdef _PC_REC_XFER_ALIGN
- {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
-#endif
-#ifdef _PC_SYMLINK_MAX
- {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
-#endif
-#ifdef _PC_XATTR_ENABLED
- {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
-#endif
-#ifdef _PC_XATTR_EXISTS
- {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
-#endif
-#ifdef _PC_TIMESTAMP_RESOLUTION
- {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
-#endif
-};
-
-static int
-conv_path_confname(PyObject *arg, int *valuep)
-{
- return conv_confname(arg, valuep, posix_constants_pathconf,
- sizeof(posix_constants_pathconf)
- / sizeof(struct constdef));
-}
#endif
-#ifdef HAVE_FPATHCONF
-PyDoc_STRVAR(posix_fpathconf__doc__,
-"fpathconf(fd, name) -> integer\n\n\
-Return the configuration limit name for the file descriptor fd.\n\
-If there is no limit, return -1.");
-
-static PyObject *
-posix_fpathconf(PyObject *self, PyObject *args)
-{
- PyObject *result = NULL;
- int name, fd;
-
- if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
- conv_path_confname, &name)) {
- long limit;
+ result = PyList_New(n);
+ if (result != NULL) {
+ int i;
+ for (i = 0; i < n; ++i) {
+ PyObject *o = _PyLong_FromGid(alt_grouplist[i]);
+ if (o == NULL) {
+ Py_DECREF(result);
+ result = NULL;
+ break;
+ }
+ PyList_SET_ITEM(result, i, o);
+ }
+ }
- errno = 0;
- limit = fpathconf(fd, name);
- if (limit == -1 && errno != 0)
- posix_error();
- else
- result = PyLong_FromLong(limit);
+ if (alt_grouplist != grouplist) {
+ PyMem_Free(alt_grouplist);
}
+
return result;
}
-#endif
+#endif /* HAVE_GETGROUPS */
+#ifdef HAVE_INITGROUPS
+PyDoc_STRVAR(posix_initgroups__doc__,
+"initgroups(username, gid) -> None\n\n\
+Call the system initgroups() to initialize the group access list with all of\n\
+the groups of which the specified username is a member, plus the specified\n\
+group id.");
-#ifdef HAVE_PATHCONF
-PyDoc_STRVAR(posix_pathconf__doc__,
-"pathconf(path, name) -> integer\n\n\
-Return the configuration limit name for the file or directory path.\n\
-If there is no limit, return -1.\n\
-On some platforms, path may also be specified as an open file descriptor.\n\
- If this functionality is unavailable, using it raises an exception.");
-
+/* AC 3.5: funny apple logic */
static PyObject *
-posix_pathconf(PyObject *self, PyObject *args, PyObject *kwargs)
+posix_initgroups(PyObject *self, PyObject *args)
{
- path_t path;
- PyObject *result = NULL;
- int name;
- static char *keywords[] = {"path", "name", NULL};
-
- memset(&path, 0, sizeof(path));
- path.function_name = "pathconf";
-#ifdef HAVE_FPATHCONF
- path.allow_fd = 1;
+ PyObject *oname;
+ char *username;
+ int res;
+#ifdef __APPLE__
+ int gid;
+#else
+ gid_t gid;
#endif
- if (PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:pathconf", keywords,
- path_converter, &path,
- conv_path_confname, &name)) {
- long limit;
- errno = 0;
-#ifdef HAVE_FPATHCONF
- if (path.fd != -1)
- limit = fpathconf(path.fd, name);
- else
-#endif
- limit = pathconf(path.narrow, name);
- if (limit == -1 && errno != 0) {
- if (errno == EINVAL)
- /* could be a path or name problem */
- posix_error();
- else
- result = path_error(&path);
- }
- else
- result = PyLong_FromLong(limit);
- }
- path_cleanup(&path);
- return result;
-}
+#ifdef __APPLE__
+ if (!PyArg_ParseTuple(args, "O&i:initgroups",
+ PyUnicode_FSConverter, &oname,
+ &gid))
+#else
+ if (!PyArg_ParseTuple(args, "O&O&:initgroups",
+ PyUnicode_FSConverter, &oname,
+ _Py_Gid_Converter, &gid))
#endif
+ return NULL;
+ username = PyBytes_AS_STRING(oname);
-#ifdef HAVE_CONFSTR
-static struct constdef posix_constants_confstr[] = {
-#ifdef _CS_ARCHITECTURE
- {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
-#endif
-#ifdef _CS_GNU_LIBC_VERSION
- {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
-#endif
-#ifdef _CS_GNU_LIBPTHREAD_VERSION
- {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
-#endif
-#ifdef _CS_HOSTNAME
- {"CS_HOSTNAME", _CS_HOSTNAME},
-#endif
-#ifdef _CS_HW_PROVIDER
- {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
-#endif
-#ifdef _CS_HW_SERIAL
- {"CS_HW_SERIAL", _CS_HW_SERIAL},
-#endif
-#ifdef _CS_INITTAB_NAME
- {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
-#endif
-#ifdef _CS_LFS64_CFLAGS
- {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
-#endif
-#ifdef _CS_LFS64_LDFLAGS
- {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
-#endif
-#ifdef _CS_LFS64_LIBS
- {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
-#endif
-#ifdef _CS_LFS64_LINTFLAGS
- {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
-#endif
-#ifdef _CS_LFS_CFLAGS
- {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
-#endif
-#ifdef _CS_LFS_LDFLAGS
- {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
-#endif
-#ifdef _CS_LFS_LIBS
- {"CS_LFS_LIBS", _CS_LFS_LIBS},
-#endif
-#ifdef _CS_LFS_LINTFLAGS
- {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
-#endif
-#ifdef _CS_MACHINE
- {"CS_MACHINE", _CS_MACHINE},
-#endif
-#ifdef _CS_PATH
- {"CS_PATH", _CS_PATH},
-#endif
-#ifdef _CS_RELEASE
- {"CS_RELEASE", _CS_RELEASE},
-#endif
-#ifdef _CS_SRPC_DOMAIN
- {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
-#endif
-#ifdef _CS_SYSNAME
- {"CS_SYSNAME", _CS_SYSNAME},
-#endif
-#ifdef _CS_VERSION
- {"CS_VERSION", _CS_VERSION},
-#endif
-#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
- {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
-#endif
-#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
- {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
-#endif
-#ifdef _CS_XBS5_ILP32_OFF32_LIBS
- {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
-#endif
-#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
- {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
-#endif
-#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
- {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
-#endif
-#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
- {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
-#endif
-#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
- {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
-#endif
-#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
- {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
-#endif
-#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
- {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
-#endif
-#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
- {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
-#endif
-#ifdef _CS_XBS5_LP64_OFF64_LIBS
- {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
-#endif
-#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
- {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
-#endif
-#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
- {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
-#endif
-#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
- {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
-#endif
-#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
- {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
-#endif
-#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
- {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
-#endif
-#ifdef _MIPS_CS_AVAIL_PROCESSORS
- {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
-#endif
-#ifdef _MIPS_CS_BASE
- {"MIPS_CS_BASE", _MIPS_CS_BASE},
-#endif
-#ifdef _MIPS_CS_HOSTID
- {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
-#endif
-#ifdef _MIPS_CS_HW_NAME
- {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
-#endif
-#ifdef _MIPS_CS_NUM_PROCESSORS
- {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
-#endif
-#ifdef _MIPS_CS_OSREL_MAJ
- {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
-#endif
-#ifdef _MIPS_CS_OSREL_MIN
- {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
-#endif
-#ifdef _MIPS_CS_OSREL_PATCH
- {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
-#endif
-#ifdef _MIPS_CS_OS_NAME
- {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
-#endif
-#ifdef _MIPS_CS_OS_PROVIDER
- {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
-#endif
-#ifdef _MIPS_CS_PROCESSORS
- {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
-#endif
-#ifdef _MIPS_CS_SERIAL
- {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
-#endif
-#ifdef _MIPS_CS_VENDOR
- {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
-#endif
-};
+ res = initgroups(username, gid);
+ Py_DECREF(oname);
+ if (res == -1)
+ return PyErr_SetFromErrno(PyExc_OSError);
-static int
-conv_confstr_confname(PyObject *arg, int *valuep)
-{
- return conv_confname(arg, valuep, posix_constants_confstr,
- sizeof(posix_constants_confstr)
- / sizeof(struct constdef));
+ Py_INCREF(Py_None);
+ return Py_None;
}
+#endif /* HAVE_INITGROUPS */
+
+
+#ifdef HAVE_GETPGID
+/*[clinic input]
+os.getpgid
+
+ pid: pid_t
+
+Call the system call getpgid(), and return the result.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_getpgid__doc__,
+"getpgid($module, /, pid)\n"
+"--\n"
+"\n"
+"Call the system call getpgid(), and return the result.");
-PyDoc_STRVAR(posix_confstr__doc__,
-"confstr(name) -> string\n\n\
-Return a string-valued system configuration variable.");
+#define OS_GETPGID_METHODDEF \
+ {"getpgid", (PyCFunction)os_getpgid, METH_VARARGS|METH_KEYWORDS, os_getpgid__doc__},
+
+static PyObject *
+os_getpgid_impl(PyModuleDef *module, pid_t pid);
static PyObject *
-posix_confstr(PyObject *self, PyObject *args)
+os_getpgid(PyModuleDef *module, PyObject *args, PyObject *kwargs)
{
- PyObject *result = NULL;
- int name;
- char buffer[255];
- size_t len;
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"pid", NULL};
+ pid_t pid;
- if (!PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name))
- return NULL;
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "" _Py_PARSE_PID ":getpgid", _keywords,
+ &pid))
+ goto exit;
+ return_value = os_getpgid_impl(module, pid);
- errno = 0;
- len = confstr(name, buffer, sizeof(buffer));
- if (len == 0) {
- if (errno) {
- posix_error();
- return NULL;
- }
- else {
- Py_RETURN_NONE;
- }
- }
+exit:
+ return return_value;
+}
- if (len >= sizeof(buffer)) {
- char *buf = PyMem_Malloc(len);
- if (buf == NULL)
- return PyErr_NoMemory();
- confstr(name, buf, len);
- result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1);
- PyMem_Free(buf);
- }
- else
- result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
- return result;
+static PyObject *
+os_getpgid_impl(PyModuleDef *module, pid_t pid)
+/*[clinic end generated code: output=3db4ed686179160d input=39d710ae3baaf1c7]*/
+{
+ pid_t pgid = getpgid(pid);
+ if (pgid < 0)
+ return posix_error();
+ return PyLong_FromPid(pgid);
}
-#endif
+#endif /* HAVE_GETPGID */
-#ifdef HAVE_SYSCONF
-static struct constdef posix_constants_sysconf[] = {
-#ifdef _SC_2_CHAR_TERM
- {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
-#endif
-#ifdef _SC_2_C_BIND
- {"SC_2_C_BIND", _SC_2_C_BIND},
-#endif
-#ifdef _SC_2_C_DEV
- {"SC_2_C_DEV", _SC_2_C_DEV},
-#endif
-#ifdef _SC_2_C_VERSION
- {"SC_2_C_VERSION", _SC_2_C_VERSION},
-#endif
-#ifdef _SC_2_FORT_DEV
- {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
-#endif
-#ifdef _SC_2_FORT_RUN
- {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
-#endif
-#ifdef _SC_2_LOCALEDEF
- {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
-#endif
-#ifdef _SC_2_SW_DEV
- {"SC_2_SW_DEV", _SC_2_SW_DEV},
-#endif
-#ifdef _SC_2_UPE
- {"SC_2_UPE", _SC_2_UPE},
-#endif
-#ifdef _SC_2_VERSION
- {"SC_2_VERSION", _SC_2_VERSION},
-#endif
-#ifdef _SC_ABI_ASYNCHRONOUS_IO
- {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
-#endif
-#ifdef _SC_ACL
- {"SC_ACL", _SC_ACL},
-#endif
-#ifdef _SC_AIO_LISTIO_MAX
- {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
-#endif
-#ifdef _SC_AIO_MAX
- {"SC_AIO_MAX", _SC_AIO_MAX},
-#endif
-#ifdef _SC_AIO_PRIO_DELTA_MAX
- {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
-#endif
-#ifdef _SC_ARG_MAX
- {"SC_ARG_MAX", _SC_ARG_MAX},
-#endif
-#ifdef _SC_ASYNCHRONOUS_IO
- {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
-#endif
-#ifdef _SC_ATEXIT_MAX
- {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
-#endif
-#ifdef _SC_AUDIT
- {"SC_AUDIT", _SC_AUDIT},
-#endif
-#ifdef _SC_AVPHYS_PAGES
- {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
-#endif
-#ifdef _SC_BC_BASE_MAX
- {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
-#endif
-#ifdef _SC_BC_DIM_MAX
- {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
-#endif
-#ifdef _SC_BC_SCALE_MAX
- {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
-#endif
-#ifdef _SC_BC_STRING_MAX
- {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
-#endif
-#ifdef _SC_CAP
- {"SC_CAP", _SC_CAP},
-#endif
-#ifdef _SC_CHARCLASS_NAME_MAX
- {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
-#endif
-#ifdef _SC_CHAR_BIT
- {"SC_CHAR_BIT", _SC_CHAR_BIT},
-#endif
-#ifdef _SC_CHAR_MAX
- {"SC_CHAR_MAX", _SC_CHAR_MAX},
-#endif
-#ifdef _SC_CHAR_MIN
- {"SC_CHAR_MIN", _SC_CHAR_MIN},
+#ifdef HAVE_GETPGRP
+/*[clinic input]
+os.getpgrp
+
+Return the current process group id.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_getpgrp__doc__,
+"getpgrp($module, /)\n"
+"--\n"
+"\n"
+"Return the current process group id.");
+
+#define OS_GETPGRP_METHODDEF \
+ {"getpgrp", (PyCFunction)os_getpgrp, METH_NOARGS, os_getpgrp__doc__},
+
+static PyObject *
+os_getpgrp_impl(PyModuleDef *module);
+
+static PyObject *
+os_getpgrp(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
+{
+ return os_getpgrp_impl(module);
+}
+
+static PyObject *
+os_getpgrp_impl(PyModuleDef *module)
+/*[clinic end generated code: output=3b0d3663ea054277 input=6846fb2bb9a3705e]*/
+{
+#ifdef GETPGRP_HAVE_ARG
+ return PyLong_FromPid(getpgrp(0));
+#else /* GETPGRP_HAVE_ARG */
+ return PyLong_FromPid(getpgrp());
+#endif /* GETPGRP_HAVE_ARG */
+}
+#endif /* HAVE_GETPGRP */
+
+
+#ifdef HAVE_SETPGRP
+/*[clinic input]
+os.setpgrp
+
+Make the current process the leader of its process group.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_setpgrp__doc__,
+"setpgrp($module, /)\n"
+"--\n"
+"\n"
+"Make the current process the leader of its process group.");
+
+#define OS_SETPGRP_METHODDEF \
+ {"setpgrp", (PyCFunction)os_setpgrp, METH_NOARGS, os_setpgrp__doc__},
+
+static PyObject *
+os_setpgrp_impl(PyModuleDef *module);
+
+static PyObject *
+os_setpgrp(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
+{
+ return os_setpgrp_impl(module);
+}
+
+static PyObject *
+os_setpgrp_impl(PyModuleDef *module)
+/*[clinic end generated code: output=8fbb0ee29ef6fb2d input=1f0619fcb5731e7e]*/
+{
+#ifdef SETPGRP_HAVE_ARG
+ if (setpgrp(0, 0) < 0)
+#else /* SETPGRP_HAVE_ARG */
+ if (setpgrp() < 0)
+#endif /* SETPGRP_HAVE_ARG */
+ return posix_error();
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+#endif /* HAVE_SETPGRP */
+
+#ifdef HAVE_GETPPID
+
+#ifdef MS_WINDOWS
+#include <tlhelp32.h>
+
+static PyObject*
+win32_getppid()
+{
+ HANDLE snapshot;
+ pid_t mypid;
+ PyObject* result = NULL;
+ BOOL have_record;
+ PROCESSENTRY32 pe;
+
+ mypid = getpid(); /* This function never fails */
+
+ snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (snapshot == INVALID_HANDLE_VALUE)
+ return PyErr_SetFromWindowsErr(GetLastError());
+
+ pe.dwSize = sizeof(pe);
+ have_record = Process32First(snapshot, &pe);
+ while (have_record) {
+ if (mypid == (pid_t)pe.th32ProcessID) {
+ /* We could cache the ulong value in a static variable. */
+ result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
+ break;
+ }
+
+ have_record = Process32Next(snapshot, &pe);
+ }
+
+ /* If our loop exits and our pid was not found (result will be NULL)
+ * then GetLastError will return ERROR_NO_MORE_FILES. This is an
+ * error anyway, so let's raise it. */
+ if (!result)
+ result = PyErr_SetFromWindowsErr(GetLastError());
+
+ CloseHandle(snapshot);
+
+ return result;
+}
+#endif /*MS_WINDOWS*/
+
+
+/*[clinic input]
+os.getppid
+
+Return the parent's process id.
+
+If the parent process has already exited, Windows machines will still
+return its id; others systems will return the id of the 'init' process (1).
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_getppid__doc__,
+"getppid($module, /)\n"
+"--\n"
+"\n"
+"Return the parent\'s process id.\n"
+"\n"
+"If the parent process has already exited, Windows machines will still\n"
+"return its id; others systems will return the id of the \'init\' process (1).");
+
+#define OS_GETPPID_METHODDEF \
+ {"getppid", (PyCFunction)os_getppid, METH_NOARGS, os_getppid__doc__},
+
+static PyObject *
+os_getppid_impl(PyModuleDef *module);
+
+static PyObject *
+os_getppid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
+{
+ return os_getppid_impl(module);
+}
+
+static PyObject *
+os_getppid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=9ff3b387781edf3a input=e637cb87539c030e]*/
+{
+#ifdef MS_WINDOWS
+ return win32_getppid();
+#else
+ return PyLong_FromPid(getppid());
#endif
-#ifdef _SC_CHILD_MAX
- {"SC_CHILD_MAX", _SC_CHILD_MAX},
+}
+#endif /* HAVE_GETPPID */
+
+
+#ifdef HAVE_GETLOGIN
+/*[clinic input]
+os.getlogin
+
+Return the actual login name.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_getlogin__doc__,
+"getlogin($module, /)\n"
+"--\n"
+"\n"
+"Return the actual login name.");
+
+#define OS_GETLOGIN_METHODDEF \
+ {"getlogin", (PyCFunction)os_getlogin, METH_NOARGS, os_getlogin__doc__},
+
+static PyObject *
+os_getlogin_impl(PyModuleDef *module);
+
+static PyObject *
+os_getlogin(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
+{
+ return os_getlogin_impl(module);
+}
+
+static PyObject *
+os_getlogin_impl(PyModuleDef *module)
+/*[clinic end generated code: output=ab6211dab104cbb2 input=2a21ab1e917163df]*/
+{
+ PyObject *result = NULL;
+#ifdef MS_WINDOWS
+ wchar_t user_name[UNLEN + 1];
+ DWORD num_chars = Py_ARRAY_LENGTH(user_name);
+
+ if (GetUserNameW(user_name, &num_chars)) {
+ /* num_chars is the number of unicode chars plus null terminator */
+ result = PyUnicode_FromWideChar(user_name, num_chars - 1);
+ }
+ else
+ result = PyErr_SetFromWindowsErr(GetLastError());
+#else
+ char *name;
+ int old_errno = errno;
+
+ errno = 0;
+ name = getlogin();
+ if (name == NULL) {
+ if (errno)
+ posix_error();
+ else
+ PyErr_SetString(PyExc_OSError, "unable to determine login name");
+ }
+ else
+ result = PyUnicode_DecodeFSDefault(name);
+ errno = old_errno;
#endif
-#ifdef _SC_CLK_TCK
- {"SC_CLK_TCK", _SC_CLK_TCK},
-#endif
-#ifdef _SC_COHER_BLKSZ
- {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
-#endif
-#ifdef _SC_COLL_WEIGHTS_MAX
- {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
-#endif
-#ifdef _SC_DCACHE_ASSOC
- {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
-#endif
-#ifdef _SC_DCACHE_BLKSZ
- {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
-#endif
-#ifdef _SC_DCACHE_LINESZ
- {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
-#endif
-#ifdef _SC_DCACHE_SZ
- {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
-#endif
-#ifdef _SC_DCACHE_TBLKSZ
- {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
-#endif
-#ifdef _SC_DELAYTIMER_MAX
- {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
-#endif
-#ifdef _SC_EQUIV_CLASS_MAX
- {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
-#endif
-#ifdef _SC_EXPR_NEST_MAX
- {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
-#endif
-#ifdef _SC_FSYNC
- {"SC_FSYNC", _SC_FSYNC},
-#endif
-#ifdef _SC_GETGR_R_SIZE_MAX
- {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
-#endif
-#ifdef _SC_GETPW_R_SIZE_MAX
- {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
-#endif
-#ifdef _SC_ICACHE_ASSOC
- {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
-#endif
-#ifdef _SC_ICACHE_BLKSZ
- {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
-#endif
-#ifdef _SC_ICACHE_LINESZ
- {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
-#endif
-#ifdef _SC_ICACHE_SZ
- {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
-#endif
-#ifdef _SC_INF
- {"SC_INF", _SC_INF},
-#endif
-#ifdef _SC_INT_MAX
- {"SC_INT_MAX", _SC_INT_MAX},
-#endif
-#ifdef _SC_INT_MIN
- {"SC_INT_MIN", _SC_INT_MIN},
-#endif
-#ifdef _SC_IOV_MAX
- {"SC_IOV_MAX", _SC_IOV_MAX},
-#endif
-#ifdef _SC_IP_SECOPTS
- {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
-#endif
-#ifdef _SC_JOB_CONTROL
- {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
-#endif
-#ifdef _SC_KERN_POINTERS
- {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
-#endif
-#ifdef _SC_KERN_SIM
- {"SC_KERN_SIM", _SC_KERN_SIM},
-#endif
-#ifdef _SC_LINE_MAX
- {"SC_LINE_MAX", _SC_LINE_MAX},
-#endif
-#ifdef _SC_LOGIN_NAME_MAX
- {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
-#endif
-#ifdef _SC_LOGNAME_MAX
- {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
-#endif
-#ifdef _SC_LONG_BIT
- {"SC_LONG_BIT", _SC_LONG_BIT},
-#endif
-#ifdef _SC_MAC
- {"SC_MAC", _SC_MAC},
-#endif
-#ifdef _SC_MAPPED_FILES
- {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
-#endif
-#ifdef _SC_MAXPID
- {"SC_MAXPID", _SC_MAXPID},
-#endif
-#ifdef _SC_MB_LEN_MAX
- {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
-#endif
-#ifdef _SC_MEMLOCK
- {"SC_MEMLOCK", _SC_MEMLOCK},
-#endif
-#ifdef _SC_MEMLOCK_RANGE
- {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
-#endif
-#ifdef _SC_MEMORY_PROTECTION
- {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
-#endif
-#ifdef _SC_MESSAGE_PASSING
- {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
-#endif
-#ifdef _SC_MMAP_FIXED_ALIGNMENT
- {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
-#endif
-#ifdef _SC_MQ_OPEN_MAX
- {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
+ return result;
+}
+#endif /* HAVE_GETLOGIN */
+
+
+#ifdef HAVE_GETUID
+/*[clinic input]
+os.getuid
+
+Return the current process's user id.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_getuid__doc__,
+"getuid($module, /)\n"
+"--\n"
+"\n"
+"Return the current process\'s user id.");
+
+#define OS_GETUID_METHODDEF \
+ {"getuid", (PyCFunction)os_getuid, METH_NOARGS, os_getuid__doc__},
+
+static PyObject *
+os_getuid_impl(PyModuleDef *module);
+
+static PyObject *
+os_getuid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
+{
+ return os_getuid_impl(module);
+}
+
+static PyObject *
+os_getuid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=77e0dcf2e37d1e89 input=b53c8b35f110a516]*/
+{
+ return _PyLong_FromUid(getuid());
+}
+#endif /* HAVE_GETUID */
+
+
+#ifdef MS_WINDOWS
+#define HAVE_KILL
+#endif /* MS_WINDOWS */
+
+#ifdef HAVE_KILL
+/*[clinic input]
+os.kill
+
+ pid: pid_t
+ signal: Py_ssize_t
+ /
+
+Kill a process with a signal.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_kill__doc__,
+"kill($module, pid, signal, /)\n"
+"--\n"
+"\n"
+"Kill a process with a signal.");
+
+#define OS_KILL_METHODDEF \
+ {"kill", (PyCFunction)os_kill, METH_VARARGS, os_kill__doc__},
+
+static PyObject *
+os_kill_impl(PyModuleDef *module, pid_t pid, Py_ssize_t signal);
+
+static PyObject *
+os_kill(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ pid_t pid;
+ Py_ssize_t signal;
+
+ if (!PyArg_ParseTuple(args,
+ "" _Py_PARSE_PID "n:kill",
+ &pid, &signal))
+ goto exit;
+ return_value = os_kill_impl(module, pid, signal);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_kill_impl(PyModuleDef *module, pid_t pid, Py_ssize_t signal)
+/*[clinic end generated code: output=2f5c77920ed575e6 input=61a36b86ca275ab9]*/
+#ifndef MS_WINDOWS
+{
+ if (kill(pid, (int)signal) == -1)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#else /* !MS_WINDOWS */
+{
+ PyObject *result;
+ DWORD sig = (DWORD)signal;
+ DWORD err;
+ HANDLE handle;
+
+ /* Console processes which share a common console can be sent CTRL+C or
+ CTRL+BREAK events, provided they handle said events. */
+ if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
+ if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
+ err = GetLastError();
+ PyErr_SetFromWindowsErr(err);
+ }
+ else
+ Py_RETURN_NONE;
+ }
+
+ /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
+ attempt to open and terminate the process. */
+ handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
+ if (handle == NULL) {
+ err = GetLastError();
+ return PyErr_SetFromWindowsErr(err);
+ }
+
+ if (TerminateProcess(handle, sig) == 0) {
+ err = GetLastError();
+ result = PyErr_SetFromWindowsErr(err);
+ } else {
+ Py_INCREF(Py_None);
+ result = Py_None;
+ }
+
+ CloseHandle(handle);
+ return result;
+}
+#endif /* !MS_WINDOWS */
+#endif /* HAVE_KILL */
+
+
+#ifdef HAVE_KILLPG
+/*[clinic input]
+os.killpg
+
+ pgid: pid_t
+ signal: int
+ /
+
+Kill a process group with a signal.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_killpg__doc__,
+"killpg($module, pgid, signal, /)\n"
+"--\n"
+"\n"
+"Kill a process group with a signal.");
+
+#define OS_KILLPG_METHODDEF \
+ {"killpg", (PyCFunction)os_killpg, METH_VARARGS, os_killpg__doc__},
+
+static PyObject *
+os_killpg_impl(PyModuleDef *module, pid_t pgid, int signal);
+
+static PyObject *
+os_killpg(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ pid_t pgid;
+ int signal;
+
+ if (!PyArg_ParseTuple(args,
+ "" _Py_PARSE_PID "i:killpg",
+ &pgid, &signal))
+ goto exit;
+ return_value = os_killpg_impl(module, pgid, signal);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_killpg_impl(PyModuleDef *module, pid_t pgid, int signal)
+/*[clinic end generated code: output=0e05215d1c007e01 input=38b5449eb8faec19]*/
+{
+ /* XXX some man pages make the `pgid` parameter an int, others
+ a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
+ take the same type. Moreover, pid_t is always at least as wide as
+ int (else compilation of this module fails), which is safe. */
+ if (killpg(pgid, signal) == -1)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_KILLPG */
+
+
+#ifdef HAVE_PLOCK
+#ifdef HAVE_SYS_LOCK_H
+#include <sys/lock.h>
+#endif
+
+/*[clinic input]
+os.plock
+ op: int
+ /
+
+Lock program segments into memory.");
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_plock__doc__,
+"plock($module, op, /)\n"
+"--\n"
+"\n"
+"Lock program segments into memory.\");");
+
+#define OS_PLOCK_METHODDEF \
+ {"plock", (PyCFunction)os_plock, METH_VARARGS, os_plock__doc__},
+
+static PyObject *
+os_plock_impl(PyModuleDef *module, int op);
+
+static PyObject *
+os_plock(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int op;
+
+ if (!PyArg_ParseTuple(args,
+ "i:plock",
+ &op))
+ goto exit;
+ return_value = os_plock_impl(module, op);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_plock_impl(PyModuleDef *module, int op)
+/*[clinic end generated code: output=2744fe4b6e5f4dbc input=e6e5e348e1525f60]*/
+{
+ if (plock(op) == -1)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_PLOCK */
+
+
+#ifdef HAVE_SETUID
+/*[clinic input]
+os.setuid
+
+ uid: uid_t
+ /
+
+Set the current process's user id.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_setuid__doc__,
+"setuid($module, uid, /)\n"
+"--\n"
+"\n"
+"Set the current process\'s user id.");
+
+#define OS_SETUID_METHODDEF \
+ {"setuid", (PyCFunction)os_setuid, METH_VARARGS, os_setuid__doc__},
+
+static PyObject *
+os_setuid_impl(PyModuleDef *module, uid_t uid);
+
+static PyObject *
+os_setuid(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ uid_t uid;
+
+ if (!PyArg_ParseTuple(args,
+ "O&:setuid",
+ _Py_Uid_Converter, &uid))
+ goto exit;
+ return_value = os_setuid_impl(module, uid);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_setuid_impl(PyModuleDef *module, uid_t uid)
+/*[clinic end generated code: output=aea344bc22ccf400 input=c921a3285aa22256]*/
+{
+ if (setuid(uid) < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_SETUID */
+
+
+#ifdef HAVE_SETEUID
+/*[clinic input]
+os.seteuid
+
+ euid: uid_t
+ /
+
+Set the current process's effective user id.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_seteuid__doc__,
+"seteuid($module, euid, /)\n"
+"--\n"
+"\n"
+"Set the current process\'s effective user id.");
+
+#define OS_SETEUID_METHODDEF \
+ {"seteuid", (PyCFunction)os_seteuid, METH_VARARGS, os_seteuid__doc__},
+
+static PyObject *
+os_seteuid_impl(PyModuleDef *module, uid_t euid);
+
+static PyObject *
+os_seteuid(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ uid_t euid;
+
+ if (!PyArg_ParseTuple(args,
+ "O&:seteuid",
+ _Py_Uid_Converter, &euid))
+ goto exit;
+ return_value = os_seteuid_impl(module, euid);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_seteuid_impl(PyModuleDef *module, uid_t euid)
+/*[clinic end generated code: output=6e824cce4f3b8a5d input=ba93d927e4781aa9]*/
+{
+ if (seteuid(euid) < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_SETEUID */
+
+
+#ifdef HAVE_SETEGID
+/*[clinic input]
+os.setegid
+
+ egid: gid_t
+ /
+
+Set the current process's effective group id.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_setegid__doc__,
+"setegid($module, egid, /)\n"
+"--\n"
+"\n"
+"Set the current process\'s effective group id.");
+
+#define OS_SETEGID_METHODDEF \
+ {"setegid", (PyCFunction)os_setegid, METH_VARARGS, os_setegid__doc__},
+
+static PyObject *
+os_setegid_impl(PyModuleDef *module, gid_t egid);
+
+static PyObject *
+os_setegid(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ gid_t egid;
+
+ if (!PyArg_ParseTuple(args,
+ "O&:setegid",
+ _Py_Gid_Converter, &egid))
+ goto exit;
+ return_value = os_setegid_impl(module, egid);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_setegid_impl(PyModuleDef *module, gid_t egid)
+/*[clinic end generated code: output=80a32263a4d56a9c input=4080526d0ccd6ce3]*/
+{
+ if (setegid(egid) < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_SETEGID */
+
+
+#ifdef HAVE_SETREUID
+/*[clinic input]
+os.setreuid
+
+ ruid: uid_t
+ euid: uid_t
+ /
+
+Set the current process's real and effective user ids.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_setreuid__doc__,
+"setreuid($module, ruid, euid, /)\n"
+"--\n"
+"\n"
+"Set the current process\'s real and effective user ids.");
+
+#define OS_SETREUID_METHODDEF \
+ {"setreuid", (PyCFunction)os_setreuid, METH_VARARGS, os_setreuid__doc__},
+
+static PyObject *
+os_setreuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid);
+
+static PyObject *
+os_setreuid(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ uid_t ruid;
+ uid_t euid;
+
+ if (!PyArg_ParseTuple(args,
+ "O&O&:setreuid",
+ _Py_Uid_Converter, &ruid, _Py_Uid_Converter, &euid))
+ goto exit;
+ return_value = os_setreuid_impl(module, ruid, euid);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_setreuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid)
+/*[clinic end generated code: output=d7f226f943dad739 input=0ca8978de663880c]*/
+{
+ if (setreuid(ruid, euid) < 0) {
+ return posix_error();
+ } else {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+}
+#endif /* HAVE_SETREUID */
+
+
+#ifdef HAVE_SETREGID
+/*[clinic input]
+os.setregid
+
+ rgid: gid_t
+ egid: gid_t
+ /
+
+Set the current process's real and effective group ids.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_setregid__doc__,
+"setregid($module, rgid, egid, /)\n"
+"--\n"
+"\n"
+"Set the current process\'s real and effective group ids.");
+
+#define OS_SETREGID_METHODDEF \
+ {"setregid", (PyCFunction)os_setregid, METH_VARARGS, os_setregid__doc__},
+
+static PyObject *
+os_setregid_impl(PyModuleDef *module, gid_t rgid, gid_t egid);
+
+static PyObject *
+os_setregid(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ gid_t rgid;
+ gid_t egid;
+
+ if (!PyArg_ParseTuple(args,
+ "O&O&:setregid",
+ _Py_Gid_Converter, &rgid, _Py_Gid_Converter, &egid))
+ goto exit;
+ return_value = os_setregid_impl(module, rgid, egid);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_setregid_impl(PyModuleDef *module, gid_t rgid, gid_t egid)
+/*[clinic end generated code: output=a82d9ab70f8e6562 input=c59499f72846db78]*/
+{
+ if (setregid(rgid, egid) < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_SETREGID */
+
+
+#ifdef HAVE_SETGID
+/*[clinic input]
+os.setgid
+ gid: gid_t
+ /
+
+Set the current process's group id.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_setgid__doc__,
+"setgid($module, gid, /)\n"
+"--\n"
+"\n"
+"Set the current process\'s group id.");
+
+#define OS_SETGID_METHODDEF \
+ {"setgid", (PyCFunction)os_setgid, METH_VARARGS, os_setgid__doc__},
+
+static PyObject *
+os_setgid_impl(PyModuleDef *module, gid_t gid);
+
+static PyObject *
+os_setgid(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ gid_t gid;
+
+ if (!PyArg_ParseTuple(args,
+ "O&:setgid",
+ _Py_Gid_Converter, &gid))
+ goto exit;
+ return_value = os_setgid_impl(module, gid);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_setgid_impl(PyModuleDef *module, gid_t gid)
+/*[clinic end generated code: output=08287886db435f23 input=27d30c4059045dc6]*/
+{
+ if (setgid(gid) < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_SETGID */
+
+
+#ifdef HAVE_SETGROUPS
+/*[clinic input]
+os.setgroups
+
+ groups: object
+ /
+
+Set the groups of the current process to list.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_setgroups__doc__,
+"setgroups($module, groups, /)\n"
+"--\n"
+"\n"
+"Set the groups of the current process to list.");
+
+#define OS_SETGROUPS_METHODDEF \
+ {"setgroups", (PyCFunction)os_setgroups, METH_O, os_setgroups__doc__},
+
+static PyObject *
+os_setgroups(PyModuleDef *module, PyObject *groups)
+/*[clinic end generated code: output=0b8de65d5b3cda94 input=fa742ca3daf85a7e]*/
+{
+ int i, len;
+ gid_t grouplist[MAX_GROUPS];
+
+ if (!PySequence_Check(groups)) {
+ PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
+ return NULL;
+ }
+ len = PySequence_Size(groups);
+ if (len > MAX_GROUPS) {
+ PyErr_SetString(PyExc_ValueError, "too many groups");
+ return NULL;
+ }
+ for(i = 0; i < len; i++) {
+ PyObject *elem;
+ elem = PySequence_GetItem(groups, i);
+ if (!elem)
+ return NULL;
+ if (!PyLong_Check(elem)) {
+ PyErr_SetString(PyExc_TypeError,
+ "groups must be integers");
+ Py_DECREF(elem);
+ return NULL;
+ } else {
+ if (!_Py_Gid_Converter(elem, &grouplist[i])) {
+ Py_DECREF(elem);
+ return NULL;
+ }
+ }
+ Py_DECREF(elem);
+ }
+
+ if (setgroups(len, grouplist) < 0)
+ return posix_error();
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+#endif /* HAVE_SETGROUPS */
+
+#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
+static PyObject *
+wait_helper(pid_t pid, int status, struct rusage *ru)
+{
+ PyObject *result;
+ static PyObject *struct_rusage;
+ _Py_IDENTIFIER(struct_rusage);
+
+ if (pid == -1)
+ return posix_error();
+
+ if (struct_rusage == NULL) {
+ PyObject *m = PyImport_ImportModuleNoBlock("resource");
+ if (m == NULL)
+ return NULL;
+ struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage);
+ Py_DECREF(m);
+ if (struct_rusage == NULL)
+ return NULL;
+ }
+
+ /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
+ result = PyStructSequence_New((PyTypeObject*) struct_rusage);
+ if (!result)
+ return NULL;
+
+#ifndef doubletime
+#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
+#endif
+
+ PyStructSequence_SET_ITEM(result, 0,
+ PyFloat_FromDouble(doubletime(ru->ru_utime)));
+ PyStructSequence_SET_ITEM(result, 1,
+ PyFloat_FromDouble(doubletime(ru->ru_stime)));
+#define SET_INT(result, index, value)\
+ PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
+ SET_INT(result, 2, ru->ru_maxrss);
+ SET_INT(result, 3, ru->ru_ixrss);
+ SET_INT(result, 4, ru->ru_idrss);
+ SET_INT(result, 5, ru->ru_isrss);
+ SET_INT(result, 6, ru->ru_minflt);
+ SET_INT(result, 7, ru->ru_majflt);
+ SET_INT(result, 8, ru->ru_nswap);
+ SET_INT(result, 9, ru->ru_inblock);
+ SET_INT(result, 10, ru->ru_oublock);
+ SET_INT(result, 11, ru->ru_msgsnd);
+ SET_INT(result, 12, ru->ru_msgrcv);
+ SET_INT(result, 13, ru->ru_nsignals);
+ SET_INT(result, 14, ru->ru_nvcsw);
+ SET_INT(result, 15, ru->ru_nivcsw);
+#undef SET_INT
+
+ if (PyErr_Occurred()) {
+ Py_DECREF(result);
+ return NULL;
+ }
+
+ return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
+}
+#endif /* HAVE_WAIT3 || HAVE_WAIT4 */
+
+
+#ifdef HAVE_WAIT3
+/*[clinic input]
+os.wait3
+
+ options: int
+Wait for completion of a child process.
+
+Returns a tuple of information about the child process:
+ (pid, status, rusage)
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_wait3__doc__,
+"wait3($module, /, options)\n"
+"--\n"
+"\n"
+"Wait for completion of a child process.\n"
+"\n"
+"Returns a tuple of information about the child process:\n"
+" (pid, status, rusage)");
+
+#define OS_WAIT3_METHODDEF \
+ {"wait3", (PyCFunction)os_wait3, METH_VARARGS|METH_KEYWORDS, os_wait3__doc__},
+
+static PyObject *
+os_wait3_impl(PyModuleDef *module, int options);
+
+static PyObject *
+os_wait3(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"options", NULL};
+ int options;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "i:wait3", _keywords,
+ &options))
+ goto exit;
+ return_value = os_wait3_impl(module, options);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_wait3_impl(PyModuleDef *module, int options)
+/*[clinic end generated code: output=1f2a63b6a93cbb57 input=8ac4c56956b61710]*/
+{
+ pid_t pid;
+ struct rusage ru;
+ int async_err = 0;
+ WAIT_TYPE status;
+ WAIT_STATUS_INT(status) = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ pid = wait3(&status, options, &ru);
+ Py_END_ALLOW_THREADS
+ } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (pid < 0)
+ return (!async_err) ? posix_error() : NULL;
+
+ return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
+}
+#endif /* HAVE_WAIT3 */
+
+
+#ifdef HAVE_WAIT4
+/*[clinic input]
+
+os.wait4
+
+ pid: pid_t
+ options: int
+
+Wait for completion of a specific child process.
+
+Returns a tuple of information about the child process:
+ (pid, status, rusage)
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_wait4__doc__,
+"wait4($module, /, pid, options)\n"
+"--\n"
+"\n"
+"Wait for completion of a specific child process.\n"
+"\n"
+"Returns a tuple of information about the child process:\n"
+" (pid, status, rusage)");
+
+#define OS_WAIT4_METHODDEF \
+ {"wait4", (PyCFunction)os_wait4, METH_VARARGS|METH_KEYWORDS, os_wait4__doc__},
+
+static PyObject *
+os_wait4_impl(PyModuleDef *module, pid_t pid, int options);
+
+static PyObject *
+os_wait4(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"pid", "options", NULL};
+ pid_t pid;
+ int options;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "" _Py_PARSE_PID "i:wait4", _keywords,
+ &pid, &options))
+ goto exit;
+ return_value = os_wait4_impl(module, pid, options);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_wait4_impl(PyModuleDef *module, pid_t pid, int options)
+/*[clinic end generated code: output=20dfb05289d37dc6 input=d11deed0750600ba]*/
+{
+ pid_t res;
+ struct rusage ru;
+ int async_err = 0;
+ WAIT_TYPE status;
+ WAIT_STATUS_INT(status) = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ res = wait4(pid, &status, options, &ru);
+ Py_END_ALLOW_THREADS
+ } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (res < 0)
+ return (!async_err) ? posix_error() : NULL;
+
+ return wait_helper(res, WAIT_STATUS_INT(status), &ru);
+}
+#endif /* HAVE_WAIT4 */
+
+
+#if defined(HAVE_WAITID) && !defined(__APPLE__)
+/*[clinic input]
+os.waitid
+
+ idtype: idtype_t
+ Must be one of be P_PID, P_PGID or P_ALL.
+ id: id_t
+ The id to wait on.
+ options: int
+ Constructed from the ORing of one or more of WEXITED, WSTOPPED
+ or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
+ /
+
+Returns the result of waiting for a process or processes.
+
+Returns either waitid_result or None if WNOHANG is specified and there are
+no children in a waitable state.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_waitid__doc__,
+"waitid($module, idtype, id, options, /)\n"
+"--\n"
+"\n"
+"Returns the result of waiting for a process or processes.\n"
+"\n"
+" idtype\n"
+" Must be one of be P_PID, P_PGID or P_ALL.\n"
+" id\n"
+" The id to wait on.\n"
+" options\n"
+" Constructed from the ORing of one or more of WEXITED, WSTOPPED\n"
+" or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n"
+"\n"
+"Returns either waitid_result or None if WNOHANG is specified and there are\n"
+"no children in a waitable state.");
+
+#define OS_WAITID_METHODDEF \
+ {"waitid", (PyCFunction)os_waitid, METH_VARARGS, os_waitid__doc__},
+
+static PyObject *
+os_waitid_impl(PyModuleDef *module, idtype_t idtype, id_t id, int options);
+
+static PyObject *
+os_waitid(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ idtype_t idtype;
+ id_t id;
+ int options;
+
+ if (!PyArg_ParseTuple(args,
+ "i" _Py_PARSE_PID "i:waitid",
+ &idtype, &id, &options))
+ goto exit;
+ return_value = os_waitid_impl(module, idtype, id, options);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_waitid_impl(PyModuleDef *module, idtype_t idtype, id_t id, int options)
+/*[clinic end generated code: output=fb44bf97f01021b2 input=d8e7f76e052b7920]*/
+{
+ PyObject *result;
+ int res;
+ int async_err = 0;
+ siginfo_t si;
+ si.si_pid = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ res = waitid(idtype, id, &si, options);
+ Py_END_ALLOW_THREADS
+ } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (res < 0)
+ return (!async_err) ? posix_error() : NULL;
+
+ if (si.si_pid == 0)
+ Py_RETURN_NONE;
+
+ result = PyStructSequence_New(&WaitidResultType);
+ if (!result)
+ return NULL;
+
+ PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
+ PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
+ PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
+ PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
+ PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
+ if (PyErr_Occurred()) {
+ Py_DECREF(result);
+ return NULL;
+ }
+
+ return result;
+}
+#endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
+
+
+#if defined(HAVE_WAITPID)
+/*[clinic input]
+os.waitpid
+ pid: pid_t
+ options: int
+ /
+
+Wait for completion of a given child process.
+
+Returns a tuple of information regarding the child process:
+ (pid, status)
+
+The options argument is ignored on Windows.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_waitpid__doc__,
+"waitpid($module, pid, options, /)\n"
+"--\n"
+"\n"
+"Wait for completion of a given child process.\n"
+"\n"
+"Returns a tuple of information regarding the child process:\n"
+" (pid, status)\n"
+"\n"
+"The options argument is ignored on Windows.");
+
+#define OS_WAITPID_METHODDEF \
+ {"waitpid", (PyCFunction)os_waitpid, METH_VARARGS, os_waitpid__doc__},
+
+static PyObject *
+os_waitpid_impl(PyModuleDef *module, pid_t pid, int options);
+
+static PyObject *
+os_waitpid(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ pid_t pid;
+ int options;
+
+ if (!PyArg_ParseTuple(args,
+ "" _Py_PARSE_PID "i:waitpid",
+ &pid, &options))
+ goto exit;
+ return_value = os_waitpid_impl(module, pid, options);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_waitpid_impl(PyModuleDef *module, pid_t pid, int options)
+/*[clinic end generated code: output=095a6b00af70b7ac input=0bf1666b8758fda3]*/
+{
+ pid_t res;
+ int async_err = 0;
+ WAIT_TYPE status;
+ WAIT_STATUS_INT(status) = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ res = waitpid(pid, &status, options);
+ Py_END_ALLOW_THREADS
+ } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (res < 0)
+ return (!async_err) ? posix_error() : NULL;
+
+ return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
+}
+#elif defined(HAVE_CWAIT)
+/* MS C has a variant of waitpid() that's usable for most purposes. */
+/*[clinic input]
+os.waitpid
+ pid: Py_intptr_t
+ options: int
+ /
+
+Wait for completion of a given process.
+
+Returns a tuple of information regarding the process:
+ (pid, status << 8)
+
+The options argument is ignored on Windows.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_waitpid__doc__,
+"waitpid($module, pid, options, /)\n"
+"--\n"
+"\n"
+"Wait for completion of a given process.\n"
+"\n"
+"Returns a tuple of information regarding the process:\n"
+" (pid, status << 8)\n"
+"\n"
+"The options argument is ignored on Windows.");
+
+#define OS_WAITPID_METHODDEF \
+ {"waitpid", (PyCFunction)os_waitpid, METH_VARARGS, os_waitpid__doc__},
+
+static PyObject *
+os_waitpid_impl(PyModuleDef *module, Py_intptr_t pid, int options);
+
+static PyObject *
+os_waitpid(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ Py_intptr_t pid;
+ int options;
+
+ if (!PyArg_ParseTuple(args,
+ "" _Py_PARSE_INTPTR "i:waitpid",
+ &pid, &options))
+ goto exit;
+ return_value = os_waitpid_impl(module, pid, options);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_waitpid_impl(PyModuleDef *module, Py_intptr_t pid, int options)
+/*[clinic end generated code: output=c20b95b15ad44a3a input=444c8f51cca5b862]*/
+{
+ int status;
+ Py_intptr_t res;
+ int async_err = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ res = _cwait(&status, pid, options);
+ Py_END_ALLOW_THREADS
+ } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (res != 0)
+ return (!async_err) ? posix_error() : NULL;
+
+ /* shift the status left a byte so this is more like the POSIX waitpid */
+ return Py_BuildValue(_Py_PARSE_INTPTR "i", res, status << 8);
+}
+#endif
+
+
+#ifdef HAVE_WAIT
+/*[clinic input]
+os.wait
+
+Wait for completion of a child process.
+
+Returns a tuple of information about the child process:
+ (pid, status)
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_wait__doc__,
+"wait($module, /)\n"
+"--\n"
+"\n"
+"Wait for completion of a child process.\n"
+"\n"
+"Returns a tuple of information about the child process:\n"
+" (pid, status)");
+
+#define OS_WAIT_METHODDEF \
+ {"wait", (PyCFunction)os_wait, METH_NOARGS, os_wait__doc__},
+
+static PyObject *
+os_wait_impl(PyModuleDef *module);
+
+static PyObject *
+os_wait(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
+{
+ return os_wait_impl(module);
+}
+
+static PyObject *
+os_wait_impl(PyModuleDef *module)
+/*[clinic end generated code: output=2a83a9d164e7e6a8 input=03b0182d4a4700ce]*/
+{
+ pid_t pid;
+ int async_err = 0;
+ WAIT_TYPE status;
+ WAIT_STATUS_INT(status) = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ pid = wait(&status);
+ Py_END_ALLOW_THREADS
+ } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (pid < 0)
+ return (!async_err) ? posix_error() : NULL;
+
+ return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
+}
+#endif /* HAVE_WAIT */
+
+
+#if defined(HAVE_READLINK) || defined(MS_WINDOWS)
+PyDoc_STRVAR(readlink__doc__,
+"readlink(path, *, dir_fd=None) -> path\n\n\
+Return a string representing the path to which the symbolic link points.\n\
+\n\
+If dir_fd is not None, it should be a file descriptor open to a directory,\n\
+ and path should be relative; path will then be relative to that directory.\n\
+dir_fd may not be implemented on your platform.\n\
+ If it is unavailable, using it will raise a NotImplementedError.");
+#endif
+
+#ifdef HAVE_READLINK
+
+/* AC 3.5: merge win32 and not together */
+static PyObject *
+posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ path_t path;
+ int dir_fd = DEFAULT_DIR_FD;
+ char buffer[MAXPATHLEN];
+ ssize_t length;
+ PyObject *return_value = NULL;
+ static char *keywords[] = {"path", "dir_fd", NULL};
+
+ memset(&path, 0, sizeof(path));
+ path.function_name = "readlink";
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords,
+ path_converter, &path,
+ READLINKAT_DIR_FD_CONVERTER, &dir_fd))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+#ifdef HAVE_READLINKAT
+ if (dir_fd != DEFAULT_DIR_FD)
+ length = readlinkat(dir_fd, path.narrow, buffer, sizeof(buffer));
+ else
+#endif
+ length = readlink(path.narrow, buffer, sizeof(buffer));
+ Py_END_ALLOW_THREADS
+
+ if (length < 0) {
+ return_value = path_error(&path);
+ goto exit;
+ }
+
+ if (PyUnicode_Check(path.object))
+ return_value = PyUnicode_DecodeFSDefaultAndSize(buffer, length);
+ else
+ return_value = PyBytes_FromStringAndSize(buffer, length);
+exit:
+ path_cleanup(&path);
+ return return_value;
+}
+
+#endif /* HAVE_READLINK */
+
+#if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
+
+static PyObject *
+win_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ wchar_t *path;
+ DWORD n_bytes_returned;
+ DWORD io_result;
+ PyObject *po, *result;
+ int dir_fd;
+ HANDLE reparse_point_handle;
+
+ char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+ REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
+ wchar_t *print_name;
+
+ static char *keywords[] = {"path", "dir_fd", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U|$O&:readlink", keywords,
+ &po,
+ dir_fd_unavailable, &dir_fd
+ ))
+ return NULL;
+
+ path = PyUnicode_AsUnicode(po);
+ if (path == NULL)
+ return NULL;
+
+ /* First get a handle to the reparse point */
+ Py_BEGIN_ALLOW_THREADS
+ reparse_point_handle = CreateFileW(
+ path,
+ 0,
+ 0,
+ 0,
+ OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
+ 0);
+ Py_END_ALLOW_THREADS
+
+ if (reparse_point_handle==INVALID_HANDLE_VALUE)
+ return win32_error_object("readlink", po);
+
+ Py_BEGIN_ALLOW_THREADS
+ /* New call DeviceIoControl to read the reparse point */
+ io_result = DeviceIoControl(
+ reparse_point_handle,
+ FSCTL_GET_REPARSE_POINT,
+ 0, 0, /* in buffer */
+ target_buffer, sizeof(target_buffer),
+ &n_bytes_returned,
+ 0 /* we're not using OVERLAPPED_IO */
+ );
+ CloseHandle(reparse_point_handle);
+ Py_END_ALLOW_THREADS
+
+ if (io_result==0)
+ return win32_error_object("readlink", po);
+
+ if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "not a symbolic link");
+ return NULL;
+ }
+ print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer +
+ rdb->SymbolicLinkReparseBuffer.PrintNameOffset;
+
+ result = PyUnicode_FromWideChar(print_name,
+ rdb->SymbolicLinkReparseBuffer.PrintNameLength/2);
+ return result;
+}
+
+#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
+
+
+
+#ifdef HAVE_SYMLINK
+
+#if defined(MS_WINDOWS)
+
+/* Grab CreateSymbolicLinkW dynamically from kernel32 */
+static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPWSTR, LPWSTR, DWORD) = NULL;
+static DWORD (CALLBACK *Py_CreateSymbolicLinkA)(LPSTR, LPSTR, DWORD) = NULL;
+
+static int
+check_CreateSymbolicLink(void)
+{
+ HINSTANCE hKernel32;
+ /* only recheck */
+ if (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA)
+ return 1;
+ hKernel32 = GetModuleHandleW(L"KERNEL32");
+ *(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32,
+ "CreateSymbolicLinkW");
+ *(FARPROC*)&Py_CreateSymbolicLinkA = GetProcAddress(hKernel32,
+ "CreateSymbolicLinkA");
+ return (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA);
+}
+
+/* Remove the last portion of the path */
+static void
+_dirnameW(WCHAR *path)
+{
+ WCHAR *ptr;
+
+ /* walk the path from the end until a backslash is encountered */
+ for(ptr = path + wcslen(path); ptr != path; ptr--) {
+ if (*ptr == L'\\' || *ptr == L'/')
+ break;
+ }
+ *ptr = 0;
+}
+
+/* Remove the last portion of the path */
+static void
+_dirnameA(char *path)
+{
+ char *ptr;
+
+ /* walk the path from the end until a backslash is encountered */
+ for(ptr = path + strlen(path); ptr != path; ptr--) {
+ if (*ptr == '\\' || *ptr == '/')
+ break;
+ }
+ *ptr = 0;
+}
+
+/* Is this path absolute? */
+static int
+_is_absW(const WCHAR *path)
+{
+ return path[0] == L'\\' || path[0] == L'/' || path[1] == L':';
+
+}
+
+/* Is this path absolute? */
+static int
+_is_absA(const char *path)
+{
+ return path[0] == '\\' || path[0] == '/' || path[1] == ':';
+
+}
+
+/* join root and rest with a backslash */
+static void
+_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
+{
+ size_t root_len;
+
+ if (_is_absW(rest)) {
+ wcscpy(dest_path, rest);
+ return;
+ }
+
+ root_len = wcslen(root);
+
+ wcscpy(dest_path, root);
+ if(root_len) {
+ dest_path[root_len] = L'\\';
+ root_len++;
+ }
+ wcscpy(dest_path+root_len, rest);
+}
+
+/* join root and rest with a backslash */
+static void
+_joinA(char *dest_path, const char *root, const char *rest)
+{
+ size_t root_len;
+
+ if (_is_absA(rest)) {
+ strcpy(dest_path, rest);
+ return;
+ }
+
+ root_len = strlen(root);
+
+ strcpy(dest_path, root);
+ if(root_len) {
+ dest_path[root_len] = '\\';
+ root_len++;
+ }
+ strcpy(dest_path+root_len, rest);
+}
+
+/* Return True if the path at src relative to dest is a directory */
+static int
+_check_dirW(WCHAR *src, WCHAR *dest)
+{
+ WIN32_FILE_ATTRIBUTE_DATA src_info;
+ WCHAR dest_parent[MAX_PATH];
+ WCHAR src_resolved[MAX_PATH] = L"";
+
+ /* dest_parent = os.path.dirname(dest) */
+ wcscpy(dest_parent, dest);
+ _dirnameW(dest_parent);
+ /* src_resolved = os.path.join(dest_parent, src) */
+ _joinW(src_resolved, dest_parent, src);
+ return (
+ GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
+ && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
+ );
+}
+
+/* Return True if the path at src relative to dest is a directory */
+static int
+_check_dirA(char *src, char *dest)
+{
+ WIN32_FILE_ATTRIBUTE_DATA src_info;
+ char dest_parent[MAX_PATH];
+ char src_resolved[MAX_PATH] = "";
+
+ /* dest_parent = os.path.dirname(dest) */
+ strcpy(dest_parent, dest);
+ _dirnameA(dest_parent);
+ /* src_resolved = os.path.join(dest_parent, src) */
+ _joinA(src_resolved, dest_parent, src);
+ return (
+ GetFileAttributesExA(src_resolved, GetFileExInfoStandard, &src_info)
+ && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
+ );
+}
+#endif
+
+
+/*[clinic input]
+os.symlink
+ src: path_t
+ dst: path_t
+ target_is_directory: bool = False
+ *
+ dir_fd: dir_fd(requires='symlinkat')=None
+
+# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
+
+Create a symbolic link pointing to src named dst.
+
+target_is_directory is required on Windows if the target is to be
+ interpreted as a directory. (On Windows, symlink requires
+ Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
+ target_is_directory is ignored on non-Windows platforms.
+
+If dir_fd is not None, it should be a file descriptor open to a directory,
+ and path should be relative; path will then be relative to that directory.
+dir_fd may not be implemented on your platform.
+ If it is unavailable, using it will raise a NotImplementedError.
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_symlink__doc__,
+"symlink($module, /, src, dst, target_is_directory=False, *, dir_fd=None)\n"
+"--\n"
+"\n"
+"Create a symbolic link pointing to src named dst.\n"
+"\n"
+"target_is_directory is required on Windows if the target is to be\n"
+" interpreted as a directory. (On Windows, symlink requires\n"
+" Windows 6.0 or greater, and raises a NotImplementedError otherwise.)\n"
+" target_is_directory is ignored on non-Windows platforms.\n"
+"\n"
+"If dir_fd is not None, it should be a file descriptor open to a directory,\n"
+" and path should be relative; path will then be relative to that directory.\n"
+"dir_fd may not be implemented on your platform.\n"
+" If it is unavailable, using it will raise a NotImplementedError.");
+
+#define OS_SYMLINK_METHODDEF \
+ {"symlink", (PyCFunction)os_symlink, METH_VARARGS|METH_KEYWORDS, os_symlink__doc__},
+
+static PyObject *
+os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd);
+
+static PyObject *
+os_symlink(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"src", "dst", "target_is_directory", "dir_fd", NULL};
+ path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0);
+ path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0);
+ int target_is_directory = 0;
+ int dir_fd = DEFAULT_DIR_FD;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O&O&|p$O&:symlink", _keywords,
+ path_converter, &src, path_converter, &dst, &target_is_directory, SYMLINKAT_DIR_FD_CONVERTER, &dir_fd))
+ goto exit;
+ return_value = os_symlink_impl(module, &src, &dst, target_is_directory, dir_fd);
+
+exit:
+ /* Cleanup for src */
+ path_cleanup(&src);
+ /* Cleanup for dst */
+ path_cleanup(&dst);
+
+ return return_value;
+}
+
+static PyObject *
+os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd)
+/*[clinic end generated code: output=1a31e6d88aafe9b6 input=e820ec4472547bc3]*/
+{
+#ifdef MS_WINDOWS
+ DWORD result;
+#else
+ int result;
+#endif
+
+#ifdef MS_WINDOWS
+ if (!check_CreateSymbolicLink()) {
+ PyErr_SetString(PyExc_NotImplementedError,
+ "CreateSymbolicLink functions not found");
+ return NULL;
+ }
+ if (!win32_can_symlink) {
+ PyErr_SetString(PyExc_OSError, "symbolic link privilege not held");
+ return NULL;
+ }
+#endif
+
+ if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
+ PyErr_SetString(PyExc_ValueError,
+ "symlink: src and dst must be the same type");
+ return NULL;
+ }
+
+#ifdef MS_WINDOWS
+
+ Py_BEGIN_ALLOW_THREADS
+ if (dst->wide) {
+ /* if src is a directory, ensure target_is_directory==1 */
+ target_is_directory |= _check_dirW(src->wide, dst->wide);
+ result = Py_CreateSymbolicLinkW(dst->wide, src->wide,
+ target_is_directory);
+ }
+ else {
+ /* if src is a directory, ensure target_is_directory==1 */
+ target_is_directory |= _check_dirA(src->narrow, dst->narrow);
+ result = Py_CreateSymbolicLinkA(dst->narrow, src->narrow,
+ target_is_directory);
+ }
+ Py_END_ALLOW_THREADS
+
+ if (!result)
+ return path_error2(src, dst);
+
+#else
+
+ Py_BEGIN_ALLOW_THREADS
+#if HAVE_SYMLINKAT
+ if (dir_fd != DEFAULT_DIR_FD)
+ result = symlinkat(src->narrow, dir_fd, dst->narrow);
+ else
+#endif
+ result = symlink(src->narrow, dst->narrow);
+ Py_END_ALLOW_THREADS
+
+ if (result)
+ return path_error2(src, dst);
+#endif
+
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_SYMLINK */
+
+
+
+
+static PyStructSequence_Field times_result_fields[] = {
+ {"user", "user time"},
+ {"system", "system time"},
+ {"children_user", "user time of children"},
+ {"children_system", "system time of children"},
+ {"elapsed", "elapsed time since an arbitrary point in the past"},
+ {NULL}
+};
+
+PyDoc_STRVAR(times_result__doc__,
+"times_result: Result from os.times().\n\n\
+This object may be accessed either as a tuple of\n\
+ (user, system, children_user, children_system, elapsed),\n\
+or via the attributes user, system, children_user, children_system,\n\
+and elapsed.\n\
+\n\
+See os.times for more information.");
+
+static PyStructSequence_Desc times_result_desc = {
+ "times_result", /* name */
+ times_result__doc__, /* doc */
+ times_result_fields,
+ 5
+};
+
+static PyTypeObject TimesResultType;
+
+#ifdef MS_WINDOWS
+#define HAVE_TIMES /* mandatory, for the method table */
+#endif
+
+#ifdef HAVE_TIMES
+
+static PyObject *
+build_times_result(double user, double system,
+ double children_user, double children_system,
+ double elapsed)
+{
+ PyObject *value = PyStructSequence_New(&TimesResultType);
+ if (value == NULL)
+ return NULL;
+
+#define SET(i, field) \
+ { \
+ PyObject *o = PyFloat_FromDouble(field); \
+ if (!o) { \
+ Py_DECREF(value); \
+ return NULL; \
+ } \
+ PyStructSequence_SET_ITEM(value, i, o); \
+ } \
+
+ SET(0, user);
+ SET(1, system);
+ SET(2, children_user);
+ SET(3, children_system);
+ SET(4, elapsed);
+
+#undef SET
+
+ return value;
+}
+
+
+#ifndef MS_WINDOWS
+#define NEED_TICKS_PER_SECOND
+static long ticks_per_second = -1;
+#endif /* MS_WINDOWS */
+
+/*[clinic input]
+os.times
+
+Return a collection containing process timing information.
+
+The object returned behaves like a named tuple with these fields:
+ (utime, stime, cutime, cstime, elapsed_time)
+All fields are floating point numbers.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_times__doc__,
+"times($module, /)\n"
+"--\n"
+"\n"
+"Return a collection containing process timing information.\n"
+"\n"
+"The object returned behaves like a named tuple with these fields:\n"
+" (utime, stime, cutime, cstime, elapsed_time)\n"
+"All fields are floating point numbers.");
+
+#define OS_TIMES_METHODDEF \
+ {"times", (PyCFunction)os_times, METH_NOARGS, os_times__doc__},
+
+static PyObject *
+os_times_impl(PyModuleDef *module);
+
+static PyObject *
+os_times(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
+{
+ return os_times_impl(module);
+}
+
+static PyObject *
+os_times_impl(PyModuleDef *module)
+/*[clinic end generated code: output=b86896d031a9b768 input=2bf9df3d6ab2e48b]*/
+#ifdef MS_WINDOWS
+{
+ FILETIME create, exit, kernel, user;
+ HANDLE hProc;
+ hProc = GetCurrentProcess();
+ GetProcessTimes(hProc, &create, &exit, &kernel, &user);
+ /* The fields of a FILETIME structure are the hi and lo part
+ of a 64-bit value expressed in 100 nanosecond units.
+ 1e7 is one second in such units; 1e-7 the inverse.
+ 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
+ */
+ return build_times_result(
+ (double)(user.dwHighDateTime*429.4967296 +
+ user.dwLowDateTime*1e-7),
+ (double)(kernel.dwHighDateTime*429.4967296 +
+ kernel.dwLowDateTime*1e-7),
+ (double)0,
+ (double)0,
+ (double)0);
+}
+#else /* MS_WINDOWS */
+{
+
+
+ struct tms t;
+ clock_t c;
+ errno = 0;
+ c = times(&t);
+ if (c == (clock_t) -1)
+ return posix_error();
+ return build_times_result(
+ (double)t.tms_utime / ticks_per_second,
+ (double)t.tms_stime / ticks_per_second,
+ (double)t.tms_cutime / ticks_per_second,
+ (double)t.tms_cstime / ticks_per_second,
+ (double)c / ticks_per_second);
+}
+#endif /* MS_WINDOWS */
+#endif /* HAVE_TIMES */
+
+
+#ifdef HAVE_GETSID
+/*[clinic input]
+os.getsid
+
+ pid: pid_t
+ /
+
+Call the system call getsid(pid) and return the result.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_getsid__doc__,
+"getsid($module, pid, /)\n"
+"--\n"
+"\n"
+"Call the system call getsid(pid) and return the result.");
+
+#define OS_GETSID_METHODDEF \
+ {"getsid", (PyCFunction)os_getsid, METH_VARARGS, os_getsid__doc__},
+
+static PyObject *
+os_getsid_impl(PyModuleDef *module, pid_t pid);
+
+static PyObject *
+os_getsid(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ pid_t pid;
+
+ if (!PyArg_ParseTuple(args,
+ "" _Py_PARSE_PID ":getsid",
+ &pid))
+ goto exit;
+ return_value = os_getsid_impl(module, pid);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_getsid_impl(PyModuleDef *module, pid_t pid)
+/*[clinic end generated code: output=ea8390f395f4e0e1 input=eeb2b923a30ce04e]*/
+{
+ int sid;
+ sid = getsid(pid);
+ if (sid < 0)
+ return posix_error();
+ return PyLong_FromLong((long)sid);
+}
+#endif /* HAVE_GETSID */
+
+
+#ifdef HAVE_SETSID
+/*[clinic input]
+os.setsid
+
+Call the system call setsid().
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_setsid__doc__,
+"setsid($module, /)\n"
+"--\n"
+"\n"
+"Call the system call setsid().");
+
+#define OS_SETSID_METHODDEF \
+ {"setsid", (PyCFunction)os_setsid, METH_NOARGS, os_setsid__doc__},
+
+static PyObject *
+os_setsid_impl(PyModuleDef *module);
+
+static PyObject *
+os_setsid(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
+{
+ return os_setsid_impl(module);
+}
+
+static PyObject *
+os_setsid_impl(PyModuleDef *module)
+/*[clinic end generated code: output=2a9a1435d8d764d5 input=5fff45858e2f0776]*/
+{
+ if (setsid() < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_SETSID */
+
+
+#ifdef HAVE_SETPGID
+/*[clinic input]
+os.setpgid
+
+ pid: pid_t
+ pgrp: pid_t
+ /
+
+Call the system call setpgid(pid, pgrp).
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_setpgid__doc__,
+"setpgid($module, pid, pgrp, /)\n"
+"--\n"
+"\n"
+"Call the system call setpgid(pid, pgrp).");
+
+#define OS_SETPGID_METHODDEF \
+ {"setpgid", (PyCFunction)os_setpgid, METH_VARARGS, os_setpgid__doc__},
+
+static PyObject *
+os_setpgid_impl(PyModuleDef *module, pid_t pid, pid_t pgrp);
+
+static PyObject *
+os_setpgid(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ pid_t pid;
+ pid_t pgrp;
+
+ if (!PyArg_ParseTuple(args,
+ "" _Py_PARSE_PID "" _Py_PARSE_PID ":setpgid",
+ &pid, &pgrp))
+ goto exit;
+ return_value = os_setpgid_impl(module, pid, pgrp);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_setpgid_impl(PyModuleDef *module, pid_t pid, pid_t pgrp)
+/*[clinic end generated code: output=7ad79b725f890e1f input=fceb395eca572e1a]*/
+{
+ if (setpgid(pid, pgrp) < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_SETPGID */
+
+
+#ifdef HAVE_TCGETPGRP
+/*[clinic input]
+os.tcgetpgrp
+
+ fd: int
+ /
+
+Return the process group associated with the terminal specified by fd.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_tcgetpgrp__doc__,
+"tcgetpgrp($module, fd, /)\n"
+"--\n"
+"\n"
+"Return the process group associated with the terminal specified by fd.");
+
+#define OS_TCGETPGRP_METHODDEF \
+ {"tcgetpgrp", (PyCFunction)os_tcgetpgrp, METH_VARARGS, os_tcgetpgrp__doc__},
+
+static PyObject *
+os_tcgetpgrp_impl(PyModuleDef *module, int fd);
+
+static PyObject *
+os_tcgetpgrp(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+
+ if (!PyArg_ParseTuple(args,
+ "i:tcgetpgrp",
+ &fd))
+ goto exit;
+ return_value = os_tcgetpgrp_impl(module, fd);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_tcgetpgrp_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=abcf52ed4c8d22cb input=7f6c18eac10ada86]*/
+{
+ pid_t pgid = tcgetpgrp(fd);
+ if (pgid < 0)
+ return posix_error();
+ return PyLong_FromPid(pgid);
+}
+#endif /* HAVE_TCGETPGRP */
+
+
+#ifdef HAVE_TCSETPGRP
+/*[clinic input]
+os.tcsetpgrp
+
+ fd: int
+ pgid: pid_t
+ /
+
+Set the process group associated with the terminal specified by fd.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_tcsetpgrp__doc__,
+"tcsetpgrp($module, fd, pgid, /)\n"
+"--\n"
+"\n"
+"Set the process group associated with the terminal specified by fd.");
+
+#define OS_TCSETPGRP_METHODDEF \
+ {"tcsetpgrp", (PyCFunction)os_tcsetpgrp, METH_VARARGS, os_tcsetpgrp__doc__},
+
+static PyObject *
+os_tcsetpgrp_impl(PyModuleDef *module, int fd, pid_t pgid);
+
+static PyObject *
+os_tcsetpgrp(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ pid_t pgid;
+
+ if (!PyArg_ParseTuple(args,
+ "i" _Py_PARSE_PID ":tcsetpgrp",
+ &fd, &pgid))
+ goto exit;
+ return_value = os_tcsetpgrp_impl(module, fd, pgid);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_tcsetpgrp_impl(PyModuleDef *module, int fd, pid_t pgid)
+/*[clinic end generated code: output=76f9bb8fd00f20f5 input=5bdc997c6a619020]*/
+{
+ if (tcsetpgrp(fd, pgid) < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_TCSETPGRP */
+
+/* Functions acting on file descriptors */
+
+#ifdef O_CLOEXEC
+extern int _Py_open_cloexec_works;
+#endif
+
+
+/*[clinic input]
+os.open -> int
+ path: path_t
+ flags: int
+ mode: int = 0o777
+ *
+ dir_fd: dir_fd(requires='openat') = None
+
+# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
+
+Open a file for low level IO. Returns a file descriptor (integer).
+
+If dir_fd is not None, it should be a file descriptor open to a directory,
+ and path should be relative; path will then be relative to that directory.
+dir_fd may not be implemented on your platform.
+ If it is unavailable, using it will raise a NotImplementedError.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_open__doc__,
+"open($module, /, path, flags, mode=511, *, dir_fd=None)\n"
+"--\n"
+"\n"
+"Open a file for low level IO. Returns a file descriptor (integer).\n"
+"\n"
+"If dir_fd is not None, it should be a file descriptor open to a directory,\n"
+" and path should be relative; path will then be relative to that directory.\n"
+"dir_fd may not be implemented on your platform.\n"
+" If it is unavailable, using it will raise a NotImplementedError.");
+
+#define OS_OPEN_METHODDEF \
+ {"open", (PyCFunction)os_open, METH_VARARGS|METH_KEYWORDS, os_open__doc__},
+
+static int
+os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, int dir_fd);
+
+static PyObject *
+os_open(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"path", "flags", "mode", "dir_fd", NULL};
+ path_t path = PATH_T_INITIALIZE("open", "path", 0, 0);
+ int flags;
+ int mode = 511;
+ int dir_fd = DEFAULT_DIR_FD;
+ int _return_value;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O&i|i$O&:open", _keywords,
+ path_converter, &path, &flags, &mode, OPENAT_DIR_FD_CONVERTER, &dir_fd))
+ goto exit;
+ _return_value = os_open_impl(module, &path, flags, mode, dir_fd);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromLong((long)_return_value);
+
+exit:
+ /* Cleanup for path */
+ path_cleanup(&path);
+
+ return return_value;
+}
+
+static int
+os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, int dir_fd)
+/*[clinic end generated code: output=05b68fc4ed5e29c9 input=ad8623b29acd2934]*/
+{
+ int fd;
+ int async_err = 0;
+
+#ifdef O_CLOEXEC
+ int *atomic_flag_works = &_Py_open_cloexec_works;
+#elif !defined(MS_WINDOWS)
+ int *atomic_flag_works = NULL;
+#endif
+
+#ifdef MS_WINDOWS
+ flags |= O_NOINHERIT;
+#elif defined(O_CLOEXEC)
+ flags |= O_CLOEXEC;
+#endif
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+#ifdef MS_WINDOWS
+ if (path->wide)
+ fd = _wopen(path->wide, flags, mode);
+ else
+#endif
+#ifdef HAVE_OPENAT
+ if (dir_fd != DEFAULT_DIR_FD)
+ fd = openat(dir_fd, path->narrow, flags, mode);
+ else
+#endif
+ fd = open(path->narrow, flags, mode);
+ Py_END_ALLOW_THREADS
+ } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
+ if (fd == -1) {
+ if (!async_err)
+ PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
+ return -1;
+ }
+
+#ifndef MS_WINDOWS
+ if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
+ close(fd);
+ return -1;
+ }
+#endif
+
+ return fd;
+}
+
+
+/*[clinic input]
+os.close
+
+ fd: int
+
+Close a file descriptor.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_close__doc__,
+"close($module, /, fd)\n"
+"--\n"
+"\n"
+"Close a file descriptor.");
+
+#define OS_CLOSE_METHODDEF \
+ {"close", (PyCFunction)os_close, METH_VARARGS|METH_KEYWORDS, os_close__doc__},
+
+static PyObject *
+os_close_impl(PyModuleDef *module, int fd);
+
+static PyObject *
+os_close(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"fd", NULL};
+ int fd;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "i:close", _keywords,
+ &fd))
+ goto exit;
+ return_value = os_close_impl(module, fd);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_close_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=927004e29ad55808 input=2bc42451ca5c3223]*/
+{
+ int res;
+ if (!_PyVerify_fd(fd))
+ return posix_error();
+ /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
+ * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
+ * for more details.
+ */
+ Py_BEGIN_ALLOW_THREADS
+ res = close(fd);
+ Py_END_ALLOW_THREADS
+ if (res < 0)
+ return posix_error();
+ Py_RETURN_NONE;
+}
+
+
+/*[clinic input]
+os.closerange
+
+ fd_low: int
+ fd_high: int
+ /
+
+Closes all file descriptors in [fd_low, fd_high), ignoring errors.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_closerange__doc__,
+"closerange($module, fd_low, fd_high, /)\n"
+"--\n"
+"\n"
+"Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
+
+#define OS_CLOSERANGE_METHODDEF \
+ {"closerange", (PyCFunction)os_closerange, METH_VARARGS, os_closerange__doc__},
+
+static PyObject *
+os_closerange_impl(PyModuleDef *module, int fd_low, int fd_high);
+
+static PyObject *
+os_closerange(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd_low;
+ int fd_high;
+
+ if (!PyArg_ParseTuple(args,
+ "ii:closerange",
+ &fd_low, &fd_high))
+ goto exit;
+ return_value = os_closerange_impl(module, fd_low, fd_high);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_closerange_impl(PyModuleDef *module, int fd_low, int fd_high)
+/*[clinic end generated code: output=0a929ece386811c3 input=5855a3d053ebd4ec]*/
+{
+ int i;
+ Py_BEGIN_ALLOW_THREADS
+ for (i = fd_low; i < fd_high; i++)
+ if (_PyVerify_fd(i))
+ close(i);
+ Py_END_ALLOW_THREADS
+ Py_RETURN_NONE;
+}
+
+
+/*[clinic input]
+os.dup -> int
+
+ fd: int
+ /
+
+Return a duplicate of a file descriptor.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_dup__doc__,
+"dup($module, fd, /)\n"
+"--\n"
+"\n"
+"Return a duplicate of a file descriptor.");
+
+#define OS_DUP_METHODDEF \
+ {"dup", (PyCFunction)os_dup, METH_VARARGS, os_dup__doc__},
+
+static int
+os_dup_impl(PyModuleDef *module, int fd);
+
+static PyObject *
+os_dup(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ int _return_value;
+
+ if (!PyArg_ParseTuple(args,
+ "i:dup",
+ &fd))
+ goto exit;
+ _return_value = os_dup_impl(module, fd);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+static int
+os_dup_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=75943e057b25e1bd input=6f10f7ea97f7852a]*/
+{
+ return _Py_dup(fd);
+}
+
+
+/*[clinic input]
+os.dup2
+ fd: int
+ fd2: int
+ inheritable: bool=True
+
+Duplicate file descriptor.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_dup2__doc__,
+"dup2($module, /, fd, fd2, inheritable=True)\n"
+"--\n"
+"\n"
+"Duplicate file descriptor.");
+
+#define OS_DUP2_METHODDEF \
+ {"dup2", (PyCFunction)os_dup2, METH_VARARGS|METH_KEYWORDS, os_dup2__doc__},
+
+static PyObject *
+os_dup2_impl(PyModuleDef *module, int fd, int fd2, int inheritable);
+
+static PyObject *
+os_dup2(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"fd", "fd2", "inheritable", NULL};
+ int fd;
+ int fd2;
+ int inheritable = 1;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "ii|p:dup2", _keywords,
+ &fd, &fd2, &inheritable))
+ goto exit;
+ return_value = os_dup2_impl(module, fd, fd2, inheritable);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_dup2_impl(PyModuleDef *module, int fd, int fd2, int inheritable)
+/*[clinic end generated code: output=531e482dd11a99a0 input=76e96f511be0352f]*/
+{
+ int res;
+#if defined(HAVE_DUP3) && \
+ !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
+ /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
+ int dup3_works = -1;
+#endif
+
+ if (!_PyVerify_fd_dup2(fd, fd2))
+ return posix_error();
+
+ /* dup2() can fail with EINTR if the target FD is already open, because it
+ * then has to be closed. See os_close_impl() for why we don't handle EINTR
+ * upon close(), and therefore below.
+ */
+#ifdef MS_WINDOWS
+ Py_BEGIN_ALLOW_THREADS
+ res = dup2(fd, fd2);
+ Py_END_ALLOW_THREADS
+ if (res < 0)
+ return posix_error();
+
+ /* Character files like console cannot be make non-inheritable */
+ if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
+ close(fd2);
+ return NULL;
+ }
+
+#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
+ Py_BEGIN_ALLOW_THREADS
+ if (!inheritable)
+ res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
+ else
+ res = dup2(fd, fd2);
+ Py_END_ALLOW_THREADS
+ if (res < 0)
+ return posix_error();
+
+#else
+
+#ifdef HAVE_DUP3
+ if (!inheritable && dup3_works != 0) {
+ Py_BEGIN_ALLOW_THREADS
+ res = dup3(fd, fd2, O_CLOEXEC);
+ Py_END_ALLOW_THREADS
+ if (res < 0) {
+ if (dup3_works == -1)
+ dup3_works = (errno != ENOSYS);
+ if (dup3_works)
+ return posix_error();
+ }
+ }
+
+ if (inheritable || dup3_works == 0)
+ {
+#endif
+ Py_BEGIN_ALLOW_THREADS
+ res = dup2(fd, fd2);
+ Py_END_ALLOW_THREADS
+ if (res < 0)
+ return posix_error();
+
+ if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
+ close(fd2);
+ return NULL;
+ }
+#ifdef HAVE_DUP3
+ }
+#endif
+
+#endif
+
+ Py_RETURN_NONE;
+}
+
+
+#ifdef HAVE_LOCKF
+/*[clinic input]
+os.lockf
+
+ fd: int
+ An open file descriptor.
+ command: int
+ One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
+ length: Py_off_t
+ The number of bytes to lock, starting at the current position.
+ /
+
+Apply, test or remove a POSIX lock on an open file descriptor.
+
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_lockf__doc__,
+"lockf($module, fd, command, length, /)\n"
+"--\n"
+"\n"
+"Apply, test or remove a POSIX lock on an open file descriptor.\n"
+"\n"
+" fd\n"
+" An open file descriptor.\n"
+" command\n"
+" One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.\n"
+" length\n"
+" The number of bytes to lock, starting at the current position.");
+
+#define OS_LOCKF_METHODDEF \
+ {"lockf", (PyCFunction)os_lockf, METH_VARARGS, os_lockf__doc__},
+
+static PyObject *
+os_lockf_impl(PyModuleDef *module, int fd, int command, Py_off_t length);
+
+static PyObject *
+os_lockf(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ int command;
+ Py_off_t length;
+
+ if (!PyArg_ParseTuple(args,
+ "iiO&:lockf",
+ &fd, &command, Py_off_t_converter, &length))
+ goto exit;
+ return_value = os_lockf_impl(module, fd, command, length);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_lockf_impl(PyModuleDef *module, int fd, int command, Py_off_t length)
+/*[clinic end generated code: output=1b28346ac7335c0f input=65da41d2106e9b79]*/
+{
+ int res;
+
+ Py_BEGIN_ALLOW_THREADS
+ res = lockf(fd, command, length);
+ Py_END_ALLOW_THREADS
+
+ if (res < 0)
+ return posix_error();
+
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_LOCKF */
+
+
+/*[clinic input]
+os.lseek -> Py_off_t
+
+ fd: int
+ position: Py_off_t
+ how: int
+ /
+
+Set the position of a file descriptor. Return the new position.
+
+Return the new cursor position in number of bytes
+relative to the beginning of the file.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_lseek__doc__,
+"lseek($module, fd, position, how, /)\n"
+"--\n"
+"\n"
+"Set the position of a file descriptor. Return the new position.\n"
+"\n"
+"Return the new cursor position in number of bytes\n"
+"relative to the beginning of the file.");
+
+#define OS_LSEEK_METHODDEF \
+ {"lseek", (PyCFunction)os_lseek, METH_VARARGS, os_lseek__doc__},
+
+static Py_off_t
+os_lseek_impl(PyModuleDef *module, int fd, Py_off_t position, int how);
+
+static PyObject *
+os_lseek(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ Py_off_t position;
+ int how;
+ Py_off_t _return_value;
+
+ if (!PyArg_ParseTuple(args,
+ "iO&i:lseek",
+ &fd, Py_off_t_converter, &position, &how))
+ goto exit;
+ _return_value = os_lseek_impl(module, fd, position, how);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromPy_off_t(_return_value);
+
+exit:
+ return return_value;
+}
+
+static Py_off_t
+os_lseek_impl(PyModuleDef *module, int fd, Py_off_t position, int how)
+/*[clinic end generated code: output=88cfc146f55667af input=902654ad3f96a6d3]*/
+{
+ Py_off_t result;
+
+ if (!_PyVerify_fd(fd)) {
+ posix_error();
+ return -1;
+ }
+#ifdef SEEK_SET
+ /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
+ switch (how) {
+ case 0: how = SEEK_SET; break;
+ case 1: how = SEEK_CUR; break;
+ case 2: how = SEEK_END; break;
+ }
+#endif /* SEEK_END */
+
+ if (PyErr_Occurred())
+ return -1;
+
+ if (!_PyVerify_fd(fd)) {
+ posix_error();
+ return -1;
+ }
+ Py_BEGIN_ALLOW_THREADS
+#ifdef MS_WINDOWS
+ result = _lseeki64(fd, position, how);
+#else
+ result = lseek(fd, position, how);
+#endif
+ Py_END_ALLOW_THREADS
+ if (result < 0)
+ posix_error();
+
+ return result;
+}
+
+
+/*[clinic input]
+os.read
+ fd: int
+ length: Py_ssize_t
+ /
+
+Read from a file descriptor. Returns a bytes object.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_read__doc__,
+"read($module, fd, length, /)\n"
+"--\n"
+"\n"
+"Read from a file descriptor. Returns a bytes object.");
+
+#define OS_READ_METHODDEF \
+ {"read", (PyCFunction)os_read, METH_VARARGS, os_read__doc__},
+
+static PyObject *
+os_read_impl(PyModuleDef *module, int fd, Py_ssize_t length);
+
+static PyObject *
+os_read(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ Py_ssize_t length;
+
+ if (!PyArg_ParseTuple(args,
+ "in:read",
+ &fd, &length))
+ goto exit;
+ return_value = os_read_impl(module, fd, length);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_read_impl(PyModuleDef *module, int fd, Py_ssize_t length)
+/*[clinic end generated code: output=1f3bc27260a24968 input=1df2eaa27c0bf1d3]*/
+{
+ Py_ssize_t n;
+ int async_err = 0;
+ PyObject *buffer;
+
+ if (length < 0) {
+ errno = EINVAL;
+ return posix_error();
+ }
+ if (!_PyVerify_fd(fd))
+ return posix_error();
+
+#ifdef MS_WINDOWS
+ #define READ_CAST (int)
+ if (length > INT_MAX)
+ length = INT_MAX;
+#else
+ #define READ_CAST
+#endif
+
+ buffer = PyBytes_FromStringAndSize((char *)NULL, length);
+ if (buffer == NULL)
+ return NULL;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ n = read(fd, PyBytes_AS_STRING(buffer), READ_CAST length);
+ Py_END_ALLOW_THREADS
+ } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
+ if (n < 0) {
+ Py_DECREF(buffer);
+ return (!async_err) ? posix_error() : NULL;
+ }
+
+ if (n != length)
+ _PyBytes_Resize(&buffer, n);
+
+ return buffer;
+}
+
+#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
+ || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV)
+static Py_ssize_t
+iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type)
+{
+ int i, j;
+ Py_ssize_t blen, total = 0;
+
+ *iov = PyMem_New(struct iovec, cnt);
+ if (*iov == NULL) {
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ *buf = PyMem_New(Py_buffer, cnt);
+ if (*buf == NULL) {
+ PyMem_Del(*iov);
+ PyErr_NoMemory();
+ return -1;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ PyObject *item = PySequence_GetItem(seq, i);
+ if (item == NULL)
+ goto fail;
+ if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
+ Py_DECREF(item);
+ goto fail;
+ }
+ Py_DECREF(item);
+ (*iov)[i].iov_base = (*buf)[i].buf;
+ blen = (*buf)[i].len;
+ (*iov)[i].iov_len = blen;
+ total += blen;
+ }
+ return total;
+
+fail:
+ PyMem_Del(*iov);
+ for (j = 0; j < i; j++) {
+ PyBuffer_Release(&(*buf)[j]);
+ }
+ PyMem_Del(*buf);
+ return -1;
+}
+
+static void
+iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
+{
+ int i;
+ PyMem_Del(iov);
+ for (i = 0; i < cnt; i++) {
+ PyBuffer_Release(&buf[i]);
+ }
+ PyMem_Del(buf);
+}
+#endif
+
+
+#ifdef HAVE_READV
+/*[clinic input]
+os.readv -> Py_ssize_t
+
+ fd: int
+ buffers: object
+ /
+
+Read from a file descriptor fd into an iterable of buffers.
+
+The buffers should be mutable buffers accepting bytes.
+readv will transfer data into each buffer until it is full
+and then move on to the next buffer in the sequence to hold
+the rest of the data.
+
+readv returns the total number of bytes read,
+which may be less than the total capacity of all the buffers.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_readv__doc__,
+"readv($module, fd, buffers, /)\n"
+"--\n"
+"\n"
+"Read from a file descriptor fd into an iterable of buffers.\n"
+"\n"
+"The buffers should be mutable buffers accepting bytes.\n"
+"readv will transfer data into each buffer until it is full\n"
+"and then move on to the next buffer in the sequence to hold\n"
+"the rest of the data.\n"
+"\n"
+"readv returns the total number of bytes read,\n"
+"which may be less than the total capacity of all the buffers.");
+
+#define OS_READV_METHODDEF \
+ {"readv", (PyCFunction)os_readv, METH_VARARGS, os_readv__doc__},
+
+static Py_ssize_t
+os_readv_impl(PyModuleDef *module, int fd, PyObject *buffers);
+
+static PyObject *
+os_readv(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ PyObject *buffers;
+ Py_ssize_t _return_value;
+
+ if (!PyArg_ParseTuple(args,
+ "iO:readv",
+ &fd, &buffers))
+ goto exit;
+ _return_value = os_readv_impl(module, fd, buffers);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromSsize_t(_return_value);
+
+exit:
+ return return_value;
+}
+
+static Py_ssize_t
+os_readv_impl(PyModuleDef *module, int fd, PyObject *buffers)
+/*[clinic end generated code: output=72748b1c32a6e2a1 input=e679eb5dbfa0357d]*/
+{
+ int cnt;
+ Py_ssize_t n;
+ int async_err = 0;
+ struct iovec *iov;
+ Py_buffer *buf;
+
+ if (!PySequence_Check(buffers)) {
+ PyErr_SetString(PyExc_TypeError,
+ "readv() arg 2 must be a sequence");
+ return -1;
+ }
+
+ cnt = PySequence_Size(buffers);
+
+ if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
+ return -1;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ n = readv(fd, iov, cnt);
+ Py_END_ALLOW_THREADS
+ } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
+ iov_cleanup(iov, buf, cnt);
+ if (n < 0) {
+ if (!async_err)
+ posix_error();
+ return -1;
+ }
+
+ return n;
+}
+#endif /* HAVE_READV */
+
+
+#ifdef HAVE_PREAD
+/*[clinic input]
+# TODO length should be size_t! but Python doesn't support parsing size_t yet.
+os.pread
+
+ fd: int
+ length: int
+ offset: Py_off_t
+ /
+
+Read a number of bytes from a file descriptor starting at a particular offset.
+
+Read length bytes from file descriptor fd, starting at offset bytes from
+the beginning of the file. The file offset remains unchanged.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_pread__doc__,
+"pread($module, fd, length, offset, /)\n"
+"--\n"
+"\n"
+"Read a number of bytes from a file descriptor starting at a particular offset.\n"
+"\n"
+"Read length bytes from file descriptor fd, starting at offset bytes from\n"
+"the beginning of the file. The file offset remains unchanged.");
+
+#define OS_PREAD_METHODDEF \
+ {"pread", (PyCFunction)os_pread, METH_VARARGS, os_pread__doc__},
+
+static PyObject *
+os_pread_impl(PyModuleDef *module, int fd, int length, Py_off_t offset);
+
+static PyObject *
+os_pread(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ int length;
+ Py_off_t offset;
+
+ if (!PyArg_ParseTuple(args,
+ "iiO&:pread",
+ &fd, &length, Py_off_t_converter, &offset))
+ goto exit;
+ return_value = os_pread_impl(module, fd, length, offset);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_pread_impl(PyModuleDef *module, int fd, int length, Py_off_t offset)
+/*[clinic end generated code: output=7b62bf6c06e20ae8 input=084948dcbaa35d4c]*/
+{
+ Py_ssize_t n;
+ int async_err = 0;
+ PyObject *buffer;
+
+ if (length < 0) {
+ errno = EINVAL;
+ return posix_error();
+ }
+ buffer = PyBytes_FromStringAndSize((char *)NULL, length);
+ if (buffer == NULL)
+ return NULL;
+ if (!_PyVerify_fd(fd)) {
+ Py_DECREF(buffer);
+ return posix_error();
+ }
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
+ Py_END_ALLOW_THREADS
+ } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
+ if (n < 0) {
+ Py_DECREF(buffer);
+ return (!async_err) ? posix_error() : NULL;
+ }
+ if (n != length)
+ _PyBytes_Resize(&buffer, n);
+ return buffer;
+}
+#endif /* HAVE_PREAD */
+
+
+/*[clinic input]
+os.write -> Py_ssize_t
+
+ fd: int
+ data: Py_buffer
+ /
+
+Write a bytes object to a file descriptor.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_write__doc__,
+"write($module, fd, data, /)\n"
+"--\n"
+"\n"
+"Write a bytes object to a file descriptor.");
+
+#define OS_WRITE_METHODDEF \
+ {"write", (PyCFunction)os_write, METH_VARARGS, os_write__doc__},
+
+static Py_ssize_t
+os_write_impl(PyModuleDef *module, int fd, Py_buffer *data);
+
+static PyObject *
+os_write(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ Py_buffer data = {NULL, NULL};
+ Py_ssize_t _return_value;
+
+ if (!PyArg_ParseTuple(args,
+ "iy*:write",
+ &fd, &data))
+ goto exit;
+ _return_value = os_write_impl(module, fd, &data);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromSsize_t(_return_value);
+
+exit:
+ /* Cleanup for data */
+ if (data.obj)
+ PyBuffer_Release(&data);
+
+ return return_value;
+}
+
+static Py_ssize_t
+os_write_impl(PyModuleDef *module, int fd, Py_buffer *data)
+/*[clinic end generated code: output=aeb96acfdd4d5112 input=3207e28963234f3c]*/
+{
+ Py_ssize_t size;
+ int async_err = 0;
+ Py_ssize_t len = data->len;
+
+ if (!_PyVerify_fd(fd)) {
+ posix_error();
+ return -1;
+ }
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+#ifdef MS_WINDOWS
+ if (len > INT_MAX)
+ len = INT_MAX;
+ size = write(fd, data->buf, (int)len);
+#else
+ size = write(fd, data->buf, len);
+#endif
+ Py_END_ALLOW_THREADS
+ } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
+ if (size < 0) {
+ if (!async_err)
+ posix_error();
+ return -1;
+ }
+ return size;
+}
+
+#ifdef HAVE_SENDFILE
+PyDoc_STRVAR(posix_sendfile__doc__,
+"sendfile(out, in, offset, nbytes) -> byteswritten\n\
+sendfile(out, in, offset, nbytes, headers=None, trailers=None, flags=0)\n\
+ -> byteswritten\n\
+Copy nbytes bytes from file descriptor in to file descriptor out.");
+
+/* AC 3.5: don't bother converting, has optional group*/
+static PyObject *
+posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
+{
+ int in, out;
+ Py_ssize_t ret;
+ int async_err = 0;
+ off_t offset;
+
+#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+#ifndef __APPLE__
+ Py_ssize_t len;
+#endif
+ PyObject *headers = NULL, *trailers = NULL;
+ Py_buffer *hbuf, *tbuf;
+ off_t sbytes;
+ struct sf_hdtr sf;
+ int flags = 0;
+ static char *keywords[] = {"out", "in",
+ "offset", "count",
+ "headers", "trailers", "flags", NULL};
+
+ sf.headers = NULL;
+ sf.trailers = NULL;
+
+#ifdef __APPLE__
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
+ keywords, &out, &in, Py_off_t_converter, &offset, Py_off_t_converter, &sbytes,
+#else
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
+ keywords, &out, &in, Py_off_t_converter, &offset, &len,
+#endif
+ &headers, &trailers, &flags))
+ return NULL;
+ if (headers != NULL) {
+ if (!PySequence_Check(headers)) {
+ PyErr_SetString(PyExc_TypeError,
+ "sendfile() headers must be a sequence or None");
+ return NULL;
+ } else {
+ Py_ssize_t i = 0; /* Avoid uninitialized warning */
+ sf.hdr_cnt = PySequence_Size(headers);
+ if (sf.hdr_cnt > 0 &&
+ (i = iov_setup(&(sf.headers), &hbuf,
+ headers, sf.hdr_cnt, PyBUF_SIMPLE)) < 0)
+ return NULL;
+#ifdef __APPLE__
+ sbytes += i;
+#endif
+ }
+ }
+ if (trailers != NULL) {
+ if (!PySequence_Check(trailers)) {
+ PyErr_SetString(PyExc_TypeError,
+ "sendfile() trailers must be a sequence or None");
+ return NULL;
+ } else {
+ Py_ssize_t i = 0; /* Avoid uninitialized warning */
+ sf.trl_cnt = PySequence_Size(trailers);
+ if (sf.trl_cnt > 0 &&
+ (i = iov_setup(&(sf.trailers), &tbuf,
+ trailers, sf.trl_cnt, PyBUF_SIMPLE)) < 0)
+ return NULL;
+#ifdef __APPLE__
+ sbytes += i;
+#endif
+ }
+ }
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+#ifdef __APPLE__
+ ret = sendfile(in, out, offset, &sbytes, &sf, flags);
+#else
+ ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
+#endif
+ Py_END_ALLOW_THREADS
+ } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
+ if (sf.headers != NULL)
+ iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
+ if (sf.trailers != NULL)
+ iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
+
+ if (ret < 0) {
+ if ((errno == EAGAIN) || (errno == EBUSY)) {
+ if (sbytes != 0) {
+ // some data has been sent
+ goto done;
+ }
+ else {
+ // no data has been sent; upper application is supposed
+ // to retry on EAGAIN or EBUSY
+ return posix_error();
+ }
+ }
+ return (!async_err) ? posix_error() : NULL;
+ }
+ goto done;
+
+done:
+ #if !defined(HAVE_LARGEFILE_SUPPORT)
+ return Py_BuildValue("l", sbytes);
+ #else
+ return Py_BuildValue("L", sbytes);
+ #endif
+
+#else
+ Py_ssize_t count;
+ PyObject *offobj;
+ static char *keywords[] = {"out", "in",
+ "offset", "count", NULL};
+ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
+ keywords, &out, &in, &offobj, &count))
+ return NULL;
+#ifdef linux
+ if (offobj == Py_None) {
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ ret = sendfile(out, in, NULL, count);
+ Py_END_ALLOW_THREADS
+ } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (ret < 0)
+ return (!async_err) ? posix_error() : NULL;
+ return Py_BuildValue("n", ret);
+ }
+#endif
+ if (!Py_off_t_converter(offobj, &offset))
+ return NULL;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ ret = sendfile(out, in, &offset, count);
+ Py_END_ALLOW_THREADS
+ } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (ret < 0)
+ return (!async_err) ? posix_error() : NULL;
+ return Py_BuildValue("n", ret);
+#endif
+}
+#endif /* HAVE_SENDFILE */
+
+
+/*[clinic input]
+os.fstat
+
+ fd : int
+
+Perform a stat system call on the given file descriptor.
+
+Like stat(), but for an open file descriptor.
+Equivalent to os.stat(fd).
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_fstat__doc__,
+"fstat($module, /, fd)\n"
+"--\n"
+"\n"
+"Perform a stat system call on the given file descriptor.\n"
+"\n"
+"Like stat(), but for an open file descriptor.\n"
+"Equivalent to os.stat(fd).");
+
+#define OS_FSTAT_METHODDEF \
+ {"fstat", (PyCFunction)os_fstat, METH_VARARGS|METH_KEYWORDS, os_fstat__doc__},
+
+static PyObject *
+os_fstat_impl(PyModuleDef *module, int fd);
+
+static PyObject *
+os_fstat(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"fd", NULL};
+ int fd;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "i:fstat", _keywords,
+ &fd))
+ goto exit;
+ return_value = os_fstat_impl(module, fd);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_fstat_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=dae4a9678c7bd881 input=27e0e0ebbe5600c9]*/
+{
+ STRUCT_STAT st;
+ int res;
+ int async_err = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ res = FSTAT(fd, &st);
+ Py_END_ALLOW_THREADS
+ } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ if (res != 0) {
+#ifdef MS_WINDOWS
+ return PyErr_SetFromWindowsErr(0);
+#else
+ return (!async_err) ? posix_error() : NULL;
+#endif
+ }
+
+ return _pystat_fromstructstat(&st);
+}
+
+
+/*[clinic input]
+os.isatty -> bool
+ fd: int
+ /
+
+Return True if the fd is connected to a terminal.
+
+Return True if the file descriptor is an open file descriptor
+connected to the slave end of a terminal.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_isatty__doc__,
+"isatty($module, fd, /)\n"
+"--\n"
+"\n"
+"Return True if the fd is connected to a terminal.\n"
+"\n"
+"Return True if the file descriptor is an open file descriptor\n"
+"connected to the slave end of a terminal.");
+
+#define OS_ISATTY_METHODDEF \
+ {"isatty", (PyCFunction)os_isatty, METH_VARARGS, os_isatty__doc__},
+
+static int
+os_isatty_impl(PyModuleDef *module, int fd);
+
+static PyObject *
+os_isatty(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ int _return_value;
+
+ if (!PyArg_ParseTuple(args,
+ "i:isatty",
+ &fd))
+ goto exit;
+ _return_value = os_isatty_impl(module, fd);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyBool_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+static int
+os_isatty_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=4bfadbfe22715097 input=08ce94aa1eaf7b5e]*/
+{
+ if (!_PyVerify_fd(fd))
+ return 0;
+ return isatty(fd);
+}
+
+
+#ifdef HAVE_PIPE
+/*[clinic input]
+os.pipe
+
+Create a pipe.
+
+Returns a tuple of two file descriptors:
+ (read_fd, write_fd)
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_pipe__doc__,
+"pipe($module, /)\n"
+"--\n"
+"\n"
+"Create a pipe.\n"
+"\n"
+"Returns a tuple of two file descriptors:\n"
+" (read_fd, write_fd)");
+
+#define OS_PIPE_METHODDEF \
+ {"pipe", (PyCFunction)os_pipe, METH_NOARGS, os_pipe__doc__},
+
+static PyObject *
+os_pipe_impl(PyModuleDef *module);
+
+static PyObject *
+os_pipe(PyModuleDef *module, PyObject *Py_UNUSED(ignored))
+{
+ return os_pipe_impl(module);
+}
+
+static PyObject *
+os_pipe_impl(PyModuleDef *module)
+/*[clinic end generated code: output=0da2479f2266e774 input=02535e8c8fa6c4d4]*/
+{
+ int fds[2];
+#ifdef MS_WINDOWS
+ HANDLE read, write;
+ SECURITY_ATTRIBUTES attr;
+ BOOL ok;
+#else
+ int res;
+#endif
+
+#ifdef MS_WINDOWS
+ attr.nLength = sizeof(attr);
+ attr.lpSecurityDescriptor = NULL;
+ attr.bInheritHandle = FALSE;
+
+ Py_BEGIN_ALLOW_THREADS
+ ok = CreatePipe(&read, &write, &attr, 0);
+ if (ok) {
+ fds[0] = _open_osfhandle((Py_intptr_t)read, _O_RDONLY);
+ fds[1] = _open_osfhandle((Py_intptr_t)write, _O_WRONLY);
+ if (fds[0] == -1 || fds[1] == -1) {
+ CloseHandle(read);
+ CloseHandle(write);
+ ok = 0;
+ }
+ }
+ Py_END_ALLOW_THREADS
+
+ if (!ok)
+ return PyErr_SetFromWindowsErr(0);
+#else
+
+#ifdef HAVE_PIPE2
+ Py_BEGIN_ALLOW_THREADS
+ res = pipe2(fds, O_CLOEXEC);
+ Py_END_ALLOW_THREADS
+
+ if (res != 0 && errno == ENOSYS)
+ {
+#endif
+ Py_BEGIN_ALLOW_THREADS
+ res = pipe(fds);
+ Py_END_ALLOW_THREADS
+
+ if (res == 0) {
+ if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
+ close(fds[0]);
+ close(fds[1]);
+ return NULL;
+ }
+ if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
+ close(fds[0]);
+ close(fds[1]);
+ return NULL;
+ }
+ }
+#ifdef HAVE_PIPE2
+ }
+#endif
+
+ if (res != 0)
+ return PyErr_SetFromErrno(PyExc_OSError);
+#endif /* !MS_WINDOWS */
+ return Py_BuildValue("(ii)", fds[0], fds[1]);
+}
+#endif /* HAVE_PIPE */
+
+
+#ifdef HAVE_PIPE2
+/*[clinic input]
+os.pipe2
+
+ flags: int
+ /
+
+Create a pipe with flags set atomically.
+
+Returns a tuple of two file descriptors:
+ (read_fd, write_fd)
+
+flags can be constructed by ORing together one or more of these values:
+O_NONBLOCK, O_CLOEXEC.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_pipe2__doc__,
+"pipe2($module, flags, /)\n"
+"--\n"
+"\n"
+"Create a pipe with flags set atomically.\n"
+"\n"
+"Returns a tuple of two file descriptors:\n"
+" (read_fd, write_fd)\n"
+"\n"
+"flags can be constructed by ORing together one or more of these values:\n"
+"O_NONBLOCK, O_CLOEXEC.");
+
+#define OS_PIPE2_METHODDEF \
+ {"pipe2", (PyCFunction)os_pipe2, METH_VARARGS, os_pipe2__doc__},
+
+static PyObject *
+os_pipe2_impl(PyModuleDef *module, int flags);
+
+static PyObject *
+os_pipe2(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int flags;
+
+ if (!PyArg_ParseTuple(args,
+ "i:pipe2",
+ &flags))
+ goto exit;
+ return_value = os_pipe2_impl(module, flags);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_pipe2_impl(PyModuleDef *module, int flags)
+/*[clinic end generated code: output=9e27c799ce19220b input=f261b6e7e63c6817]*/
+{
+ int fds[2];
+ int res;
+
+ res = pipe2(fds, flags);
+ if (res != 0)
+ return posix_error();
+ return Py_BuildValue("(ii)", fds[0], fds[1]);
+}
+#endif /* HAVE_PIPE2 */
+
+
+#ifdef HAVE_WRITEV
+/*[clinic input]
+os.writev -> Py_ssize_t
+ fd: int
+ buffers: object
+ /
+
+Iterate over buffers, and write the contents of each to a file descriptor.
+
+Returns the total number of bytes written.
+buffers must be a sequence of bytes-like objects.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_writev__doc__,
+"writev($module, fd, buffers, /)\n"
+"--\n"
+"\n"
+"Iterate over buffers, and write the contents of each to a file descriptor.\n"
+"\n"
+"Returns the total number of bytes written.\n"
+"buffers must be a sequence of bytes-like objects.");
+
+#define OS_WRITEV_METHODDEF \
+ {"writev", (PyCFunction)os_writev, METH_VARARGS, os_writev__doc__},
+
+static Py_ssize_t
+os_writev_impl(PyModuleDef *module, int fd, PyObject *buffers);
+
+static PyObject *
+os_writev(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ PyObject *buffers;
+ Py_ssize_t _return_value;
+
+ if (!PyArg_ParseTuple(args,
+ "iO:writev",
+ &fd, &buffers))
+ goto exit;
+ _return_value = os_writev_impl(module, fd, buffers);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromSsize_t(_return_value);
+
+exit:
+ return return_value;
+}
+
+static Py_ssize_t
+os_writev_impl(PyModuleDef *module, int fd, PyObject *buffers)
+/*[clinic end generated code: output=591c662dccbe4951 input=5b8d17fe4189d2fe]*/
+{
+ int cnt;
+ Py_ssize_t result;
+ int async_err = 0;
+ struct iovec *iov;
+ Py_buffer *buf;
+
+ if (!PySequence_Check(buffers)) {
+ PyErr_SetString(PyExc_TypeError,
+ "writev() arg 2 must be a sequence");
+ return -1;
+ }
+ cnt = PySequence_Size(buffers);
+
+ if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
+ return -1;
+ }
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ result = writev(fd, iov, cnt);
+ Py_END_ALLOW_THREADS
+ } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
+ iov_cleanup(iov, buf, cnt);
+ if (result < 0 && !async_err)
+ posix_error();
+
+ return result;
+}
+#endif /* HAVE_WRITEV */
+
+
+#ifdef HAVE_PWRITE
+/*[clinic input]
+os.pwrite -> Py_ssize_t
+
+ fd: int
+ buffer: Py_buffer
+ offset: Py_off_t
+ /
+
+Write bytes to a file descriptor starting at a particular offset.
+
+Write buffer to fd, starting at offset bytes from the beginning of
+the file. Returns the number of bytes writte. Does not change the
+current file offset.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_pwrite__doc__,
+"pwrite($module, fd, buffer, offset, /)\n"
+"--\n"
+"\n"
+"Write bytes to a file descriptor starting at a particular offset.\n"
+"\n"
+"Write buffer to fd, starting at offset bytes from the beginning of\n"
+"the file. Returns the number of bytes writte. Does not change the\n"
+"current file offset.");
+
+#define OS_PWRITE_METHODDEF \
+ {"pwrite", (PyCFunction)os_pwrite, METH_VARARGS, os_pwrite__doc__},
+
+static Py_ssize_t
+os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, Py_off_t offset);
+
+static PyObject *
+os_pwrite(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ Py_buffer buffer = {NULL, NULL};
+ Py_off_t offset;
+ Py_ssize_t _return_value;
+
+ if (!PyArg_ParseTuple(args,
+ "iy*O&:pwrite",
+ &fd, &buffer, Py_off_t_converter, &offset))
+ goto exit;
+ _return_value = os_pwrite_impl(module, fd, &buffer, offset);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromSsize_t(_return_value);
+
+exit:
+ /* Cleanup for buffer */
+ if (buffer.obj)
+ PyBuffer_Release(&buffer);
+
+ return return_value;
+}
+
+static Py_ssize_t
+os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, Py_off_t offset)
+/*[clinic end generated code: output=ec9cc5b2238e96a7 input=19903f1b3dd26377]*/
+{
+ Py_ssize_t size;
+ int async_err = 0;
+
+ if (!_PyVerify_fd(fd)) {
+ posix_error();
+ return -1;
+ }
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
+ Py_END_ALLOW_THREADS
+ } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+
+ if (size < 0 && !async_err)
+ posix_error();
+ return size;
+}
+#endif /* HAVE_PWRITE */
+
+
+#ifdef HAVE_MKFIFO
+/*[clinic input]
+os.mkfifo
+
+ path: path_t
+ mode: int=0o666
+ *
+ dir_fd: dir_fd(requires='mkfifoat')=None
+
+Create a "fifo" (a POSIX named pipe).
+
+If dir_fd is not None, it should be a file descriptor open to a directory,
+ and path should be relative; path will then be relative to that directory.
+dir_fd may not be implemented on your platform.
+ If it is unavailable, using it will raise a NotImplementedError.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_mkfifo__doc__,
+"mkfifo($module, /, path, mode=438, *, dir_fd=None)\n"
+"--\n"
+"\n"
+"Create a \"fifo\" (a POSIX named pipe).\n"
+"\n"
+"If dir_fd is not None, it should be a file descriptor open to a directory,\n"
+" and path should be relative; path will then be relative to that directory.\n"
+"dir_fd may not be implemented on your platform.\n"
+" If it is unavailable, using it will raise a NotImplementedError.");
+
+#define OS_MKFIFO_METHODDEF \
+ {"mkfifo", (PyCFunction)os_mkfifo, METH_VARARGS|METH_KEYWORDS, os_mkfifo__doc__},
+
+static PyObject *
+os_mkfifo_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd);
+
+static PyObject *
+os_mkfifo(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"path", "mode", "dir_fd", NULL};
+ path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0);
+ int mode = 438;
+ int dir_fd = DEFAULT_DIR_FD;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O&|i$O&:mkfifo", _keywords,
+ path_converter, &path, &mode, MKFIFOAT_DIR_FD_CONVERTER, &dir_fd))
+ goto exit;
+ return_value = os_mkfifo_impl(module, &path, mode, dir_fd);
+
+exit:
+ /* Cleanup for path */
+ path_cleanup(&path);
+
+ return return_value;
+}
+
+static PyObject *
+os_mkfifo_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd)
+/*[clinic end generated code: output=b3321927546893d0 input=73032e98a36e0e19]*/
+{
+ int result;
+ int async_err = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+#ifdef HAVE_MKFIFOAT
+ if (dir_fd != DEFAULT_DIR_FD)
+ result = mkfifoat(dir_fd, path->narrow, mode);
+ else
+#endif
+ result = mkfifo(path->narrow, mode);
+ Py_END_ALLOW_THREADS
+ } while (result != 0 && errno == EINTR &&
+ !(async_err = PyErr_CheckSignals()));
+ if (result != 0)
+ return (!async_err) ? posix_error() : NULL;
+
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_MKFIFO */
+
+
+#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
+/*[clinic input]
+os.mknod
+
+ path: path_t
+ mode: int=0o600
+ device: dev_t=0
+ *
+ dir_fd: dir_fd(requires='mknodat')=None
+
+Create a node in the file system.
+
+Create a node in the file system (file, device special file or named pipe)
+at path. mode specifies both the permissions to use and the
+type of node to be created, being combined (bitwise OR) with one of
+S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,
+device defines the newly created device special file (probably using
+os.makedev()). Otherwise device is ignored.
+
+If dir_fd is not None, it should be a file descriptor open to a directory,
+ and path should be relative; path will then be relative to that directory.
+dir_fd may not be implemented on your platform.
+ If it is unavailable, using it will raise a NotImplementedError.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_mknod__doc__,
+"mknod($module, /, path, mode=384, device=0, *, dir_fd=None)\n"
+"--\n"
+"\n"
+"Create a node in the file system.\n"
+"\n"
+"Create a node in the file system (file, device special file or named pipe)\n"
+"at path. mode specifies both the permissions to use and the\n"
+"type of node to be created, being combined (bitwise OR) with one of\n"
+"S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,\n"
+"device defines the newly created device special file (probably using\n"
+"os.makedev()). Otherwise device is ignored.\n"
+"\n"
+"If dir_fd is not None, it should be a file descriptor open to a directory,\n"
+" and path should be relative; path will then be relative to that directory.\n"
+"dir_fd may not be implemented on your platform.\n"
+" If it is unavailable, using it will raise a NotImplementedError.");
+
+#define OS_MKNOD_METHODDEF \
+ {"mknod", (PyCFunction)os_mknod, METH_VARARGS|METH_KEYWORDS, os_mknod__doc__},
+
+static PyObject *
+os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, int dir_fd);
+
+static PyObject *
+os_mknod(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"path", "mode", "device", "dir_fd", NULL};
+ path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0);
+ int mode = 384;
+ dev_t device = 0;
+ int dir_fd = DEFAULT_DIR_FD;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O&|iO&$O&:mknod", _keywords,
+ path_converter, &path, &mode, _Py_Dev_Converter, &device, MKNODAT_DIR_FD_CONVERTER, &dir_fd))
+ goto exit;
+ return_value = os_mknod_impl(module, &path, mode, device, dir_fd);
+
+exit:
+ /* Cleanup for path */
+ path_cleanup(&path);
+
+ return return_value;
+}
+
+static PyObject *
+os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, int dir_fd)
+/*[clinic end generated code: output=f71d54eaf9bb6f1a input=ee44531551a4d83b]*/
+{
+ int result;
+ int async_err = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+#ifdef HAVE_MKNODAT
+ if (dir_fd != DEFAULT_DIR_FD)
+ result = mknodat(dir_fd, path->narrow, mode, device);
+ else
+#endif
+ result = mknod(path->narrow, mode, device);
+ Py_END_ALLOW_THREADS
+ } while (result != 0 && errno == EINTR &&
+ !(async_err = PyErr_CheckSignals()));
+ if (result != 0)
+ return (!async_err) ? posix_error() : NULL;
+
+ Py_RETURN_NONE;
+}
+#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
+
+
+#ifdef HAVE_DEVICE_MACROS
+/*[clinic input]
+os.major -> unsigned_int
+
+ device: dev_t
+ /
+
+Extracts a device major number from a raw device number.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_major__doc__,
+"major($module, device, /)\n"
+"--\n"
+"\n"
+"Extracts a device major number from a raw device number.");
+
+#define OS_MAJOR_METHODDEF \
+ {"major", (PyCFunction)os_major, METH_VARARGS, os_major__doc__},
+
+static unsigned int
+os_major_impl(PyModuleDef *module, dev_t device);
+
+static PyObject *
+os_major(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ dev_t device;
+ unsigned int _return_value;
+
+ if (!PyArg_ParseTuple(args,
+ "O&:major",
+ _Py_Dev_Converter, &device))
+ goto exit;
+ _return_value = os_major_impl(module, device);
+ if ((_return_value == (unsigned int)-1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromUnsignedLong((unsigned long)_return_value);
+
+exit:
+ return return_value;
+}
+
+static unsigned int
+os_major_impl(PyModuleDef *module, dev_t device)
+/*[clinic end generated code: output=a2d06e908ebf95b5 input=1e16a4d30c4d4462]*/
+{
+ return major(device);
+}
+
+
+/*[clinic input]
+os.minor -> unsigned_int
+
+ device: dev_t
+ /
+
+Extracts a device minor number from a raw device number.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_minor__doc__,
+"minor($module, device, /)\n"
+"--\n"
+"\n"
+"Extracts a device minor number from a raw device number.");
+
+#define OS_MINOR_METHODDEF \
+ {"minor", (PyCFunction)os_minor, METH_VARARGS, os_minor__doc__},
+
+static unsigned int
+os_minor_impl(PyModuleDef *module, dev_t device);
+
+static PyObject *
+os_minor(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ dev_t device;
+ unsigned int _return_value;
+
+ if (!PyArg_ParseTuple(args,
+ "O&:minor",
+ _Py_Dev_Converter, &device))
+ goto exit;
+ _return_value = os_minor_impl(module, device);
+ if ((_return_value == (unsigned int)-1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromUnsignedLong((unsigned long)_return_value);
+
+exit:
+ return return_value;
+}
+
+static unsigned int
+os_minor_impl(PyModuleDef *module, dev_t device)
+/*[clinic end generated code: output=6332287ee3f006e2 input=0842c6d23f24c65e]*/
+{
+ return minor(device);
+}
+
+
+/*[clinic input]
+os.makedev -> dev_t
+
+ major: int
+ minor: int
+ /
+
+Composes a raw device number from the major and minor device numbers.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_makedev__doc__,
+"makedev($module, major, minor, /)\n"
+"--\n"
+"\n"
+"Composes a raw device number from the major and minor device numbers.");
+
+#define OS_MAKEDEV_METHODDEF \
+ {"makedev", (PyCFunction)os_makedev, METH_VARARGS, os_makedev__doc__},
+
+static dev_t
+os_makedev_impl(PyModuleDef *module, int major, int minor);
+
+static PyObject *
+os_makedev(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int major;
+ int minor;
+ dev_t _return_value;
+
+ if (!PyArg_ParseTuple(args,
+ "ii:makedev",
+ &major, &minor))
+ goto exit;
+ _return_value = os_makedev_impl(module, major, minor);
+ if ((_return_value == (dev_t)-1) && PyErr_Occurred())
+ goto exit;
+ return_value = _PyLong_FromDev(_return_value);
+
+exit:
+ return return_value;
+}
+
+static dev_t
+os_makedev_impl(PyModuleDef *module, int major, int minor)
+/*[clinic end generated code: output=38e9a9774c96511a input=4b9fd8fc73cbe48f]*/
+{
+ return makedev(major, minor);
+}
+#endif /* HAVE_DEVICE_MACROS */
+
+
+#ifdef HAVE_FTRUNCATE
+/*[clinic input]
+os.ftruncate
+
+ fd: int
+ length: Py_off_t
+ /
+
+Truncate a file, specified by file descriptor, to a specific length.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_ftruncate__doc__,
+"ftruncate($module, fd, length, /)\n"
+"--\n"
+"\n"
+"Truncate a file, specified by file descriptor, to a specific length.");
+
+#define OS_FTRUNCATE_METHODDEF \
+ {"ftruncate", (PyCFunction)os_ftruncate, METH_VARARGS, os_ftruncate__doc__},
+
+static PyObject *
+os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length);
+
+static PyObject *
+os_ftruncate(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ Py_off_t length;
+
+ if (!PyArg_ParseTuple(args,
+ "iO&:ftruncate",
+ &fd, Py_off_t_converter, &length))
+ goto exit;
+ return_value = os_ftruncate_impl(module, fd, length);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length)
+/*[clinic end generated code: output=62326766cb9b76bf input=63b43641e52818f2]*/
+{
+ int result;
+ int async_err = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ result = ftruncate(fd, length);
+ Py_END_ALLOW_THREADS
+ } while (result != 0 && errno == EINTR &&
+ !(async_err = PyErr_CheckSignals()));
+ if (result != 0)
+ return (!async_err) ? posix_error() : NULL;
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_FTRUNCATE */
+
+
+#ifdef HAVE_TRUNCATE
+/*[clinic input]
+os.truncate
+ path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
+ length: Py_off_t
+
+Truncate a file, specified by path, to a specific length.
+
+On some platforms, path may also be specified as an open file descriptor.
+ If this functionality is unavailable, using it raises an exception.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_truncate__doc__,
+"truncate($module, /, path, length)\n"
+"--\n"
+"\n"
+"Truncate a file, specified by path, to a specific length.\n"
+"\n"
+"On some platforms, path may also be specified as an open file descriptor.\n"
+" If this functionality is unavailable, using it raises an exception.");
+
+#define OS_TRUNCATE_METHODDEF \
+ {"truncate", (PyCFunction)os_truncate, METH_VARARGS|METH_KEYWORDS, os_truncate__doc__},
+
+static PyObject *
+os_truncate_impl(PyModuleDef *module, path_t *path, Py_off_t length);
+
+static PyObject *
+os_truncate(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"path", "length", NULL};
+ path_t path = PATH_T_INITIALIZE("truncate", "path", 0, PATH_HAVE_FTRUNCATE);
+ Py_off_t length;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O&O&:truncate", _keywords,
+ path_converter, &path, Py_off_t_converter, &length))
+ goto exit;
+ return_value = os_truncate_impl(module, &path, length);
+
+exit:
+ /* Cleanup for path */
+ path_cleanup(&path);
+
+ return return_value;
+}
+
+static PyObject *
+os_truncate_impl(PyModuleDef *module, path_t *path, Py_off_t length)
+/*[clinic end generated code: output=6bd76262d2e027c6 input=77229cf0b50a9b77]*/
+{
+ int result;
+
+ Py_BEGIN_ALLOW_THREADS
+#ifdef HAVE_FTRUNCATE
+ if (path->fd != -1)
+ result = ftruncate(path->fd, length);
+ else
+#endif
+ result = truncate(path->narrow, length);
+ Py_END_ALLOW_THREADS
+ if (result < 0)
+ return path_error(path);
+
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_TRUNCATE */
+
+
+/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
+ and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
+ defined, which is the case in Python on AIX. AIX bug report:
+ http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
+#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
+# define POSIX_FADVISE_AIX_BUG
+#endif
+
+
+#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
+/*[clinic input]
+os.posix_fallocate
+
+ fd: int
+ offset: Py_off_t
+ length: Py_off_t
+ /
+
+Ensure a file has allocated at least a particular number of bytes on disk.
+
+Ensure that the file specified by fd encompasses a range of bytes
+starting at offset bytes from the beginning and continuing for length bytes.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_posix_fallocate__doc__,
+"posix_fallocate($module, fd, offset, length, /)\n"
+"--\n"
+"\n"
+"Ensure a file has allocated at least a particular number of bytes on disk.\n"
+"\n"
+"Ensure that the file specified by fd encompasses a range of bytes\n"
+"starting at offset bytes from the beginning and continuing for length bytes.");
+
+#define OS_POSIX_FALLOCATE_METHODDEF \
+ {"posix_fallocate", (PyCFunction)os_posix_fallocate, METH_VARARGS, os_posix_fallocate__doc__},
+
+static PyObject *
+os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length);
+
+static PyObject *
+os_posix_fallocate(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ Py_off_t offset;
+ Py_off_t length;
+
+ if (!PyArg_ParseTuple(args,
+ "iO&O&:posix_fallocate",
+ &fd, Py_off_t_converter, &offset, Py_off_t_converter, &length))
+ goto exit;
+ return_value = os_posix_fallocate_impl(module, fd, offset, length);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length)
+/*[clinic end generated code: output=0cd702d2065c79db input=d7a2ef0ab2ca52fb]*/
+{
+ int result;
+ int async_err = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ result = posix_fallocate(fd, offset, length);
+ Py_END_ALLOW_THREADS
+ } while (result != 0 && errno == EINTR &&
+ !(async_err = PyErr_CheckSignals()));
+ if (result != 0)
+ return (!async_err) ? posix_error() : NULL;
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
+
+
+#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
+/*[clinic input]
+os.posix_fadvise
+
+ fd: int
+ offset: Py_off_t
+ length: Py_off_t
+ advice: int
+ /
+
+Announce an intention to access data in a specific pattern.
+
+Announce an intention to access data in a specific pattern, thus allowing
+the kernel to make optimizations.
+The advice applies to the region of the file specified by fd starting at
+offset and continuing for length bytes.
+advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
+POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
+POSIX_FADV_DONTNEED.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_posix_fadvise__doc__,
+"posix_fadvise($module, fd, offset, length, advice, /)\n"
+"--\n"
+"\n"
+"Announce an intention to access data in a specific pattern.\n"
+"\n"
+"Announce an intention to access data in a specific pattern, thus allowing\n"
+"the kernel to make optimizations.\n"
+"The advice applies to the region of the file specified by fd starting at\n"
+"offset and continuing for length bytes.\n"
+"advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n"
+"POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or\n"
+"POSIX_FADV_DONTNEED.");
+
+#define OS_POSIX_FADVISE_METHODDEF \
+ {"posix_fadvise", (PyCFunction)os_posix_fadvise, METH_VARARGS, os_posix_fadvise__doc__},
+
+static PyObject *
+os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length, int advice);
+
+static PyObject *
+os_posix_fadvise(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ Py_off_t offset;
+ Py_off_t length;
+ int advice;
+
+ if (!PyArg_ParseTuple(args,
+ "iO&O&i:posix_fadvise",
+ &fd, Py_off_t_converter, &offset, Py_off_t_converter, &length, &advice))
+ goto exit;
+ return_value = os_posix_fadvise_impl(module, fd, offset, length, advice);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length, int advice)
+/*[clinic end generated code: output=dad93f32c04dd4f7 input=0fbe554edc2f04b5]*/
+{
+ int result;
+ int async_err = 0;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ result = posix_fadvise(fd, offset, length, advice);
+ Py_END_ALLOW_THREADS
+ } while (result != 0 && errno == EINTR &&
+ !(async_err = PyErr_CheckSignals()));
+ if (result != 0)
+ return (!async_err) ? posix_error() : NULL;
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
+
+#ifdef HAVE_PUTENV
+
+/* Save putenv() parameters as values here, so we can collect them when they
+ * get re-set with another call for the same key. */
+static PyObject *posix_putenv_garbage;
+
+static void
+posix_putenv_garbage_setitem(PyObject *name, PyObject *value)
+{
+ /* Install the first arg and newstr in posix_putenv_garbage;
+ * this will cause previous value to be collected. This has to
+ * happen after the real putenv() call because the old value
+ * was still accessible until then. */
+ if (PyDict_SetItem(posix_putenv_garbage, name, value))
+ /* really not much we can do; just leak */
+ PyErr_Clear();
+ else
+ Py_DECREF(value);
+}
+
+
+#ifdef MS_WINDOWS
+/*[clinic input]
+os.putenv
+
+ name: unicode
+ value: unicode
+ /
+
+Change or add an environment variable.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_putenv__doc__,
+"putenv($module, name, value, /)\n"
+"--\n"
+"\n"
+"Change or add an environment variable.");
+
+#define OS_PUTENV_METHODDEF \
+ {"putenv", (PyCFunction)os_putenv, METH_VARARGS, os_putenv__doc__},
+
+static PyObject *
+os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value);
+
+static PyObject *
+os_putenv(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *name;
+ PyObject *value;
+
+ if (!PyArg_ParseTuple(args,
+ "UU:putenv",
+ &name, &value))
+ goto exit;
+ return_value = os_putenv_impl(module, name, value);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value)
+/*[clinic end generated code: output=5ce9ef9b15606e7e input=ba586581c2e6105f]*/
+{
+ wchar_t *env;
+
+ PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value);
+ if (unicode == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ if (_MAX_ENV < PyUnicode_GET_LENGTH(unicode)) {
+ PyErr_Format(PyExc_ValueError,
+ "the environment variable is longer than %u characters",
+ _MAX_ENV);
+ goto error;
+ }
+
+ env = PyUnicode_AsUnicode(unicode);
+ if (env == NULL)
+ goto error;
+ if (_wputenv(env)) {
+ posix_error();
+ goto error;
+ }
+
+ posix_putenv_garbage_setitem(name, unicode);
+ Py_RETURN_NONE;
+
+error:
+ Py_DECREF(unicode);
+ return NULL;
+}
+#else /* MS_WINDOWS */
+/*[clinic input]
+os.putenv
+
+ name: FSConverter
+ value: FSConverter
+ /
+
+Change or add an environment variable.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_putenv__doc__,
+"putenv($module, name, value, /)\n"
+"--\n"
+"\n"
+"Change or add an environment variable.");
+
+#define OS_PUTENV_METHODDEF \
+ {"putenv", (PyCFunction)os_putenv, METH_VARARGS, os_putenv__doc__},
+
+static PyObject *
+os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value);
+
+static PyObject *
+os_putenv(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *name = NULL;
+ PyObject *value = NULL;
+
+ if (!PyArg_ParseTuple(args,
+ "O&O&:putenv",
+ PyUnicode_FSConverter, &name, PyUnicode_FSConverter, &value))
+ goto exit;
+ return_value = os_putenv_impl(module, name, value);
+
+exit:
+ /* Cleanup for name */
+ Py_XDECREF(name);
+ /* Cleanup for value */
+ Py_XDECREF(value);
+
+ return return_value;
+}
+
+static PyObject *
+os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value)
+/*[clinic end generated code: output=85ab223393dc7afd input=a97bc6152f688d31]*/
+{
+ PyObject *bytes = NULL;
+ char *env;
+ char *name_string = PyBytes_AsString(name);
+ char *value_string = PyBytes_AsString(value);
+
+ bytes = PyBytes_FromFormat("%s=%s", name_string, value_string);
+ if (bytes == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ env = PyBytes_AS_STRING(bytes);
+ if (putenv(env)) {
+ Py_DECREF(bytes);
+ return posix_error();
+ }
+
+ posix_putenv_garbage_setitem(name, bytes);
+ Py_RETURN_NONE;
+}
+#endif /* MS_WINDOWS */
+#endif /* HAVE_PUTENV */
+
+
+#ifdef HAVE_UNSETENV
+/*[clinic input]
+os.unsetenv
+ name: FSConverter
+ /
+
+Delete an environment variable.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_unsetenv__doc__,
+"unsetenv($module, name, /)\n"
+"--\n"
+"\n"
+"Delete an environment variable.");
+
+#define OS_UNSETENV_METHODDEF \
+ {"unsetenv", (PyCFunction)os_unsetenv, METH_VARARGS, os_unsetenv__doc__},
+
+static PyObject *
+os_unsetenv_impl(PyModuleDef *module, PyObject *name);
+
+static PyObject *
+os_unsetenv(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ PyObject *name = NULL;
+
+ if (!PyArg_ParseTuple(args,
+ "O&:unsetenv",
+ PyUnicode_FSConverter, &name))
+ goto exit;
+ return_value = os_unsetenv_impl(module, name);
+
+exit:
+ /* Cleanup for name */
+ Py_XDECREF(name);
+
+ return return_value;
+}
+
+static PyObject *
+os_unsetenv_impl(PyModuleDef *module, PyObject *name)
+/*[clinic end generated code: output=91318c995f9a0767 input=2bb5288a599c7107]*/
+{
+#ifndef HAVE_BROKEN_UNSETENV
+ int err;
+#endif
+
+#ifdef HAVE_BROKEN_UNSETENV
+ unsetenv(PyBytes_AS_STRING(name));
+#else
+ err = unsetenv(PyBytes_AS_STRING(name));
+ if (err)
+ return posix_error();
+#endif
+
+ /* Remove the key from posix_putenv_garbage;
+ * this will cause it to be collected. This has to
+ * happen after the real unsetenv() call because the
+ * old value was still accessible until then.
+ */
+ if (PyDict_DelItem(posix_putenv_garbage, name)) {
+ /* really not much we can do; just leak */
+ PyErr_Clear();
+ }
+ Py_RETURN_NONE;
+}
+#endif /* HAVE_UNSETENV */
+
+
+/*[clinic input]
+os.strerror
+
+ code: int
+ /
+
+Translate an error code to a message string.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_strerror__doc__,
+"strerror($module, code, /)\n"
+"--\n"
+"\n"
+"Translate an error code to a message string.");
+
+#define OS_STRERROR_METHODDEF \
+ {"strerror", (PyCFunction)os_strerror, METH_VARARGS, os_strerror__doc__},
+
+static PyObject *
+os_strerror_impl(PyModuleDef *module, int code);
+
+static PyObject *
+os_strerror(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int code;
+
+ if (!PyArg_ParseTuple(args,
+ "i:strerror",
+ &code))
+ goto exit;
+ return_value = os_strerror_impl(module, code);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_strerror_impl(PyModuleDef *module, int code)
+/*[clinic end generated code: output=8665c70bb2ca4720 input=75a8673d97915a91]*/
+{
+ char *message = strerror(code);
+ if (message == NULL) {
+ PyErr_SetString(PyExc_ValueError,
+ "strerror() argument out of range");
+ return NULL;
+ }
+ return PyUnicode_DecodeLocale(message, "surrogateescape");
+}
+
+
+#ifdef HAVE_SYS_WAIT_H
+#ifdef WCOREDUMP
+/*[clinic input]
+os.WCOREDUMP -> bool
+
+ status: int
+ /
+
+Return True if the process returning status was dumped to a core file.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_WCOREDUMP__doc__,
+"WCOREDUMP($module, status, /)\n"
+"--\n"
+"\n"
+"Return True if the process returning status was dumped to a core file.");
+
+#define OS_WCOREDUMP_METHODDEF \
+ {"WCOREDUMP", (PyCFunction)os_WCOREDUMP, METH_VARARGS, os_WCOREDUMP__doc__},
+
+static int
+os_WCOREDUMP_impl(PyModuleDef *module, int status);
+
+static PyObject *
+os_WCOREDUMP(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int status;
+ int _return_value;
+
+ if (!PyArg_ParseTuple(args,
+ "i:WCOREDUMP",
+ &status))
+ goto exit;
+ _return_value = os_WCOREDUMP_impl(module, status);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyBool_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+static int
+os_WCOREDUMP_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=e04d55c09c299828 input=8b05e7ab38528d04]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WCOREDUMP(wait_status);
+}
+#endif /* WCOREDUMP */
+
+
+#ifdef WIFCONTINUED
+/*[clinic input]
+os.WIFCONTINUED -> bool
+
+ status: int
+
+Return True if a particular process was continued from a job control stop.
+
+Return True if the process returning status was continued from a
+job control stop.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_WIFCONTINUED__doc__,
+"WIFCONTINUED($module, /, status)\n"
+"--\n"
+"\n"
+"Return True if a particular process was continued from a job control stop.\n"
+"\n"
+"Return True if the process returning status was continued from a\n"
+"job control stop.");
+
+#define OS_WIFCONTINUED_METHODDEF \
+ {"WIFCONTINUED", (PyCFunction)os_WIFCONTINUED, METH_VARARGS|METH_KEYWORDS, os_WIFCONTINUED__doc__},
+
+static int
+os_WIFCONTINUED_impl(PyModuleDef *module, int status);
+
+static PyObject *
+os_WIFCONTINUED(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"status", NULL};
+ int status;
+ int _return_value;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "i:WIFCONTINUED", _keywords,
+ &status))
+ goto exit;
+ _return_value = os_WIFCONTINUED_impl(module, status);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyBool_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+static int
+os_WIFCONTINUED_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=9c4e6105a4520ab5 input=e777e7d38eb25bd9]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WIFCONTINUED(wait_status);
+}
+#endif /* WIFCONTINUED */
+
+
+#ifdef WIFSTOPPED
+/*[clinic input]
+os.WIFSTOPPED -> bool
+
+ status: int
+
+Return True if the process returning status was stopped.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_WIFSTOPPED__doc__,
+"WIFSTOPPED($module, /, status)\n"
+"--\n"
+"\n"
+"Return True if the process returning status was stopped.");
+
+#define OS_WIFSTOPPED_METHODDEF \
+ {"WIFSTOPPED", (PyCFunction)os_WIFSTOPPED, METH_VARARGS|METH_KEYWORDS, os_WIFSTOPPED__doc__},
+
+static int
+os_WIFSTOPPED_impl(PyModuleDef *module, int status);
+
+static PyObject *
+os_WIFSTOPPED(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"status", NULL};
+ int status;
+ int _return_value;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "i:WIFSTOPPED", _keywords,
+ &status))
+ goto exit;
+ _return_value = os_WIFSTOPPED_impl(module, status);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyBool_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+static int
+os_WIFSTOPPED_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=e0de2da8ec9593ff input=043cb7f1289ef904]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WIFSTOPPED(wait_status);
+}
+#endif /* WIFSTOPPED */
+
+
+#ifdef WIFSIGNALED
+/*[clinic input]
+os.WIFSIGNALED -> bool
+
+ status: int
+
+Return True if the process returning status was terminated by a signal.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_WIFSIGNALED__doc__,
+"WIFSIGNALED($module, /, status)\n"
+"--\n"
+"\n"
+"Return True if the process returning status was terminated by a signal.");
+
+#define OS_WIFSIGNALED_METHODDEF \
+ {"WIFSIGNALED", (PyCFunction)os_WIFSIGNALED, METH_VARARGS|METH_KEYWORDS, os_WIFSIGNALED__doc__},
+
+static int
+os_WIFSIGNALED_impl(PyModuleDef *module, int status);
+
+static PyObject *
+os_WIFSIGNALED(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"status", NULL};
+ int status;
+ int _return_value;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "i:WIFSIGNALED", _keywords,
+ &status))
+ goto exit;
+ _return_value = os_WIFSIGNALED_impl(module, status);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyBool_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+static int
+os_WIFSIGNALED_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=f14d106558f406be input=d55ba7cc9ce5dc43]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WIFSIGNALED(wait_status);
+}
+#endif /* WIFSIGNALED */
+
+
+#ifdef WIFEXITED
+/*[clinic input]
+os.WIFEXITED -> bool
+
+ status: int
+
+Return True if the process returning status exited via the exit() system call.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_WIFEXITED__doc__,
+"WIFEXITED($module, /, status)\n"
+"--\n"
+"\n"
+"Return True if the process returning status exited via the exit() system call.");
+
+#define OS_WIFEXITED_METHODDEF \
+ {"WIFEXITED", (PyCFunction)os_WIFEXITED, METH_VARARGS|METH_KEYWORDS, os_WIFEXITED__doc__},
+
+static int
+os_WIFEXITED_impl(PyModuleDef *module, int status);
+
+static PyObject *
+os_WIFEXITED(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"status", NULL};
+ int status;
+ int _return_value;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "i:WIFEXITED", _keywords,
+ &status))
+ goto exit;
+ _return_value = os_WIFEXITED_impl(module, status);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyBool_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+static int
+os_WIFEXITED_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=2f76087d53721255 input=d63775a6791586c0]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WIFEXITED(wait_status);
+}
+#endif /* WIFEXITED */
+
+
+#ifdef WEXITSTATUS
+/*[clinic input]
+os.WEXITSTATUS -> int
+
+ status: int
+
+Return the process return code from status.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_WEXITSTATUS__doc__,
+"WEXITSTATUS($module, /, status)\n"
+"--\n"
+"\n"
+"Return the process return code from status.");
+
+#define OS_WEXITSTATUS_METHODDEF \
+ {"WEXITSTATUS", (PyCFunction)os_WEXITSTATUS, METH_VARARGS|METH_KEYWORDS, os_WEXITSTATUS__doc__},
+
+static int
+os_WEXITSTATUS_impl(PyModuleDef *module, int status);
+
+static PyObject *
+os_WEXITSTATUS(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"status", NULL};
+ int status;
+ int _return_value;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "i:WEXITSTATUS", _keywords,
+ &status))
+ goto exit;
+ _return_value = os_WEXITSTATUS_impl(module, status);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+static int
+os_WEXITSTATUS_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=13b6c270e2a326b1 input=e1fb4944e377585b]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WEXITSTATUS(wait_status);
+}
+#endif /* WEXITSTATUS */
+
+
+#ifdef WTERMSIG
+/*[clinic input]
+os.WTERMSIG -> int
+
+ status: int
+
+Return the signal that terminated the process that provided the status value.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_WTERMSIG__doc__,
+"WTERMSIG($module, /, status)\n"
+"--\n"
+"\n"
+"Return the signal that terminated the process that provided the status value.");
+
+#define OS_WTERMSIG_METHODDEF \
+ {"WTERMSIG", (PyCFunction)os_WTERMSIG, METH_VARARGS|METH_KEYWORDS, os_WTERMSIG__doc__},
+
+static int
+os_WTERMSIG_impl(PyModuleDef *module, int status);
+
+static PyObject *
+os_WTERMSIG(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"status", NULL};
+ int status;
+ int _return_value;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "i:WTERMSIG", _keywords,
+ &status))
+ goto exit;
+ _return_value = os_WTERMSIG_impl(module, status);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+static int
+os_WTERMSIG_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=bf1fd4b002d0a9ed input=727fd7f84ec3f243]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WTERMSIG(wait_status);
+}
+#endif /* WTERMSIG */
+
+
+#ifdef WSTOPSIG
+/*[clinic input]
+os.WSTOPSIG -> int
+
+ status: int
+
+Return the signal that stopped the process that provided the status value.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_WSTOPSIG__doc__,
+"WSTOPSIG($module, /, status)\n"
+"--\n"
+"\n"
+"Return the signal that stopped the process that provided the status value.");
+
+#define OS_WSTOPSIG_METHODDEF \
+ {"WSTOPSIG", (PyCFunction)os_WSTOPSIG, METH_VARARGS|METH_KEYWORDS, os_WSTOPSIG__doc__},
+
+static int
+os_WSTOPSIG_impl(PyModuleDef *module, int status);
+
+static PyObject *
+os_WSTOPSIG(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"status", NULL};
+ int status;
+ int _return_value;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "i:WSTOPSIG", _keywords,
+ &status))
+ goto exit;
+ _return_value = os_WSTOPSIG_impl(module, status);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromLong((long)_return_value);
+
+exit:
+ return return_value;
+}
+
+static int
+os_WSTOPSIG_impl(PyModuleDef *module, int status)
+/*[clinic end generated code: output=92e1647d29ee0549 input=46ebf1d1b293c5c1]*/
+{
+ WAIT_TYPE wait_status;
+ WAIT_STATUS_INT(wait_status) = status;
+ return WSTOPSIG(wait_status);
+}
+#endif /* WSTOPSIG */
+#endif /* HAVE_SYS_WAIT_H */
+
+
+#ifndef OS_WCOREDUMP_METHODDEF
+#define OS_WCOREDUMP_METHODDEF
+#endif /* OS_WCOREDUMP_METHODDEF */
+
+#ifndef OS_WIFCONTINUED_METHODDEF
+#define OS_WIFCONTINUED_METHODDEF
+#endif /* OS_WIFCONTINUED_METHODDEF */
+
+#ifndef OS_WIFSTOPPED_METHODDEF
+#define OS_WIFSTOPPED_METHODDEF
+#endif /* OS_WIFSTOPPED_METHODDEF */
+
+#ifndef OS_WIFSIGNALED_METHODDEF
+#define OS_WIFSIGNALED_METHODDEF
+#endif /* OS_WIFSIGNALED_METHODDEF */
+
+#ifndef OS_WIFEXITED_METHODDEF
+#define OS_WIFEXITED_METHODDEF
+#endif /* OS_WIFEXITED_METHODDEF */
+
+#ifndef OS_WEXITSTATUS_METHODDEF
+#define OS_WEXITSTATUS_METHODDEF
+#endif /* OS_WEXITSTATUS_METHODDEF */
+
+#ifndef OS_WTERMSIG_METHODDEF
+#define OS_WTERMSIG_METHODDEF
+#endif /* OS_WTERMSIG_METHODDEF */
+
+#ifndef OS_WSTOPSIG_METHODDEF
+#define OS_WSTOPSIG_METHODDEF
+#endif /* OS_WSTOPSIG_METHODDEF */
+
+
+#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
+#ifdef _SCO_DS
+/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
+ needed definitions in sys/statvfs.h */
+#define _SVID3
+#endif
+#include <sys/statvfs.h>
+
+static PyObject*
+_pystatvfs_fromstructstatvfs(struct statvfs st) {
+ PyObject *v = PyStructSequence_New(&StatVFSResultType);
+ if (v == NULL)
+ return NULL;
+
+#if !defined(HAVE_LARGEFILE_SUPPORT)
+ PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
+ PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
+ PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
+ PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
+ PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
+ PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
+ PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
+ PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
+ PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
+ PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
+#else
+ PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
+ PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
+ PyStructSequence_SET_ITEM(v, 2,
+ PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
+ PyStructSequence_SET_ITEM(v, 3,
+ PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
+ PyStructSequence_SET_ITEM(v, 4,
+ PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
+ PyStructSequence_SET_ITEM(v, 5,
+ PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
+ PyStructSequence_SET_ITEM(v, 6,
+ PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
+ PyStructSequence_SET_ITEM(v, 7,
+ PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
+ PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
+ PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
+#endif
+ if (PyErr_Occurred()) {
+ Py_DECREF(v);
+ return NULL;
+ }
+
+ return v;
+}
+
+
+/*[clinic input]
+os.fstatvfs
+ fd: int
+ /
+
+Perform an fstatvfs system call on the given fd.
+
+Equivalent to statvfs(fd).
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_fstatvfs__doc__,
+"fstatvfs($module, fd, /)\n"
+"--\n"
+"\n"
+"Perform an fstatvfs system call on the given fd.\n"
+"\n"
+"Equivalent to statvfs(fd).");
+
+#define OS_FSTATVFS_METHODDEF \
+ {"fstatvfs", (PyCFunction)os_fstatvfs, METH_VARARGS, os_fstatvfs__doc__},
+
+static PyObject *
+os_fstatvfs_impl(PyModuleDef *module, int fd);
+
+static PyObject *
+os_fstatvfs(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+
+ if (!PyArg_ParseTuple(args,
+ "i:fstatvfs",
+ &fd))
+ goto exit;
+ return_value = os_fstatvfs_impl(module, fd);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_fstatvfs_impl(PyModuleDef *module, int fd)
+/*[clinic end generated code: output=0e32bf07f946ec0d input=d8122243ac50975e]*/
+{
+ int result;
+ int async_err = 0;
+ struct statvfs st;
+
+ do {
+ Py_BEGIN_ALLOW_THREADS
+ result = fstatvfs(fd, &st);
+ Py_END_ALLOW_THREADS
+ } while (result != 0 && errno == EINTR &&
+ !(async_err = PyErr_CheckSignals()));
+ if (result != 0)
+ return (!async_err) ? posix_error() : NULL;
+
+ return _pystatvfs_fromstructstatvfs(st);
+}
+#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
+
+
+#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
+#include <sys/statvfs.h>
+/*[clinic input]
+os.statvfs
+
+ path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
+
+Perform a statvfs system call on the given path.
+
+path may always be specified as a string.
+On some platforms, path may also be specified as an open file descriptor.
+ If this functionality is unavailable, using it raises an exception.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_statvfs__doc__,
+"statvfs($module, /, path)\n"
+"--\n"
+"\n"
+"Perform a statvfs system call on the given path.\n"
+"\n"
+"path may always be specified as a string.\n"
+"On some platforms, path may also be specified as an open file descriptor.\n"
+" If this functionality is unavailable, using it raises an exception.");
+
+#define OS_STATVFS_METHODDEF \
+ {"statvfs", (PyCFunction)os_statvfs, METH_VARARGS|METH_KEYWORDS, os_statvfs__doc__},
+
+static PyObject *
+os_statvfs_impl(PyModuleDef *module, path_t *path);
+
+static PyObject *
+os_statvfs(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"path", NULL};
+ path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, PATH_HAVE_FSTATVFS);
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O&:statvfs", _keywords,
+ path_converter, &path))
+ goto exit;
+ return_value = os_statvfs_impl(module, &path);
+
+exit:
+ /* Cleanup for path */
+ path_cleanup(&path);
+
+ return return_value;
+}
+
+static PyObject *
+os_statvfs_impl(PyModuleDef *module, path_t *path)
+/*[clinic end generated code: output=00ff54983360b446 input=3f5c35791c669bd9]*/
+{
+ int result;
+ struct statvfs st;
+
+ Py_BEGIN_ALLOW_THREADS
+#ifdef HAVE_FSTATVFS
+ if (path->fd != -1) {
+#ifdef __APPLE__
+ /* handle weak-linking on Mac OS X 10.3 */
+ if (fstatvfs == NULL) {
+ fd_specified("statvfs", path->fd);
+ return NULL;
+ }
+#endif
+ result = fstatvfs(path->fd, &st);
+ }
+ else
+#endif
+ result = statvfs(path->narrow, &st);
+ Py_END_ALLOW_THREADS
+
+ if (result) {
+ return path_error(path);
+ }
+
+ return _pystatvfs_fromstructstatvfs(st);
+}
+#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
+
+
+#ifdef MS_WINDOWS
+/*[clinic input]
+os._getdiskusage
+
+ path: Py_UNICODE
+
+Return disk usage statistics about the given path as a (total, free) tuple.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os__getdiskusage__doc__,
+"_getdiskusage($module, /, path)\n"
+"--\n"
+"\n"
+"Return disk usage statistics about the given path as a (total, free) tuple.");
+
+#define OS__GETDISKUSAGE_METHODDEF \
+ {"_getdiskusage", (PyCFunction)os__getdiskusage, METH_VARARGS|METH_KEYWORDS, os__getdiskusage__doc__},
+
+static PyObject *
+os__getdiskusage_impl(PyModuleDef *module, Py_UNICODE *path);
+
+static PyObject *
+os__getdiskusage(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"path", NULL};
+ Py_UNICODE *path;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "u:_getdiskusage", _keywords,
+ &path))
+ goto exit;
+ return_value = os__getdiskusage_impl(module, path);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os__getdiskusage_impl(PyModuleDef *module, Py_UNICODE *path)
+/*[clinic end generated code: output=054c972179b13708 input=6458133aed893c78]*/
+{
+ BOOL retval;
+ ULARGE_INTEGER _, total, free;
+
+ Py_BEGIN_ALLOW_THREADS
+ retval = GetDiskFreeSpaceExW(path, &_, &total, &free);
+ Py_END_ALLOW_THREADS
+ if (retval == 0)
+ return PyErr_SetFromWindowsErr(0);
+
+ return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
+}
+#endif /* MS_WINDOWS */
+
+
+/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
+ * It maps strings representing configuration variable names to
+ * integer values, allowing those functions to be called with the
+ * magic names instead of polluting the module's namespace with tons of
+ * rarely-used constants. There are three separate tables that use
+ * these definitions.
+ *
+ * This code is always included, even if none of the interfaces that
+ * need it are included. The #if hackery needed to avoid it would be
+ * sufficiently pervasive that it's not worth the loss of readability.
+ */
+struct constdef {
+ char *name;
+ long value;
+};
+
+static int
+conv_confname(PyObject *arg, int *valuep, struct constdef *table,
+ size_t tablesize)
+{
+ if (PyLong_Check(arg)) {
+ *valuep = PyLong_AS_LONG(arg);
+ return 1;
+ }
+ else {
+ /* look up the value in the table using a binary search */
+ size_t lo = 0;
+ size_t mid;
+ size_t hi = tablesize;
+ int cmp;
+ const char *confname;
+ if (!PyUnicode_Check(arg)) {
+ PyErr_SetString(PyExc_TypeError,
+ "configuration names must be strings or integers");
+ return 0;
+ }
+ confname = _PyUnicode_AsString(arg);
+ if (confname == NULL)
+ return 0;
+ while (lo < hi) {
+ mid = (lo + hi) / 2;
+ cmp = strcmp(confname, table[mid].name);
+ if (cmp < 0)
+ hi = mid;
+ else if (cmp > 0)
+ lo = mid + 1;
+ else {
+ *valuep = table[mid].value;
+ return 1;
+ }
+ }
+ PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
+ return 0;
+ }
+}
+
+
+#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
+static struct constdef posix_constants_pathconf[] = {
+#ifdef _PC_ABI_AIO_XFER_MAX
+ {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
+#endif
+#ifdef _PC_ABI_ASYNC_IO
+ {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
+#endif
+#ifdef _PC_ASYNC_IO
+ {"PC_ASYNC_IO", _PC_ASYNC_IO},
+#endif
+#ifdef _PC_CHOWN_RESTRICTED
+ {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
+#endif
+#ifdef _PC_FILESIZEBITS
+ {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
+#endif
+#ifdef _PC_LAST
+ {"PC_LAST", _PC_LAST},
+#endif
+#ifdef _PC_LINK_MAX
+ {"PC_LINK_MAX", _PC_LINK_MAX},
+#endif
+#ifdef _PC_MAX_CANON
+ {"PC_MAX_CANON", _PC_MAX_CANON},
+#endif
+#ifdef _PC_MAX_INPUT
+ {"PC_MAX_INPUT", _PC_MAX_INPUT},
+#endif
+#ifdef _PC_NAME_MAX
+ {"PC_NAME_MAX", _PC_NAME_MAX},
+#endif
+#ifdef _PC_NO_TRUNC
+ {"PC_NO_TRUNC", _PC_NO_TRUNC},
+#endif
+#ifdef _PC_PATH_MAX
+ {"PC_PATH_MAX", _PC_PATH_MAX},
+#endif
+#ifdef _PC_PIPE_BUF
+ {"PC_PIPE_BUF", _PC_PIPE_BUF},
+#endif
+#ifdef _PC_PRIO_IO
+ {"PC_PRIO_IO", _PC_PRIO_IO},
+#endif
+#ifdef _PC_SOCK_MAXBUF
+ {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
+#endif
+#ifdef _PC_SYNC_IO
+ {"PC_SYNC_IO", _PC_SYNC_IO},
+#endif
+#ifdef _PC_VDISABLE
+ {"PC_VDISABLE", _PC_VDISABLE},
+#endif
+#ifdef _PC_ACL_ENABLED
+ {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
+#endif
+#ifdef _PC_MIN_HOLE_SIZE
+ {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
+#endif
+#ifdef _PC_ALLOC_SIZE_MIN
+ {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
+#endif
+#ifdef _PC_REC_INCR_XFER_SIZE
+ {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
+#endif
+#ifdef _PC_REC_MAX_XFER_SIZE
+ {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
+#endif
+#ifdef _PC_REC_MIN_XFER_SIZE
+ {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
+#endif
+#ifdef _PC_REC_XFER_ALIGN
+ {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
+#endif
+#ifdef _PC_SYMLINK_MAX
+ {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
+#endif
+#ifdef _PC_XATTR_ENABLED
+ {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
+#endif
+#ifdef _PC_XATTR_EXISTS
+ {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
+#endif
+#ifdef _PC_TIMESTAMP_RESOLUTION
+ {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
+#endif
+};
+
+static int
+conv_path_confname(PyObject *arg, int *valuep)
+{
+ return conv_confname(arg, valuep, posix_constants_pathconf,
+ sizeof(posix_constants_pathconf)
+ / sizeof(struct constdef));
+}
+#endif
+
+
+#ifdef HAVE_FPATHCONF
+/*[clinic input]
+os.fpathconf -> long
+
+ fd: int
+ name: path_confname
+ /
+
+Return the configuration limit name for the file descriptor fd.
+
+If there is no limit, return -1.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_fpathconf__doc__,
+"fpathconf($module, fd, name, /)\n"
+"--\n"
+"\n"
+"Return the configuration limit name for the file descriptor fd.\n"
+"\n"
+"If there is no limit, return -1.");
+
+#define OS_FPATHCONF_METHODDEF \
+ {"fpathconf", (PyCFunction)os_fpathconf, METH_VARARGS, os_fpathconf__doc__},
+
+static long
+os_fpathconf_impl(PyModuleDef *module, int fd, int name);
+
+static PyObject *
+os_fpathconf(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int fd;
+ int name;
+ long _return_value;
+
+ if (!PyArg_ParseTuple(args,
+ "iO&:fpathconf",
+ &fd, conv_path_confname, &name))
+ goto exit;
+ _return_value = os_fpathconf_impl(module, fd, name);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromLong(_return_value);
+
+exit:
+ return return_value;
+}
+
+static long
+os_fpathconf_impl(PyModuleDef *module, int fd, int name)
+/*[clinic end generated code: output=3bf04b40e0523a8c input=5942a024d3777810]*/
+{
+ long limit;
+
+ errno = 0;
+ limit = fpathconf(fd, name);
+ if (limit == -1 && errno != 0)
+ posix_error();
+
+ return limit;
+}
+#endif /* HAVE_FPATHCONF */
+
+
+#ifdef HAVE_PATHCONF
+/*[clinic input]
+os.pathconf -> long
+ path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
+ name: path_confname
+
+Return the configuration limit name for the file or directory path.
+
+If there is no limit, return -1.
+On some platforms, path may also be specified as an open file descriptor.
+ If this functionality is unavailable, using it raises an exception.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_pathconf__doc__,
+"pathconf($module, /, path, name)\n"
+"--\n"
+"\n"
+"Return the configuration limit name for the file or directory path.\n"
+"\n"
+"If there is no limit, return -1.\n"
+"On some platforms, path may also be specified as an open file descriptor.\n"
+" If this functionality is unavailable, using it raises an exception.");
+
+#define OS_PATHCONF_METHODDEF \
+ {"pathconf", (PyCFunction)os_pathconf, METH_VARARGS|METH_KEYWORDS, os_pathconf__doc__},
+
+static long
+os_pathconf_impl(PyModuleDef *module, path_t *path, int name);
+
+static PyObject *
+os_pathconf(PyModuleDef *module, PyObject *args, PyObject *kwargs)
+{
+ PyObject *return_value = NULL;
+ static char *_keywords[] = {"path", "name", NULL};
+ path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, PATH_HAVE_FPATHCONF);
+ int name;
+ long _return_value;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O&O&:pathconf", _keywords,
+ path_converter, &path, conv_path_confname, &name))
+ goto exit;
+ _return_value = os_pathconf_impl(module, &path, name);
+ if ((_return_value == -1) && PyErr_Occurred())
+ goto exit;
+ return_value = PyLong_FromLong(_return_value);
+
+exit:
+ /* Cleanup for path */
+ path_cleanup(&path);
+
+ return return_value;
+}
+
+static long
+os_pathconf_impl(PyModuleDef *module, path_t *path, int name)
+/*[clinic end generated code: output=1a53e125b6cf63e4 input=bc3e2a985af27e5e]*/
+{
+ long limit;
+
+ errno = 0;
+#ifdef HAVE_FPATHCONF
+ if (path->fd != -1)
+ limit = fpathconf(path->fd, name);
+ else
+#endif
+ limit = pathconf(path->narrow, name);
+ if (limit == -1 && errno != 0) {
+ if (errno == EINVAL)
+ /* could be a path or name problem */
+ posix_error();
+ else
+ path_error(path);
+ }
+
+ return limit;
+}
+#endif /* HAVE_PATHCONF */
+
+#ifdef HAVE_CONFSTR
+static struct constdef posix_constants_confstr[] = {
+#ifdef _CS_ARCHITECTURE
+ {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
+#endif
+#ifdef _CS_GNU_LIBC_VERSION
+ {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
+#endif
+#ifdef _CS_GNU_LIBPTHREAD_VERSION
+ {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
+#endif
+#ifdef _CS_HOSTNAME
+ {"CS_HOSTNAME", _CS_HOSTNAME},
+#endif
+#ifdef _CS_HW_PROVIDER
+ {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
+#endif
+#ifdef _CS_HW_SERIAL
+ {"CS_HW_SERIAL", _CS_HW_SERIAL},
+#endif
+#ifdef _CS_INITTAB_NAME
+ {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
+#endif
+#ifdef _CS_LFS64_CFLAGS
+ {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
+#endif
+#ifdef _CS_LFS64_LDFLAGS
+ {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
+#endif
+#ifdef _CS_LFS64_LIBS
+ {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
+#endif
+#ifdef _CS_LFS64_LINTFLAGS
+ {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
+#endif
+#ifdef _CS_LFS_CFLAGS
+ {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
+#endif
+#ifdef _CS_LFS_LDFLAGS
+ {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
+#endif
+#ifdef _CS_LFS_LIBS
+ {"CS_LFS_LIBS", _CS_LFS_LIBS},
+#endif
+#ifdef _CS_LFS_LINTFLAGS
+ {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
+#endif
+#ifdef _CS_MACHINE
+ {"CS_MACHINE", _CS_MACHINE},
+#endif
+#ifdef _CS_PATH
+ {"CS_PATH", _CS_PATH},
+#endif
+#ifdef _CS_RELEASE
+ {"CS_RELEASE", _CS_RELEASE},
+#endif
+#ifdef _CS_SRPC_DOMAIN
+ {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
+#endif
+#ifdef _CS_SYSNAME
+ {"CS_SYSNAME", _CS_SYSNAME},
+#endif
+#ifdef _CS_VERSION
+ {"CS_VERSION", _CS_VERSION},
+#endif
+#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
+ {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
+#endif
+#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
+ {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
+#endif
+#ifdef _CS_XBS5_ILP32_OFF32_LIBS
+ {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
+#endif
+#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
+ {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
+#endif
+#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
+ {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
+#endif
+#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
+ {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
+#endif
+#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
+ {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
+#endif
+#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
+ {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
+#endif
+#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
+ {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
+#endif
+#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
+ {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
+#endif
+#ifdef _CS_XBS5_LP64_OFF64_LIBS
+ {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
+#endif
+#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
+ {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
+#endif
+#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
+ {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
+#endif
+#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
+ {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
+#endif
+#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
+ {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
+#endif
+#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
+ {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
+#endif
+#ifdef _MIPS_CS_AVAIL_PROCESSORS
+ {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
+#endif
+#ifdef _MIPS_CS_BASE
+ {"MIPS_CS_BASE", _MIPS_CS_BASE},
+#endif
+#ifdef _MIPS_CS_HOSTID
+ {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
+#endif
+#ifdef _MIPS_CS_HW_NAME
+ {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
+#endif
+#ifdef _MIPS_CS_NUM_PROCESSORS
+ {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
+#endif
+#ifdef _MIPS_CS_OSREL_MAJ
+ {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
+#endif
+#ifdef _MIPS_CS_OSREL_MIN
+ {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
+#endif
+#ifdef _MIPS_CS_OSREL_PATCH
+ {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
+#endif
+#ifdef _MIPS_CS_OS_NAME
+ {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
+#endif
+#ifdef _MIPS_CS_OS_PROVIDER
+ {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
+#endif
+#ifdef _MIPS_CS_PROCESSORS
+ {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
+#endif
+#ifdef _MIPS_CS_SERIAL
+ {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
+#endif
+#ifdef _MIPS_CS_VENDOR
+ {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
+#endif
+};
+
+static int
+conv_confstr_confname(PyObject *arg, int *valuep)
+{
+ return conv_confname(arg, valuep, posix_constants_confstr,
+ sizeof(posix_constants_confstr)
+ / sizeof(struct constdef));
+}
+
+
+/*[clinic input]
+os.confstr
+
+ name: confstr_confname
+ /
+
+Return a string-valued system configuration variable.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(os_confstr__doc__,
+"confstr($module, name, /)\n"
+"--\n"
+"\n"
+"Return a string-valued system configuration variable.");
+
+#define OS_CONFSTR_METHODDEF \
+ {"confstr", (PyCFunction)os_confstr, METH_VARARGS, os_confstr__doc__},
+
+static PyObject *
+os_confstr_impl(PyModuleDef *module, int name);
+
+static PyObject *
+os_confstr(PyModuleDef *module, PyObject *args)
+{
+ PyObject *return_value = NULL;
+ int name;
+
+ if (!PyArg_ParseTuple(args,
+ "O&:confstr",
+ conv_confstr_confname, &name))
+ goto exit;
+ return_value = os_confstr_impl(module, name);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+os_confstr_impl(PyModuleDef *module, int name)
+/*[clinic end generated code: output=3f5e8aba9f8e3174 input=18fb4d0567242e65]*/
+{
+ PyObject *result = NULL;
+ char buffer[255];
+ size_t len;
+
+ errno = 0;
+ len = confstr(name, buffer, sizeof(buffer));
+ if (len == 0) {
+ if (errno) {
+ posix_error();
+ return NULL;
+ }
+ else {
+ Py_RETURN_NONE;
+ }
+ }
+
+ if (len >= sizeof(buffer)) {
+ size_t len2;
+ char *buf = PyMem_Malloc(len);
+ if (buf == NULL)
+ return PyErr_NoMemory();
+ len2 = confstr(name, buf, len);
+ assert(len == len2);
+ result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1);
+ PyMem_Free(buf);
+ }
+ else
+ result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
+ return result;
+}
+#endif /* HAVE_CONFSTR */
+
+
+#ifdef HAVE_SYSCONF
+static struct constdef posix_constants_sysconf[] = {
+#ifdef _SC_2_CHAR_TERM
+ {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
+#endif
+#ifdef _SC_2_C_BIND
+ {"SC_2_C_BIND", _SC_2_C_BIND},
+#endif
+#ifdef _SC_2_C_DEV
+ {"SC_2_C_DEV", _SC_2_C_DEV},
+#endif
+#ifdef _SC_2_C_VERSION
+ {"SC_2_C_VERSION", _SC_2_C_VERSION},
+#endif
+#ifdef _SC_2_FORT_DEV
+ {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
+#endif
+#ifdef _SC_2_FORT_RUN
+ {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
+#endif
+#ifdef _SC_2_LOCALEDEF
+ {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
+#endif
+#ifdef _SC_2_SW_DEV
+ {"SC_2_SW_DEV", _SC_2_SW_DEV},
+#endif
+#ifdef _SC_2_UPE
+ {"SC_2_UPE", _SC_2_UPE},
+#endif
+#ifdef _SC_2_VERSION
+ {"SC_2_VERSION", _SC_2_VERSION},
+#endif
+#ifdef _SC_ABI_ASYNCHRONOUS_IO
+ {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
+#endif
+#ifdef _SC_ACL
+ {"SC_ACL", _SC_ACL},
+#endif
+#ifdef _SC_AIO_LISTIO_MAX
+ {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
+#endif
+#ifdef _SC_AIO_MAX
+ {"SC_AIO_MAX", _SC_AIO_MAX},
+#endif
+#ifdef _SC_AIO_PRIO_DELTA_MAX
+ {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
+#endif
+#ifdef _SC_ARG_MAX
+ {"SC_ARG_MAX", _SC_ARG_MAX},
+#endif
+#ifdef _SC_ASYNCHRONOUS_IO
+ {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
+#endif
+#ifdef _SC_ATEXIT_MAX
+ {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
+#endif
+#ifdef _SC_AUDIT
+ {"SC_AUDIT", _SC_AUDIT},
+#endif
+#ifdef _SC_AVPHYS_PAGES
+ {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
+#endif
+#ifdef _SC_BC_BASE_MAX
+ {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
+#endif
+#ifdef _SC_BC_DIM_MAX
+ {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
+#endif
+#ifdef _SC_BC_SCALE_MAX
+ {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
+#endif
+#ifdef _SC_BC_STRING_MAX
+ {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
+#endif
+#ifdef _SC_CAP
+ {"SC_CAP", _SC_CAP},
+#endif
+#ifdef _SC_CHARCLASS_NAME_MAX
+ {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
+#endif
+#ifdef _SC_CHAR_BIT
+ {"SC_CHAR_BIT", _SC_CHAR_BIT},
+#endif
+#ifdef _SC_CHAR_MAX
+ {"SC_CHAR_MAX", _SC_CHAR_MAX},
+#endif
+#ifdef _SC_CHAR_MIN
+ {"SC_CHAR_MIN", _SC_CHAR_MIN},
+#endif
+#ifdef _SC_CHILD_MAX
+ {"SC_CHILD_MAX", _SC_CHILD_MAX},
+#endif
+#ifdef _SC_CLK_TCK
+ {"SC_CLK_TCK", _SC_CLK_TCK},
+#endif
+#ifdef _SC_COHER_BLKSZ
+ {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
+#endif
+#ifdef _SC_COLL_WEIGHTS_MAX
+ {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
+#endif
+#ifdef _SC_DCACHE_ASSOC
+ {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
+#endif
+#ifdef _SC_DCACHE_BLKSZ
+ {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
+#endif
+#ifdef _SC_DCACHE_LINESZ
+ {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
+#endif
+#ifdef _SC_DCACHE_SZ
+ {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
+#endif
+#ifdef _SC_DCACHE_TBLKSZ
+ {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
+#endif
+#ifdef _SC_DELAYTIMER_MAX
+ {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
+#endif
+#ifdef _SC_EQUIV_CLASS_MAX
+ {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
+#endif
+#ifdef _SC_EXPR_NEST_MAX
+ {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
+#endif
+#ifdef _SC_FSYNC
+ {"SC_FSYNC", _SC_FSYNC},
+#endif
+#ifdef _SC_GETGR_R_SIZE_MAX
+ {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
+#endif
+#ifdef _SC_GETPW_R_SIZE_MAX
+ {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
+#endif
+#ifdef _SC_ICACHE_ASSOC
+ {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
+#endif
+#ifdef _SC_ICACHE_BLKSZ
+ {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
+#endif
+#ifdef _SC_ICACHE_LINESZ
+ {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
+#endif
+#ifdef _SC_ICACHE_SZ
+ {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
+#endif
+#ifdef _SC_INF
+ {"SC_INF", _SC_INF},
+#endif
+#ifdef _SC_INT_MAX
+ {"SC_INT_MAX", _SC_INT_MAX},
+#endif
+#ifdef _SC_INT_MIN
+ {"SC_INT_MIN", _SC_INT_MIN},
+#endif
+#ifdef _SC_IOV_MAX
+ {"SC_IOV_MAX", _SC_IOV_MAX},
+#endif
+#ifdef _SC_IP_SECOPTS
+ {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
+#endif
+#ifdef _SC_JOB_CONTROL
+ {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
+#endif
+#ifdef _SC_KERN_POINTERS
+ {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
+#endif
+#ifdef _SC_KERN_SIM
+ {"SC_KERN_SIM", _SC_KERN_SIM},
+#endif
+#ifdef _SC_LINE_MAX
+ {"SC_LINE_MAX", _SC_LINE_MAX},
+#endif
+#ifdef _SC_LOGIN_NAME_MAX
+ {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
+#endif
+#ifdef _SC_LOGNAME_MAX
+ {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
+#endif
+#ifdef _SC_LONG_BIT
+ {"SC_LONG_BIT", _SC_LONG_BIT},
+#endif
+#ifdef _SC_MAC
+ {"SC_MAC", _SC_MAC},
+#endif
+#ifdef _SC_MAPPED_FILES
+ {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
+#endif
+#ifdef _SC_MAXPID
+ {"SC_MAXPID", _SC_MAXPID},
+#endif
+#ifdef _SC_MB_LEN_MAX
+ {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
+#endif
+#ifdef _SC_MEMLOCK
+ {"SC_MEMLOCK", _SC_MEMLOCK},
+#endif
+#ifdef _SC_MEMLOCK_RANGE
+ {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
+#endif
+#ifdef _SC_MEMORY_PROTECTION
+ {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
+#endif
+#ifdef _SC_MESSAGE_PASSING
+ {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
+#endif
+#ifdef _SC_MMAP_FIXED_ALIGNMENT
+ {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
+#endif
+#ifdef _SC_MQ_OPEN_MAX
+ {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
#endif
#ifdef _SC_MQ_PRIO_MAX
{"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},