diff options
Diffstat (limited to 'rdiff-backup/src/cmodule.c')
-rw-r--r-- | rdiff-backup/src/cmodule.c | 187 |
1 files changed, 125 insertions, 62 deletions
diff --git a/rdiff-backup/src/cmodule.c b/rdiff-backup/src/cmodule.c index ea10415..074f939 100644 --- a/rdiff-backup/src/cmodule.c +++ b/rdiff-backup/src/cmodule.c @@ -1,16 +1,40 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2002 Ben Escoto + * + * This file is part of rdiff-backup. + * + * rdiff-backup is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, Inc., 675 Mass Ave, + * Cambridge MA 02139, USA; either version 2 of the License, or (at + * your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + + #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <Python.h> #include <errno.h> +static PyObject *UnknownFileTypeError; +static PyObject *c_make_file_dict(PyObject *self, PyObject *args); +static PyObject *long2str(PyObject *self, PyObject *args); +static PyObject *str2long(PyObject *self, PyObject *args); + + +/* Turn a stat structure into a python dictionary. The preprocessor + stuff taken from Python's posixmodule.c */ static PyObject *c_make_file_dict(self, args) PyObject *self; PyObject *args; { + PyObject *size, *inode, *mtime, *atime, *devloc, *return_val; char *filename, filetype[5]; struct stat sbuf; - mode_t mode; + long int mode, perms; if (!PyArg_ParseTuple(args, "s", &filename)) return NULL; if (lstat(filename, &sbuf) != 0) { @@ -21,7 +45,27 @@ static PyObject *c_make_file_dict(self, args) return NULL; } } - mode = sbuf.st_mode; +#ifdef HAVE_LARGEFILE_SUPPORT + size = PyLong_FromLongLong((LONG_LONG)sbuf.st_size); + inode = PyLong_FromLongLong((LONG_LONG)sbuf.st_ino); +#else + size = PyInt_FromLong((long)sbuf.st_size); + inode = PyInt_FromLong((long)sbuf.st_ino); +#endif + mode = (long)sbuf.st_mode; + perms = mode & (S_IRWXU | S_IRWXG | S_IRWXO); +#if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS) + devloc = PyLong_FromLongLong((LONG_LONG)sbuf.st_dev); +#else + devloc = PyInt_FromLong((long)sbuf.st_dev); +#endif +#if SIZEOF_TIME_T > SIZEOF_LONG + mtime = PyLong_FromLongLong((LONG_LONG)sbuf.st_mtime); + atime = PyLong_FromLongLong((LONG_LONG)sbuf.st_atime); +#else + mtime = PyInt_FromLong((long)sbuf.st_mtime); + atime = PyLong_FromLongLong((long)sbuf.st_atime); +#endif /* Build return dictionary from stat struct */ if (S_ISREG(mode) || S_ISDIR(mode) || S_ISSOCK(mode) || S_ISFIFO(mode)) { @@ -30,17 +74,17 @@ static PyObject *c_make_file_dict(self, args) else if S_ISDIR(mode) strcpy(filetype, "dir"); else if S_ISSOCK(mode) strcpy(filetype, "sock"); else strcpy(filetype, "fifo"); - return Py_BuildValue("{s:s,s:l,s:i,s:i,s:i,s:l,s:i,s:i,s:l,s:l}", + return Py_BuildValue("{s:s,s:N,s:l,s:l,s:l,s:N,s:N,s:l,s:N,s:N}", "type", filetype, - "size", (long int)sbuf.st_size, - "perms", (int)(mode & S_IRWXU), - "uid", (int)sbuf.st_uid, - "gid", (int)sbuf.st_gid, - "inode", (long int)sbuf.st_ino, - "devloc", (int)sbuf.st_dev, - "nlink", (int)sbuf.st_nlink, - "mtime", (long int)sbuf.st_mtime, - "atime", (long int)sbuf.st_atime); + "size", size, + "perms", perms, + "uid", (long)sbuf.st_uid, + "gid", (long)sbuf.st_gid, + "inode", inode, + "devloc", devloc, + "nlink", (long)sbuf.st_nlink, + "mtime", mtime, + "atime", atime); } else if S_ISLNK(mode) { /* Symbolic links */ char linkname[1024]; @@ -51,89 +95,108 @@ static PyObject *c_make_file_dict(self, args) } linkname[len_link] = '\0'; - return Py_BuildValue("{s:s,s:l,s:i,s:i,s:i,s:l,s:i,s:i,s:s}", - "type", "sym", - "size", (long int)sbuf.st_size, - "perms", (int)(mode & S_IRWXU), - "uid", (int)sbuf.st_uid, - "gid", (int)sbuf.st_gid, - "inode", (long int)sbuf.st_ino, - "devloc", (int)sbuf.st_dev, - "nlink", (int)sbuf.st_nlink, - "linkname", linkname); + return_val = Py_BuildValue("{s:s,s:N,s:l,s:l,s:l,s:N,s:N,s:l,s:s}", + "type", "sym", + "size", size, + "perms", perms, + "uid", (long)sbuf.st_uid, + "gid", (long)sbuf.st_gid, + "inode", inode, + "devloc", devloc, + "nlink", (long)sbuf.st_nlink, + "linkname", linkname); + Py_DECREF(mtime); + Py_DECREF(atime); + return return_val; } else if (S_ISCHR(mode) || S_ISBLK(mode)) { /* Device files */ char devtype[2]; - int devnums = (int)sbuf.st_rdev; +#if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS) + LONG_LONG devnums = (LONG_LONG)sbuf.st_rdev; + PyObject *major_num = PyLong_FromLongLong(devnums >> 8); +#else + long int devnums = (long)sbuf.st_dev; + PyObject *major_num = PyInt_FromLong(devnums >> 8); +#endif + int minor_num = (int)(devnums & 0xff); if S_ISCHR(mode) strcpy(devtype, "c"); else strcpy(devtype, "b"); - return Py_BuildValue("{s:s,s:l,s:i,s:i,s:i,s:l,s:i,s:i,s:O}", - "type", "dev", - "size", (long int)sbuf.st_size, - "perms", (int)(mode & S_IRWXU), - "uid", (int)sbuf.st_uid, - "gid", (int)sbuf.st_gid, - "inode", (long int)sbuf.st_ino, - "devloc", (int)sbuf.st_dev, - "nlink", (int)sbuf.st_nlink, - "devnums", Py_BuildValue("(s,i,i)", devtype, - devnums >> 8, - devnums & 0xff), - "mtime", (long int)sbuf.st_mtime, - "atime", (long int)sbuf.st_atime); + return_val = Py_BuildValue("{s:s,s:N,s:l,s:l,s:l,s:N,s:N,s:l,s:N}", + "type", "dev", + "size", size, + "perms", perms, + "uid", (long)sbuf.st_uid, + "gid", (long)sbuf.st_gid, + "inode", inode, + "devloc", devloc, + "nlink", (long)sbuf.st_nlink, + "devnums", Py_BuildValue("(s,O,i)", devtype, + major_num, minor_num)); + Py_DECREF(mtime); + Py_DECREF(atime); + return return_val; } else { - /* Unrecognized file type - pretend it isn't there */ - errno = ENOENT; - PyErr_SetFromErrno(PyExc_OSError); + /* Unrecognized file type - raise exception */ + Py_DECREF(size); + Py_DECREF(inode); + Py_DECREF(devloc); + Py_DECREF(mtime); + Py_DECREF(atime); + PyErr_SetString(UnknownFileTypeError, filename); return NULL; } } + +/* Convert python long into 7 byte string */ static PyObject *long2str(self, args) PyObject *self; PyObject *args; { unsigned char s[7]; - int sindex; - unsigned long long int l; - PyObject *pylong; - - if (!PyArg_ParseTuple(args, "O", &pylong)) return NULL; - l = PyLong_AsUnsignedLongLong(pylong); - for(sindex = 0; sindex <= 6; sindex++) { - s[sindex] = l % 256; - l /= 256; - } - return Py_BuildValue("s#", s, 7); + PyLongObject *pylong; + PyObject *return_val; + + if (!PyArg_ParseTuple(args, "O!", &PyLong_Type, &pylong)) return NULL; + if (_PyLong_AsByteArray(pylong, s, 7, 0, 0) != 0) return NULL; + else return Py_BuildValue("s#", s, 7); + return return_val; } + +/* Reverse of above; convert 7 byte string into python long */ static PyObject *str2long(self, args) PyObject *self; PyObject *args; { unsigned char *s; - unsigned long long int l = 0; - int sindex, ssize; + int ssize; if (!PyArg_ParseTuple(args, "s#", &s, &ssize)) return NULL; - if (ssize != 7) return Py_BuildValue("i", -1); - for(sindex=6; sindex >= 0; sindex--) - l = l*256 + s[sindex]; - return PyLong_FromLongLong(l); + if (ssize != 7) { + PyErr_SetString(PyExc_TypeError, "Single argument must be 7 char string"); + return NULL; + } + return _PyLong_FromByteArray(s, 7, 0, 0); } + static PyMethodDef CMethods[] = { {"make_file_dict", c_make_file_dict, METH_VARARGS, "Make dictionary from file stat"}, - {"long2str", long2str, METH_VARARGS, - "Convert long int to 7 byte string"}, - {"str2long", str2long, METH_VARARGS, - "Convert 7 byte string to long int"}, + {"long2str", long2str, METH_VARARGS, "Convert python long to 7 byte string"}, + {"str2long", str2long, METH_VARARGS, "Convert 7 byte string to python long"}, {NULL, NULL, 0, NULL} }; void initC(void) { - (void) Py_InitModule("C", CMethods); + PyObject *m, *d; + + m = Py_InitModule("C", CMethods); + d = PyModule_GetDict(m); + UnknownFileTypeError = PyErr_NewException("C.UnknownFileTypeError", + NULL, NULL); + PyDict_SetItemString(d, "UnknownFileTypeError", UnknownFileTypeError); } |