{
char *buf = NULL;
Py_ssize_t buflen;
- struct symlink_reparse_struct *syml = NULL;
+ struct symlink_reparse_struct syml = {
+ .flags = 0,
+ };
PyObject *result = NULL;
+ int ret;
bool ok;
ok = PyArg_ParseTuple(args, PYARG_BYTES_LEN ":get", &buf, &buflen);
return NULL;
}
- syml = symlink_reparse_buffer_parse(NULL, (uint8_t *)buf, buflen);
- if (syml == NULL) {
- PyErr_NoMemory();
+ ret = symlink_reparse_buffer_parse(NULL, &syml, (uint8_t *)buf, buflen);
+ if (ret != 0) {
+ errno = ret;
+ PyErr_SetFromErrno(PyExc_RuntimeError);
return NULL;
}
- result = Py_BuildValue(
- "ssII",
- syml->substitute_name,
- syml->print_name,
- (unsigned)syml->unparsed_path_length,
- (unsigned)syml->flags);
- TALLOC_FREE(syml);
+ result = Py_BuildValue("ssII",
+ syml.substitute_name,
+ syml.print_name,
+ (unsigned)syml.unparsed_path_length,
+ (unsigned)syml.flags);
+
+ TALLOC_FREE(syml.print_name);
+ TALLOC_FREE(syml.substitute_name);
return result;
}
return ret;
}
-struct symlink_reparse_struct *symlink_reparse_buffer_parse(
- TALLOC_CTX *mem_ctx, const uint8_t *src, size_t srclen)
+int symlink_reparse_buffer_parse(TALLOC_CTX *mem_ctx,
+ struct symlink_reparse_struct *dst,
+ const uint8_t *src,
+ size_t srclen)
{
- struct symlink_reparse_struct *result = NULL;
uint16_t reparse_data_length;
uint16_t substitute_name_offset, substitute_name_length;
uint16_t print_name_offset, print_name_length;
if (srclen < 20) {
DBG_DEBUG("srclen = %zu, expected >= 20\n", srclen);
- goto fail;
+ return EINVAL;
}
if (IVAL(src, 0) != IO_REPARSE_TAG_SYMLINK) {
DBG_DEBUG("Got ReparseTag %8.8x, expected %8.8x\n",
IVAL(src, 0),
IO_REPARSE_TAG_SYMLINK);
- goto fail;
+ return EINVAL;
}
reparse_data_length = SVAL(src, 4);
if (reparse_data_length < 12) {
DBG_DEBUG("reparse_data_length = %"PRIu16", expected >= 12\n",
reparse_data_length);
- goto fail;
+ return EINVAL;
}
if (smb_buffer_oob(srclen - 8, reparse_data_length, 0)) {
DBG_DEBUG("reparse_data_length (%"PRIu16") too large for "
"src_len (%zu)\n",
reparse_data_length,
srclen);
- goto fail;
+ return EINVAL;
}
if (smb_buffer_oob(reparse_data_length - 12, substitute_name_offset,
substitute_name_length)) {
substitute_name_offset,
substitute_name_length,
reparse_data_length - 12);
- goto fail;
+ return EINVAL;
}
if (smb_buffer_oob(reparse_data_length - 12, print_name_offset,
print_name_length)) {
print_name_offset,
print_name_length,
reparse_data_length - 12);
- goto fail;
+ return EINVAL;
}
- result = talloc_zero(mem_ctx, struct symlink_reparse_struct);
- if (result == NULL) {
- DBG_DEBUG("talloc failed\n");
- goto fail;
- }
+ *dst = (struct symlink_reparse_struct) {
+ .unparsed_path_length = PULL_LE_U16(src, 6),
+ .flags = PULL_LE_U32(src, 16),
+ };
- ok = convert_string_talloc(
- result,
- CH_UTF16,
- CH_UNIX,
- src + 20 + substitute_name_offset,
- substitute_name_length,
- &result->substitute_name,
- NULL);
+ ok = convert_string_talloc(mem_ctx,
+ CH_UTF16,
+ CH_UNIX,
+ src + 20 + substitute_name_offset,
+ substitute_name_length,
+ &dst->substitute_name,
+ NULL);
if (!ok) {
+ int ret = errno;
DBG_DEBUG("convert_string_talloc for substitute_name "
"failed\n");
- goto fail;
+ return ret;
}
- ok = convert_string_talloc(
- result,
- CH_UTF16,
- CH_UNIX,
- src + 20 + print_name_offset,
- print_name_length,
- &result->print_name,
- NULL);
+ ok = convert_string_talloc(mem_ctx,
+ CH_UTF16,
+ CH_UNIX,
+ src + 20 + print_name_offset,
+ print_name_length,
+ &dst->print_name,
+ NULL);
if (!ok) {
+ int ret = errno;
DBG_DEBUG("convert_string_talloc for print_name failed\n");
- goto fail;
+ TALLOC_FREE(dst->substitute_name);
+ return ret;
}
- result->unparsed_path_length = SVAL(src, 6);
- result->flags = IVAL(src, 16);
-
- return result;
-fail:
- TALLOC_FREE(result);
- return NULL;
+ return 0;
}
TALLOC_CTX *mem_ctx,
uint8_t **pdst,
size_t *pdstlen);
-struct symlink_reparse_struct *symlink_reparse_buffer_parse(
- TALLOC_CTX *mem_ctx, const uint8_t *src, size_t srclen);
+int symlink_reparse_buffer_parse(TALLOC_CTX *mem_ctx,
+ struct symlink_reparse_struct *dst,
+ const uint8_t *src,
+ size_t srclen);
#endif
{
struct symlink_reparse_struct *symlink = NULL;
uint32_t symlink_length, error_tag;
+ int ret;
if (buflen < 8) {
DBG_DEBUG("buffer too short: %zu bytes\n", buflen);
return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
- symlink = symlink_reparse_buffer_parse(
- mem_ctx, buf+8, buflen-8);
+ symlink = talloc(mem_ctx, struct symlink_reparse_struct);
if (symlink == NULL) {
- DBG_DEBUG("symlink_reparse_buffer_parse failed\n");
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = symlink_reparse_buffer_parse(
+ symlink, symlink, buf+8, buflen-8);
+ if (ret != 0) {
+ DBG_DEBUG("symlink_reparse_buffer_parse failed: %s\n", strerror(ret));
return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
{
struct cli_readlink_state *state = tevent_req_data(
req, struct cli_readlink_state);
- struct symlink_reparse_struct *symlink = NULL;
+ struct symlink_reparse_struct symlink = { .flags = 0, };
NTSTATUS status;
+ int ret;
if (tevent_req_is_nterror(req, &status)) {
return status;
return NT_STATUS_OK;
}
- symlink = symlink_reparse_buffer_parse(
- talloc_tos(), state->data, state->num_data);
- if (symlink == NULL) {
+ ret = symlink_reparse_buffer_parse(
+ talloc_tos(), &symlink, state->data, state->num_data);
+ if (ret != 0) {
return NT_STATUS_INVALID_NETWORK_RESPONSE;
}
if (psubstitute_name != NULL) {
*psubstitute_name = talloc_move(
- mem_ctx, &symlink->substitute_name);
+ mem_ctx, &symlink.substitute_name);
}
if (pprint_name != NULL) {
- *pprint_name = talloc_move(mem_ctx, &symlink->print_name);
+ *pprint_name = talloc_move(mem_ctx, &symlink.print_name);
}
if (pflags != NULL) {
- *pflags = symlink->flags;
+ *pflags = symlink.flags;
}
- TALLOC_FREE(symlink);
+ TALLOC_FREE(symlink.print_name);
+ TALLOC_FREE(symlink.substitute_name);
return NT_STATUS_OK;
}