Skip to content

Instantly share code, notes, and snippets.

@gawen
Created February 6, 2015 14:17
Show Gist options
  • Save gawen/b376cb02f360205e7a1c to your computer and use it in GitHub Desktop.
Save gawen/b376cb02f360205e7a1c to your computer and use it in GitHub Desktop.
Rename/Replace function behind "os.replace" in Python 3
static PyObject *
internal_rename(PyObject *args, PyObject *kwargs, int is_replace)
{
char *function_name = is_replace ? "replace" : "rename";
path_t src;
path_t dst;
int src_dir_fd = DEFAULT_DIR_FD;
int dst_dir_fd = DEFAULT_DIR_FD;
int dir_fd_specified;
PyObject *return_value = NULL;
char format[24];
static char *keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL};
#ifdef MS_WINDOWS
BOOL result;
int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
#else
int result;
#endif
memset(&src, 0, sizeof(src));
memset(&dst, 0, sizeof(dst));
src.function_name = function_name;
dst.function_name = function_name;
strcpy(format, "O&O&|$O&O&:");
strcat(format, function_name);
if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, keywords,
path_converter, &src,
path_converter, &dst,
dir_fd_converter, &src_dir_fd,
dir_fd_converter, &dst_dir_fd))
return NULL;
dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
(dst_dir_fd != DEFAULT_DIR_FD);
#ifndef HAVE_RENAMEAT
if (dir_fd_specified) {
argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
goto exit;
}
#endif
if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) {
PyErr_Format(PyExc_ValueError,
"%s: src and dst must be the same type", function_name);
goto exit;
}
#ifdef MS_WINDOWS
Py_BEGIN_ALLOW_THREADS
if (src.wide)
result = MoveFileExW(src.wide, dst.wide, flags);
else
result = MoveFileExA(src.narrow, dst.narrow, flags);
Py_END_ALLOW_THREADS
if (!result) {
return_value = path_error2(&src, &dst);
goto exit;
}
#else
Py_BEGIN_ALLOW_THREADS
#ifdef HAVE_RENAMEAT
if (dir_fd_specified)
result = renameat(src_dir_fd, src.narrow, dst_dir_fd, dst.narrow);
else
#endif
result = rename(src.narrow, dst.narrow);
Py_END_ALLOW_THREADS
if (result) {
return_value = path_error2(&src, &dst);
goto exit;
}
#endif
Py_INCREF(Py_None);
return_value = Py_None;
exit:
path_cleanup(&src);
path_cleanup(&dst);
return return_value;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment