summaryrefslogtreecommitdiffstats
path: root/Modules/posixmodule.c
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2012-05-06 01:22:14 (GMT)
committerBenjamin Peterson <benjamin@python.org>2012-05-06 01:22:14 (GMT)
commiteaa5eeef57238d8daf2e6a4ca0c622258c8a9c23 (patch)
tree5fd9ed01b383d818d84091f91efa22ce48b1bccb /Modules/posixmodule.c
parentcfe6f2af3cdf485cb376cd313866612796becaae (diff)
downloadcpython-eaa5eeef57238d8daf2e6a4ca0c622258c8a9c23.zip
cpython-eaa5eeef57238d8daf2e6a4ca0c622258c8a9c23.tar.gz
cpython-eaa5eeef57238d8daf2e6a4ca0c622258c8a9c23.tar.bz2
Backed out changeset 709850f1ec67
Diffstat (limited to 'Modules/posixmodule.c')
-rw-r--r--Modules/posixmodule.c364
1 files changed, 31 insertions, 333 deletions
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 7b45154..dc3302c 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -398,268 +398,6 @@ static int win32_can_symlink = 0;
#endif
#endif
-/*
- * De-vararg'd PyArg_ParseTupleAndKeywords()
- */
-typedef struct argument_path_s {
- struct argument_path_s *next;
- PyObject *object;
- char *format;
- wchar_t **wide;
- char **narrow;
- Py_ssize_t *length;
-} argument_path_t;
-
-typedef struct {
- PyObject *args;
- PyObject *kwargs;
- char format[32];
- char *format_trace;
- char *keywords[8];
- int keyword_count;
- PyObject **varargs[16];
- int vararg_count;
- const char *function_name;
- argument_path_t *path_head;
-} argument_parser_table_t;
-
-#define APT_DECLARE(apt, fname) \
- argument_parser_table_t apt; \
- memset(&apt, 0, sizeof(apt)); \
- apt.function_name = fname; \
- apt.args = args; \
- apt.kwargs = kwargs; \
- apt.format_trace = apt.format
-
-#define _APT_ARGUMENT_OBJECT(apt, name, variable, format) \
- *apt.format_trace++ = (format); \
- apt.keywords[apt.keyword_count++] = (name); \
- apt.varargs[apt.vararg_count++] = (PyObject **)(variable); \
-
-#define APT_ARGUMENT_OBJECT(apt, name, variable) \
- _APT_ARGUMENT_OBJECT(apt, name, variable, 'O')
-
-#define APT_ARGUMENT_OBJECT_WITH_CONVERTER(apt, name, variable, converter) \
- apt.varargs[apt.vararg_count++] = (PyObject **)converter; \
- APT_ARGUMENT_OBJECT(apt, name, variable); \
- *apt.format_trace++ = '&'; \
-
-#define APT_ARGUMENT_UNICODE(apt, name, variable) \
- _APT_ARGUMENT_OBJECT(apt, name, variable, 'U')
-
-#define APT_ARGUMENT_BYTES(apt, name, variable) \
- _APT_ARGUMENT_OBJECT(apt, name, variable, 'y')
-
-#define APT_ARGUMENT_INT(apt, name, variable) \
- _APT_ARGUMENT_OBJECT(apt, name, variable, 'i')
-
-static int
-bool_converter(PyObject *object, void *address) {
- int *output = (int *)address;
- int value = PyObject_IsTrue(object);
- if (value == -1)
- return 0;
- *output = value;
- return 1;
-}
-
-#define APT_ARGUMENT_BOOL(apt, name, variable) \
- _APT_ARGUMENT_OBJECT(apt, name, variable, 'p')
-
-#if !MS_WINDOWS
- #define _APT_DEFAULT_PATH_TYPE 'U'
- #define _APT_PATH_BEFORE ;
- #define _APT_PATH_AFTER ;
-#else
- #define _APT_DEFAULT_PATH_TYPE 'O'
- #define _APT_PATH_BEFORE apt.varargs[apt.vararg_count++] = (PyObject **)PyUnicode_FSConverter;
- #define _APT_PATH_AFTER *apt.format_trace++ = '&';
-#endif
-
-#define APT_ARGUMENT_PATH(apt, name, w, n, l) \
- { \
- argument_path_t *_path_ = (argument_path_t *)alloca(sizeof(argument_path_t)); \
- _APT_PATH_BEFORE; \
- memset(_path_, 0, sizeof(*_path_)); \
- _path_->wide = w; \
- _path_->narrow = n; \
- _path_->length = l; \
- _path_->next = apt.path_head; \
- apt.path_head = _path_; \
- _APT_ARGUMENT_OBJECT(apt, name, &_path_->object, _APT_DEFAULT_PATH_TYPE); \
- _APT_PATH_AFTER; \
- } \
-
-#define APT_OPTIONAL(apt) \
- *apt.format_trace++ = '|' \
-
-#define APT_KEYWORD_ONLY(apt) \
- *apt.format_trace++ = '$' \
-
-
-static int apt_parse(argument_parser_table_t *apt) {
- argument_path_t *trace;
-
- *apt->format_trace++ = ':';
- strcpy(apt->format_trace, apt->function_name);
- apt->keywords[apt->keyword_count] = NULL;
-
- for (;;) {
- int result;
-
- switch (apt->vararg_count) {
- case 0:
- PyErr_SetString(PyExc_RuntimeError, "suspiciously too few arguments for apt_parse");
- return 0;
-
- #define APT_PREAMBLE \
- result = PyArg_ParseTupleAndKeywords(apt->args, apt->kwargs, apt->format, apt->keywords, \
-
- #define APT_POSTSCRIPT \
- ); \
- break; \
-
- case 1:
- APT_PREAMBLE
- apt->varargs[0]
- APT_POSTSCRIPT
- case 2:
- APT_PREAMBLE
- apt->varargs[0],
- apt->varargs[1]
- APT_POSTSCRIPT
- case 3:
- APT_PREAMBLE
- apt->varargs[0],
- apt->varargs[1],
- apt->varargs[2]
- APT_POSTSCRIPT
- case 4:
- APT_PREAMBLE
- apt->varargs[0],
- apt->varargs[1],
- apt->varargs[2],
- apt->varargs[3]
- APT_POSTSCRIPT
- case 5:
- APT_PREAMBLE
- apt->varargs[0],
- apt->varargs[1],
- apt->varargs[2],
- apt->varargs[3],
- apt->varargs[4]
- APT_POSTSCRIPT
- case 6:
- APT_PREAMBLE
- apt->varargs[0],
- apt->varargs[1],
- apt->varargs[2],
- apt->varargs[3],
- apt->varargs[4],
- apt->varargs[5]
- APT_POSTSCRIPT
- case 7:
- APT_PREAMBLE
- apt->varargs[0],
- apt->varargs[1],
- apt->varargs[2],
- apt->varargs[3],
- apt->varargs[4],
- apt->varargs[5],
- apt->varargs[6]
- APT_POSTSCRIPT
- case 8:
- APT_PREAMBLE
- apt->varargs[0],
- apt->varargs[1],
- apt->varargs[2],
- apt->varargs[3],
- apt->varargs[4],
- apt->varargs[5],
- apt->varargs[6],
- apt->varargs[7]
- APT_POSTSCRIPT
- default:
- PyErr_SetString(PyExc_RuntimeError, "too many arguments for apt_parse");
- return 0;
- }
-
- if (result) {
- for (trace = apt->path_head; trace != NULL; trace = trace->next) {
-#if MS_WINDOWS
- switch (*trace->format) {
- case 'U':
- *trace->wide = PyUnicode_AsUnicode(trace->object);
- if (trace->length)
- *trace->length = PyUnicode_GET_SIZE(trace->object);
- break;
- case 'y'
- if (win32_warn_bytes_api())
- return 0;
- *trace->narrow = trace->object;
- if (trace->length)
- *trace->length = strlen((char *)trace->object);
- break;
- default:
- PyErr_SetString(PyExc_RuntimeError, "unexpected format character in apt_parse");
- return 0;
- }
-#else
- assert(*trace->format == 'O');
- *trace->narrow = PyBytes_AsString(trace->object);
- if (trace->length)
- *trace->length = PyBytes_GET_SIZE(trace->object);
-#endif
- }
- return result;
- }
-
-#if !MS_WINDOWS
- break;
-#else
- for (trace = apt->path_head; trace != NULL; trace = trace->next) {
- /*
- * try flipping paths between wide and narrow.
- *
- * each element always started with wide.
- * so:
- * * if we see a wide, flip it to narrow and stop.
- * * if we see a narrow, flip it to wide and move on to the next field.
- * * if we run out of fields, we have exhausted all possibilities. fail.
- *
- * (conceptually it helps to think of the fields as a binary number
- * with as many digits as there are entries in the path list.
- * wide is 0, narrow is 1. we keep incrementing the number
- * until we wrap around to 0 again.)
- */
- if (*trace->format == 'U') {
- *trace->format = 'y';
- break;
- }
- if (*trace->format == 'y') {
- *trace->format = 'U';
- continue;
- }
- PyErr_SetString(PyExc_RuntimeError, "unexpected format character in apt_parse");
- return 0;
- }
- if (!trace)
- break;
-#endif
- }
-
- return 0;
-}
-
-static void apt_cleanup(argument_parser_table_t *apt) {
-#if !MS_WINDOWS
- argument_path_t *trace;
- for (trace = apt->path_head; trace != NULL; trace = trace->next) {
- Py_XDECREF(trace->object);
- }
-#endif
-}
-
/* A helper used by a number of POSIX-only functions */
#ifndef MS_WINDOWS
static int
@@ -2204,12 +1942,6 @@ posix_do_stat(PyObject *self, PyObject *args,
/* POSIX methods */
-#ifdef AT_FDCWD
-#define DEFAULT_DIR_FD AT_FDCWD
-#else
-#define DEFAULT_DIR_FD (-100)
-#endif
-
PyDoc_STRVAR(posix_access__doc__,
"access(path, mode) -> True if granted, False otherwise\n\n\
Use the real uid/gid to test for access to a path. Note that most\n\
@@ -2219,54 +1951,34 @@ specified access to the path. The mode argument can be F_OK to test\n\
existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
static PyObject *
-posix_access(PyObject *self, PyObject *args, PyObject *kwargs)
+posix_access(PyObject *self, PyObject *args)
{
+ const char *path;
int mode;
- int dir_fd = DEFAULT_DIR_FD;
- wchar_t *wide_path;
- char *path;
- int follow_symlinks = 1;
- int effective_ids = 0;
#ifdef MS_WINDOWS
DWORD attr;
-#else
- int res;
-#endif
-
- APT_DECLARE(apt, "access");
- APT_ARGUMENT_PATH(apt, "path", &wide_path, &path, NULL);
- APT_ARGUMENT_INT(apt, "mode", &mode);
- APT_OPTIONAL(apt);
- APT_KEYWORD_ONLY(apt);
- APT_ARGUMENT_INT(apt, "dir_fd", &dir_fd);
- APT_ARGUMENT_BOOL(apt, "follow_symlinks", &follow_symlinks);
- APT_ARGUMENT_BOOL(apt, "effective_ids", &effective_ids);
-
-#define ACCESS_FAIL_IF_KEYWORD_USED \
- if (dir_fd != DEFAULT_DIR_FD) \
- PyErr_SetString(PyExc_NotImplementedError, "access: dir_fd unavailable on this platform"); \
- if (!follow_symlinks) \
- PyErr_SetString(PyExc_NotImplementedError, "access: follow_symlinks unavailable on this platform"); \
- if (effective_ids) \
- PyErr_SetString(PyExc_NotImplementedError, "access: effective_ids unavailable on this platform")
-
- if (!apt_parse(&apt))
+ PyObject *po;
+ if (PyArg_ParseTuple(args, "Ui:access", &po, &mode)) {
+ wchar_t* wpath = PyUnicode_AsUnicode(po);
+ if (wpath == NULL)
+ return NULL;
+ Py_BEGIN_ALLOW_THREADS
+ attr = GetFileAttributesW(wpath);
+ Py_END_ALLOW_THREADS
+ goto finish;
+ }
+ /* Drop the argument parsing error as narrow strings
+ are also valid. */
+ PyErr_Clear();
+ if (!PyArg_ParseTuple(args, "yi:access", &path, &mode))
+ return NULL;
+ if (win32_warn_bytes_api())
return NULL;
- Py_RETURN_NONE;
-
-#ifdef MS_WINDOWS
- ACCESS_FAIL_IF_KEYWORD_USED;
-
Py_BEGIN_ALLOW_THREADS
- if (wide != NULL)
- attr = GetFileAttributesW(wide_path);
- else
- attr = GetFileAttributesA(path);
+ attr = GetFileAttributesA(path);
Py_END_ALLOW_THREADS
-
- apt_cleanup(&apt);
-
+finish:
if (attr == 0xFFFFFFFF)
/* File does not exist, or cannot read attributes */
return PyBool_FromLong(0);
@@ -2277,28 +1989,16 @@ posix_access(PyObject *self, PyObject *args, PyObject *kwargs)
|| !(attr & FILE_ATTRIBUTE_READONLY)
|| (attr & FILE_ATTRIBUTE_DIRECTORY));
#else
-
- if ((dir_fd != DEFAULT_DIR_FD)
- || effective_ids || !follow_symlinks) {
-#ifdef HAVE_FACCESSAT
- int flags = 0;
- if (!follow_symlinks)
- flags |= AT_SYMLINK_NOFOLLOW;
- if (effective_ids)
- flags |= AT_EACCESS;
- Py_BEGIN_ALLOW_THREADS
- res = faccessat(dir_fd, path, mode, flags);
- Py_END_ALLOW_THREADS
-#else
- ACCESS_FAIL_IF_KEYWORD_USED;
-#endif
- } else {
- Py_BEGIN_ALLOW_THREADS
- res = access(path, mode);
- Py_END_ALLOW_THREADS
- }
-
- apt_cleanup(&apt);
+ PyObject *opath;
+ int res;
+ if (!PyArg_ParseTuple(args, "O&i:access",
+ PyUnicode_FSConverter, &opath, &mode))
+ return NULL;
+ path = PyBytes_AsString(opath);
+ Py_BEGIN_ALLOW_THREADS
+ res = access(path, mode);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(opath);
return PyBool_FromLong(res == 0);
#endif
}
@@ -10896,9 +10596,7 @@ get_terminal_size(PyObject *self, PyObject *args)
static PyMethodDef posix_methods[] = {
- {"access", (PyCFunction)posix_access,
- METH_VARARGS | METH_KEYWORDS,
- posix_access__doc__},
+ {"access", posix_access, METH_VARARGS, posix_access__doc__},
#ifdef HAVE_TTYNAME
{"ttyname", posix_ttyname, METH_VARARGS, posix_ttyname__doc__},
#endif