Merge branch 'v3-2-test' of ssh://git.samba.org/data/git/samba into v3-2-test
[nivanova/samba-autobuild/.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;
25     int debug = 0;
26     int numeric = 0;
27     int full_time_names = 0;
28     enum acl_mode mode = SMB_ACL_LIST;
29     static char *the_acl = NULL;
30     int ret;
31     char *p;
32     char *debugstr;
33     char path[1024];
34     char value[1024];
35     poptContext pc;
36     struct poptOption long_options[] =
37         {
38             POPT_AUTOHELP
39             {
40                 "numeric", 'n', POPT_ARG_NONE, &numeric,
41                 1, "Don't resolve sids or masks to names"
42             },
43             {
44                 "debug", 'd', POPT_ARG_INT, &debug,
45                 0, "Set debug level (0-100)"
46             },
47             {
48                 "full_time_names", 'f', POPT_ARG_NONE, &full_time_names,
49                 1,
50                 "Use new style xattr names, which include CREATE_TIME"
51             },
52             {
53                 "delete", 'D', POPT_ARG_STRING, NULL,
54                 'D', "Delete an acl", "ACL"
55             },
56             {
57                 "modify", 'M', POPT_ARG_STRING, NULL,
58                 'M', "Modify an acl", "ACL"
59             },
60             {
61                 "add", 'a', POPT_ARG_STRING, NULL,
62                 'a', "Add an acl", "ACL"
63             },
64             {
65                 "set", 'S', POPT_ARG_STRING, NULL,
66                 'S', "Set acls", "ACLS"
67             },
68             {
69                 "chown", 'C', POPT_ARG_STRING, NULL,
70                 'C', "Change ownership of a file", "USERNAME"
71             },
72             {
73                 "chgrp", 'G', POPT_ARG_STRING, NULL,
74                 'G', "Change group ownership of a file", "GROUPNAME"
75             },
76             {
77                 "get", 'g', POPT_ARG_STRING, NULL,
78                 'g', "Get a specific acl attribute", "ACL"
79             },
80             {
81                 NULL
82             }
83         };
84     
85     setbuf(stdout, NULL);
86
87     pc = poptGetContext("smbcacls", argc, argv, long_options, 0);
88     
89     poptSetOtherOptionHelp(pc, "smb://server1/share1/filename");
90     
91     while ((opt = poptGetNextOpt(pc)) != -1) {
92         switch (opt) {
93         case 'S':
94             the_acl = strdup(poptGetOptArg(pc));
95             mode = SMB_ACL_SET;
96             break;
97             
98         case 'D':
99             the_acl = strdup(poptGetOptArg(pc));
100             mode = SMB_ACL_DELETE;
101             break;
102             
103         case 'M':
104             the_acl = strdup(poptGetOptArg(pc));
105             mode = SMB_ACL_MODIFY;
106             break;
107             
108         case 'a':
109             the_acl = strdup(poptGetOptArg(pc));
110             mode = SMB_ACL_ADD;
111             break;
112
113         case 'g':
114             the_acl = strdup(poptGetOptArg(pc));
115             mode = SMB_ACL_GET;
116             break;
117
118         case 'C':
119             the_acl = strdup(poptGetOptArg(pc));
120             mode = SMB_ACL_CHOWN;
121             break;
122
123         case 'G':
124             the_acl = strdup(poptGetOptArg(pc));
125             mode = SMB_ACL_CHGRP;
126             break;
127         }
128     }
129     
130     /* Make connection to server */
131     if(!poptPeekArg(pc)) { 
132         poptPrintUsage(pc, stderr, 0);
133         return 1;
134     }
135     
136     strcpy(path, poptGetArg(pc));
137     
138     if (smbc_init(get_auth_data_fn, debug) != 0)
139     {
140         printf("Could not initialize smbc_ library\n");
141         return 1;
142     }
143
144     if (full_time_names) {
145         SMBCCTX *context = smbc_set_context(NULL);
146         smbc_option_set(context, "full_time_names", 1);
147     }
148     
149     /* Perform requested action */
150     
151     switch(mode)
152     {
153     case SMB_ACL_LIST:
154         ret = smbc_listxattr(path, value, sizeof(value)-2);
155         if (ret < 0)
156         {
157             printf("Could not get attribute list for [%s] %d: %s\n",
158                    path, errno, strerror(errno));
159             return 1;
160         }
161
162         /*
163          * The list of attributes has a series of null-terminated strings.
164          * The list of strings terminates with an extra null byte, thus two in
165          * a row.  Ensure that our buffer, which is conceivably shorter than
166          * the list of attributes, actually ends with two null bytes in a row.
167          */
168         value[sizeof(value) - 2] = '\0';
169         value[sizeof(value) - 1] = '\0';
170         printf("Supported attributes:\n");
171         for (p = value; *p; p += strlen(p) + 1)
172         {
173             printf("\t%s\n", p);
174         }
175         break;
176
177     case SMB_ACL_GET:
178         if (the_acl == NULL)
179         {
180             if (numeric)
181             {
182                 the_acl = "system.*";
183             }
184             else
185             {
186                 the_acl = "system.*+";
187             }
188         }
189         ret = smbc_getxattr(path, the_acl, value, sizeof(value));
190         if (ret < 0)
191         {
192             printf("Could not get attributes for [%s] %d: %s\n",
193                    path, errno, strerror(errno));
194             return 1;
195         }
196         
197         printf("Attributes for [%s] are:\n%s\n", path, value);
198         break;
199
200     case SMB_ACL_ADD:
201         flags = SMBC_XATTR_FLAG_CREATE;
202         debugstr = "add attributes";
203         goto do_set;
204         
205     case SMB_ACL_MODIFY:
206         flags = SMBC_XATTR_FLAG_REPLACE;
207         debugstr = "modify attributes";
208         goto do_set;
209
210     case SMB_ACL_CHOWN:
211         snprintf(value, sizeof(value),
212                  "system.nt_sec_desc.owner%s:%s",
213                  numeric ? "" : "+", the_acl);
214         the_acl = value;
215         debugstr = "chown owner";
216         goto do_set;
217
218     case SMB_ACL_CHGRP:
219         snprintf(value, sizeof(value),
220                  "system.nt_sec_desc.group%s:%s",
221                  numeric ? "" : "+", the_acl);
222         the_acl = value;
223         debugstr = "change group";
224         goto do_set;
225
226     case SMB_ACL_SET:
227         flags = 0;
228         debugstr = "set attributes";
229         
230       do_set:
231         if ((p = strchr(the_acl, ':')) == NULL)
232         {
233             printf("Missing value.  ACL must be name:value pair\n");
234             return 1;
235         }
236
237         *p++ = '\0';
238         
239         ret = smbc_setxattr(path, the_acl, p, strlen(p), flags);
240         if (ret < 0)
241         {
242             printf("Could not %s for [%s] %d: %s\n",
243                    debugstr, path, errno, strerror(errno));
244             return 1;
245         }
246         break;
247
248     case SMB_ACL_DELETE:
249         ret = smbc_removexattr(path, the_acl);
250         if (ret < 0)
251         {
252             printf("Could not remove attribute %s for [%s] %d:%s\n",
253                    the_acl, path, errno, strerror(errno));
254             return 1;
255         }
256         break;
257
258     default:
259         printf("operation not yet implemented\n");
260         break;
261     }
262     
263     return 0;
264 }