s3: smbd: Locking - re-add pending lock records if we fail to acquire a lock (and...
[Samba.git] / source3 / modules / vfs_tru64acl.c
blob97f4d5c30bc228d61f595e4d35035f73a1586c25
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"
21 #include "system/filesys.h"
22 #include "smbd/smbd.h"
23 #include "modules/vfs_tru64acl.h"
25 /* prototypes for private functions first - for clarity */
27 static struct smb_acl_t *tru64_acl_to_smb_acl(const struct acl *tru64_acl,
28 TALLOC_CTX *mem_ctx);
29 static bool tru64_ace_to_smb_ace(acl_entry_t tru64_ace,
30 struct smb_acl_entry *smb_ace);
31 static acl_t smb_acl_to_tru64_acl(const SMB_ACL_T smb_acl);
32 static acl_tag_t smb_tag_to_tru64(SMB_ACL_TAG_T smb_tag);
33 static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag);
34 static acl_perm_t smb_permset_to_tru64(SMB_ACL_PERM_T smb_permset);
35 static SMB_ACL_PERM_T tru64_permset_to_smb(const acl_perm_t tru64_permset);
38 /* public functions - the api */
40 SMB_ACL_T tru64acl_sys_acl_get_file(vfs_handle_struct *handle,
41 const char *path_p,
42 SMB_ACL_TYPE_T type,
43 TALLOC_CTX *mem_ctx)
45 struct smb_acl_t *result;
46 acl_type_t the_acl_type;
47 acl_t tru64_acl;
49 DEBUG(10, ("Hi! This is tru64acl_sys_acl_get_file.\n"));
51 switch(type) {
52 case SMB_ACL_TYPE_ACCESS:
53 the_acl_type = ACL_TYPE_ACCESS;
54 break;
55 case SMB_ACL_TYPE_DEFAULT:
56 the_acl_type = ACL_TYPE_DEFAULT;
57 break;
58 default:
59 errno = EINVAL;
60 return NULL;
63 tru64_acl = acl_get_file((char *)path_p, the_acl_type);
65 if (tru64_acl == NULL) {
66 return NULL;
69 result = tru64_acl_to_smb_acl(tru64_acl, mem_ctx);
70 acl_free(tru64_acl);
71 return result;
74 SMB_ACL_T tru64acl_sys_acl_get_fd(vfs_handle_struct *handle,
75 files_struct *fsp,
76 TALLOC_CTX *mem_ctx)
78 struct smb_acl_t *result;
79 acl_t tru64_acl = acl_get_fd(fsp->fh->fd, ACL_TYPE_ACCESS);
81 if (tru64_acl == NULL) {
82 return NULL;
85 result = tru64_acl_to_smb_acl(tru64_acl, mem_ctx);
86 acl_free(tru64_acl);
87 return result;
90 int tru64acl_sys_acl_set_file(vfs_handle_struct *handle,
91 const char *name,
92 SMB_ACL_TYPE_T type,
93 SMB_ACL_T theacl)
95 int res;
96 acl_type_t the_acl_type;
97 acl_t tru64_acl;
99 DEBUG(10, ("tru64acl_sys_acl_set_file called with name %s, type %d\n",
100 name, type));
102 switch(type) {
103 case SMB_ACL_TYPE_ACCESS:
104 DEBUGADD(10, ("got acl type ACL_TYPE_ACCESS\n"));
105 the_acl_type = ACL_TYPE_ACCESS;
106 break;
107 case SMB_ACL_TYPE_DEFAULT:
108 DEBUGADD(10, ("got acl type ACL_TYPE_DEFAULT\n"));
109 the_acl_type = ACL_TYPE_DEFAULT;
110 break;
111 default:
112 DEBUGADD(10, ("invalid acl type\n"));
113 errno = EINVAL;
114 goto fail;
117 tru64_acl = smb_acl_to_tru64_acl(theacl);
118 if (tru64_acl == NULL) {
119 DEBUG(10, ("smb_acl_to_tru64_acl failed!\n"));
120 goto fail;
122 DEBUG(10, ("got tru64 acl...\n"));
123 res = acl_set_file((char *)name, the_acl_type, tru64_acl);
124 acl_free(tru64_acl);
125 if (res != 0) {
126 DEBUG(10, ("acl_set_file failed: %s\n", strerror(errno)));
127 goto fail;
129 return res;
130 fail:
131 DEBUG(1, ("tru64acl_sys_acl_set_file failed!\n"));
132 return -1;
135 int tru64acl_sys_acl_set_fd(vfs_handle_struct *handle,
136 files_struct *fsp,
137 SMB_ACL_T theacl)
139 int res;
140 acl_t tru64_acl = smb_acl_to_tru64_acl(theacl);
141 if (tru64_acl == NULL) {
142 return -1;
144 res = acl_set_fd(fsp->fh->fd, ACL_TYPE_ACCESS, tru64_acl);
145 acl_free(tru64_acl);
146 return res;
150 int tru64acl_sys_acl_delete_def_file(vfs_handle_struct *handle,
151 const char *path)
153 return acl_delete_def_file((char *)path);
157 /* private functions */
159 static struct smb_acl_t *tru64_acl_to_smb_acl(const struct acl *tru64_acl,
160 TALLOC_CTX *mem_ctx)
162 struct smb_acl_t *result;
163 acl_entry_t entry;
165 DEBUG(10, ("Hi! This is tru64_acl_to_smb_acl.\n"));
167 if ((result = sys_acl_init(mem_ctx)) == NULL) {
168 DEBUG(0, ("sys_acl_init() failed in tru64_acl_to_smb_acl\n"));
169 errno = ENOMEM;
170 goto fail;
172 if (acl_first_entry((struct acl *)tru64_acl) != 0) {
173 DEBUG(10, ("acl_first_entry failed: %s\n", strerror(errno)));
174 goto fail;
176 while ((entry = acl_get_entry((struct acl *)tru64_acl)) != NULL) {
177 result->acl = talloc_realloc(result, result->acl, struct smb_acl_entry,
178 result->count + 1);
179 if (result->acl == NULL) {
180 TALLOC_FREE(result);
181 DEBUG(0, ("talloc_realloc failed in tru64_acl_to_smb_acl\n"));
182 errno = ENOMEM;
183 goto fail;
185 /* XYZ */
186 if (!tru64_ace_to_smb_ace(entry, &result->acl[result->count])) {
187 TALLOC_FREE(result);
188 goto fail;
190 result->count += 1;
192 return result;
194 fail:
195 TALLOC_FREE(result);
196 DEBUG(1, ("tru64_acl_to_smb_acl failed!\n"));
197 return NULL;
200 static bool tru64_ace_to_smb_ace(acl_entry_t tru64_ace,
201 struct smb_acl_entry *smb_ace)
203 acl_tag_t tru64_tag;
204 acl_permset_t permset;
205 SMB_ACL_TAG_T smb_tag_type;
206 SMB_ACL_PERM_T smb_permset;
207 void *qualifier;
209 if (acl_get_tag_type(tru64_ace, &tru64_tag) != 0) {
210 DEBUG(0, ("acl_get_tag_type failed: %s\n", strerror(errno)));
211 return False;
214 /* On could set the tag type directly to save a function call,
215 * but I like this better... */
216 smb_tag_type = tru64_tag_to_smb(tru64_tag);
217 if (smb_tag_type == 0) {
218 DEBUG(3, ("invalid tag type given: %d\n", tru64_tag));
219 return False;
221 if (sys_acl_set_tag_type(smb_ace, smb_tag_type) != 0) {
222 DEBUG(3, ("sys_acl_set_tag_type failed: %s\n",
223 strerror(errno)));
224 return False;
226 qualifier = acl_get_qualifier(tru64_ace);
227 if (qualifier != NULL) {
228 if (sys_acl_set_qualifier(smb_ace, qualifier) != 0) {
229 DEBUG(3, ("sys_acl_set_qualifier failed\n"));
230 return False;
233 if (acl_get_permset(tru64_ace, &permset) != 0) {
234 DEBUG(3, ("acl_get_permset failed: %s\n", strerror(errno)));
235 return False;
237 smb_permset = tru64_permset_to_smb(*permset);
238 if (sys_acl_set_permset(smb_ace, &smb_permset) != 0) {
239 DEBUG(3, ("sys_acl_set_permset failed: %s\n", strerror(errno)));
240 return False;
242 return True;
245 static acl_t smb_acl_to_tru64_acl(const SMB_ACL_T smb_acl)
247 acl_t result;
248 acl_entry_t tru64_entry;
249 int i;
250 char *acl_text;
251 ssize_t acl_text_len;
253 /* The tru64 acl_init function takes a size_t value
254 * instead of a count of entries (as with posix).
255 * the size parameter "Specifies the size of the working
256 * storage in bytes" (according to the man page).
257 * But it is unclear to me, how this size is to be
258 * calculated.
260 * It should not matter, since acl_create_entry enlarges
261 * the working storage at need. ... */
263 DEBUG(10, ("Hi! This is smb_acl_to_tru64_acl.\n"));
265 result = acl_init(1);
267 if (result == NULL) {
268 DEBUG(3, ("acl_init failed!\n"));
269 goto fail;
272 DEBUGADD(10, ("parsing acl entries...\n"));
273 for (i = 0; i < smb_acl->count; i++) {
274 /* XYZ - maybe eliminate this direct access? */
275 const struct smb_acl_entry *smb_entry = &smb_acl->acl[i];
276 acl_tag_t tru64_tag;
277 acl_perm_t tru64_permset;
279 tru64_tag = smb_tag_to_tru64(smb_entry->a_type);
280 if (tru64_tag == -1) {
281 DEBUG(3, ("smb_tag_to_tru64 failed!\n"));
282 goto fail;
285 if (tru64_tag == ACL_MASK) {
286 DEBUGADD(10, (" - acl type ACL_MASK: not implemented on Tru64 ==> skipping\n"));
287 continue;
290 tru64_entry = acl_create_entry(&result);
291 if (tru64_entry == NULL) {
292 DEBUG(3, ("acl_create_entry failed: %s\n",
293 strerror(errno)));
294 goto fail;
297 if (acl_set_tag_type(tru64_entry, tru64_tag) != 0) {
298 DEBUG(3, ("acl_set_tag_type(%d) failed: %s\n",
299 strerror(errno)));
300 goto fail;
303 switch (smb_entry->a_type) {
304 case SMB_ACL_USER:
305 if (acl_set_qualifier(tru64_entry,
306 (int *)&smb_entry->info.user.uid) != 0)
308 DEBUG(3, ("acl_set_qualifier failed: %s\n",
309 strerror(errno)));
310 goto fail;
312 DEBUGADD(10, (" - setting uid to %d\n", smb_entry->info.user.uid));
313 break;
314 case SMB_ACL_GROUP:
315 if (acl_set_qualifier(tru64_entry,
316 (int *)&smb_entry->info.group.gid) != 0)
318 DEBUG(3, ("acl_set_qualifier failed: %s\n",
319 strerror(errno)));
320 goto fail;
322 DEBUGADD(10, (" - setting gid to %d\n", smb_entry->info.group.gid));
323 break;
324 default:
325 break;
328 tru64_permset = smb_permset_to_tru64(smb_entry->a_perm);
329 if (tru64_permset == -1) {
330 DEBUG(3, ("smb_permset_to_tru64 failed!\n"));
331 goto fail;
333 DEBUGADD(10, (" - setting perms to %0d\n", tru64_permset));
334 if (acl_set_permset(tru64_entry, &tru64_permset) != 0)
336 DEBUG(3, ("acl_set_permset failed: %s\n", strerror(errno)));
337 goto fail;
339 } /* for */
340 DEBUGADD(10, ("done parsing acl entries\n"));
342 tru64_entry = NULL;
343 if (acl_valid(result, &tru64_entry) != 0) {
344 DEBUG(1, ("smb_acl_to_tru64_acl: ACL is invalid (%s)\n",
345 strerror(errno)));
346 if (tru64_entry != NULL) {
347 DEBUGADD(1, ("the acl contains duplicate entries\n"));
349 goto fail;
351 DEBUGADD(10, ("acl is valid\n"));
353 acl_text = acl_to_text(result, &acl_text_len);
354 if (acl_text == NULL) {
355 DEBUG(3, ("acl_to_text failed: %s\n", strerror(errno)));
356 goto fail;
358 DEBUG(1, ("acl_text: %s\n", acl_text));
359 free(acl_text);
361 return result;
363 fail:
364 if (result != NULL) {
365 acl_free(result);
367 DEBUG(1, ("smb_acl_to_tru64_acl failed!\n"));
368 return NULL;
371 static acl_tag_t smb_tag_to_tru64(SMB_ACL_TAG_T smb_tag)
373 acl_tag_t result;
374 switch (smb_tag) {
375 case SMB_ACL_USER:
376 result = ACL_USER;
377 DEBUGADD(10, ("got acl type ACL_USER\n"));
378 break;
379 case SMB_ACL_USER_OBJ:
380 result = ACL_USER_OBJ;
381 DEBUGADD(10, ("got acl type ACL_USER_OBJ\n"));
382 break;
383 case SMB_ACL_GROUP:
384 result = ACL_GROUP;
385 DEBUGADD(10, ("got acl type ACL_GROUP\n"));
386 break;
387 case SMB_ACL_GROUP_OBJ:
388 result = ACL_GROUP_OBJ;
389 DEBUGADD(10, ("got acl type ACL_GROUP_OBJ\n"));
390 break;
391 case SMB_ACL_OTHER:
392 result = ACL_OTHER;
393 DEBUGADD(10, ("got acl type ACL_OTHER\n"));
394 break;
395 case SMB_ACL_MASK:
396 result = ACL_MASK;
397 DEBUGADD(10, ("got acl type ACL_MASK\n"));
398 break;
399 default:
400 DEBUG(1, ("Unknown tag type %d\n", smb_tag));
401 result = -1;
403 return result;
407 static SMB_ACL_TAG_T tru64_tag_to_smb(acl_tag_t tru64_tag)
409 SMB_ACL_TAG_T smb_tag_type;
410 switch(tru64_tag) {
411 case ACL_USER:
412 smb_tag_type = SMB_ACL_USER;
413 DEBUGADD(10, ("got smb acl tag type SMB_ACL_USER\n"));
414 break;
415 case ACL_USER_OBJ:
416 smb_tag_type = SMB_ACL_USER_OBJ;
417 DEBUGADD(10, ("got smb acl tag type SMB_ACL_USER_OBJ\n"));
418 break;
419 case ACL_GROUP:
420 smb_tag_type = SMB_ACL_GROUP;
421 DEBUGADD(10, ("got smb acl tag type SMB_ACL_GROUP\n"));
422 break;
423 case ACL_GROUP_OBJ:
424 smb_tag_type = SMB_ACL_GROUP_OBJ;
425 DEBUGADD(10, ("got smb acl tag type SMB_ACL_GROUP_OBJ\n"));
426 break;
427 case ACL_OTHER:
428 smb_tag_type = SMB_ACL_OTHER;
429 DEBUGADD(10, ("got smb acl tag type SMB_ACL_OTHER\n"));
430 break;
431 case ACL_MASK:
432 smb_tag_type = SMB_ACL_MASK;
433 DEBUGADD(10, ("got smb acl tag type SMB_ACL_MASK\n"));
434 break;
435 default:
436 DEBUG(0, ("Unknown tag type %d\n", (unsigned int)tru64_tag));
437 smb_tag_type = 0;
439 return smb_tag_type;
442 static acl_perm_t smb_permset_to_tru64(SMB_ACL_PERM_T smb_permset)
444 /* originally, I thought that acl_clear_perm was the
445 * proper way to reset the permset to 0. but without
446 * initializing it to 0, acl_clear_perm fails.
447 * so probably, acl_clear_perm is not necessary here... ?! */
448 acl_perm_t tru64_permset = 0;
449 if (acl_clear_perm(&tru64_permset) != 0) {
450 DEBUG(5, ("acl_clear_perm failed: %s\n", strerror(errno)));
451 return -1;
453 /* according to original lib/sysacls.c, acl_add_perm is
454 * broken on tru64 ... */
455 tru64_permset |= ((smb_permset & SMB_ACL_READ) ? ACL_READ : 0);
456 tru64_permset |= ((smb_permset & SMB_ACL_WRITE) ? ACL_WRITE : 0);
457 tru64_permset |= ((smb_permset & SMB_ACL_EXECUTE) ? ACL_EXECUTE : 0);
458 return tru64_permset;
461 static SMB_ACL_PERM_T tru64_permset_to_smb(const acl_perm_t tru64_permset)
463 SMB_ACL_PERM_T smb_permset = 0;
464 smb_permset |= ((tru64_permset & ACL_READ) ? SMB_ACL_READ : 0);
465 smb_permset |= ((tru64_permset & ACL_WRITE) ? SMB_ACL_WRITE : 0);
466 smb_permset |= ((tru64_permset & ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
467 return smb_permset;
471 /* VFS operations structure */
473 static struct vfs_fn_pointers tru64acl_fns = {
474 .sys_acl_get_file_fn = tru64acl_sys_acl_get_file,
475 .sys_acl_get_fd_fn = tru64acl_sys_acl_get_fd,
476 .sys_acl_blob_get_file_fn = posix_sys_acl_blob_get_file,
477 .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
478 .sys_acl_set_file_fn = tru64acl_sys_acl_set_file,
479 .sys_acl_set_fd_fn = tru64acl_sys_acl_set_fd,
480 .sys_acl_delete_def_file_fn = tru64acl_sys_acl_delete_def_file,
483 NTSTATUS vfs_tru64acl_init(void);
484 NTSTATUS vfs_tru64acl_init(void)
486 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "tru64acl",
487 &tru64acl_fns);
490 /* ENTE */