py_tdbpack.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 723 行 · 第 1/2 页

C
723
字号
		if (!(nul_str = PyString_FromStringAndSize("", 1)))			goto out;	if ((PyList_Append(packed_list, coded_str) != -1)	    && (PyList_Append(packed_list, nul_str) != -1))		new_list = packed_list;  out:	Py_XDECREF(val_obj);	Py_XDECREF(unicode_obj);	Py_XDECREF(coded_str);	return new_list;}/* * Pack (LENGTH, BUFFER) pair onto the list. * * The buffer must already be a String, not Unicode, because it contains 8-bit * untranslated data.  In some cases it will actually be UTF_16_LE data. */static PyObject *pytdbpack_buffer(PyObject *val_iter, PyObject *packed_list){	PyObject *val_obj;	PyObject *new_list = NULL;		/* pull off integer and stick onto list */	if (!(packed_list = pytdbpack_number('d', val_iter, packed_list)))		return NULL;	/* this assumes that the string is the right length; the old code did	   the same. */	if (!(val_obj = PyIter_Next(val_iter)))		return NULL;	if (!PyString_Check(val_obj)) {		pytdbpack_bad_type('B', "String", val_obj);		goto out;	}		if (PyList_Append(packed_list, val_obj) != -1)		new_list = packed_list;  out:	Py_XDECREF(val_obj);	return new_list;}static PyObject *pytdbpack_bad_type(char ch,				    const char *expected,				    PyObject *val_obj){	PyObject *r = PyObject_Repr(val_obj);	if (!r)		return NULL;	PyErr_Format(PyExc_TypeError,		     "tdbpack: format '%c' requires %s, not %s",		     ch, expected, PyString_AS_STRING(r));	Py_DECREF(r);	return val_obj;}/*  XXX: glib and Samba have quicker macro for doing the endianness conversions,  but I don't know of one in plain libc, and it's probably not a big deal.  I  realize this is kind of dumb because we'll almost always be on x86, but  being safe is important.*/static void pack_le_uint32(unsigned long val_long, unsigned char *pbuf){	pbuf[0] =         val_long & 0xff;	pbuf[1] = (val_long >> 8)  & 0xff;	pbuf[2] = (val_long >> 16) & 0xff;	pbuf[3] = (val_long >> 24) & 0xff;}#if 0	/* not used */static void pack_bytes(long len, const char *from,		       unsigned char **pbuf){	memcpy(*pbuf, from, len);	(*pbuf) += len;}#endifstatic PyObject *pytdbunpack(PyObject *self,		 PyObject *args){	char *format_str, *packed_str, *ppacked;	PyObject *val_list = NULL, *ret_tuple = NULL;	PyObject *rest_string = NULL;	int format_len, packed_len;	char last_format = '#';	/* invalid */	int i;		/* get arguments */	if (!PyArg_ParseTuple(args, "ss#", &format_str, &packed_str, &packed_len))		return NULL;	format_len = strlen(format_str);		/* Allocate list to hold results.  Initially empty, and we append	   results as we go along. */	val_list = PyList_New(0);	if (!val_list)		goto failed;	ret_tuple = PyTuple_New(2);	if (!ret_tuple)		goto failed;		/* For every object, unpack.  */	for (ppacked = packed_str, i = 0; i < format_len && format_str[i] != '$'; i++) {		last_format = format_str[i];		/* packed_len is reduced in place */		if (!pytdbunpack_item(format_str[i], &ppacked, &packed_len, val_list))			goto failed;	}	/* If the last character was '$', keep going until out of space */	if (format_str[i] == '$') {		if (i == 0) {			PyErr_Format(PyExc_ValueError,				     "%s: '$' may not be first character in format",				     FUNCTION_MACRO);			return NULL;		} 		while (packed_len > 0)			if (!pytdbunpack_item(last_format, &ppacked, &packed_len, val_list))				goto failed;	}		/* save leftovers for next time */	rest_string = PyString_FromStringAndSize(ppacked, packed_len);	if (!rest_string)		goto failed;	/* return (values, rest) tuple; give up references to them */	PyTuple_SET_ITEM(ret_tuple, 0, val_list);	val_list = NULL;	PyTuple_SET_ITEM(ret_tuple, 1, rest_string);	val_list = NULL;	return ret_tuple;  failed:	/* handle failure: deallocate anything.  XDECREF forms handle NULL	   pointers for objects that haven't been allocated yet. */	Py_XDECREF(val_list);	Py_XDECREF(ret_tuple);	Py_XDECREF(rest_string);	return NULL;}static voidpytdbunpack_err_too_short(void){	PyErr_Format(PyExc_IndexError,		     "%s: data too short for unpack format", FUNCTION_MACRO);}static PyObject *pytdbunpack_uint32(char **pbuf, int *plen){	unsigned long v;	unsigned char *b;		if (*plen < 4) {		pytdbunpack_err_too_short();		return NULL;	}	b = *pbuf;	v = b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24;		(*pbuf) += 4;	(*plen) -= 4;	return PyLong_FromUnsignedLong(v);}static PyObject *pytdbunpack_int16(char **pbuf, int *plen){	long v;	unsigned char *b;		if (*plen < 2) {		pytdbunpack_err_too_short();		return NULL;	}	b = *pbuf;	v = b[0] | b[1]<<8;		(*pbuf) += 2;	(*plen) -= 2;	return PyInt_FromLong(v);}static PyObject *pytdbunpack_string(char **pbuf, int *plen, const char *encoding){	int len;	char *nul_ptr, *start;	start = *pbuf;		nul_ptr = memchr(start, '\0', *plen);	if (!nul_ptr) {		pytdbunpack_err_too_short();		return NULL;	}	len = nul_ptr - start;	*pbuf += len + 1;	/* skip \0 */	*plen -= len + 1;	return PyString_Decode(start, len, encoding, NULL);}static PyObject *pytdbunpack_buffer(char **pbuf, int *plen, PyObject *val_list){	/* first get 32-bit len */	long slen;	unsigned char *b;	unsigned char *start;	PyObject *str_obj = NULL, *len_obj = NULL;		if (*plen < 4) {		pytdbunpack_err_too_short();		return NULL;	}		b = *pbuf;	slen = b[0] | b[1]<<8 | b[2]<<16 | b[3]<<24;	if (slen < 0) { /* surely you jest */		PyErr_Format(PyExc_ValueError,			     "%s: buffer seems to have negative length", FUNCTION_MACRO);		return NULL;	}	(*pbuf) += 4;	(*plen) -= 4;	start = *pbuf;	if (*plen < slen) {		PyErr_Format(PyExc_IndexError,			     "%s: not enough data to unpack buffer: "			     "need %d bytes, have %d", FUNCTION_MACRO,			     (int) slen, *plen);		return NULL;	}	(*pbuf) += slen;	(*plen) -= slen;	if (!(len_obj = PyInt_FromLong(slen)))		goto failed;	if (PyList_Append(val_list, len_obj) == -1)		goto failed;		if (!(str_obj = PyString_FromStringAndSize(start, slen)))		goto failed;		if (PyList_Append(val_list, str_obj) == -1)		goto failed;		Py_DECREF(len_obj);	Py_DECREF(str_obj);		return val_list;  failed:	Py_XDECREF(len_obj);	/* handles NULL */	Py_XDECREF(str_obj);	return NULL;}/* Unpack a single field from packed data, according to format character CH.   Remaining data is at *PBUF, of *PLEN.   *PBUF is advanced, and *PLEN reduced to reflect the amount of data that has   been consumed.   Returns a reference to None, or NULL for failure.*/static PyObject *pytdbunpack_item(char ch,				  char **pbuf,				  int *plen,				  PyObject *val_list){	PyObject *unpacked;		if (ch == 'w') {	/* 16-bit int */		unpacked = pytdbunpack_int16(pbuf, plen);	}	else if (ch == 'd' || ch == 'p') { /* 32-bit int */		/* pointers can just come through as integers */		unpacked = pytdbunpack_uint32(pbuf, plen);	}	else if (ch == 'f' || ch == 'P') { /* nul-term string  */		unpacked = pytdbunpack_string(pbuf, plen, pytdb_unix_encoding);	}	else if (ch == 'B') { /* length, buffer */		return pytdbunpack_buffer(pbuf, plen, val_list);	}	else {		PyErr_Format(PyExc_ValueError,			     "%s: format character '%c' is not supported",                              FUNCTION_MACRO, ch);				return NULL;	}	/* otherwise OK */	if (!unpacked)		return NULL;	if (PyList_Append(val_list, unpacked) == -1)		val_list = NULL;	/* PyList_Append takes a new reference to the inserted object.	   Therefore, we no longer need the original reference. */	Py_DECREF(unpacked);		return val_list;}static PyMethodDef pytdbpack_methods[] = {	{ "pack", pytdbpack, METH_VARARGS, (char *) pytdbpack_doc },	{ "unpack", pytdbunpack, METH_VARARGS, (char *) pytdbunpack_doc },};DL_EXPORT(void)inittdbpack(void){	Py_InitModule3("tdbpack", pytdbpack_methods,		       (char *) pytdbpack_docstring);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?