python:tests: Store keys as bytes rather than as lists of ints
[samba.git] / examples / libsmbclient / testacl.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <popt.h>
5 #include "libsmbclient.h"
6 #include "get_auth_data_fn.h"
7
8 enum acl_mode
9 {
10         SMB_ACL_LIST,
11         SMB_ACL_GET,
12         SMB_ACL_SET,
13         SMB_ACL_DELETE,
14         SMB_ACL_MODIFY,
15         SMB_ACL_ADD,
16         SMB_ACL_CHOWN,
17         SMB_ACL_CHGRP
18 };
19
20
21 int main(int argc, const char *argv[])
22 {
23         int opt;
24         int flags = 0;
25         int debug = 0;
26         int numeric = 0;
27         int stat_and_retry = 0;
28         int full_time_names = 0;
29         enum acl_mode mode = SMB_ACL_LIST;
30         static const char *the_acl = NULL;
31         int ret;
32         char *p;
33         const char *debugstr;
34         char path[1024];
35         char value[1024];
36         poptContext pc;
37         struct stat st;
38         struct poptOption long_options[] =
39         {
40                 POPT_AUTOHELP
41                 {
42                         .longName   = "numeric",
43                         .shortName  = 'n',
44                         .argInfo    = POPT_ARG_NONE,
45                         .arg        = &numeric,
46                         .val        = 1,
47                         .descrip    = "Don't resolve sids or masks to names"
48                 },
49                 {
50                         .longName   = "debug",
51                         .shortName  = 'd',
52                         .argInfo    = POPT_ARG_INT,
53                         .arg        = &debug,
54                         .val        = 0,
55                         .descrip    = "Set debug level (0-100)"
56                 },
57                 {
58                         .longName   = "full_time_names",
59                         .shortName  = 'f',
60                         .argInfo    = POPT_ARG_NONE,
61                         .arg        = &full_time_names,
62                         .val        = 1,
63                         .descrip    = "Use new style xattr names, which include CREATE_TIME"
64                 },
65                 {
66                         .longName   = "delete",
67                         .shortName  = 'D',
68                         .argInfo    = POPT_ARG_STRING,
69                         .arg        = NULL,
70                         .val        = 'D',
71                         .descrip    = "Delete an acl",
72                         .argDescrip = "ACL"
73                 },
74                 {
75                         .longName   = "modify",
76                         .shortName  = 'M',
77                         .argInfo    = POPT_ARG_STRING,
78                         .arg        = NULL,
79                         .val        = 'M',
80                         .descrip    = "Modify an acl",
81                         .argDescrip = "ACL"
82                 },
83                 {
84                         .longName   = "add",
85                         .shortName  = 'a',
86                         .argInfo    = POPT_ARG_STRING,
87                         .arg        = NULL,
88                         .val        = 'a',
89                         .descrip    = "Add an acl",
90                         .argDescrip = "ACL"
91                 },
92                 {
93                         .longName   = "set",
94                         .shortName  = 'S',
95                         .argInfo    = POPT_ARG_STRING,
96                         .arg        = NULL,
97                         .val        = 'S',
98                         .descrip    = "Set acls",
99                         .argDescrip = "ACLS"
100                 },
101                 {
102                         .longName   = "chown",
103                         .shortName  = 'C',
104                         .argInfo    = POPT_ARG_STRING,
105                         .arg        = NULL,
106                         .val        = 'C',
107                         .descrip    = "Change ownership of a file",
108                         .argDescrip = "USERNAME"
109                 },
110                 {
111                         .longName   = "chgrp",
112                         .shortName  = 'G',
113                         .argInfo    = POPT_ARG_STRING,
114                         .arg        = NULL,
115                         .val        = 'G',
116                         .descrip    = "Change group ownership of a file",
117                         .argDescrip = "GROUPNAME"
118                 },
119                 {
120                         .longName   = "get",
121                         .shortName  = 'g',
122                         .argInfo    = POPT_ARG_STRING,
123                         .arg        = NULL,
124                         .val        = 'g',
125                         .descrip    = "Get a specific acl attribute",
126                         .argDescrip = "ACL"
127                 },
128                 {
129                         .longName   = "stat_and_retry",
130                         .shortName  = 'R',
131                         .argInfo    = POPT_ARG_NONE,
132                         .arg        = &stat_and_retry,
133                         .val        = 1,
134                         .descrip    = "After 'get' do 'stat' and another 'get'"
135                 },
136                 POPT_TABLEEND
137         };
138
139         setbuf(stdout, NULL);
140
141         pc = poptGetContext("smbcacls", argc, argv, long_options, 0);
142
143         poptSetOtherOptionHelp(pc, "smb://server1/share1/filename");
144
145         while ((opt = poptGetNextOpt(pc)) != -1) {
146                 switch (opt) {
147                 case 'S':
148                         the_acl = strdup(poptGetOptArg(pc));
149                         mode = SMB_ACL_SET;
150                         break;
151
152                 case 'D':
153                         the_acl = strdup(poptGetOptArg(pc));
154                         mode = SMB_ACL_DELETE;
155                         break;
156
157                 case 'M':
158                         the_acl = strdup(poptGetOptArg(pc));
159                         mode = SMB_ACL_MODIFY;
160                         break;
161
162                 case 'a':
163                         the_acl = strdup(poptGetOptArg(pc));
164                         mode = SMB_ACL_ADD;
165                         break;
166
167                 case 'g':
168                         the_acl = strdup(poptGetOptArg(pc));
169                         mode = SMB_ACL_GET;
170                         break;
171
172                 case 'C':
173                         the_acl = strdup(poptGetOptArg(pc));
174                         mode = SMB_ACL_CHOWN;
175                         break;
176
177                 case 'G':
178                         the_acl = strdup(poptGetOptArg(pc));
179                         mode = SMB_ACL_CHGRP;
180                         break;
181                 }
182         }
183
184         /* Make connection to server */
185         if(!poptPeekArg(pc)) {
186                 poptPrintUsage(pc, stderr, 0);
187                 return 1;
188         }
189
190         strncpy(path, poptGetArg(pc), sizeof(path));
191         path[sizeof(path)-1] = '\0';
192
193         if (smbc_init(get_auth_data_fn, debug) != 0)
194         {
195                 printf("Could not initialize smbc_ library\n");
196                 return 1;
197         }
198
199         if (full_time_names) {
200                 SMBCCTX *context = smbc_set_context(NULL);
201                 smbc_setOptionFullTimeNames(context, 1);
202         }
203
204         /* Perform requested action */
205
206         switch(mode)
207         {
208         case SMB_ACL_LIST:
209                 ret = smbc_listxattr(path, value, sizeof(value)-2);
210                 if (ret < 0)
211                 {
212                         printf("Could not get attribute list for [%s] %d: %s\n",
213                                         path, errno, strerror(errno));
214                         return 1;
215                 }
216
217                 /*
218                  * The list of attributes has a series of null-terminated strings.
219                  * The list of strings terminates with an extra null byte, thus two in
220                  * a row.  Ensure that our buffer, which is conceivably shorter than
221                  * the list of attributes, actually ends with two null bytes in a row.
222                  */
223                 value[sizeof(value) - 2] = '\0';
224                 value[sizeof(value) - 1] = '\0';
225                 printf("Supported attributes:\n");
226                 for (p = value; *p; p += strlen(p) + 1)
227                 {
228                         printf("\t%s\n", p);
229                 }
230                 break;
231
232         case SMB_ACL_GET:
233                 do
234                 {
235                         if (the_acl == NULL)
236                         {
237                                 if (numeric)
238                                 {
239                                         the_acl = "system.*";
240                                 }
241                                 else
242                                 {
243                                         the_acl = "system.*+";
244                                 }
245                         }
246                         ret = smbc_getxattr(path, the_acl, value, sizeof(value));
247                         if (ret < 0)
248                         {
249                                 printf("Could not get attributes for [%s] %d: %s\n",
250                                                 path, errno, strerror(errno));
251                                 return 1;
252                         }
253
254                         printf("Attributes for [%s] are:\n%s\n", path, value);
255
256                         if (stat_and_retry)
257                         {
258                                 if (smbc_stat(path, &st) < 0)
259                                 {
260                                         perror("smbc_stat");
261                                         return 1;
262                                 }
263                         }
264
265                         --stat_and_retry;
266                 } while (stat_and_retry >= 0);
267                 break;
268
269         case SMB_ACL_ADD:
270                 flags = SMBC_XATTR_FLAG_CREATE;
271                 debugstr = "add attributes";
272                 goto do_set;
273
274         case SMB_ACL_MODIFY:
275                 flags = SMBC_XATTR_FLAG_REPLACE;
276                 debugstr = "modify attributes";
277                 goto do_set;
278
279         case SMB_ACL_CHOWN:
280                 snprintf(value, sizeof(value),
281                                 "system.nt_sec_desc.owner%s:%s",
282                                 numeric ? "" : "+", the_acl);
283                 the_acl = value;
284                 debugstr = "chown owner";
285                 goto do_set;
286
287         case SMB_ACL_CHGRP:
288                 snprintf(value, sizeof(value),
289                                 "system.nt_sec_desc.group%s:%s",
290                                 numeric ? "" : "+", the_acl);
291                 the_acl = value;
292                 debugstr = "change group";
293                 goto do_set;
294
295         case SMB_ACL_SET:
296                 flags = 0;
297                 debugstr = "set attributes";
298
299 do_set:
300                 if ((p = strchr(the_acl, ':')) == NULL)
301                 {
302                         printf("Missing value.  ACL must be name:value pair\n");
303                         return 1;
304                 }
305
306                 *p++ = '\0';
307
308                 ret = smbc_setxattr(path, the_acl, p, strlen(p), flags);
309                 if (ret < 0)
310                 {
311                         printf("Could not %s for [%s] %d: %s\n",
312                                         debugstr, path, errno, strerror(errno));
313                         return 1;
314                 }
315                 break;
316
317         case SMB_ACL_DELETE:
318                 ret = smbc_removexattr(path, the_acl);
319                 if (ret < 0)
320                 {
321                         printf("Could not remove attribute %s for [%s] %d:%s\n",
322                                         the_acl, path, errno, strerror(errno));
323                         return 1;
324                 }
325                 break;
326
327         default:
328                 printf("operation not yet implemented\n");
329                 break;
330         }
331
332         return 0;
333 }