WHATSNEW: Start release notes for 3.5.9.
[Samba.git] / source3 / modules / vfs_tru64acl.c
bloba97886844498542179938704b2f59889b2cdd509
1 /*
2 Unix SMB/Netbios implementation.
3 VFS module to get and set Tru64 acls
4 Copyright (C) Michael Adam 2006,2008
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
22 /* prototypes for private functions first - for clarity */
24 static struct smb_acl_t *tru64_acl_to_smb_acl(const struct acl *tru64_acl);
25 static bool tru64_ace_to_smb_ace(acl_entry_t tru64_ace,
26 struct smb_acl_entry *smb_ace);
27 static acl_t smb_acl_to_tru64_acl(const SMB_ACL_T smb_acl);
28 static acl_tag_t smb_tag_to_tru64(SMB_ACL_TAG_T smb_tag);
29 static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag);
30 static acl_perm_t smb_permset_to_tru64(SMB_ACL_PERM_T smb_permset);
31 static SMB_ACL_PERM_T tru64_permset_to_smb(const acl_perm_t tru64_permset);
34 /* public functions - the api */
36 SMB_ACL_T tru64acl_sys_acl_get_file(vfs_handle_struct *handle,
37 const char *path_p,
38 SMB_ACL_TYPE_T type)
40 struct smb_acl_t *result;
41 acl_type_t the_acl_type;
42 acl_t tru64_acl;
44 DEBUG(10, ("Hi! This is tru64acl_sys_acl_get_file.\n"));
46 switch(type) {
47 case SMB_ACL_TYPE_ACCESS:
48 the_acl_type = ACL_TYPE_ACCESS;
49 break;
50 case SMB_ACL_TYPE_DEFAULT:
51 the_acl_type = ACL_TYPE_DEFAULT;
52 break;
53 default:
54 errno = EINVAL;
55 return NULL;
58 tru64_acl = acl_get_file((char *)path_p, the_acl_type);
60 if (tru64_acl == NULL) {
61 return NULL;
64 result = tru64_acl_to_smb_acl(tru64_acl);
65 acl_free(tru64_acl);
66 return result;
69 SMB_ACL_T tru64acl_sys_acl_get_fd(vfs_handle_struct *handle,
70 files_struct *fsp)
72 struct smb_acl_t *result;
73 acl_t tru64_acl = acl_get_fd(fsp->fh->fd, ACL_TYPE_ACCESS);
75 if (tru64_acl == NULL) {
76 return NULL;
79 result = tru64_acl_to_smb_acl(tru64_acl);
80 acl_free(tru64_acl);
81 return result;
84 int tru64acl_sys_acl_set_file(vfs_handle_struct *handle,
85 const char *name,
86 SMB_ACL_TYPE_T type,
87 SMB_ACL_T theacl)
89 int res;
90 acl_type_t the_acl_type;
91 acl_t tru64_acl;
93 DEBUG(10, ("tru64acl_sys_acl_set_file called with name %s, type %d\n",
94 name, type));
96 switch(type) {
97 case SMB_ACL_TYPE_ACCESS:
98 DEBUGADD(10, ("got acl type ACL_TYPE_ACCESS\n"));
99 the_acl_type = ACL_TYPE_ACCESS;
100 break;
101 case SMB_ACL_TYPE_DEFAULT:
102 DEBUGADD(10, ("got acl type ACL_TYPE_DEFAULT\n"));
103 the_acl_type = ACL_TYPE_DEFAULT;
104 break;
105 default:
106 DEBUGADD(10, ("invalid acl type\n"));
107 errno = EINVAL;
108 goto fail;
111 tru64_acl = smb_acl_to_tru64_acl(theacl);
112 if (tru64_acl == NULL) {
113 DEBUG(10, ("smb_acl_to_tru64_acl failed!\n"));
114 goto fail;
116 DEBUG(10, ("got tru64 acl...\n"));
117 res = acl_set_file((char *)name, the_acl_type, tru64_acl);
118 acl_free(tru64_acl);
119 if (res != 0) {
120 DEBUG(10, ("acl_set_file failed: %s\n", strerror(errno)));
121 goto fail;
123 return res;
124 fail:
125 DEBUG(1, ("tru64acl_sys_acl_set_file failed!\n"));
126 return -1;
129 int tru64acl_sys_acl_set_fd(vfs_handle_struct *handle,
130 files_struct *fsp,
131 SMB_ACL_T theacl)
133 int res;
134 acl_t tru64_acl = smb_acl_to_tru64_acl(theacl);
135 if (tru64_acl == NULL) {
136 return -1;
138 res = acl_set_fd(fsp->fh->fd, ACL_TYPE_ACCESS, tru64_acl);
139 acl_free(tru64_acl);
140 return res;
144 int tru64acl_sys_acl_delete_def_file(vfs_handle_struct *handle,
145 const char *path)
147 return acl_delete_def_file((char *)path);
151 /* private functions */
153 static struct smb_acl_t *tru64_acl_to_smb_acl(const struct acl *tru64_acl)
155 struct smb_acl_t *result;
156 acl_entry_t entry;
158 DEBUG(10, ("Hi! This is tru64_acl_to_smb_acl.\n"));
160 if ((result = SMB_MALLOC_P(struct smb_acl_t)) == NULL) {
161 DEBUG(0, ("SMB_MALLOC_P failed in tru64_acl_to_smb_acl\n"));
162 errno = ENOMEM;
163 goto fail;
165 ZERO_STRUCTP(result);
166 if (acl_first_entry((struct acl *)tru64_acl) != 0) {
167 DEBUG(10, ("acl_first_entry failed: %s\n", strerror(errno)));
168 goto fail;
170 while ((entry = acl_get_entry((struct acl *)tru64_acl)) != NULL) {
171 result = SMB_REALLOC(result, sizeof(struct smb_acl_t) +
172 (sizeof(struct smb_acl_entry) *
173 (result->count + 1)));
174 if (result == NULL) {
175 DEBUG(0, ("SMB_REALLOC failed in tru64_acl_to_smb_acl\n"));
176 errno = ENOMEM;
177 goto fail;
179 /* XYZ */
180 if (!tru64_ace_to_smb_ace(entry, &result->acl[result->count])) {
181 SAFE_FREE(result);
182 goto fail;
184 result->count += 1;
186 return result;
188 fail:
189 if (result != NULL) {
190 SAFE_FREE(result);
192 DEBUG(1, ("tru64_acl_to_smb_acl failed!\n"));
193 return NULL;
196 static bool tru64_ace_to_smb_ace(acl_entry_t tru64_ace,
197 struct smb_acl_entry *smb_ace)
199 acl_tag_t tru64_tag;
200 acl_permset_t permset;
201 SMB_ACL_TAG_T smb_tag_type;
202 SMB_ACL_PERM_T smb_permset;
203 void *qualifier;
205 if (acl_get_tag_type(tru64_ace, &tru64_tag) != 0) {
206 DEBUG(0, ("acl_get_tag_type failed: %s\n", strerror(errno)));
207 return False;
210 /* On could set the tag type directly to save a function call,
211 * but I like this better... */
212 smb_tag_type = tru64_tag_to_smb(tru64_tag);
213 if (smb_tag_type == 0) {
214 DEBUG(3, ("invalid tag type given: %d\n", tru64_tag));
215 return False;
217 if (sys_acl_set_tag_type(smb_ace, smb_tag_type) != 0) {
218 DEBUG(3, ("sys_acl_set_tag_type failed: %s\n",
219 strerror(errno)));
220 return False;
222 qualifier = acl_get_qualifier(tru64_ace);
223 if (qualifier != NULL) {
224 if (sys_acl_set_qualifier(smb_ace, qualifier) != 0) {
225 DEBUG(3, ("sys_acl_set_qualifier failed\n"));
226 return False;
229 if (acl_get_permset(tru64_ace, &permset) != 0) {
230 DEBUG(3, ("acl_get_permset failed: %s\n", strerror(errno)));
231 return False;
233 smb_permset = tru64_permset_to_smb(*permset);
234 if (sys_acl_set_permset(smb_ace, &smb_permset) != 0) {
235 DEBUG(3, ("sys_acl_set_permset failed: %s\n", strerror(errno)));
236 return False;
238 return True;
241 static acl_t smb_acl_to_tru64_acl(const SMB_ACL_T smb_acl)
243 acl_t result;
244 acl_entry_t tru64_entry;
245 int i;
246 char *acl_text;
247 ssize_t acl_text_len;
249 /* The tru64 acl_init function takes a size_t value
250 * instead of a count of entries (as with posix).
251 * the size parameter "Specifies the size of the working
252 * storage in bytes" (according to the man page).
253 * But it is unclear to me, how this size is to be
254 * calculated.
256 * It should not matter, since acl_create_entry enlarges
257 * the working storage at need. ... */
259 DEBUG(10, ("Hi! This is smb_acl_to_tru64_acl.\n"));
261 result = acl_init(1);
263 if (result == NULL) {
264 DEBUG(3, ("acl_init failed!\n"));
265 goto fail;
268 DEBUGADD(10, ("parsing acl entries...\n"));
269 for (i = 0; i < smb_acl->count; i++) {
270 /* XYZ - maybe eliminate this direct access? */
271 const struct smb_acl_entry *smb_entry = &smb_acl->acl[i];
272 acl_tag_t tru64_tag;
273 acl_perm_t tru64_permset;
275 tru64_tag = smb_tag_to_tru64(smb_entry->a_type);
276 if (tru64_tag == -1) {
277 DEBUG(3, ("smb_tag_to_tru64 failed!\n"));
278 goto fail;
281 if (tru64_tag == ACL_MASK) {
282 DEBUGADD(10, (" - acl type ACL_MASK: not implemented on Tru64 ==> skipping\n"));
283 continue;
286 tru64_entry = acl_create_entry(&result);
287 if (tru64_entry == NULL) {
288 DEBUG(3, ("acl_create_entry failed: %s\n",
289 strerror(errno)));
290 goto fail;
293 if (acl_set_tag_type(tru64_entry, tru64_tag) != 0) {
294 DEBUG(3, ("acl_set_tag_type(%d) failed: %s\n",
295 strerror(errno)));
296 goto fail;
299 switch (smb_entry->a_type) {
300 case SMB_ACL_USER:
301 if (acl_set_qualifier(tru64_entry,
302 (int *)&smb_entry->uid) != 0)
304 DEBUG(3, ("acl_set_qualifier failed: %s\n",
305 strerror(errno)));
306 goto fail;
308 DEBUGADD(10, (" - setting uid to %d\n", smb_entry->uid));
309 break;
310 case SMB_ACL_GROUP:
311 if (acl_set_qualifier(tru64_entry,
312 (int *)&smb_entry->gid) != 0)
314 DEBUG(3, ("acl_set_qualifier failed: %s\n",
315 strerror(errno)));
316 goto fail;
318 DEBUGADD(10, (" - setting gid to %d\n", smb_entry->gid));
319 break;
320 default:
321 break;
324 tru64_permset = smb_permset_to_tru64(smb_entry->a_perm);
325 if (tru64_permset == -1) {
326 DEBUG(3, ("smb_permset_to_tru64 failed!\n"));
327 goto fail;
329 DEBUGADD(10, (" - setting perms to %0d\n", tru64_permset));
330 if (acl_set_permset(tru64_entry, &tru64_permset) != 0)
332 DEBUG(3, ("acl_set_permset failed: %s\n", strerror(errno)));
333 goto fail;
335 } /* for */
336 DEBUGADD(10, ("done parsing acl entries\n"));
338 tru64_entry = NULL;
339 if (acl_valid(result, &tru64_entry) != 0) {
340 DEBUG(1, ("smb_acl_to_tru64_acl: ACL is invalid (%s)\n",
341 strerror(errno)));
342 if (tru64_entry != NULL) {
343 DEBUGADD(1, ("the acl contains duplicate entries\n"));
345 goto fail;
347 DEBUGADD(10, ("acl is valid\n"));
349 acl_text = acl_to_text(result, &acl_text_len);
350 if (acl_text == NULL) {
351 DEBUG(3, ("acl_to_text failed: %s\n", strerror(errno)));
352 goto fail;
354 DEBUG(1, ("acl_text: %s\n", acl_text));
355 free(acl_text);
357 return result;
359 fail:
360 if (result != NULL) {
361 acl_free(result);
363 DEBUG(1, ("smb_acl_to_tru64_acl failed!\n"));
364 return NULL;
367 static acl_tag_t smb_tag_to_tru64(SMB_ACL_TAG_T smb_tag)
369 acl_tag_t result;
370 switch (smb_tag) {
371 case SMB_ACL_USER:
372 result = ACL_USER;
373 DEBUGADD(10, ("got acl type ACL_USER\n"));
374 break;
375 case SMB_ACL_USER_OBJ:
376 result = ACL_USER_OBJ;
377 DEBUGADD(10, ("got acl type ACL_USER_OBJ\n"));
378 break;
379 case SMB_ACL_GROUP:
380 result = ACL_GROUP;
381 DEBUGADD(10, ("got acl type ACL_GROUP\n"));
382 break;
383 case SMB_ACL_GROUP_OBJ:
384 result = ACL_GROUP_OBJ;
385 DEBUGADD(10, ("got acl type ACL_GROUP_OBJ\n"));
386 break;
387 case SMB_ACL_OTHER:
388 result = ACL_OTHER;
389 DEBUGADD(10, ("got acl type ACL_OTHER\n"));
390 break;
391 case SMB_ACL_MASK:
392 result = ACL_MASK;
393 DEBUGADD(10, ("got acl type ACL_MASK\n"));
394 break;
395 default:
396 DEBUG(1, ("Unknown tag type %d\n", smb_tag));
397 result = -1;
399 return result;
403 static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag)
405 SMB_ACL_TAG_T smb_tag_type;
406 switch(tru64_tag) {
407 case ACL_USER:
408 smb_tag_type = SMB_ACL_USER;
409 DEBUGADD(10, ("got smb acl tag type SMB_ACL_USER\n"));
410 break;
411 case ACL_USER_OBJ:
412 smb_tag_type = SMB_ACL_USER_OBJ;
413 DEBUGADD(10, ("got smb acl tag type SMB_ACL_USER_OBJ\n"));
414 break;
415 case ACL_GROUP:
416 smb_tag_type = SMB_ACL_GROUP;
417 DEBUGADD(10, ("got smb acl tag type SMB_ACL_GROUP\n"));
418 break;
419 case ACL_GROUP_OBJ:
420 smb_tag_type = SMB_ACL_GROUP_OBJ;
421 DEBUGADD(10, ("got smb acl tag type SMB_ACL_GROUP_OBJ\n"));
422 break;
423 case ACL_OTHER:
424 smb_tag_type = SMB_ACL_OTHER;
425 DEBUGADD(10, ("got smb acl tag type SMB_ACL_OTHER\n"));
426 break;
427 case ACL_MASK:
428 smb_tag_type = SMB_ACL_MASK;
429 DEBUGADD(10, ("got smb acl tag type SMB_ACL_MASK\n"));
430 break;
431 default:
432 DEBUG(0, ("Unknown tag type %d\n", (unsigned int)tru64_tag));
433 smb_tag_type = 0;
435 return smb_tag_type;
438 static acl_perm_t smb_permset_to_tru64(SMB_ACL_PERM_T smb_permset)
440 /* originally, I thought that acl_clear_perm was the
441 * proper way to reset the permset to 0. but without
442 * initializing it to 0, acl_clear_perm fails.
443 * so probably, acl_clear_perm is not necessary here... ?! */
444 acl_perm_t tru64_permset = 0;
445 if (acl_clear_perm(&tru64_permset) != 0) {
446 DEBUG(5, ("acl_clear_perm failed: %s\n", strerror(errno)));
447 return -1;
449 /* according to original lib/sysacls.c, acl_add_perm is
450 * broken on tru64 ... */
451 tru64_permset |= ((smb_permset & SMB_ACL_READ) ? ACL_READ : 0);
452 tru64_permset |= ((smb_permset & SMB_ACL_WRITE) ? ACL_WRITE : 0);
453 tru64_permset |= ((smb_permset & SMB_ACL_EXECUTE) ? ACL_EXECUTE : 0);
454 return tru64_permset;
457 static SMB_ACL_PERM_T tru64_permset_to_smb(const acl_perm_t tru64_permset)
459 SMB_ACL_PERM_T smb_permset = 0;
460 smb_permset |= ((tru64_permset & ACL_READ) ? SMB_ACL_READ : 0);
461 smb_permset |= ((tru64_permset & ACL_WRITE) ? SMB_ACL_WRITE : 0);
462 smb_permset |= ((tru64_permset & ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
463 return smb_permset;
467 /* VFS operations structure */
469 static struct vfs_fn_pointers tru64acl_fns = {
470 .sys_acl_get_file = tru64acl_sys_acl_get_file,
471 .sys_acl_get_fd = tru64acl_sys_acl_get_fd,
472 .sys_acl_set_file = tru64acl_sys_acl_set_file,
473 .sys_acl_set_fd = tru64acl_sys_acl_set_fd,
474 .sys_acl_delete_def_file = tru64acl_sys_acl_delete_def_file,
477 NTSTATUS vfs_tru64acl_init(void);
478 NTSTATUS vfs_tru64acl_init(void)
480 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "tru64acl",
481 &tru64acl_fns);
484 /* ENTE */