Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
cfe6f2af
Commit
cfe6f2af
authored
May 05, 2012
by
Larry Hastings
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update Misc/NEWS for issues #14127 and #14705. (And, technically, #10148.)
parent
faf91e75
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
333 additions
and
31 deletions
+333
-31
Modules/posixmodule.c
Modules/posixmodule.c
+333
-31
No files found.
Modules/posixmodule.c
View file @
cfe6f2af
...
...
@@ -398,6 +398,268 @@ 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
...
...
@@ -1942,6 +2204,12 @@ 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
\
...
...
@@ -1951,34 +2219,54 @@ 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
)
posix_access
(
PyObject
*
self
,
PyObject
*
args
,
PyObject
*
kwargs
)
{
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
;
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
())
#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
))
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
);
Py_END_ALLOW_THREADS
finish:
apt_cleanup
(
&
apt
);
if
(
attr
==
0xFFFFFFFF
)
/* File does not exist, or cannot read attributes */
return
PyBool_FromLong
(
0
);
...
...
@@ -1989,16 +2277,28 @@ finish:
||
!
(
attr
&
FILE_ATTRIBUTE_READONLY
)
||
(
attr
&
FILE_ATTRIBUTE_DIRECTORY
));
#else
PyObject
*
opath
;
int
res
;
if
(
!
PyArg_ParseTuple
(
args
,
"O&i:access"
,
PyUnicode_FSConverter
,
&
opath
,
&
mode
))
return
NULL
;
path
=
PyBytes_AsString
(
opath
);
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
Py_DECREF
(
opath
);
}
apt_cleanup
(
&
apt
);
return
PyBool_FromLong
(
res
==
0
);
#endif
}
...
...
@@ -10596,7 +10896,9 @@ get_terminal_size(PyObject *self, PyObject *args)
static
PyMethodDef
posix_methods
[]
=
{
{
"access"
,
posix_access
,
METH_VARARGS
,
posix_access__doc__
},
{
"access"
,
(
PyCFunction
)
posix_access
,
METH_VARARGS
|
METH_KEYWORDS
,
posix_access__doc__
},
#ifdef HAVE_TTYNAME
{
"ttyname"
,
posix_ttyname
,
METH_VARARGS
,
posix_ttyname__doc__
},
#endif
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment