/* * ocfs2module.c * * OCFS2 python binding. * * Copyright (C) 2004, 2005 Oracle. All rights reserved. * * Author: Manish Singh * * This program 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; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have recieved a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. */ #include #include #include #include #include "ocfs2/ocfs2.h" #define Filesystem_Check(op) PyObject_TypeCheck(op, &Filesystem_Type) #define DInode_Check(op) PyObject_TypeCheck(op, &DInode_Type) #define DirEntry_Check(op) PyObject_TypeCheck(op, &DirEntry_Type) #define SuperBlock_Check(op) PyObject_TypeCheck(op, &SuperBlock_Type) #define DirScanIter_Check(op) PyObject_TypeCheck(op, &DirScanIter_Type) typedef struct { PyObject_HEAD PyObject *device; ocfs2_filesys *fs; } Filesystem; typedef struct { PyObject_HEAD Filesystem *fs_obj; struct ocfs2_dinode dinode; } DInode; typedef struct { PyObject_HEAD Filesystem *fs_obj; struct ocfs2_dir_entry dentry; } DirEntry; typedef struct { PyObject_HEAD Filesystem *fs_obj; struct ocfs2_super_block super; } SuperBlock; typedef struct { PyObject_HEAD Filesystem *fs_obj; ocfs2_dir_scan *scan; } DirScanIter; static PyObject *ocfs2_error; #define CHECK_ERROR(call) do { \ ret = call; \ if (ret) \ { \ PyErr_SetString (ocfs2_error, error_message (ret)); \ return NULL; \ } \ } while (0) #define DINODE_U64_GETTER(name) \ static PyObject * \ dinode_ ## name (DInode *self, void *closure) \ { \ return PyLong_FromUnsignedLongLong (self->dinode.i_ ## name); \ } #define DINODE_GETTER_ENTRY(name) \ {"i_" #name, (getter)dinode_ ## name, (setter)0} DINODE_U64_GETTER(size) DINODE_U64_GETTER(atime) DINODE_U64_GETTER(ctime) DINODE_U64_GETTER(mtime) DINODE_U64_GETTER(dtime) DINODE_U64_GETTER(blkno) DINODE_U64_GETTER(last_eb_blk) static PyObject * dinode_rdev (DInode *self, void *closure) { return PyLong_FromUnsignedLongLong (self->dinode.id1.dev1.i_rdev); } static PyObject * dinode_jflags (DInode *self, void *closure) { return PyInt_FromLong (self->dinode.id1.journal1.ij_flags); } static PyGetSetDef dinode_getsets[] = { DINODE_GETTER_ENTRY (size), DINODE_GETTER_ENTRY (atime), DINODE_GETTER_ENTRY (ctime), DINODE_GETTER_ENTRY (mtime), DINODE_GETTER_ENTRY (dtime), DINODE_GETTER_ENTRY (blkno), DINODE_GETTER_ENTRY (last_eb_blk), DINODE_GETTER_ENTRY (rdev), {"ij_flags", (getter)dinode_jflags, (setter)0}, {NULL} }; #undef DINODE_U64_GETTER #undef DINODE_GETTER_ENTRY #define DINODE_STR_MEMBER(name) \ {"i_" #name, T_STRING_INPLACE, offsetof (DInode, dinode.i_ ## name), RO} #define DINODE_S16_MEMBER(name) \ {"i_" #name, T_SHORT, offsetof (DInode, dinode.i_ ## name), RO} #define DINODE_U16_MEMBER(name) \ {"i_" #name, T_USHORT, offsetof (DInode, dinode.i_ ## name), RO} #define DINODE_U32_MEMBER(name) \ {"i_" #name, T_UINT, offsetof (DInode, dinode.i_ ## name), RO} #define DINODE_BITMAP_MEMBER(name) \ {"i_" #name, T_UINT, offsetof (DInode, dinode.id1.bitmap1.i_ ## name), RO} static PyMemberDef dinode_members[] = { DINODE_STR_MEMBER (signature), DINODE_U32_MEMBER (generation), DINODE_S16_MEMBER (suballoc_slot), DINODE_U16_MEMBER (suballoc_bit), DINODE_U32_MEMBER (clusters), DINODE_U32_MEMBER (uid), DINODE_U32_MEMBER (gid), DINODE_U16_MEMBER (mode), DINODE_U16_MEMBER (links_count), DINODE_U32_MEMBER (flags), DINODE_U32_MEMBER (fs_generation), DINODE_BITMAP_MEMBER (used), DINODE_BITMAP_MEMBER (total), {"fs", T_OBJECT, offsetof (DInode, fs_obj), RO}, {0} }; #undef DINODE_STR_MEMBER #undef DINODE_S16_MEMBER #undef DINODE_U16_MEMBER #undef DINODE_U32_MEMBER #undef DINODE_BITMAP_MEMBER static void dinode_dealloc (DInode *self) { Py_DECREF (self->fs_obj); PyObject_DEL (self); } static PyObject * dinode_repr (DInode *self) { char blkno[32]; snprintf (blkno, sizeof (blkno), "%"PRIu64, (uint64_t)self->dinode.i_blkno); return PyString_FromFormat ("", blkno, PyString_AS_STRING (self->fs_obj->device)); } static PyTypeObject DInode_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "ocfs2.DInode", /* tp_name */ sizeof(DInode), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)dinode_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)dinode_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ dinode_members, /* tp_members */ dinode_getsets, /* tp_getset */ }; static PyObject * dinode_new (Filesystem *fs_obj, struct ocfs2_dinode *dinode) { DInode *self; self = PyObject_NEW (DInode, &DInode_Type); if (self == NULL) return NULL; Py_INCREF (fs_obj); self->fs_obj = fs_obj; memcpy (&self->dinode, dinode, sizeof (*dinode)); return (PyObject *) self; } static PyObject * dir_entry_name (DirEntry *self, void *closure) { return PyString_FromStringAndSize (self->dentry.name, self->dentry.name_len); } static PyObject * dir_entry_inode (DirEntry *self, void *closure) { return PyLong_FromUnsignedLongLong (self->dentry.inode); } static PyGetSetDef dir_entry_getsets[] = { {"name", (getter)dir_entry_name, (setter)0}, {"inode", (getter)dir_entry_inode, (setter)0}, {NULL} }; static PyMemberDef dir_entry_members[] = { {"rec_len", T_USHORT, offsetof (DirEntry, dentry.rec_len), RO}, {"file_type", T_UBYTE, offsetof (DirEntry, dentry.file_type), RO}, {"fs", T_OBJECT, offsetof (DirEntry, fs_obj), RO}, {0} }; static void dir_entry_dealloc (DirEntry *self) { PyObject_DEL (self); } static PyObject * dir_entry_repr (DirEntry *self) { char name[OCFS2_MAX_FILENAME_LEN + 1]; strncpy (name, self->dentry.name, self->dentry.name_len); name[self->dentry.name_len] = '\0'; return PyString_FromFormat ("", name, PyString_AS_STRING (self->fs_obj->device)); } static PyTypeObject DirEntry_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "ocfs2.DirEntry", /* tp_name */ sizeof(DirEntry), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)dir_entry_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)dir_entry_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ dir_entry_members, /* tp_members */ dir_entry_getsets, /* tp_getset */ }; static PyObject * dir_entry_new (Filesystem *fs_obj, struct ocfs2_dir_entry *dentry) { DirEntry *self; self = PyObject_NEW (DirEntry, &DirEntry_Type); if (self == NULL) return NULL; Py_INCREF (fs_obj); self->fs_obj = fs_obj; memcpy (&self->dentry, dentry, sizeof (*dentry)); return (PyObject *) self; } #define SUPER_U64_GETTER(name) \ static PyObject * \ super_ ## name (SuperBlock *self, void *closure) \ { \ return PyLong_FromUnsignedLongLong (self->super.s_ ## name); \ } #define SUPER_GETTER_ENTRY(name) \ {"s_" #name, (getter)super_ ## name, (setter)0} SUPER_U64_GETTER (lastcheck) SUPER_U64_GETTER (root_blkno) SUPER_U64_GETTER (system_dir_blkno) SUPER_U64_GETTER (first_cluster_group) static PyObject * super_uuid (SuperBlock *self, void *closure) { return PyString_FromStringAndSize ((char *)self->super.s_uuid, sizeof (self->super.s_uuid)); } static PyObject * super_uuid_unparsed (SuperBlock *self, void *closure) { char buf[40]; uuid_unparse (self->super.s_uuid, buf); return PyString_FromString (buf); } static PyGetSetDef super_getsets[] = { SUPER_GETTER_ENTRY (lastcheck), SUPER_GETTER_ENTRY (root_blkno), SUPER_GETTER_ENTRY (system_dir_blkno), SUPER_GETTER_ENTRY (first_cluster_group), SUPER_GETTER_ENTRY (uuid), {"uuid_unparsed", (getter)super_uuid_unparsed, (setter)0}, {NULL} }; #undef SUPER_U64_GETTER #undef SUPER_GETTER_ENTRY #define SUPER_U16_MEMBER(name) \ {"s_" #name, T_USHORT, offsetof (SuperBlock, super.s_ ## name), RO} #define SUPER_U32_MEMBER(name) \ {"s_" #name, T_UINT, offsetof (SuperBlock, super.s_ ## name), RO} static PyMemberDef super_members[] = { SUPER_U16_MEMBER (major_rev_level), SUPER_U16_MEMBER (minor_rev_level), SUPER_U16_MEMBER (mnt_count), SUPER_U16_MEMBER (state), SUPER_U16_MEMBER (errors), SUPER_U32_MEMBER (checkinterval), SUPER_U32_MEMBER (creator_os), SUPER_U32_MEMBER (feature_compat), SUPER_U32_MEMBER (feature_incompat), SUPER_U32_MEMBER (feature_ro_compat), SUPER_U32_MEMBER (blocksize_bits), SUPER_U32_MEMBER (clustersize_bits), SUPER_U16_MEMBER (max_slots), {"s_label", T_STRING_INPLACE, offsetof (SuperBlock, super.s_label), RO}, {"fs", T_OBJECT, offsetof (SuperBlock, fs_obj), RO}, {0} }; #undef SUPER_U16_MEMBER #undef SUPER_U32_MEMBER static void super_dealloc (SuperBlock *self) { Py_DECREF (self->fs_obj); PyObject_DEL (self); } static PyObject * super_repr (SuperBlock *self) { return PyString_FromFormat ("", PyString_AS_STRING (self->fs_obj->device)); } static PyTypeObject SuperBlock_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "ocfs2.SuperBlock", /* tp_name */ sizeof(SuperBlock), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)super_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)super_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ super_members, /* tp_members */ super_getsets, /* tp_getset */ }; static PyObject * super_new (Filesystem *fs_obj, struct ocfs2_dinode *fs_super) { SuperBlock *self; self = PyObject_NEW (SuperBlock, &SuperBlock_Type); if (self == NULL) return NULL; Py_INCREF (fs_obj); self->fs_obj = fs_obj; memcpy (&self->super, &fs_super->id2.i_super, sizeof (self->super)); return (PyObject *) self; } static void dir_scan_iter_dealloc (DirScanIter *self) { if (self->scan) ocfs2_close_dir_scan (self->scan); Py_XDECREF (self->fs_obj); PyObject_DEL (self); } static PyObject * dir_scan_iter_getiter (DirScanIter *self) { Py_INCREF (self); return (PyObject *) self; } static PyObject * dir_scan_iter_next (DirScanIter *self) { errcode_t ret; struct ocfs2_dir_entry dirent; if (self->scan == NULL) { PyErr_SetNone (PyExc_StopIteration); return NULL; } CHECK_ERROR (ocfs2_get_next_dir_entry (self->scan, &dirent)); if (dirent.rec_len == 0) { ocfs2_close_dir_scan (self->scan); self->scan = NULL; Py_DECREF (self->fs_obj); self->fs_obj = NULL; PyErr_SetNone (PyExc_StopIteration); return NULL; } return dir_entry_new (self->fs_obj, &dirent); } static PyTypeObject DirScanIter_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "ocfs2.DirScanIter", /* tp_name */ sizeof(DirScanIter), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)dir_scan_iter_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_ITER, /* tp_flags */ NULL, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ (getiterfunc)dir_scan_iter_getiter, /* tp_iter */ (iternextfunc)dir_scan_iter_next, /* tp_iternext */ }; static PyObject * dir_scan_iter_new (Filesystem *fs_obj, ocfs2_dir_scan *scan) { DirScanIter *self; self = PyObject_NEW (DirScanIter, &DirScanIter_Type); if (self == NULL) { ocfs2_close_dir_scan (scan); return NULL; } Py_INCREF (fs_obj); self->fs_obj = fs_obj; self->scan = scan; return (PyObject *) self; } static PyObject * fs_flush (Filesystem *self) { errcode_t ret; CHECK_ERROR (ocfs2_flush (self->fs)); Py_INCREF(Py_None); return Py_None; } static PyObject * fs_clusters_to_blocks (Filesystem *self, PyObject *args, PyObject *kwargs) { unsigned int clusters; uint64_t blocks; static char *kwlist[] = { "clusters", NULL }; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "I:clusters_to_blocks", kwlist, &clusters)) return NULL; blocks = ocfs2_clusters_to_blocks (self->fs, clusters); return PyLong_FromUnsignedLongLong (blocks); } static PyObject * fs_blocks_to_clusters (Filesystem *self, PyObject *args, PyObject *kwargs) { unsigned long long blocks; uint32_t clusters; static char *kwlist[] = { "blocks", NULL }; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "K:blocks_to_clusters", kwlist, &blocks)) return NULL; clusters = ocfs2_clusters_to_blocks (self->fs, blocks); return PyInt_FromLong (clusters); } static PyObject * fs_blocks_in_bytes (Filesystem *self, PyObject *args, PyObject *kwargs) { unsigned long long bytes; uint64_t blocks; static char *kwlist[] = { "bytes", NULL }; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "K:blocks_in_bytes", kwlist, &bytes)) return NULL; blocks = ocfs2_blocks_in_bytes (self->fs, bytes); return PyLong_FromUnsignedLongLong (blocks); } static PyObject * fs_clusters_in_blocks (Filesystem *self, PyObject *args, PyObject *kwargs) { unsigned long long blocks; uint32_t clusters; static char *kwlist[] = { "blocks", NULL }; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "K:clusters_in_blocks", kwlist, &blocks)) return NULL; clusters = ocfs2_clusters_in_blocks (self->fs, blocks); return PyInt_FromLong (clusters); } static PyObject * fs_block_out_of_range (Filesystem *self, PyObject *args, PyObject *kwargs) { unsigned long long block; int ret; static char *kwlist[] = { "block", NULL }; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "K:block_out_of_range", kwlist, &block)) return NULL; ret = ocfs2_block_out_of_range(self->fs, block); return PyBool_FromLong (ret); } static PyObject * fs_lookup_system_inode (Filesystem *self, PyObject *args, PyObject *kwargs) { errcode_t ret; int type, slot_num = OCFS2_INVALID_SLOT; uint64_t blkno; static char *kwlist[] = { "type", "slot_num", NULL }; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "i|i:lookup_system_inode", kwlist, &type, &slot_num)) return NULL; CHECK_ERROR (ocfs2_lookup_system_inode(self->fs, type, slot_num, &blkno)); return PyLong_FromUnsignedLongLong (blkno); } static PyObject * fs_read_cached_inode (Filesystem *self, PyObject *args, PyObject *kwargs) { errcode_t ret; unsigned long long blkno; ocfs2_cached_inode *cinode; PyObject *dinode; static char *kwlist[] = { "blkno", NULL }; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "K:read_cached_inode", kwlist, &blkno)) return NULL; CHECK_ERROR (ocfs2_read_cached_inode (self->fs, blkno, &cinode)); dinode = dinode_new (self, cinode->ci_inode); /* XXX: error check */ ocfs2_free_cached_inode (self->fs, cinode); return dinode; } typedef struct { PyObject *func; PyObject *data; Filesystem *fs; } WalkData; static int walk_dirs (struct ocfs2_dir_entry *dirent, uint64_t blocknr, int offset, int blocksize, char *buf, void *priv_data) { PyObject *de; WalkData *data = priv_data; de = dir_entry_new (data->fs, dirent); if (de == NULL) return OCFS2_DIRENT_ERROR; /* XXX: handle errors */ if (data->data) PyObject_CallFunction (data->func, "OiiO", de, offset, blocksize, data->data); else PyObject_CallFunction (data->func, "Oii", de, offset, blocksize); Py_DECREF (de); return 0; } static PyObject * fs_dir_iterate (Filesystem *self, PyObject *args, PyObject *kwargs) { errcode_t ret; WalkData wdata; PyObject *py_func, *py_data = NULL, *py_dir = NULL; uint64_t dir; int flags = OCFS2_DIRENT_FLAG_EXCLUDE_DOTS; static char *kwlist[] = { "callback", "data", "dir", "flags", NULL }; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O|OOi:dir_iterate", kwlist, &py_func, &py_data, &py_dir, &flags)) return NULL; if (!PyCallable_Check (py_func)) { PyErr_SetString (PyExc_TypeError, "callback must be a callable object"); return NULL; } if (py_dir == NULL || py_dir == Py_None) dir = self->fs->fs_root_blkno; else if (DirEntry_Check (py_dir)) dir = ((DirEntry *) py_dir)->dentry.inode; else if (PyInt_Check (py_dir)) dir = PyInt_AsUnsignedLongMask (py_dir); else if (PyLong_Check (py_dir)) dir = PyLong_AsUnsignedLongLongMask (py_dir); else { PyErr_SetString (PyExc_TypeError, "dir must be DirEntry or integer"); return NULL; } Py_INCREF (py_func); wdata.func = py_func; Py_XINCREF (py_data); wdata.data = py_data; wdata.fs = self; /* XXX: handle errors */ ret = ocfs2_dir_iterate (self->fs, dir, flags, NULL, walk_dirs, &wdata); Py_DECREF (py_func); Py_XDECREF (py_data); Py_INCREF (Py_None); return Py_None; } static PyObject * fs_dir_scan (Filesystem *self, PyObject *args, PyObject *kwargs) { errcode_t ret; PyObject *py_dir = NULL; uint64_t dir; int flags = OCFS2_DIR_SCAN_FLAG_EXCLUDE_DOTS; ocfs2_dir_scan *scan; static char *kwlist[] = { "dir", "flags", NULL }; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|Oi:dir_scan", kwlist, &py_dir, &flags)) return NULL; if (py_dir == NULL || py_dir == Py_None) dir = self->fs->fs_root_blkno; else if (DirEntry_Check (py_dir)) dir = ((DirEntry *) py_dir)->dentry.inode; else if (PyInt_Check (py_dir)) dir = PyInt_AsUnsignedLongMask (py_dir); else if (PyLong_Check (py_dir)) dir = PyLong_AsUnsignedLongLongMask (py_dir); else { PyErr_SetString (PyExc_TypeError, "dir must be DirEntry or integer"); return NULL; } CHECK_ERROR (ocfs2_open_dir_scan (self->fs, dir, flags, &scan)); return dir_scan_iter_new (self, scan); } static PyMethodDef fs_methods[] = { {"flush", (PyCFunction)fs_flush, METH_NOARGS}, {"clusters_to_blocks", (PyCFunction)fs_clusters_to_blocks, METH_KEYWORDS}, {"blocks_to_clusters", (PyCFunction)fs_blocks_to_clusters, METH_KEYWORDS}, {"blocks_in_bytes", (PyCFunction)fs_blocks_in_bytes, METH_KEYWORDS}, {"clusters_in_blocks", (PyCFunction)fs_clusters_in_blocks, METH_KEYWORDS}, {"block_out_of_range", (PyCFunction)fs_block_out_of_range, METH_KEYWORDS}, {"lookup_system_inode", (PyCFunction)fs_lookup_system_inode, METH_KEYWORDS}, {"read_cached_inode", (PyCFunction)fs_read_cached_inode, METH_KEYWORDS}, {"dir_iterate", (PyCFunction)fs_dir_iterate, METH_KEYWORDS}, {"iterdir", (PyCFunction)fs_dir_scan, METH_KEYWORDS}, {NULL, NULL} }; static PyObject * fs_super (Filesystem *self, void *closure) { return super_new (self, self->fs->fs_super); } static PyObject * fs_orig_super (Filesystem *self, void *closure) { return super_new (self, self->fs->fs_orig_super); } static PyObject * fs_uuid_str (Filesystem *self, void *closure) { return PyString_FromString (self->fs->uuid_str); } #define FS_U32_GETTER(name) \ static PyObject * \ fs_ ## name (Filesystem *self, void *closure) \ { \ return PyInt_FromLong (self->fs->fs_ ## name); \ } #define FS_UINT_GETTER FS_U32_GETTER #define FS_U64_GETTER(name) \ static PyObject * \ fs_ ## name (Filesystem *self, void *closure) \ { \ return PyLong_FromUnsignedLongLong (self->fs->fs_ ## name); \ } #define FS_GETTER_ENTRY(name) \ {"fs_" #name, (getter)fs_ ## name, (setter)0} FS_U32_GETTER (flags) FS_UINT_GETTER (blocksize) FS_UINT_GETTER (clustersize) FS_U32_GETTER (clusters) FS_U64_GETTER (blocks) FS_U32_GETTER (umask) FS_U64_GETTER (root_blkno) FS_U64_GETTER (sysdir_blkno) FS_U64_GETTER (first_cg_blkno) static PyGetSetDef fs_getsets[] = { FS_GETTER_ENTRY (flags), FS_GETTER_ENTRY (super), FS_GETTER_ENTRY (orig_super), FS_GETTER_ENTRY (blocksize), FS_GETTER_ENTRY (clustersize), FS_GETTER_ENTRY (clusters), FS_GETTER_ENTRY (blocks), FS_GETTER_ENTRY (umask), FS_GETTER_ENTRY (root_blkno), FS_GETTER_ENTRY (sysdir_blkno), FS_GETTER_ENTRY (first_cg_blkno), {"uuid_str", (getter)fs_uuid_str, (setter)0}, {NULL} }; #undef FS_UINT_GETTER #undef FS_U32_GETTER #undef FS_U64_GETTER #undef FS_GETTER_ENTRY static PyMemberDef fs_members[] = { {"device", T_OBJECT, offsetof (Filesystem, device), RO}, {"fs_devname", T_OBJECT, offsetof (Filesystem, device), RO}, {0} }; static void fs_dealloc (Filesystem *self) { if (self->fs) ocfs2_close (self->fs); Py_XDECREF (self->device); PyObject_DEL (self); } static PyObject * fs_repr (Filesystem *self) { return PyString_FromFormat("", PyString_AS_STRING (self->device)); } static int fs_init (Filesystem *self, PyObject *args, PyObject *kwargs) { errcode_t ret; char *device; int flags = OCFS2_FLAG_RO | OCFS2_FLAG_BUFFERED; unsigned int superblock = 0, blksize = 0; static char *kwlist[] = { "device", "flags", "superblock", "blocksize", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iII:ocfs2.Filesystem.__init__", kwlist, &device, &flags, &superblock, &blksize)) return -1; self->fs = NULL; self->device = PyString_FromString (device); if (self->device == NULL) return -1; ret = ocfs2_open (device, flags, superblock, blksize, &self->fs); if (ret) { Py_DECREF (self->device); self->device = NULL; PyErr_SetString (ocfs2_error, error_message (ret)); return -1; } return 0; } static PyTypeObject Filesystem_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "ocfs2.Filesystem", /* tp_name */ sizeof(Filesystem), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)fs_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ (reprfunc)fs_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ NULL, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ fs_methods, /* tp_methods */ fs_members, /* tp_members */ fs_getsets, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc)fs_init, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ }; static PyMethodDef ocfs2_methods[] = { {NULL, NULL} /* sentinel */ }; static void add_constants (PyObject *m) { #define ADD_INT_CONSTANT(name) \ PyModule_AddIntConstant (m, #name, OCFS2_ ## name) #define ADD_STR_CONSTANT(name) \ PyModule_AddStringConstant (m, #name, OCFS2_ ## name) ADD_INT_CONSTANT (SUPER_BLOCK_BLKNO); ADD_INT_CONSTANT (MIN_CLUSTERSIZE); ADD_INT_CONSTANT (MAX_CLUSTERSIZE); ADD_INT_CONSTANT (MIN_BLOCKSIZE); ADD_INT_CONSTANT (MAX_BLOCKSIZE); ADD_INT_CONSTANT (SUPER_MAGIC); ADD_STR_CONSTANT (SUPER_BLOCK_SIGNATURE); ADD_STR_CONSTANT (INODE_SIGNATURE); ADD_STR_CONSTANT (EXTENT_BLOCK_SIGNATURE); ADD_STR_CONSTANT (GROUP_DESC_SIGNATURE); ADD_INT_CONSTANT (VALID_FL); ADD_INT_CONSTANT (ORPHANED_FL); ADD_INT_CONSTANT (SYSTEM_FL); ADD_INT_CONSTANT (SUPER_BLOCK_FL); ADD_INT_CONSTANT (LOCAL_ALLOC_FL); ADD_INT_CONSTANT (BITMAP_FL); ADD_INT_CONSTANT (JOURNAL_FL); ADD_INT_CONSTANT (HEARTBEAT_FL); ADD_INT_CONSTANT (CHAIN_FL); ADD_INT_CONSTANT (JOURNAL_DIRTY_FL); ADD_INT_CONSTANT (ERROR_FS); ADD_INT_CONSTANT (MAX_FILENAME_LEN); ADD_INT_CONSTANT (MAX_SLOTS); ADD_INT_CONSTANT (INVALID_SLOT); ADD_INT_CONSTANT (VOL_UUID_LEN); ADD_INT_CONSTANT (MAX_VOL_LABEL_LEN); ADD_INT_CONSTANT (MIN_JOURNAL_SIZE); ADD_INT_CONSTANT (FIRST_ONLINE_SYSTEM_INODE); ADD_INT_CONSTANT (LAST_GLOBAL_SYSTEM_INODE); ADD_INT_CONSTANT (FT_UNKNOWN); ADD_INT_CONSTANT (FT_REG_FILE); ADD_INT_CONSTANT (FT_DIR); ADD_INT_CONSTANT (FT_CHRDEV); ADD_INT_CONSTANT (FT_BLKDEV); ADD_INT_CONSTANT (FT_FIFO); ADD_INT_CONSTANT (FT_SOCK); ADD_INT_CONSTANT (FT_SYMLINK); ADD_INT_CONSTANT (FT_MAX); ADD_INT_CONSTANT (LINK_MAX); ADD_INT_CONSTANT (FLAG_RO); ADD_INT_CONSTANT (FLAG_RW); ADD_INT_CONSTANT (FLAG_CHANGED); ADD_INT_CONSTANT (FLAG_DIRTY); ADD_INT_CONSTANT (FLAG_SWAP_BYTES); ADD_INT_CONSTANT (FLAG_BUFFERED); ADD_INT_CONSTANT (FLAG_NO_REV_CHECK); ADD_INT_CONSTANT (DIRENT_CHANGED); ADD_INT_CONSTANT (DIRENT_ABORT); ADD_INT_CONSTANT (DIRENT_ERROR); ADD_INT_CONSTANT (DIRENT_FLAG_INCLUDE_EMPTY); ADD_INT_CONSTANT (DIRENT_FLAG_INCLUDE_REMOVED); ADD_INT_CONSTANT (DIRENT_FLAG_EXCLUDE_DOTS); #undef ADD_INT_CONSTANT #undef ADD_STR_CONSTANT #define ADD_INT_CONSTANT(name) \ PyModule_AddIntConstant (m, #name, name) ADD_INT_CONSTANT (BAD_BLOCK_SYSTEM_INODE); ADD_INT_CONSTANT (GLOBAL_INODE_ALLOC_SYSTEM_INODE); ADD_INT_CONSTANT (SLOT_MAP_SYSTEM_INODE); ADD_INT_CONSTANT (HEARTBEAT_SYSTEM_INODE); ADD_INT_CONSTANT (GLOBAL_BITMAP_SYSTEM_INODE); ADD_INT_CONSTANT (ORPHAN_DIR_SYSTEM_INODE); ADD_INT_CONSTANT (EXTENT_ALLOC_SYSTEM_INODE); ADD_INT_CONSTANT (INODE_ALLOC_SYSTEM_INODE); ADD_INT_CONSTANT (JOURNAL_SYSTEM_INODE); ADD_INT_CONSTANT (LOCAL_ALLOC_SYSTEM_INODE); ADD_INT_CONSTANT (NUM_SYSTEM_INODES); #undef ADD_INT_CONSTANT } void initocfs2 (void) { PyObject *m; if (PyType_Ready (&DInode_Type) < 0) return; if (PyType_Ready (&DirEntry_Type) < 0) return; if (PyType_Ready (&SuperBlock_Type) < 0) return; if (PyType_Ready (&DirScanIter_Type) < 0) return; Filesystem_Type.tp_new = PyType_GenericNew; if (PyType_Ready (&Filesystem_Type) < 0) return; initialize_ocfs_error_table (); m = Py_InitModule ("ocfs2", ocfs2_methods); ocfs2_error = PyErr_NewException ("ocfs2.error", PyExc_RuntimeError, NULL); if (ocfs2_error) { Py_INCREF (ocfs2_error); PyModule_AddObject (m, "error", ocfs2_error); } Py_INCREF (&DInode_Type); PyModule_AddObject (m, "DInode", (PyObject *) &DInode_Type); Py_INCREF (&DirEntry_Type); PyModule_AddObject (m, "DirEntry", (PyObject *) &DirEntry_Type); Py_INCREF (&SuperBlock_Type); PyModule_AddObject (m, "SuperBlock", (PyObject *) &SuperBlock_Type); Py_INCREF (&DirScanIter_Type); PyModule_AddObject (m, "DirScanIter", (PyObject *) &DirScanIter_Type); Py_INCREF (&Filesystem_Type); PyModule_AddObject (m, "Filesystem", (PyObject *) &Filesystem_Type); add_constants (m); if (PyErr_Occurred ()) Py_FatalError ("can't initialize module ocfs2"); }