Esempio n. 1
0
//-------------------------------------------------------------------------
// Converts an IDC variable to a Python variable
// If py_var points to an existing object then the object will be updated
// If py_var points to an existing immutable object then ZERO is returned
// Returns one of CIP_xxxx. Check pywraps.hpp
int idcvar_to_pyvar(
  const idc_value_t &idc_var,
  ref_t *py_var)
{
  PYW_GIL_CHECK_LOCKED_SCOPE();
  switch ( idc_var.vtype )
  {
  case VT_PVOID:
    if ( *py_var == NULL )
    {
      newref_t nr(PyCObject_FromVoidPtr(idc_var.pvoid, NULL));
      *py_var = nr;
    }
    else
    {
      return CIP_IMMUTABLE;
    }
    break;

  case VT_INT64:
    {
      // Recycle?
      if ( *py_var != NULL )
      {
        // Recycling an int64 object?
        int t = get_pyidc_cvt_type(py_var->o);
        if ( t != PY_ICID_INT64 )
          return CIP_IMMUTABLE; // Cannot recycle immutable object
        // Update the attribute
        PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, PyLong_FromLongLong(idc_var.i64));
        return CIP_OK;
      }
      ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_CVT_INT64));
      if ( py_cls == NULL )
        return CIP_FAILED;
      *py_var = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, PyLong_FromLongLong(idc_var.i64), NULL));
      if ( PyW_GetError() || *py_var == NULL )
        return CIP_FAILED;
      break;
    }

#if !defined(NO_OBSOLETE_FUNCS) || defined(__EXPR_SRC)
  case VT_STR:
    *py_var = newref_t(PyString_FromString(idc_var.str));
    break;

#endif
  case VT_STR2:
    if ( *py_var == NULL )
    {
      const qstring &s = idc_var.qstr();
      *py_var = newref_t(PyString_FromStringAndSize(s.begin(), s.length()));
      break;
    }
    else
      return CIP_IMMUTABLE; // Cannot recycle immutable object
  case VT_LONG:
    // Cannot recycle immutable objects
    if ( *py_var != NULL )
      return CIP_IMMUTABLE;
    *py_var = newref_t(cvt_to_pylong(idc_var.num));
    break;
  case VT_FLOAT:
    if ( *py_var == NULL )
    {
      double x;
      if ( ph.realcvt(&x, (uint16 *)idc_var.e, (sizeof(x)/2-1)|010) != 0 )
        INTERR(30160);

      *py_var = newref_t(PyFloat_FromDouble(x));
      break;
    }
    else
      return CIP_IMMUTABLE;

  case VT_REF:
    {
      if ( *py_var == NULL )
      {
        ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_CVT_BYREF));
        if ( py_cls == NULL )
          return CIP_FAILED;

        // Create a byref object with None value. We populate it later
        *py_var = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, Py_None, NULL));
        if ( PyW_GetError() || *py_var == NULL )
          return CIP_FAILED;
      }
      int t = get_pyidc_cvt_type(py_var->o);
      if ( t != PY_ICID_BYREF )
        return CIP_FAILED;

      // Dereference
      // (Since we are not using VREF_COPY flag, we can safely const_cast)
      idc_value_t *dref_v = VarDeref(const_cast<idc_value_t *>(&idc_var), VREF_LOOP);
      if ( dref_v == NULL )
        return CIP_FAILED;

      // Can we recycle the object?
      ref_t new_py_val(PyW_TryGetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR));
      if ( new_py_val != NULL )
      {
        // Recycle
        t = idcvar_to_pyvar(*dref_v, &new_py_val);

        // Success? Nothing more to be done
        if ( t == CIP_OK )
          return CIP_OK;

        // Clear it so we don't recycle it
        new_py_val = ref_t();
      }
      // Try to convert (not recycle)
      if ( idcvar_to_pyvar(*dref_v, &new_py_val) != CIP_OK )
        return CIP_FAILED;

      // Update the attribute
      PyObject_SetAttrString(py_var->o, S_PY_IDCCVT_VALUE_ATTR, new_py_val.o);
      break;
    }

    // Can convert back into a Python object or Python dictionary
    // (Depending if py_var will be recycled and it was a dictionary)
  case VT_OBJ:
    {
      // Check if this IDC object has __cvt_id__ and the __idc_cvt_value__ fields
      idc_value_t idc_val;
      if (    VarGetAttr(&idc_var, S_PY_IDCCVT_ID_ATTR, &idc_val) == eOk
        && VarGetAttr(&idc_var, S_PY_IDCCVT_VALUE_ATTR, &idc_val) == eOk )
      {
        // Extract the object
        *py_var = borref_t((PyObject *) idc_val.pvoid);
        return CIP_OK_OPAQUE;
      }
      ref_t obj;
      bool is_dict = false;

      // Need to create a new object?
      if ( *py_var == NULL )
      {
        // Get skeleton class reference
        ref_t py_cls(get_idaapi_attr_by_id(PY_CLSID_APPCALL_SKEL_OBJ));
        if ( py_cls == NULL )
          return CIP_FAILED;

        // Call constructor
        obj = newref_t(PyObject_CallFunctionObjArgs(py_cls.o, NULL));
        if ( PyW_GetError() || obj == NULL )
          return CIP_FAILED;
      }
      else
      {
        // Recycle existing variable
        obj = *py_var;
        if ( PyDict_Check(obj.o) )
          is_dict = true;
      }

      // Walk the IDC attributes and store into python
      for (const char *attr_name = VarFirstAttr(&idc_var);
        attr_name != NULL;
        attr_name = VarNextAttr(&idc_var, attr_name) )
      {
        // Get the attribute
        idc_value_t v;
        VarGetAttr(&idc_var, attr_name, &v, true);

        // Convert attribute to a python value (recursively)
        ref_t py_attr;
        int cvt = idcvar_to_pyvar(v, &py_attr);
        if ( cvt <= CIP_IMMUTABLE )
          return CIP_FAILED;
        if ( is_dict )
          PyDict_SetItemString(obj.o, attr_name, py_attr.o);
        else
          PyObject_SetAttrString(obj.o, attr_name, py_attr.o);
      }
      *py_var = obj;
      break;
    }
    // Unhandled type
  default:
    *py_var = ref_t();
    return CIP_FAILED;
  }
  return CIP_OK;
}
Esempio n. 2
0
/* Retrieves the size
 * Returns a Python object if successful or NULL on error
 */
PyObject *pyewf_file_entry_get_size(
           pyewf_file_entry_t *pyewf_file_entry )
{
	char error_string[ PYEWF_ERROR_STRING_SIZE ];

	libcerror_error_t *error = NULL;
	static char *function    = "pyewf_file_entry_get_size";
	size64_t size            = 0;
	int result               = 0;

	if( pyewf_file_entry == NULL )
	{
		PyErr_Format(
		 PyExc_TypeError,
		 "%s: invalid file entry.",
		 function );

		return( NULL );
	}
	Py_BEGIN_ALLOW_THREADS

	result = libewf_file_entry_get_size(
	          pyewf_file_entry->file_entry,
	          &size,
	          &error );

	Py_END_ALLOW_THREADS

	if( result != 1 )
	{
		if( libcerror_error_backtrace_sprint(
		     error,
		     error_string,
		     PYEWF_ERROR_STRING_SIZE ) == -1 )
                {
			PyErr_Format(
			 PyExc_IOError,
			 "%s: unable to retrieve size.",
			 function );
		}
		else
		{
			PyErr_Format(
			 PyExc_IOError,
			 "%s: unable to retrieve size.\n%s",
			 function,
			 error_string );
		}
		libcerror_error_free(
		 &error );

		return( NULL );
	}
#if defined( HAVE_LONG_LONG )
	if( size > (size64_t) LLONG_MAX )
	{
		PyErr_Format(
		 PyExc_OverflowError,
		 "%s: size value exceeds maximum.",
		 function );

		return( NULL );
	}
	return( PyLong_FromLongLong(
	         (long long) size ) );
#else
	if( size > (size64_t) LONG_MAX )
	{
		PyErr_Format(
		 PyExc_OverflowError,
		 "%s: size value exceeds maximum.",
		 function );

		return( NULL );
	}
	return( PyLong_FromLong(
	         (long) size ) );
#endif
}
Esempio n. 3
0
inline PyObject *cvt_to_pylong(int64 v)
{
  return PyLong_FromLongLong(v);
}
Esempio n. 4
0
/* Retrieves the entry modification date and time as an integer
 * Returns a Python object if successful or NULL on error
 */
PyObject *pyewf_file_entry_get_entry_modification_time_as_integer(
           pyewf_file_entry_t *pyewf_file_entry )
{
	char error_string[ PYEWF_ERROR_STRING_SIZE ];

	libcerror_error_t *error = NULL;
	static char *function    = "pyewf_file_entry_get_entry_modification_time_as_integer";
	uint32_t posix_time      = 0;
	int result               = 0;

	if( pyewf_file_entry == NULL )
	{
		PyErr_Format(
		 PyExc_ValueError,
		 "%s: invalid file entry.",
		 function );

		return( NULL );
	}
	Py_BEGIN_ALLOW_THREADS

	result = libewf_file_entry_get_entry_modification_time(
	          pyewf_file_entry->file_entry,
	          &posix_time,
	          &error );

	Py_END_ALLOW_THREADS

	if( result != 1 )
	{
		if( libcerror_error_backtrace_sprint(
		     error,
		     error_string,
		     PYEWF_ERROR_STRING_SIZE ) == -1 )
		{
			PyErr_Format(
			 PyExc_IOError,
			 "%s: unable to retrieve entry modification time.",
			 function );
		}
		else
		{
			PyErr_Format(
			 PyExc_IOError,
			 "%s: unable to retrieve entry modification time.\n%s",
			 function,
			 error_string );
		}
		libcerror_error_free(
		 &error );

		return( NULL );
	}
#if defined( HAVE_LONG_LONG )
	if( (uint64_t) posix_time > (uint64_t) LLONG_MAX )
	{
		PyErr_Format(
		 PyExc_OverflowError,
		 "%s: POSIX time value exceeds maximum.",
		 function );

		return( NULL );
	}
	return( PyLong_FromLongLong(
	         (long long) posix_time ) );
#else
	if( (uint64_t) posix_time > (uint64_t) LONG_MAX )
	{
		PyErr_Format(
		 PyExc_OverflowError,
		 "%s: POSIX time value exceeds maximum.",
		 function );

		return( NULL );
	}
	return( PyLong_FromLong(
	         (long) posix_time ) );
#endif
}
Esempio n. 5
0
PyObject *
PyMember_GetOne(const char *addr, PyMemberDef *l)
{
    PyObject *v;
    if ((l->flags & READ_RESTRICTED) &&
        PyEval_GetRestricted()) {
        PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
        return NULL;
    }
    addr += l->offset;
    switch (l->type) {
    case T_BOOL:
        v = PyBool_FromLong(*(char*)addr);
        break;
    case T_BYTE:
        v = PyInt_FromLong(*(char*)addr);
        break;
    case T_UBYTE:
        v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
        break;
    case T_SHORT:
        v = PyInt_FromLong(*(short*)addr);
        break;
    case T_USHORT:
        v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
        break;
    case T_INT:
        v = PyInt_FromLong(*(int*)addr);
        break;
    case T_UINT:
        v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
        break;
    case T_LONG:
        v = PyInt_FromLong(*(long*)addr);
        break;
    case T_ULONG:
        v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
        break;
    case T_PYSSIZET:
        v = PyInt_FromSsize_t(*(Py_ssize_t*)addr);
        break;
    case T_FLOAT:
        v = PyFloat_FromDouble((double)*(float*)addr);
        break;
    case T_DOUBLE:
        v = PyFloat_FromDouble(*(double*)addr);
        break;
    case T_STRING:
        if (*(char**)addr == NULL) {
            Py_INCREF(Py_None);
            v = Py_None;
        }
        else
            v = PyString_FromString(*(char**)addr);
        break;
    case T_STRING_INPLACE:
        v = PyString_FromString((char*)addr);
        break;
    case T_CHAR:
        v = PyString_FromStringAndSize((char*)addr, 1);
        break;
    case T_OBJECT:
        v = *(PyObject **)addr;
        if (v == NULL)
            v = Py_None;
        Py_INCREF(v);
        break;
    case T_OBJECT_EX:
        v = *(PyObject **)addr;
        if (v == NULL)
            PyErr_SetString(PyExc_AttributeError, l->name);
        Py_XINCREF(v);
        break;
#ifdef HAVE_LONG_LONG
    case T_LONGLONG:
        v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr);
        break;
    case T_ULONGLONG:
        v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr);
        break;
#endif /* HAVE_LONG_LONG */
    default:
        PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
        v = NULL;
    }
    return v;
}
Esempio n. 6
0
static void *createIntegerObject(const redisReadTask *task, long long value) {
    PyObject *obj;
    obj = PyLong_FromLongLong(value);
    return tryParentize(task, obj);
}
Esempio n. 7
0
PyObject *
PyObject_FromMetalink(LrMetalink *metalink)
{
    PyObject *dict, *sub_list;

    if (!metalink)
        Py_RETURN_NONE;

    if ((dict = PyDict_New()) == NULL)
        return NULL;

    PyDict_SetItemString(dict, "filename",
            PyStringOrNone_FromString(metalink->filename));
    PyDict_SetItemString(dict, "timestamp",
            PyLong_FromLongLong((PY_LONG_LONG)metalink->timestamp));
    PyDict_SetItemString(dict, "size",
            PyLong_FromLongLong((PY_LONG_LONG)metalink->size));

    // Hashes
    if ((sub_list = PyList_New(0)) == NULL) {
        PyDict_Clear(dict);
        return NULL;
    }
    PyDict_SetItemString(dict, "hashes", sub_list);

    for (GSList *elem = metalink->hashes; elem; elem = g_slist_next(elem)) {
        LrMetalinkHash *metalinkhash = elem->data;
        PyObject *tuple;
        if ((tuple = PyTuple_New(2)) == NULL) {
            PyDict_Clear(dict);
            return NULL;
        }
        PyTuple_SetItem(tuple, 0,
                PyStringOrNone_FromString(metalinkhash->type));
        PyTuple_SetItem(tuple, 1,
                PyStringOrNone_FromString(metalinkhash->value));
        PyList_Append(sub_list, tuple);
    }

    // Urls
    if ((sub_list = PyList_New(0)) == NULL) {
        PyDict_Clear(dict);
        return NULL;
    }
    PyDict_SetItemString(dict, "urls", sub_list);

    for (GSList *elem = metalink->urls; elem; elem = g_slist_next(elem)) {
        LrMetalinkUrl *metalinkurl = elem->data;
        PyObject *udict;
        if ((udict = PyDict_New()) == NULL) {
            PyDict_Clear(dict);
            return NULL;
        }
        PyDict_SetItemString(udict, "protocol",
                PyStringOrNone_FromString(metalinkurl->protocol));
        PyDict_SetItemString(udict, "type",
                PyStringOrNone_FromString(metalinkurl->type));
        PyDict_SetItemString(udict, "location",
                PyStringOrNone_FromString(metalinkurl->location));
        PyDict_SetItemString(udict, "preference",
                PyLong_FromLong((long) metalinkurl->preference));
        PyDict_SetItemString(udict, "url",
                PyStringOrNone_FromString(metalinkurl->url));
        PyList_Append(sub_list, udict);
    }

    // Alternates

    if (metalink->alternates) {

        if ((sub_list = PyList_New(0)) == NULL) {
            PyDict_Clear(dict);
            return NULL;
        }
        PyDict_SetItemString(dict, "alternates", sub_list);

        for (GSList *elem = metalink->alternates; elem; elem = g_slist_next(elem)) {
            LrMetalinkAlternate *ma = elem->data;
            PyObject *udict;
            if ((udict = PyDict_New()) == NULL) {
                PyDict_Clear(dict);
                return NULL;
            }
            PyDict_SetItemString(udict, "timestamp",
                PyLong_FromLongLong((PY_LONG_LONG)ma->timestamp));
            PyDict_SetItemString(udict, "size",
                PyLong_FromLongLong((PY_LONG_LONG)ma->size));

            PyObject *usub_list;
            if ((usub_list = PyList_New(0)) == NULL) {
                PyDict_Clear(dict);
                return NULL;
            }
            PyDict_SetItemString(udict, "hashes", usub_list);

            for (GSList *subelem = ma->hashes; subelem; subelem = g_slist_next(subelem)) {
                LrMetalinkHash *metalinkhash = subelem->data;
                PyObject *tuple;
                if ((tuple = PyTuple_New(2)) == NULL) {
                    PyDict_Clear(dict);
                    return NULL;
                }
                PyTuple_SetItem(tuple, 0,
                        PyStringOrNone_FromString(metalinkhash->type));
                PyTuple_SetItem(tuple, 1,
                        PyStringOrNone_FromString(metalinkhash->value));
                PyList_Append(usub_list, tuple);
            }

            PyList_Append(sub_list, udict);
        }
    }

    return dict;
}
Esempio n. 8
0
static PyObject *
pygvfinfo_getattr(PyGnomeVFSFileInfo *self, const gchar *attr)
{
    GnomeVFSFileInfo *finfo;

    finfo = self->finfo;
    if (!strcmp(attr, "__members__")) {
	return Py_BuildValue("[ssssssssssssssssss]", "atime", "block_count",
			     "ctime", "device", "flags", "gid", "inode",
			     "io_block_size", "link_count", "mime_type",
			     "mtime", "name", "permissions", "access", "size",
			     "symlink_name", "type", "uid", "valid_fields");
    } else if (!strcmp(attr, "name")) {
	if (finfo->name)
	    return PyString_FromString(finfo->name);
	Py_INCREF(Py_None);
	return Py_None;
    } else if (!strcmp(attr, "valid_fields")) {
	return PyInt_FromLong(finfo->valid_fields);
    } else if (!strcmp(attr, "type")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE)) {
	    PyErr_SetString(PyExc_ValueError, "type field has no valid value");
	    return NULL;
	}
	return PyInt_FromLong(finfo->type);
    } else if (!strcmp(attr, "permissions")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS)) {
	    PyErr_SetString(PyExc_ValueError,
			    "permissions field has no valid value");
	    return NULL;
	}
	return PyInt_FromLong(finfo->permissions & (~PYGNOME_VFS_ACCESS_BITS));
    } else if (!strcmp(attr, "access")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_ACCESS)) {
	    PyErr_SetString(PyExc_ValueError,
			    "access field has no valid value");
	    return NULL;
	}
	return PyInt_FromLong(finfo->permissions & PYGNOME_VFS_ACCESS_BITS);
    } else if (!strcmp(attr, "flags")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_FLAGS)) {
	    PyErr_SetString(PyExc_ValueError,"flags field has no valid value");
	    return NULL;
	}
	return PyInt_FromLong(finfo->flags);
    } else if (!strcmp(attr, "device")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_DEVICE)) {
	    PyErr_SetString(PyExc_ValueError,
			    "device field has no valid value");
	    return NULL;
	}
	if (finfo->device <= G_MAXLONG)
	    return PyInt_FromLong(finfo->device);
	else
	    return PyLong_FromUnsignedLongLong(finfo->device);
    } else if (!strcmp(attr, "inode")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_INODE)) {
	    PyErr_SetString(PyExc_ValueError,"inode field has no valid value");
	    return NULL;
	}
	if (finfo->inode <= G_MAXLONG)
	    return PyInt_FromLong(finfo->inode);
	else
	    return PyLong_FromUnsignedLongLong(finfo->inode);
    } else if (!strcmp(attr, "link_count")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_LINK_COUNT)) {
	    PyErr_SetString(PyExc_ValueError,
			    "link_count field has no valid value");
	    return NULL;
	}
	if (finfo->link_count < G_MAXLONG)
	    return PyInt_FromLong(finfo->link_count);
	else
	    return PyLong_FromUnsignedLong(finfo->link_count);
    } else if (!strcmp(attr, "uid")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_IDS)) {
	    PyErr_SetString(PyExc_ValueError, "uid field has no valid value");
	    return NULL;
	}
	if (finfo->uid < G_MAXLONG)
	    return PyInt_FromLong(finfo->uid);
	else
	    return PyLong_FromUnsignedLong(finfo->uid);
    } else if (!strcmp(attr, "gid")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_IDS)) {
	    PyErr_SetString(PyExc_ValueError, "gid field has no valid value");
	    return NULL;
	}
	if (finfo->gid < G_MAXLONG)
	    return PyInt_FromLong(finfo->gid);
	else
	    return PyLong_FromUnsignedLong(finfo->gid);
    } else if (!strcmp(attr, "size")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE)) {
	    PyErr_SetString(PyExc_ValueError, "size field has no valid value");
	    return NULL;
	}
	if (finfo->size <= G_MAXLONG)
	    return PyInt_FromLong(finfo->size);
	else
	    return PyLong_FromUnsignedLongLong(finfo->size);
    } else if (!strcmp(attr, "block_count")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT)) {
	    PyErr_SetString(PyExc_ValueError,
			    "block_count field has no valid value");
	    return NULL;
	}
	if (finfo->block_count <= G_MAXLONG)
	    return PyInt_FromLong(finfo->block_count);
	else
	    return PyLong_FromUnsignedLongLong(finfo->block_count);
    } else if (!strcmp(attr, "io_block_size")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE)){
	    PyErr_SetString(PyExc_ValueError,
			    "io_block_size field has no valid value");
	    return NULL;
	}
	if (finfo->io_block_size < G_MAXLONG)
	    return PyInt_FromLong(finfo->io_block_size);
	else
	    return PyLong_FromUnsignedLong(finfo->io_block_size);
    } else if (!strcmp(attr, "atime")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_ATIME)) {
	    PyErr_SetString(PyExc_ValueError,"atime field has no valid value");
	    return NULL;
	}
	return PyLong_FromLongLong(finfo->atime);
    } else if (!strcmp(attr, "mtime")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MTIME)) {
	    PyErr_SetString(PyExc_ValueError,"mtime field has no valid value");
	    return NULL;
	}
	return PyLong_FromLongLong(finfo->mtime);
    } else if (!strcmp(attr, "ctime")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_CTIME)) {
	    PyErr_SetString(PyExc_ValueError,"ctime field has no valid value");
	    return NULL;
	}
	return PyLong_FromLongLong(finfo->ctime);
    } else if (!strcmp(attr, "symlink_name")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME)) {
	    PyErr_SetString(PyExc_ValueError,
			    "link_name field has no valid value");
	    return NULL;
	}
	if (finfo->symlink_name)
	    return PyString_FromString(finfo->symlink_name);
	Py_INCREF(Py_None);
	return Py_None;
    } else if (!strcmp(attr, "mime_type")) {
	if (!(finfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE)) {
	    PyErr_SetString(PyExc_ValueError,
			    "mime_type field has no valid value");
	    return NULL;
	}
	if (finfo->mime_type)
	    return PyString_FromString(finfo->mime_type);
	Py_INCREF(Py_None);
	return Py_None;
    } else {
	PyObject *name = PyString_FromString(attr);
	PyObject *ret = PyObject_GenericGetAttr((PyObject *)self, name);

	Py_DECREF(name);
	return ret;
    }
}