2 * Unix SMB/CIFS implementation.
3 * Copyright (C) Volker Lendecke 2022
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "lib/replace/system/python.h"
21 #include "python/modules.h"
22 #include "python/py3compat.h"
23 #include "libcli/util/pyerrors.h"
25 #include "smb_constants.h"
27 static PyObject
*py_reparse_put(PyObject
*module
, PyObject
*args
)
30 Py_ssize_t reparse_len
;
31 unsigned long long tag
= 0;
32 unsigned long reserved
= 0;
35 PyObject
*result
= NULL
;
36 struct reparse_data_buffer reparse_buf
= {};
39 ok
= PyArg_ParseTuple(
41 "Kk"PYARG_BYTES_LEN
":put",
50 reparse_buf
.tag
= tag
;
51 reparse_buf
.parsed
.raw
.data
= (uint8_t *)reparse
;
52 reparse_buf
.parsed
.raw
.length
= reparse_len
;
53 reparse_buf
.parsed
.raw
.reserved
= reserved
;
55 buflen
= reparse_data_buffer_marshall(&reparse_buf
, NULL
, 0);
58 PyErr_SetFromErrno(PyExc_RuntimeError
);
61 buf
= talloc_array(NULL
, uint8_t, buflen
);
66 reparse_data_buffer_marshall(&reparse_buf
, buf
, buflen
);
68 result
= PyBytes_FromStringAndSize((char *)buf
, buflen
);
73 static PyObject
*py_reparse_get(PyObject
*module
, PyObject
*args
)
77 PyObject
*result
= NULL
;
78 struct reparse_data_buffer
*rep
= NULL
;
82 ok
= PyArg_ParseTuple(args
, PYARG_BYTES_LEN
":get", &buf
, &buflen
);
87 rep
= talloc(NULL
, struct reparse_data_buffer
);
93 status
= reparse_data_buffer_parse(rep
, rep
, (uint8_t *)buf
, buflen
);
94 if (!NT_STATUS_IS_OK(status
)) {
96 PyErr_SetNTSTATUS(status
);
101 case IO_REPARSE_TAG_SYMLINK
: {
102 const struct symlink_reparse_struct
*lnk
= &rep
->parsed
.lnk
;
103 result
= Py_BuildValue("s(ssII)",
104 "IO_REPARSE_TAG_SYMLINK",
105 lnk
->substitute_name
,
107 (unsigned)lnk
->unparsed_path_length
,
108 (unsigned)lnk
->flags
);
111 case IO_REPARSE_TAG_NFS
: {
112 const struct nfs_reparse_data_buffer
*nfs
= &rep
->parsed
.nfs
;
114 case NFS_SPECFILE_LNK
:
115 result
= Py_BuildValue("ss",
117 nfs
->data
.lnk_target
);
119 case NFS_SPECFILE_BLK
:
120 result
= Py_BuildValue("sII",
122 (unsigned)nfs
->data
.dev
.major
,
123 (unsigned)nfs
->data
.dev
.minor
);
125 case NFS_SPECFILE_CHR
:
126 result
= Py_BuildValue("sII",
128 (unsigned)nfs
->data
.dev
.major
,
129 (unsigned)nfs
->data
.dev
.minor
);
131 case NFS_SPECFILE_FIFO
:
132 result
= Py_BuildValue("(s)", "NFS_SPECFILE_FIFO");
134 case NFS_SPECFILE_SOCK
:
135 result
= Py_BuildValue("(s)", "NFS_SPECFILE_SOCK");
141 if (result
== NULL
) {
142 result
= Py_BuildValue("Iy#I",
144 (const char *)rep
->parsed
.raw
.data
,
145 (Py_ssize_t
)rep
->parsed
.raw
.length
,
146 (unsigned)rep
->parsed
.raw
.reserved
);
153 static PyObject
*py_reparse_symlink_put(PyObject
*module
, PyObject
*args
)
157 struct reparse_data_buffer reparse
= {
158 .tag
= IO_REPARSE_TAG_SYMLINK
,
160 struct symlink_reparse_struct
*lnk
= &reparse
.parsed
.lnk
;
161 uint8_t stackbuf
[1024];
162 uint8_t *buf
= stackbuf
;
163 ssize_t buflen
= sizeof(stackbuf
);
164 PyObject
*result
= NULL
;
167 ok
= PyArg_ParseTuple(args
,
169 &lnk
->substitute_name
,
176 lnk
->unparsed_path_length
= unparsed
;
179 buflen
= reparse_data_buffer_marshall(&reparse
, buf
, buflen
);
181 if ((buflen
> 0) && ((size_t)buflen
> sizeof(stackbuf
))) {
182 buf
= malloc(buflen
);
183 buflen
= reparse_data_buffer_marshall(&reparse
, buf
, buflen
);
189 result
= PyBytes_FromStringAndSize((char *)buf
, buflen
);
192 if (buf
!= stackbuf
) {
199 static PyMethodDef py_reparse_symlink_methods
[] = {
201 PY_DISCARD_FUNC_SIG(PyCFunction
, py_reparse_put
),
203 "Create a reparse point blob"},
205 PY_DISCARD_FUNC_SIG(PyCFunction
, py_reparse_get
),
207 "Parse a reparse point blob"},
209 PY_DISCARD_FUNC_SIG(PyCFunction
, py_reparse_symlink_put
),
211 "Create a reparse symlink blob"},
215 static struct PyModuleDef moduledef
= {
216 PyModuleDef_HEAD_INIT
,
217 .m_name
= "reparse_symlink",
218 .m_doc
= "[un]marshall reparse symlink blobs",
220 .m_methods
= py_reparse_symlink_methods
,
223 MODULE_INIT_FUNC(reparse_symlink
)
227 m
= PyModule_Create(&moduledef
);