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 + -
显示快捷键?