sysacls.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    Samba system utilities for ACL support.
00004    Copyright (C) Jeremy Allison 2000.
00005    
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 #include "rsync.h"
00022 #include "sysacls.h" /****** ADDED ******/
00023 
00024 /****** EXTRAS -- THESE ITEMS ARE NOT FROM THE SAMBA SOURCE ******/
00025 void SAFE_FREE(void *mem)
00026 {
00027         if (mem)
00028                 free(mem);
00029 }
00030 
00031 char *uidtoname(uid_t uid)
00032 {
00033         static char idbuf[12];
00034         struct passwd *pw;
00035 
00036         if ((pw = getpwuid(uid)) == NULL) {
00037                 slprintf(idbuf, sizeof(idbuf)-1, "%ld", (long)uid);
00038                 return idbuf;
00039         }
00040         return pw->pw_name;
00041 }
00042 /****** EXTRAS -- END ******/
00043 
00044 /*
00045  This file wraps all differing system ACL interfaces into a consistent
00046  one based on the POSIX interface. It also returns the correct errors
00047  for older UNIX systems that don't support ACLs.
00048 
00049  The interfaces that each ACL implementation must support are as follows :
00050 
00051  int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
00052  int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
00053  int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p
00054  void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
00055  SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
00056  SMB_ACL_T sys_acl_get_fd(int fd)
00057  int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset);
00058  int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm);
00059  char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
00060  SMB_ACL_T sys_acl_init( int count)
00061  int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
00062  int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
00063  int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
00064  int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
00065  int sys_acl_valid( SMB_ACL_T theacl )
00066  int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
00067  int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
00068  int sys_acl_delete_def_file(const char *path)
00069 
00070  This next one is not POSIX complient - but we *have* to have it !
00071  More POSIX braindamage.
00072 
00073  int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
00074 
00075  The generic POSIX free is the following call. We split this into
00076  several different free functions as we may need to add tag info
00077  to structures when emulating the POSIX interface.
00078 
00079  int sys_acl_free( void *obj_p)
00080 
00081  The calls we actually use are :
00082 
00083  int sys_acl_free_text(char *text) - free acl_to_text
00084  int sys_acl_free_acl(SMB_ACL_T posix_acl)
00085  int sys_acl_free_qualifier(void *qualifier, SMB_ACL_TAG_T tagtype)
00086 
00087 */
00088 
00089 #if defined(HAVE_POSIX_ACLS)
00090 
00091 /* Identity mapping - easy. */
00092 
00093 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
00094 {
00095         return acl_get_entry( the_acl, entry_id, entry_p);
00096 }
00097 
00098 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
00099 {
00100         return acl_get_tag_type( entry_d, tag_type_p);
00101 }
00102 
00103 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
00104 {
00105         return acl_get_permset( entry_d, permset_p);
00106 }
00107 
00108 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
00109 {
00110         return acl_get_qualifier( entry_d);
00111 }
00112 
00113 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
00114 {
00115         return acl_get_file( path_p, type);
00116 }
00117 
00118 SMB_ACL_T sys_acl_get_fd(int fd)
00119 {
00120         return acl_get_fd(fd);
00121 }
00122 
00123 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
00124 {
00125         return acl_clear_perms(permset);
00126 }
00127 
00128 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
00129 {
00130         return acl_add_perm(permset, perm);
00131 }
00132 
00133 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
00134 {
00135 #if defined(HAVE_ACL_GET_PERM_NP)
00136         /*
00137          * Required for TrustedBSD-based ACL implementations where
00138          * non-POSIX.1e functions are denoted by a _np (non-portable)
00139          * suffix.
00140          */
00141         return acl_get_perm_np(permset, perm);
00142 #else
00143         return acl_get_perm(permset, perm);
00144 #endif
00145 }
00146 
00147 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
00148 {
00149         return acl_to_text( the_acl, plen);
00150 }
00151 
00152 SMB_ACL_T sys_acl_init( int count)
00153 {
00154         return acl_init(count);
00155 }
00156 
00157 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
00158 {
00159         return acl_create_entry(pacl, pentry);
00160 }
00161 
00162 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
00163 {
00164         return acl_set_tag_type(entry, tagtype);
00165 }
00166 
00167 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
00168 {
00169         return acl_set_qualifier(entry, qual);
00170 }
00171 
00172 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
00173 {
00174         return acl_set_permset(entry, permset);
00175 }
00176 
00177 int sys_acl_valid( SMB_ACL_T theacl )
00178 {
00179         return acl_valid(theacl);
00180 }
00181 
00182 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
00183 {
00184         return acl_set_file(name, acltype, theacl);
00185 }
00186 
00187 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
00188 {
00189         return acl_set_fd(fd, theacl);
00190 }
00191 
00192 int sys_acl_delete_def_file(const char *name)
00193 {
00194         return acl_delete_def_file(name);
00195 }
00196 
00197 int sys_acl_free_text(char *text)
00198 {
00199         return acl_free(text);
00200 }
00201 
00202 int sys_acl_free_acl(SMB_ACL_T the_acl) 
00203 {
00204         return acl_free(the_acl);
00205 }
00206 
00207 int sys_acl_free_qualifier(void *qual, UNUSED(SMB_ACL_TAG_T tagtype))
00208 {
00209         return acl_free(qual);
00210 }
00211 
00212 #elif defined(HAVE_TRU64_ACLS)
00213 /*
00214  * The interface to DEC/Compaq Tru64 UNIX ACLs
00215  * is based on Draft 13 of the POSIX spec which is
00216  * slightly different from the Draft 16 interface.
00217  * 
00218  * Also, some of the permset manipulation functions
00219  * such as acl_clear_perm() and acl_add_perm() appear
00220  * to be broken on Tru64 so we have to manipulate
00221  * the permission bits in the permset directly.
00222  */
00223 int sys_acl_get_entry( SMB_ACL_T the_acl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
00224 {
00225         SMB_ACL_ENTRY_T entry;
00226 
00227         if (entry_id == SMB_ACL_FIRST_ENTRY && acl_first_entry(the_acl) != 0) {
00228                 return -1;
00229         }
00230 
00231         errno = 0;
00232         if ((entry = acl_get_entry(the_acl)) != NULL) {
00233                 *entry_p = entry;
00234                 return 1;
00235         }
00236 
00237         return errno ? -1 : 0;
00238 }
00239 
00240 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
00241 {
00242         return acl_get_tag_type( entry_d, tag_type_p);
00243 }
00244 
00245 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
00246 {
00247         return acl_get_permset( entry_d, permset_p);
00248 }
00249 
00250 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
00251 {
00252         return acl_get_qualifier( entry_d);
00253 }
00254 
00255 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
00256 {
00257         return acl_get_file((char *)path_p, type);
00258 }
00259 
00260 SMB_ACL_T sys_acl_get_fd(int fd)
00261 {
00262         return acl_get_fd(fd, ACL_TYPE_ACCESS);
00263 }
00264 
00265 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
00266 {
00267         *permset = 0;           /* acl_clear_perm() is broken on Tru64  */
00268 
00269         return 0;
00270 }
00271 
00272 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
00273 {
00274         if (perm & ~(SMB_ACL_READ | SMB_ACL_WRITE | SMB_ACL_EXECUTE)) {
00275                 errno = EINVAL;
00276                 return -1;
00277         }
00278 
00279         *permset |= perm;       /* acl_add_perm() is broken on Tru64    */
00280 
00281         return 0;
00282 }
00283 
00284 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
00285 {
00286         return *permset & perm; /* Tru64 doesn't have acl_get_perm() */
00287 }
00288 
00289 char *sys_acl_to_text( SMB_ACL_T the_acl, ssize_t *plen)
00290 {
00291         return acl_to_text( the_acl, plen);
00292 }
00293 
00294 SMB_ACL_T sys_acl_init( int count)
00295 {
00296         return acl_init(count);
00297 }
00298 
00299 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
00300 {
00301         SMB_ACL_ENTRY_T entry;
00302 
00303         if ((entry = acl_create_entry(pacl)) == NULL) {
00304                 return -1;
00305         }
00306 
00307         *pentry = entry;
00308         return 0;
00309 }
00310 
00311 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
00312 {
00313         return acl_set_tag_type(entry, tagtype);
00314 }
00315 
00316 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
00317 {
00318         return acl_set_qualifier(entry, qual);
00319 }
00320 
00321 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
00322 {
00323         return acl_set_permset(entry, permset);
00324 }
00325 
00326 int sys_acl_valid( SMB_ACL_T theacl )
00327 {
00328         acl_entry_t     entry;
00329 
00330         return acl_valid(theacl, &entry);
00331 }
00332 
00333 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
00334 {
00335         return acl_set_file((char *)name, acltype, theacl);
00336 }
00337 
00338 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
00339 {
00340         return acl_set_fd(fd, ACL_TYPE_ACCESS, theacl);
00341 }
00342 
00343 int sys_acl_delete_def_file(const char *name)
00344 {
00345         return acl_delete_def_file((char *)name);
00346 }
00347 
00348 int sys_acl_free_text(char *text)
00349 {
00350         /*
00351          * (void) cast and explicit return 0 are for DEC UNIX
00352          *  which just #defines acl_free_text() to be free()
00353          */
00354         (void) acl_free_text(text);
00355         return 0;
00356 }
00357 
00358 int sys_acl_free_acl(SMB_ACL_T the_acl) 
00359 {
00360         return acl_free(the_acl);
00361 }
00362 
00363 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
00364 {
00365         return acl_free_qualifier(qual, tagtype);
00366 }
00367 
00368 #elif defined(HAVE_UNIXWARE_ACLS) || defined(HAVE_SOLARIS_ACLS)
00369 
00370 /*
00371  * Donated by Michael Davidson <md@sco.COM> for UnixWare / OpenUNIX.
00372  * Modified by Toomas Soome <tsoome@ut.ee> for Solaris.
00373  */
00374 
00375 /*
00376  * Note that while this code implements sufficient functionality
00377  * to support the sys_acl_* interfaces it does not provide all
00378  * of the semantics of the POSIX ACL interfaces.
00379  *
00380  * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
00381  * from a call to sys_acl_get_entry() should not be assumed to be
00382  * valid after calling any of the following functions, which may
00383  * reorder the entries in the ACL.
00384  *
00385  *      sys_acl_valid()
00386  *      sys_acl_set_file()
00387  *      sys_acl_set_fd()
00388  */
00389 
00390 /*
00391  * The only difference between Solaris and UnixWare / OpenUNIX is
00392  * that the #defines for the ACL operations have different names
00393  */
00394 #if defined(HAVE_UNIXWARE_ACLS)
00395 
00396 #define SETACL          ACL_SET
00397 #define GETACL          ACL_GET
00398 #define GETACLCNT       ACL_CNT
00399 
00400 #endif
00401 
00402 
00403 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
00404 {
00405         if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
00406                 errno = EINVAL;
00407                 return -1;
00408         }
00409 
00410         if (entry_p == NULL) {
00411                 errno = EINVAL;
00412                 return -1;
00413         }
00414 
00415         if (entry_id == SMB_ACL_FIRST_ENTRY) {
00416                 acl_d->next = 0;
00417         }
00418 
00419         if (acl_d->next < 0) {
00420                 errno = EINVAL;
00421                 return -1;
00422         }
00423 
00424         if (acl_d->next >= acl_d->count) {
00425                 return 0;
00426         }
00427 
00428         *entry_p = &acl_d->acl[acl_d->next++];
00429 
00430         return 1;
00431 }
00432 
00433 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
00434 {
00435         *type_p = entry_d->a_type;
00436 
00437         return 0;
00438 }
00439 
00440 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
00441 {
00442         *permset_p = &entry_d->a_perm;
00443 
00444         return 0;
00445 }
00446 
00447 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
00448 {
00449         if (entry_d->a_type != SMB_ACL_USER
00450             && entry_d->a_type != SMB_ACL_GROUP) {
00451                 errno = EINVAL;
00452                 return NULL;
00453         }
00454 
00455         return &entry_d->a_id;
00456 }
00457 
00458 /*
00459  * There is no way of knowing what size the ACL returned by
00460  * GETACL will be unless you first call GETACLCNT which means
00461  * making an additional system call.
00462  *
00463  * In the hope of avoiding the cost of the additional system
00464  * call in most cases, we initially allocate enough space for
00465  * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
00466  * be too small then we use GETACLCNT to find out the actual
00467  * size, reallocate the ACL buffer, and then call GETACL again.
00468  */
00469 
00470 #define INITIAL_ACL_SIZE        16
00471 
00472 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
00473 {
00474         SMB_ACL_T       acl_d;
00475         int             count;          /* # of ACL entries allocated   */
00476         int             naccess;        /* # of access ACL entries      */
00477         int             ndefault;       /* # of default ACL entries     */
00478 
00479         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
00480                 errno = EINVAL;
00481                 return NULL;
00482         }
00483 
00484         count = INITIAL_ACL_SIZE;
00485         if ((acl_d = sys_acl_init(count)) == NULL) {
00486                 return NULL;
00487         }
00488 
00489         /*
00490          * If there isn't enough space for the ACL entries we use
00491          * GETACLCNT to determine the actual number of ACL entries
00492          * reallocate and try again. This is in a loop because it
00493          * is possible that someone else could modify the ACL and
00494          * increase the number of entries between the call to
00495          * GETACLCNT and the call to GETACL.
00496          */
00497         while ((count = acl(path_p, GETACL, count, &acl_d->acl[0])) < 0
00498             && errno == ENOSPC) {
00499 
00500                 sys_acl_free_acl(acl_d);
00501 
00502                 if ((count = acl(path_p, GETACLCNT, 0, NULL)) < 0) {
00503                         return NULL;
00504                 }
00505 
00506                 if ((acl_d = sys_acl_init(count)) == NULL) {
00507                         return NULL;
00508                 }
00509         }
00510 
00511         if (count < 0) {
00512                 sys_acl_free_acl(acl_d);
00513                 return NULL;
00514         }
00515 
00516         /*
00517          * calculate the number of access and default ACL entries
00518          *
00519          * Note: we assume that the acl() system call returned a
00520          * well formed ACL which is sorted so that all of the
00521          * access ACL entries preceed any default ACL entries
00522          */
00523         for (naccess = 0; naccess < count; naccess++) {
00524                 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
00525                         break;
00526         }
00527         ndefault = count - naccess;
00528         
00529         /*
00530          * if the caller wants the default ACL we have to copy
00531          * the entries down to the start of the acl[] buffer
00532          * and mask out the ACL_DEFAULT flag from the type field
00533          */
00534         if (type == SMB_ACL_TYPE_DEFAULT) {
00535                 int     i, j;
00536 
00537                 for (i = 0, j = naccess; i < ndefault; i++, j++) {
00538                         acl_d->acl[i] = acl_d->acl[j];
00539                         acl_d->acl[i].a_type &= ~ACL_DEFAULT;
00540                 }
00541 
00542                 acl_d->count = ndefault;
00543         } else {
00544                 acl_d->count = naccess;
00545         }
00546 
00547         return acl_d;
00548 }
00549 
00550 SMB_ACL_T sys_acl_get_fd(int fd)
00551 {
00552         SMB_ACL_T       acl_d;
00553         int             count;          /* # of ACL entries allocated   */
00554         int             naccess;        /* # of access ACL entries      */
00555 
00556         count = INITIAL_ACL_SIZE;
00557         if ((acl_d = sys_acl_init(count)) == NULL) {
00558                 return NULL;
00559         }
00560 
00561         while ((count = facl(fd, GETACL, count, &acl_d->acl[0])) < 0
00562             && errno == ENOSPC) {
00563 
00564                 sys_acl_free_acl(acl_d);
00565 
00566                 if ((count = facl(fd, GETACLCNT, 0, NULL)) < 0) {
00567                         return NULL;
00568                 }
00569 
00570                 if ((acl_d = sys_acl_init(count)) == NULL) {
00571                         return NULL;
00572                 }
00573         }
00574 
00575         if (count < 0) {
00576                 sys_acl_free_acl(acl_d);
00577                 return NULL;
00578         }
00579 
00580         /*
00581          * calculate the number of access ACL entries
00582          */
00583         for (naccess = 0; naccess < count; naccess++) {
00584                 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
00585                         break;
00586         }
00587         
00588         acl_d->count = naccess;
00589 
00590         return acl_d;
00591 }
00592 
00593 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
00594 {
00595         *permset_d = 0;
00596 
00597         return 0;
00598 }
00599 
00600 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
00601 {
00602         if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
00603             && perm != SMB_ACL_EXECUTE) {
00604                 errno = EINVAL;
00605                 return -1;
00606         }
00607 
00608         if (permset_d == NULL) {
00609                 errno = EINVAL;
00610                 return -1;
00611         }
00612 
00613         *permset_d |= perm;
00614 
00615         return 0;
00616 }
00617 
00618 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
00619 {
00620         return *permset_d & perm;
00621 }
00622 
00623 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
00624 {
00625         int     i;
00626         int     len, maxlen;
00627         char    *text;
00628 
00629         /*
00630          * use an initial estimate of 20 bytes per ACL entry
00631          * when allocating memory for the text representation
00632          * of the ACL
00633          */
00634         len     = 0;
00635         maxlen  = 20 * acl_d->count;
00636         if ((text = SMB_MALLOC(maxlen)) == NULL) {
00637                 errno = ENOMEM;
00638                 return NULL;
00639         }
00640 
00641         for (i = 0; i < acl_d->count; i++) {
00642                 struct acl      *ap     = &acl_d->acl[i];
00643                 struct group    *gr;
00644                 char            tagbuf[12];
00645                 char            idbuf[12];
00646                 char            *tag;
00647                 char            *id     = "";
00648                 char            perms[4];
00649                 int             nbytes;
00650 
00651                 switch (ap->a_type) {
00652                         /*
00653                          * for debugging purposes it's probably more
00654                          * useful to dump unknown tag types rather
00655                          * than just returning an error
00656                          */
00657                         default:
00658                                 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
00659                                         ap->a_type);
00660                                 tag = tagbuf;
00661                                 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
00662                                         (long)ap->a_id);
00663                                 id = idbuf;
00664                                 break;
00665 
00666                         case SMB_ACL_USER:
00667                                 id = uidtoname(ap->a_id);
00668                         case SMB_ACL_USER_OBJ:
00669                                 tag = "user";
00670                                 break;
00671 
00672                         case SMB_ACL_GROUP:
00673                                 if ((gr = getgrgid(ap->a_id)) == NULL) {
00674                                         slprintf(idbuf, sizeof(idbuf)-1, "%ld",
00675                                                 (long)ap->a_id);
00676                                         id = idbuf;
00677                                 } else {
00678                                         id = gr->gr_name;
00679                                 }
00680                         case SMB_ACL_GROUP_OBJ:
00681                                 tag = "group";
00682                                 break;
00683 
00684                         case SMB_ACL_OTHER:
00685                                 tag = "other";
00686                                 break;
00687 
00688                         case SMB_ACL_MASK:
00689                                 tag = "mask";
00690                                 break;
00691 
00692                 }
00693 
00694                 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
00695                 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
00696                 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
00697                 perms[3] = '\0';
00698 
00699                 /*          <tag>      :  <qualifier>   :  rwx \n  \0 */
00700                 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
00701 
00702                 /*
00703                  * If this entry would overflow the buffer
00704                  * allocate enough additional memory for this
00705                  * entry and an estimate of another 20 bytes
00706                  * for each entry still to be processed
00707                  */
00708                 if ((len + nbytes) > maxlen) {
00709                         char *oldtext = text;
00710 
00711                         maxlen += nbytes + 20 * (acl_d->count - i);
00712 
00713                         if ((text = SMB_REALLOC(oldtext, maxlen)) == NULL) {
00714                                 SAFE_FREE(oldtext);
00715                                 errno = ENOMEM;
00716                                 return NULL;
00717                         }
00718                 }
00719 
00720                 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
00721                 len += nbytes - 1;
00722         }
00723 
00724         if (len_p)
00725                 *len_p = len;
00726 
00727         return text;
00728 }
00729 
00730 SMB_ACL_T sys_acl_init(int count)
00731 {
00732         SMB_ACL_T       a;
00733 
00734         if (count < 0) {
00735                 errno = EINVAL;
00736                 return NULL;
00737         }
00738 
00739         /*
00740          * note that since the definition of the structure pointed
00741          * to by the SMB_ACL_T includes the first element of the
00742          * acl[] array, this actually allocates an ACL with room
00743          * for (count+1) entries
00744          */
00745         if ((a = (SMB_ACL_T)SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
00746                 errno = ENOMEM;
00747                 return NULL;
00748         }
00749 
00750         a->size = count + 1;
00751         a->count = 0;
00752         a->next = -1;
00753 
00754         return a;
00755 }
00756 
00757 
00758 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
00759 {
00760         SMB_ACL_T       acl_d;
00761         SMB_ACL_ENTRY_T entry_d;
00762 
00763         if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
00764                 errno = EINVAL;
00765                 return -1;
00766         }
00767 
00768         if (acl_d->count >= acl_d->size) {
00769                 errno = ENOSPC;
00770                 return -1;
00771         }
00772 
00773         entry_d         = &acl_d->acl[acl_d->count++];
00774         entry_d->a_type = 0;
00775         entry_d->a_id   = -1;
00776         entry_d->a_perm = 0;
00777         *entry_p        = entry_d;
00778 
00779         return 0;
00780 }
00781 
00782 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
00783 {
00784         switch (tag_type) {
00785                 case SMB_ACL_USER:
00786                 case SMB_ACL_USER_OBJ:
00787                 case SMB_ACL_GROUP:
00788                 case SMB_ACL_GROUP_OBJ:
00789                 case SMB_ACL_OTHER:
00790                 case SMB_ACL_MASK:
00791                         entry_d->a_type = tag_type;
00792                         break;
00793                 default:
00794                         errno = EINVAL;
00795                         return -1;
00796         }
00797 
00798         return 0;
00799 }
00800 
00801 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
00802 {
00803         if (entry_d->a_type != SMB_ACL_GROUP
00804             && entry_d->a_type != SMB_ACL_USER) {
00805                 errno = EINVAL;
00806                 return -1;
00807         }
00808 
00809         entry_d->a_id = *((id_t *)qual_p);
00810 
00811         return 0;
00812 }
00813 
00814 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
00815 {
00816         if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
00817                 return EINVAL;
00818         }
00819 
00820         entry_d->a_perm = *permset_d;
00821 
00822         return 0;
00823 }
00824 
00825 /*
00826  * sort the ACL and check it for validity
00827  *
00828  * if it's a minimal ACL with only 4 entries then we
00829  * need to recalculate the mask permissions to make
00830  * sure that they are the same as the GROUP_OBJ
00831  * permissions as required by the UnixWare acl() system call.
00832  *
00833  * (note: since POSIX allows minimal ACLs which only contain
00834  * 3 entries - ie there is no mask entry - we should, in theory,
00835  * check for this and add a mask entry if necessary - however
00836  * we "know" that the caller of this interface always specifies
00837  * a mask so, in practice "this never happens" (tm) - if it *does*
00838  * happen aclsort() will fail and return an error and someone will
00839  * have to fix it ...)
00840  */
00841 
00842 static int acl_sort(SMB_ACL_T acl_d)
00843 {
00844         int     fixmask = (acl_d->count <= 4);
00845 
00846         if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) {
00847                 errno = EINVAL;
00848                 return -1;
00849         }
00850         return 0;
00851 }
00852  
00853 int sys_acl_valid(SMB_ACL_T acl_d)
00854 {
00855         return acl_sort(acl_d);
00856 }
00857 
00858 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
00859 {
00860         struct stat     s;
00861         struct acl      *acl_p;
00862         int             acl_count;
00863         struct acl      *acl_buf        = NULL;
00864         int             ret;
00865 
00866         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
00867                 errno = EINVAL;
00868                 return -1;
00869         }
00870 
00871         if (acl_sort(acl_d) != 0) {
00872                 return -1;
00873         }
00874 
00875         acl_p           = &acl_d->acl[0];
00876         acl_count       = acl_d->count;
00877 
00878         /*
00879          * if it's a directory there is extra work to do
00880          * since the acl() system call will replace both
00881          * the access ACLs and the default ACLs (if any)
00882          */
00883         if (stat(name, &s) != 0) {
00884                 return -1;
00885         }
00886         if (S_ISDIR(s.st_mode)) {
00887                 SMB_ACL_T       acc_acl;
00888                 SMB_ACL_T       def_acl;
00889                 SMB_ACL_T       tmp_acl;
00890                 int             i;
00891 
00892                 if (type == SMB_ACL_TYPE_ACCESS) {
00893                         acc_acl = acl_d;
00894                         def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
00895 
00896                 } else {
00897                         def_acl = acl_d;
00898                         acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
00899                 }
00900 
00901                 if (tmp_acl == NULL) {
00902                         return -1;
00903                 }
00904 
00905                 /*
00906                  * allocate a temporary buffer for the complete ACL
00907                  */
00908                 acl_count = acc_acl->count + def_acl->count;
00909                 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
00910 
00911                 if (acl_buf == NULL) {
00912                         sys_acl_free_acl(tmp_acl);
00913                         errno = ENOMEM;
00914                         return -1;
00915                 }
00916 
00917                 /*
00918                  * copy the access control and default entries into the buffer
00919                  */
00920                 memcpy(&acl_buf[0], &acc_acl->acl[0],
00921                         acc_acl->count * sizeof(acl_buf[0]));
00922 
00923                 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
00924                         def_acl->count * sizeof(acl_buf[0]));
00925 
00926                 /*
00927                  * set the ACL_DEFAULT flag on the default entries
00928                  */
00929                 for (i = acc_acl->count; i < acl_count; i++) {
00930                         acl_buf[i].a_type |= ACL_DEFAULT;
00931                 }
00932 
00933                 sys_acl_free_acl(tmp_acl);
00934 
00935         } else if (type != SMB_ACL_TYPE_ACCESS) {
00936                 errno = EINVAL;
00937                 return -1;
00938         }
00939 
00940         ret = acl(name, SETACL, acl_count, acl_p);
00941 
00942         SAFE_FREE(acl_buf);
00943 
00944         return ret;
00945 }
00946 
00947 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
00948 {
00949         if (acl_sort(acl_d) != 0) {
00950                 return -1;
00951         }
00952 
00953         return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);
00954 }
00955 
00956 int sys_acl_delete_def_file(const char *path)
00957 {
00958         SMB_ACL_T       acl_d;
00959         int             ret;
00960 
00961         /*
00962          * fetching the access ACL and rewriting it has
00963          * the effect of deleting the default ACL
00964          */
00965         if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
00966                 return -1;
00967         }
00968 
00969         ret = acl(path, SETACL, acl_d->count, acl_d->acl);
00970 
00971         sys_acl_free_acl(acl_d);
00972         
00973         return ret;
00974 }
00975 
00976 int sys_acl_free_text(char *text)
00977 {
00978         SAFE_FREE(text);
00979         return 0;
00980 }
00981 
00982 int sys_acl_free_acl(SMB_ACL_T acl_d) 
00983 {
00984         SAFE_FREE(acl_d);
00985         return 0;
00986 }
00987 
00988 int sys_acl_free_qualifier(UNUSED(void *qual), UNUSED(SMB_ACL_TAG_T tagtype))
00989 {
00990         return 0;
00991 }
00992 
00993 #elif defined(HAVE_HPUX_ACLS)
00994 #include <dl.h>
00995 
00996 /*
00997  * Based on the Solaris/SCO code - with modifications.
00998  */
00999 
01000 /*
01001  * Note that while this code implements sufficient functionality
01002  * to support the sys_acl_* interfaces it does not provide all
01003  * of the semantics of the POSIX ACL interfaces.
01004  *
01005  * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned
01006  * from a call to sys_acl_get_entry() should not be assumed to be
01007  * valid after calling any of the following functions, which may
01008  * reorder the entries in the ACL.
01009  *
01010  *      sys_acl_valid()
01011  *      sys_acl_set_file()
01012  *      sys_acl_set_fd()
01013  */
01014 
01015 /* This checks if the POSIX ACL system call is defined */
01016 /* which basically corresponds to whether JFS 3.3 or   */
01017 /* higher is installed. If acl() was called when it    */
01018 /* isn't defined, it causes the process to core dump   */
01019 /* so it is important to check this and avoid acl()    */
01020 /* calls if it isn't there.                            */
01021 
01022 static BOOL hpux_acl_call_presence(void)
01023 {
01024 
01025         shl_t handle = NULL;
01026         void *value;
01027         int ret_val=0;
01028         static BOOL already_checked=0;
01029 
01030         if(already_checked)
01031                 return True;
01032 
01033 
01034         ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value);
01035 
01036         if(ret_val != 0) {
01037                 DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n",
01038                         ret_val, errno, strerror(errno)));
01039                 DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n"));
01040                 return False;
01041         }
01042 
01043         DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n"));
01044 
01045         already_checked = True;
01046         return True;
01047 }
01048 
01049 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
01050 {
01051         if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
01052                 errno = EINVAL;
01053                 return -1;
01054         }
01055 
01056         if (entry_p == NULL) {
01057                 errno = EINVAL;
01058                 return -1;
01059         }
01060 
01061         if (entry_id == SMB_ACL_FIRST_ENTRY) {
01062                 acl_d->next = 0;
01063         }
01064 
01065         if (acl_d->next < 0) {
01066                 errno = EINVAL;
01067                 return -1;
01068         }
01069 
01070         if (acl_d->next >= acl_d->count) {
01071                 return 0;
01072         }
01073 
01074         *entry_p = &acl_d->acl[acl_d->next++];
01075 
01076         return 1;
01077 }
01078 
01079 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
01080 {
01081         *type_p = entry_d->a_type;
01082 
01083         return 0;
01084 }
01085 
01086 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
01087 {
01088         *permset_p = &entry_d->a_perm;
01089 
01090         return 0;
01091 }
01092 
01093 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
01094 {
01095         if (entry_d->a_type != SMB_ACL_USER
01096             && entry_d->a_type != SMB_ACL_GROUP) {
01097                 errno = EINVAL;
01098                 return NULL;
01099         }
01100 
01101         return &entry_d->a_id;
01102 }
01103 
01104 /*
01105  * There is no way of knowing what size the ACL returned by
01106  * ACL_GET will be unless you first call ACL_CNT which means
01107  * making an additional system call.
01108  *
01109  * In the hope of avoiding the cost of the additional system
01110  * call in most cases, we initially allocate enough space for
01111  * an ACL with INITIAL_ACL_SIZE entries. If this turns out to
01112  * be too small then we use ACL_CNT to find out the actual
01113  * size, reallocate the ACL buffer, and then call ACL_GET again.
01114  */
01115 
01116 #define INITIAL_ACL_SIZE        16
01117 
01118 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
01119 {
01120         SMB_ACL_T       acl_d;
01121         int             count;          /* # of ACL entries allocated   */
01122         int             naccess;        /* # of access ACL entries      */
01123         int             ndefault;       /* # of default ACL entries     */
01124 
01125         if(hpux_acl_call_presence() == False) {
01126                 /* Looks like we don't have the acl() system call on HPUX. 
01127                  * May be the system doesn't have the latest version of JFS.
01128                  */
01129                 return NULL; 
01130         }
01131 
01132         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
01133                 errno = EINVAL;
01134                 return NULL;
01135         }
01136 
01137         count = INITIAL_ACL_SIZE;
01138         if ((acl_d = sys_acl_init(count)) == NULL) {
01139                 return NULL;
01140         }
01141 
01142         /*
01143          * If there isn't enough space for the ACL entries we use
01144          * ACL_CNT to determine the actual number of ACL entries
01145          * reallocate and try again. This is in a loop because it
01146          * is possible that someone else could modify the ACL and
01147          * increase the number of entries between the call to
01148          * ACL_CNT and the call to ACL_GET.
01149          */
01150         while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) {
01151 
01152                 sys_acl_free_acl(acl_d);
01153 
01154                 if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) {
01155                         return NULL;
01156                 }
01157 
01158                 if ((acl_d = sys_acl_init(count)) == NULL) {
01159                         return NULL;
01160                 }
01161         }
01162 
01163         if (count < 0) {
01164                 sys_acl_free_acl(acl_d);
01165                 return NULL;
01166         }
01167 
01168         /*
01169          * calculate the number of access and default ACL entries
01170          *
01171          * Note: we assume that the acl() system call returned a
01172          * well formed ACL which is sorted so that all of the
01173          * access ACL entries preceed any default ACL entries
01174          */
01175         for (naccess = 0; naccess < count; naccess++) {
01176                 if (acl_d->acl[naccess].a_type & ACL_DEFAULT)
01177                         break;
01178         }
01179         ndefault = count - naccess;
01180         
01181         /*
01182          * if the caller wants the default ACL we have to copy
01183          * the entries down to the start of the acl[] buffer
01184          * and mask out the ACL_DEFAULT flag from the type field
01185          */
01186         if (type == SMB_ACL_TYPE_DEFAULT) {
01187                 int     i, j;
01188 
01189                 for (i = 0, j = naccess; i < ndefault; i++, j++) {
01190                         acl_d->acl[i] = acl_d->acl[j];
01191                         acl_d->acl[i].a_type &= ~ACL_DEFAULT;
01192                 }
01193 
01194                 acl_d->count = ndefault;
01195         } else {
01196                 acl_d->count = naccess;
01197         }
01198 
01199         return acl_d;
01200 }
01201 
01202 SMB_ACL_T sys_acl_get_fd(int fd)
01203 {
01204         /*
01205          * HPUX doesn't have the facl call. Fake it using the path.... JRA.
01206          */
01207 
01208         files_struct *fsp = file_find_fd(fd);
01209 
01210         if (fsp == NULL) {
01211                 errno = EBADF;
01212                 return NULL;
01213         }
01214 
01215         /*
01216          * We know we're in the same conn context. So we
01217          * can use the relative path.
01218          */
01219 
01220         return sys_acl_get_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
01221 }
01222 
01223 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
01224 {
01225         *permset_d = 0;
01226 
01227         return 0;
01228 }
01229 
01230 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
01231 {
01232         if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
01233             && perm != SMB_ACL_EXECUTE) {
01234                 errno = EINVAL;
01235                 return -1;
01236         }
01237 
01238         if (permset_d == NULL) {
01239                 errno = EINVAL;
01240                 return -1;
01241         }
01242 
01243         *permset_d |= perm;
01244 
01245         return 0;
01246 }
01247 
01248 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
01249 {
01250         return *permset_d & perm;
01251 }
01252 
01253 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
01254 {
01255         int     i;
01256         int     len, maxlen;
01257         char    *text;
01258 
01259         /*
01260          * use an initial estimate of 20 bytes per ACL entry
01261          * when allocating memory for the text representation
01262          * of the ACL
01263          */
01264         len     = 0;
01265         maxlen  = 20 * acl_d->count;
01266         if ((text = SMB_MALLOC(maxlen)) == NULL) {
01267                 errno = ENOMEM;
01268                 return NULL;
01269         }
01270 
01271         for (i = 0; i < acl_d->count; i++) {
01272                 struct acl      *ap     = &acl_d->acl[i];
01273                 struct group    *gr;
01274                 char            tagbuf[12];
01275                 char            idbuf[12];
01276                 char            *tag;
01277                 char            *id     = "";
01278                 char            perms[4];
01279                 int             nbytes;
01280 
01281                 switch (ap->a_type) {
01282                         /*
01283                          * for debugging purposes it's probably more
01284                          * useful to dump unknown tag types rather
01285                          * than just returning an error
01286                          */
01287                         default:
01288                                 slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x",
01289                                         ap->a_type);
01290                                 tag = tagbuf;
01291                                 slprintf(idbuf, sizeof(idbuf)-1, "%ld",
01292                                         (long)ap->a_id);
01293                                 id = idbuf;
01294                                 break;
01295 
01296                         case SMB_ACL_USER:
01297                                 id = uidtoname(ap->a_id);
01298                         case SMB_ACL_USER_OBJ:
01299                                 tag = "user";
01300                                 break;
01301 
01302                         case SMB_ACL_GROUP:
01303                                 if ((gr = getgrgid(ap->a_id)) == NULL) {
01304                                         slprintf(idbuf, sizeof(idbuf)-1, "%ld",
01305                                                 (long)ap->a_id);
01306                                         id = idbuf;
01307                                 } else {
01308                                         id = gr->gr_name;
01309                                 }
01310                         case SMB_ACL_GROUP_OBJ:
01311                                 tag = "group";
01312                                 break;
01313 
01314                         case SMB_ACL_OTHER:
01315                                 tag = "other";
01316                                 break;
01317 
01318                         case SMB_ACL_MASK:
01319                                 tag = "mask";
01320                                 break;
01321 
01322                 }
01323 
01324                 perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-';
01325                 perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-';
01326                 perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-';
01327                 perms[3] = '\0';
01328 
01329                 /*          <tag>      :  <qualifier>   :  rwx \n  \0 */
01330                 nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1;
01331 
01332                 /*
01333                  * If this entry would overflow the buffer
01334                  * allocate enough additional memory for this
01335                  * entry and an estimate of another 20 bytes
01336                  * for each entry still to be processed
01337                  */
01338                 if ((len + nbytes) > maxlen) {
01339                         char *oldtext = text;
01340 
01341                         maxlen += nbytes + 20 * (acl_d->count - i);
01342 
01343                         if ((text = SMB_REALLOC(oldtext, maxlen)) == NULL) {
01344                                 free(oldtext);
01345                                 errno = ENOMEM;
01346                                 return NULL;
01347                         }
01348                 }
01349 
01350                 slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms);
01351                 len += nbytes - 1;
01352         }
01353 
01354         if (len_p)
01355                 *len_p = len;
01356 
01357         return text;
01358 }
01359 
01360 SMB_ACL_T sys_acl_init(int count)
01361 {
01362         SMB_ACL_T       a;
01363 
01364         if (count < 0) {
01365                 errno = EINVAL;
01366                 return NULL;
01367         }
01368 
01369         /*
01370          * note that since the definition of the structure pointed
01371          * to by the SMB_ACL_T includes the first element of the
01372          * acl[] array, this actually allocates an ACL with room
01373          * for (count+1) entries
01374          */
01375         if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) {
01376                 errno = ENOMEM;
01377                 return NULL;
01378         }
01379 
01380         a->size = count + 1;
01381         a->count = 0;
01382         a->next = -1;
01383 
01384         return a;
01385 }
01386 
01387 
01388 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
01389 {
01390         SMB_ACL_T       acl_d;
01391         SMB_ACL_ENTRY_T entry_d;
01392 
01393         if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
01394                 errno = EINVAL;
01395                 return -1;
01396         }
01397 
01398         if (acl_d->count >= acl_d->size) {
01399                 errno = ENOSPC;
01400                 return -1;
01401         }
01402 
01403         entry_d         = &acl_d->acl[acl_d->count++];
01404         entry_d->a_type = 0;
01405         entry_d->a_id   = -1;
01406         entry_d->a_perm = 0;
01407         *entry_p        = entry_d;
01408 
01409         return 0;
01410 }
01411 
01412 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
01413 {
01414         switch (tag_type) {
01415                 case SMB_ACL_USER:
01416                 case SMB_ACL_USER_OBJ:
01417                 case SMB_ACL_GROUP:
01418                 case SMB_ACL_GROUP_OBJ:
01419                 case SMB_ACL_OTHER:
01420                 case SMB_ACL_MASK:
01421                         entry_d->a_type = tag_type;
01422                         break;
01423                 default:
01424                         errno = EINVAL;
01425                         return -1;
01426         }
01427 
01428         return 0;
01429 }
01430 
01431 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
01432 {
01433         if (entry_d->a_type != SMB_ACL_GROUP
01434             && entry_d->a_type != SMB_ACL_USER) {
01435                 errno = EINVAL;
01436                 return -1;
01437         }
01438 
01439         entry_d->a_id = *((id_t *)qual_p);
01440 
01441         return 0;
01442 }
01443 
01444 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
01445 {
01446         if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
01447                 return EINVAL;
01448         }
01449 
01450         entry_d->a_perm = *permset_d;
01451 
01452         return 0;
01453 }
01454 
01455 /* Structure to capture the count for each type of ACE. */
01456 
01457 struct hpux_acl_types {
01458         int n_user;
01459         int n_def_user;
01460         int n_user_obj;
01461         int n_def_user_obj;
01462 
01463         int n_group;
01464         int n_def_group;
01465         int n_group_obj;
01466         int n_def_group_obj;
01467 
01468         int n_other;
01469         int n_other_obj;
01470         int n_def_other_obj;
01471 
01472         int n_class_obj;
01473         int n_def_class_obj;
01474 
01475         int n_illegal_obj;
01476 };
01477 
01478 /* count_obj:
01479  * Counts the different number of objects in a given array of ACL
01480  * structures.
01481  * Inputs:
01482  *
01483  * acl_count      - Count of ACLs in the array of ACL strucutres.
01484  * aclp           - Array of ACL structures.
01485  * acl_type_count - Pointer to acl_types structure. Should already be
01486  *                  allocated.
01487  * Output: 
01488  *
01489  * acl_type_count - This structure is filled up with counts of various 
01490  *                  acl types.
01491  */
01492 
01493 static int hpux_count_obj(int acl_count, struct acl *aclp, struct hpux_acl_types *acl_type_count)
01494 {
01495         int i;
01496 
01497         memset(acl_type_count, 0, sizeof(struct hpux_acl_types));
01498 
01499         for(i=0;i<acl_count;i++) {
01500                 switch(aclp[i].a_type) {
01501                 case USER: 
01502                         acl_type_count->n_user++;
01503                         break;
01504                 case USER_OBJ: 
01505                         acl_type_count->n_user_obj++;
01506                         break;
01507                 case DEF_USER_OBJ: 
01508                         acl_type_count->n_def_user_obj++;
01509                         break;
01510                 case GROUP: 
01511                         acl_type_count->n_group++;
01512                         break;
01513                 case GROUP_OBJ: 
01514                         acl_type_count->n_group_obj++;
01515                         break;
01516                 case DEF_GROUP_OBJ: 
01517                         acl_type_count->n_def_group_obj++;
01518                         break;
01519                 case OTHER_OBJ: 
01520                         acl_type_count->n_other_obj++;
01521                         break;
01522                 case DEF_OTHER_OBJ: 
01523                         acl_type_count->n_def_other_obj++;
01524                         break;
01525                 case CLASS_OBJ:
01526                         acl_type_count->n_class_obj++;
01527                         break;
01528                 case DEF_CLASS_OBJ:
01529                         acl_type_count->n_def_class_obj++;
01530                         break;
01531                 case DEF_USER:
01532                         acl_type_count->n_def_user++;
01533                         break;
01534                 case DEF_GROUP:
01535                         acl_type_count->n_def_group++;
01536                         break;
01537                 default: 
01538                         acl_type_count->n_illegal_obj++;
01539                         break;
01540                 }
01541         }
01542 }
01543 
01544 /* swap_acl_entries:  Swaps two ACL entries. 
01545  *
01546  * Inputs: aclp0, aclp1 - ACL entries to be swapped.
01547  */
01548 
01549 static void hpux_swap_acl_entries(struct acl *aclp0, struct acl *aclp1)
01550 {
01551         struct acl temp_acl;
01552 
01553         temp_acl.a_type = aclp0->a_type;
01554         temp_acl.a_id = aclp0->a_id;
01555         temp_acl.a_perm = aclp0->a_perm;
01556 
01557         aclp0->a_type = aclp1->a_type;
01558         aclp0->a_id = aclp1->a_id;
01559         aclp0->a_perm = aclp1->a_perm;
01560 
01561         aclp1->a_type = temp_acl.a_type;
01562         aclp1->a_id = temp_acl.a_id;
01563         aclp1->a_perm = temp_acl.a_perm;
01564 }
01565 
01566 /* prohibited_duplicate_type
01567  * Identifies if given ACL type can have duplicate entries or 
01568  * not.
01569  *
01570  * Inputs: acl_type - ACL Type.
01571  *
01572  * Outputs: 
01573  *
01574  * Return.. 
01575  *
01576  * True - If the ACL type matches any of the prohibited types.
01577  * False - If the ACL type doesn't match any of the prohibited types.
01578  */ 
01579 
01580 static BOOL hpux_prohibited_duplicate_type(int acl_type)
01581 {
01582         switch(acl_type) {
01583                 case USER:
01584                 case GROUP:
01585                 case DEF_USER: 
01586                 case DEF_GROUP:
01587                         return True;
01588                 default:
01589                         return False;
01590         }
01591 }
01592 
01593 /* get_needed_class_perm
01594  * Returns the permissions of a ACL structure only if the ACL
01595  * type matches one of the pre-determined types for computing 
01596  * CLASS_OBJ permissions.
01597  *
01598  * Inputs: aclp - Pointer to ACL structure.
01599  */
01600 
01601 static int hpux_get_needed_class_perm(struct acl *aclp)
01602 {
01603         switch(aclp->a_type) {
01604                 case USER: 
01605                 case GROUP_OBJ: 
01606                 case GROUP: 
01607                 case DEF_USER_OBJ: 
01608                 case DEF_USER:
01609                 case DEF_GROUP_OBJ: 
01610                 case DEF_GROUP:
01611                 case DEF_CLASS_OBJ:
01612                 case DEF_OTHER_OBJ: 
01613                         return aclp->a_perm;
01614                 default: 
01615                         return 0;
01616         }
01617 }
01618 
01619 /* acl_sort for HPUX.
01620  * Sorts the array of ACL structures as per the description in
01621  * aclsort man page. Refer to aclsort man page for more details
01622  *
01623  * Inputs:
01624  *
01625  * acl_count - Count of ACLs in the array of ACL structures.
01626  * calclass  - If this is not zero, then we compute the CLASS_OBJ
01627  *             permissions.
01628  * aclp      - Array of ACL structures.
01629  *
01630  * Outputs:
01631  *
01632  * aclp     - Sorted array of ACL structures.
01633  *
01634  * Outputs:
01635  *
01636  * Returns 0 for success -1 for failure. Prints a message to the Samba
01637  * debug log in case of failure.
01638  */
01639 
01640 static int hpux_acl_sort(int acl_count, int calclass, struct acl *aclp)
01641 {
01642 #if !defined(HAVE_HPUX_ACLSORT)
01643         /*
01644          * The aclsort() system call is availabe on the latest HPUX General
01645          * Patch Bundles. So for HPUX, we developed our version of acl_sort 
01646          * function. Because, we don't want to update to a new 
01647          * HPUX GR bundle just for aclsort() call.
01648          */
01649 
01650         struct hpux_acl_types acl_obj_count;
01651         int n_class_obj_perm = 0;
01652         int i, j;
01653  
01654         if(!acl_count) {
01655                 DEBUG(10,("Zero acl count passed. Returning Success\n"));
01656                 return 0;
01657         }
01658 
01659         if(aclp == NULL) {
01660                 DEBUG(0,("Null ACL pointer in hpux_acl_sort. Returning Failure. \n"));
01661                 return -1;
01662         }
01663 
01664         /* Count different types of ACLs in the ACLs array */
01665 
01666         hpux_count_obj(acl_count, aclp, &acl_obj_count);
01667 
01668         /* There should be only one entry each of type USER_OBJ, GROUP_OBJ, 
01669          * CLASS_OBJ and OTHER_OBJ 
01670          */
01671 
01672         if( (acl_obj_count.n_user_obj  != 1) || 
01673                 (acl_obj_count.n_group_obj != 1) || 
01674                 (acl_obj_count.n_class_obj != 1) ||
01675                 (acl_obj_count.n_other_obj != 1) 
01676         ) {
01677                 DEBUG(0,("hpux_acl_sort: More than one entry or no entries for \
01678 USER OBJ or GROUP_OBJ or OTHER_OBJ or CLASS_OBJ\n"));
01679                 return -1;
01680         }
01681 
01682         /* If any of the default objects are present, there should be only
01683          * one of them each.
01684          */
01685 
01686         if( (acl_obj_count.n_def_user_obj  > 1) || (acl_obj_count.n_def_group_obj > 1) || 
01687                         (acl_obj_count.n_def_other_obj > 1) || (acl_obj_count.n_def_class_obj > 1) ) {
01688                 DEBUG(0,("hpux_acl_sort: More than one entry for DEF_CLASS_OBJ \
01689 or DEF_USER_OBJ or DEF_GROUP_OBJ or DEF_OTHER_OBJ\n"));
01690                 return -1;
01691         }
01692 
01693         /* We now have proper number of OBJ and DEF_OBJ entries. Now sort the acl 
01694          * structures.  
01695          *
01696          * Sorting crieteria - First sort by ACL type. If there are multiple entries of
01697          * same ACL type, sort by ACL id.
01698          *
01699          * I am using the trival kind of sorting method here because, performance isn't 
01700          * really effected by the ACLs feature. More over there aren't going to be more
01701          * than 17 entries on HPUX. 
01702          */
01703 
01704         for(i=0; i<acl_count;i++) {
01705                 for (j=i+1; j<acl_count; j++) {
01706                         if( aclp[i].a_type > aclp[j].a_type ) {
01707                                 /* ACL entries out of order, swap them */
01708 
01709                                 hpux_swap_acl_entries((aclp+i), (aclp+j));
01710 
01711                         } else if ( aclp[i].a_type == aclp[j].a_type ) {
01712 
01713                                 /* ACL entries of same type, sort by id */
01714 
01715                                 if(aclp[i].a_id > aclp[j].a_id) {
01716                                         hpux_swap_acl_entries((aclp+i), (aclp+j));
01717                                 } else if (aclp[i].a_id == aclp[j].a_id) {
01718                                         /* We have a duplicate entry. */
01719                                         if(hpux_prohibited_duplicate_type(aclp[i].a_type)) {
01720                                                 DEBUG(0, ("hpux_acl_sort: Duplicate entry: Type(hex): %x Id: %d\n",
01721                                                         aclp[i].a_type, aclp[i].a_id));
01722                                                 return -1;
01723                                         }
01724                                 }
01725 
01726                         }
01727                 }
01728         }
01729 
01730         /* set the class obj permissions to the computed one. */
01731         if(calclass) {
01732                 int n_class_obj_index = -1;
01733 
01734                 for(i=0;i<acl_count;i++) {
01735                         n_class_obj_perm |= hpux_get_needed_class_perm((aclp+i));
01736 
01737                         if(aclp[i].a_type == CLASS_OBJ)
01738                                 n_class_obj_index = i;
01739                 }
01740                 aclp[n_class_obj_index].a_perm = n_class_obj_perm;
01741         }
01742 
01743         return 0;
01744 #else
01745         return aclsort(acl_count, calclass, aclp);
01746 #endif
01747 }
01748 
01749 /*
01750  * sort the ACL and check it for validity
01751  *
01752  * if it's a minimal ACL with only 4 entries then we
01753  * need to recalculate the mask permissions to make
01754  * sure that they are the same as the GROUP_OBJ
01755  * permissions as required by the UnixWare acl() system call.
01756  *
01757  * (note: since POSIX allows minimal ACLs which only contain
01758  * 3 entries - ie there is no mask entry - we should, in theory,
01759  * check for this and add a mask entry if necessary - however
01760  * we "know" that the caller of this interface always specifies
01761  * a mask so, in practice "this never happens" (tm) - if it *does*
01762  * happen aclsort() will fail and return an error and someone will
01763  * have to fix it ...)
01764  */
01765 
01766 static int acl_sort(SMB_ACL_T acl_d)
01767 {
01768         int fixmask = (acl_d->count <= 4);
01769 
01770         if (hpux_acl_sort(acl_d->count, fixmask, acl_d->acl) != 0) {
01771                 errno = EINVAL;
01772                 return -1;
01773         }
01774         return 0;
01775 }
01776  
01777 int sys_acl_valid(SMB_ACL_T acl_d)
01778 {
01779         return acl_sort(acl_d);
01780 }
01781 
01782 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
01783 {
01784         struct stat     s;
01785         struct acl      *acl_p;
01786         int             acl_count;
01787         struct acl      *acl_buf        = NULL;
01788         int             ret;
01789 
01790         if(hpux_acl_call_presence() == False) {
01791                 /* Looks like we don't have the acl() system call on HPUX. 
01792                  * May be the system doesn't have the latest version of JFS.
01793                  */
01794                 errno=ENOSYS;
01795                 return -1; 
01796         }
01797 
01798         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
01799                 errno = EINVAL;
01800                 return -1;
01801         }
01802 
01803         if (acl_sort(acl_d) != 0) {
01804                 return -1;
01805         }
01806 
01807         acl_p           = &acl_d->acl[0];
01808         acl_count       = acl_d->count;
01809 
01810         /*
01811          * if it's a directory there is extra work to do
01812          * since the acl() system call will replace both
01813          * the access ACLs and the default ACLs (if any)
01814          */
01815         if (stat(name, &s) != 0) {
01816                 return -1;
01817         }
01818         if (S_ISDIR(s.st_mode)) {
01819                 SMB_ACL_T       acc_acl;
01820                 SMB_ACL_T       def_acl;
01821                 SMB_ACL_T       tmp_acl;
01822                 int             i;
01823 
01824                 if (type == SMB_ACL_TYPE_ACCESS) {
01825                         acc_acl = acl_d;
01826                         def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT);
01827 
01828                 } else {
01829                         def_acl = acl_d;
01830                         acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS);
01831                 }
01832 
01833                 if (tmp_acl == NULL) {
01834                         return -1;
01835                 }
01836 
01837                 /*
01838                  * allocate a temporary buffer for the complete ACL
01839                  */
01840                 acl_count = acc_acl->count + def_acl->count;
01841                 acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count);
01842 
01843                 if (acl_buf == NULL) {
01844                         sys_acl_free_acl(tmp_acl);
01845                         errno = ENOMEM;
01846                         return -1;
01847                 }
01848 
01849                 /*
01850                  * copy the access control and default entries into the buffer
01851                  */
01852                 memcpy(&acl_buf[0], &acc_acl->acl[0],
01853                         acc_acl->count * sizeof(acl_buf[0]));
01854 
01855                 memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0],
01856                         def_acl->count * sizeof(acl_buf[0]));
01857 
01858                 /*
01859                  * set the ACL_DEFAULT flag on the default entries
01860                  */
01861                 for (i = acc_acl->count; i < acl_count; i++) {
01862                         acl_buf[i].a_type |= ACL_DEFAULT;
01863                 }
01864 
01865                 sys_acl_free_acl(tmp_acl);
01866 
01867         } else if (type != SMB_ACL_TYPE_ACCESS) {
01868                 errno = EINVAL;
01869                 return -1;
01870         }
01871 
01872         ret = acl(name, ACL_SET, acl_count, acl_p);
01873 
01874         if (acl_buf) {
01875                 free(acl_buf);
01876         }
01877 
01878         return ret;
01879 }
01880 
01881 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
01882 {
01883         /*
01884          * HPUX doesn't have the facl call. Fake it using the path.... JRA.
01885          */
01886 
01887         files_struct *fsp = file_find_fd(fd);
01888 
01889         if (fsp == NULL) {
01890                 errno = EBADF;
01891                 return NULL;
01892         }
01893 
01894         if (acl_sort(acl_d) != 0) {
01895                 return -1;
01896         }
01897 
01898         /*
01899          * We know we're in the same conn context. So we
01900          * can use the relative path.
01901          */
01902 
01903         return sys_acl_set_file(fsp->fsp_name, SMB_ACL_TYPE_ACCESS, acl_d);
01904 }
01905 
01906 int sys_acl_delete_def_file(const char *path)
01907 {
01908         SMB_ACL_T       acl_d;
01909         int             ret;
01910 
01911         /*
01912          * fetching the access ACL and rewriting it has
01913          * the effect of deleting the default ACL
01914          */
01915         if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) {
01916                 return -1;
01917         }
01918 
01919         ret = acl(path, ACL_SET, acl_d->count, acl_d->acl);
01920 
01921         sys_acl_free_acl(acl_d);
01922         
01923         return ret;
01924 }
01925 
01926 int sys_acl_free_text(char *text)
01927 {
01928         free(text);
01929         return 0;
01930 }
01931 
01932 int sys_acl_free_acl(SMB_ACL_T acl_d) 
01933 {
01934         free(acl_d);
01935         return 0;
01936 }
01937 
01938 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
01939 {
01940         return 0;
01941 }
01942 
01943 #elif defined(HAVE_IRIX_ACLS)
01944 
01945 int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p)
01946 {
01947         if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) {
01948                 errno = EINVAL;
01949                 return -1;
01950         }
01951 
01952         if (entry_p == NULL) {
01953                 errno = EINVAL;
01954                 return -1;
01955         }
01956 
01957         if (entry_id == SMB_ACL_FIRST_ENTRY) {
01958                 acl_d->next = 0;
01959         }
01960 
01961         if (acl_d->next < 0) {
01962                 errno = EINVAL;
01963                 return -1;
01964         }
01965 
01966         if (acl_d->next >= acl_d->aclp->acl_cnt) {
01967                 return 0;
01968         }
01969 
01970         *entry_p = &acl_d->aclp->acl_entry[acl_d->next++];
01971 
01972         return 1;
01973 }
01974 
01975 int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p)
01976 {
01977         *type_p = entry_d->ae_tag;
01978 
01979         return 0;
01980 }
01981 
01982 int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
01983 {
01984         *permset_p = entry_d;
01985 
01986         return 0;
01987 }
01988 
01989 void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d)
01990 {
01991         if (entry_d->ae_tag != SMB_ACL_USER
01992             && entry_d->ae_tag != SMB_ACL_GROUP) {
01993                 errno = EINVAL;
01994                 return NULL;
01995         }
01996 
01997         return &entry_d->ae_id;
01998 }
01999 
02000 SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type)
02001 {
02002         SMB_ACL_T       a;
02003 
02004         if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
02005                 errno = ENOMEM;
02006                 return NULL;
02007         }
02008         if ((a->aclp = acl_get_file(path_p, type)) == NULL) {
02009                 SAFE_FREE(a);
02010                 return NULL;
02011         }
02012         a->next = -1;
02013         a->freeaclp = True;
02014         return a;
02015 }
02016 
02017 SMB_ACL_T sys_acl_get_fd(int fd)
02018 {
02019         SMB_ACL_T       a;
02020 
02021         if ((a = SMB_MALLOC_P(struct SMB_ACL_T)) == NULL) {
02022                 errno = ENOMEM;
02023                 return NULL;
02024         }
02025         if ((a->aclp = acl_get_fd(fd)) == NULL) {
02026                 SAFE_FREE(a);
02027                 return NULL;
02028         }
02029         a->next = -1;
02030         a->freeaclp = True;
02031         return a;
02032 }
02033 
02034 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d)
02035 {
02036         permset_d->ae_perm = 0;
02037 
02038         return 0;
02039 }
02040 
02041 int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
02042 {
02043         if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE
02044             && perm != SMB_ACL_EXECUTE) {
02045                 errno = EINVAL;
02046                 return -1;
02047         }
02048 
02049         if (permset_d == NULL) {
02050                 errno = EINVAL;
02051                 return -1;
02052         }
02053 
02054         permset_d->ae_perm |= perm;
02055 
02056         return 0;
02057 }
02058 
02059 int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm)
02060 {
02061         return permset_d->ae_perm & perm;
02062 }
02063 
02064 char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p)
02065 {
02066         return acl_to_text(acl_d->aclp, len_p);
02067 }
02068 
02069 SMB_ACL_T sys_acl_init(int count)
02070 {
02071         SMB_ACL_T       a;
02072 
02073         if (count < 0) {
02074                 errno = EINVAL;
02075                 return NULL;
02076         }
02077 
02078         if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + sizeof(struct acl))) == NULL) {
02079                 errno = ENOMEM;
02080                 return NULL;
02081         }
02082 
02083         a->next = -1;
02084         a->freeaclp = False;
02085         a->aclp = (struct acl *)(&a->aclp + sizeof(struct acl *));
02086         a->aclp->acl_cnt = 0;
02087 
02088         return a;
02089 }
02090 
02091 
02092 int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p)
02093 {
02094         SMB_ACL_T       acl_d;
02095         SMB_ACL_ENTRY_T entry_d;
02096 
02097         if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) {
02098                 errno = EINVAL;
02099                 return -1;
02100         }
02101 
02102         if (acl_d->aclp->acl_cnt >= ACL_MAX_ENTRIES) {
02103                 errno = ENOSPC;
02104                 return -1;
02105         }
02106 
02107         entry_d         = &acl_d->aclp->acl_entry[acl_d->aclp->acl_cnt++];
02108         entry_d->ae_tag = 0;
02109         entry_d->ae_id  = 0;
02110         entry_d->ae_perm        = 0;
02111         *entry_p        = entry_d;
02112 
02113         return 0;
02114 }
02115 
02116 int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type)
02117 {
02118         switch (tag_type) {
02119                 case SMB_ACL_USER:
02120                 case SMB_ACL_USER_OBJ:
02121                 case SMB_ACL_GROUP:
02122                 case SMB_ACL_GROUP_OBJ:
02123                 case SMB_ACL_OTHER:
02124                 case SMB_ACL_MASK:
02125                         entry_d->ae_tag = tag_type;
02126                         break;
02127                 default:
02128                         errno = EINVAL;
02129                         return -1;
02130         }
02131 
02132         return 0;
02133 }
02134 
02135 int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p)
02136 {
02137         if (entry_d->ae_tag != SMB_ACL_GROUP
02138             && entry_d->ae_tag != SMB_ACL_USER) {
02139                 errno = EINVAL;
02140                 return -1;
02141         }
02142 
02143         entry_d->ae_id = *((id_t *)qual_p);
02144 
02145         return 0;
02146 }
02147 
02148 int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d)
02149 {
02150         if (permset_d->ae_perm & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) {
02151                 return EINVAL;
02152         }
02153 
02154         entry_d->ae_perm = permset_d->ae_perm;
02155 
02156         return 0;
02157 }
02158 
02159 int sys_acl_valid(SMB_ACL_T acl_d)
02160 {
02161         return acl_valid(acl_d->aclp);
02162 }
02163 
02164 int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d)
02165 {
02166         return acl_set_file(name, type, acl_d->aclp);
02167 }
02168 
02169 int sys_acl_set_fd(int fd, SMB_ACL_T acl_d)
02170 {
02171         return acl_set_fd(fd, acl_d->aclp);
02172 }
02173 
02174 int sys_acl_delete_def_file(const char *name)
02175 {
02176         return acl_delete_def_file(name);
02177 }
02178 
02179 int sys_acl_free_text(char *text)
02180 {
02181         return acl_free(text);
02182 }
02183 
02184 int sys_acl_free_acl(SMB_ACL_T acl_d) 
02185 {
02186         if (acl_d->freeaclp) {
02187                 acl_free(acl_d->aclp);
02188         }
02189         acl_free(acl_d);
02190         return 0;
02191 }
02192 
02193 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
02194 {
02195         return 0;
02196 }
02197 
02198 #elif defined(HAVE_AIX_ACLS)
02199 
02200 /* Donated by Medha Date, mdate@austin.ibm.com, for IBM */
02201 
02202 int sys_acl_get_entry( SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p)
02203 {
02204         struct acl_entry_link *link;
02205         struct new_acl_entry *entry;
02206         int keep_going;
02207 
02208         DEBUG(10,("This is the count: %d\n",theacl->count));
02209 
02210         /* Check if count was previously set to -1. *
02211          * If it was, that means we reached the end *
02212          * of the acl last time.                    */
02213         if(theacl->count == -1)
02214                 return(0);
02215 
02216         link = theacl;
02217         /* To get to the next acl, traverse linked list until index *
02218          * of acl matches the count we are keeping.  This count is  *
02219          * incremented each time we return an acl entry.            */
02220 
02221         for(keep_going = 0; keep_going < theacl->count; keep_going++)
02222                 link = link->nextp;
02223 
02224         entry = *entry_p =  link->entryp;
02225 
02226         DEBUG(10,("*entry_p is %d\n",entry_p));
02227         DEBUG(10,("*entry_p->ace_access is %d\n",entry->ace_access));
02228 
02229         /* Increment count */
02230         theacl->count++;
02231         if(link->nextp == NULL)
02232                 theacl->count = -1;
02233 
02234         return(1);
02235 }
02236 
02237 int sys_acl_get_tag_type( SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p)
02238 {
02239         /* Initialize tag type */
02240 
02241         *tag_type_p = -1;
02242         DEBUG(10,("the tagtype is %d\n",entry_d->ace_id->id_type));
02243 
02244         /* Depending on what type of entry we have, *
02245          * return tag type.                         */
02246         switch(entry_d->ace_id->id_type) {
02247         case ACEID_USER:
02248                 *tag_type_p = SMB_ACL_USER;
02249                 break;
02250         case ACEID_GROUP:
02251                 *tag_type_p = SMB_ACL_GROUP;
02252                 break;
02253 
02254         case SMB_ACL_USER_OBJ:
02255         case SMB_ACL_GROUP_OBJ:
02256         case SMB_ACL_OTHER:
02257                 *tag_type_p = entry_d->ace_id->id_type;
02258                 break;
02259  
02260         default:
02261                 return(-1);
02262         }
02263 
02264         return(0);
02265 }
02266 
02267 int sys_acl_get_permset( SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p)
02268 {
02269         DEBUG(10,("Starting AIX sys_acl_get_permset\n"));
02270         *permset_p = &entry_d->ace_access;
02271         DEBUG(10,("**permset_p is %d\n",**permset_p));
02272         if(!(**permset_p & S_IXUSR) &&
02273                 !(**permset_p & S_IWUSR) &&
02274                 !(**permset_p & S_IRUSR) &&
02275                 (**permset_p != 0))
02276                         return(-1);
02277 
02278         DEBUG(10,("Ending AIX sys_acl_get_permset\n"));
02279         return(0);
02280 }
02281 
02282 void *sys_acl_get_qualifier( SMB_ACL_ENTRY_T entry_d)
02283 {
02284         return(entry_d->ace_id->id_data);
02285 }
02286 
02287 SMB_ACL_T sys_acl_get_file( const char *path_p, SMB_ACL_TYPE_T type)
02288 {
02289         struct acl *file_acl = (struct acl *)NULL;
02290         struct acl_entry *acl_entry;
02291         struct new_acl_entry *new_acl_entry;
02292         struct ace_id *idp;
02293         struct acl_entry_link *acl_entry_link;
02294         struct acl_entry_link *acl_entry_link_head;
02295         int i;
02296         int rc = 0;
02297         uid_t user_id;
02298 
02299         /* AIX has no DEFAULT */
02300         if  ( type == SMB_ACL_TYPE_DEFAULT )
02301                 return NULL;
02302 
02303         /* Get the acl using statacl */
02304  
02305         DEBUG(10,("Entering sys_acl_get_file\n"));
02306         DEBUG(10,("path_p is %s\n",path_p));
02307 
02308         file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
02309  
02310         if(file_acl == NULL) {
02311                 errno=ENOMEM;
02312                 DEBUG(0,("Error in AIX sys_acl_get_file: %d\n",errno));
02313                 return(NULL);
02314         }
02315 
02316         memset(file_acl,0,BUFSIZ);
02317 
02318         rc = statacl((char *)path_p,0,file_acl,BUFSIZ);
02319         if(rc == -1) {
02320                 DEBUG(0,("statacl returned %d with errno %d\n",rc,errno));
02321                 SAFE_FREE(file_acl);
02322                 return(NULL);
02323         }
02324 
02325         DEBUG(10,("Got facl and returned it\n"));
02326 
02327         /* Point to the first acl entry in the acl */
02328         acl_entry =  file_acl->acl_ext;
02329 
02330         /* Begin setting up the head of the linked list *
02331          * that will be used for the storing the acl    *
02332          * in a way that is useful for the posix_acls.c *
02333          * code.                                          */
02334 
02335         acl_entry_link_head = acl_entry_link = sys_acl_init(0);
02336         if(acl_entry_link_head == NULL)
02337                 return(NULL);
02338 
02339         acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
02340         if(acl_entry_link->entryp == NULL) {
02341                 SAFE_FREE(file_acl);
02342                 errno = ENOMEM;
02343                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
02344                 return(NULL);
02345         }
02346 
02347         DEBUG(10,("acl_entry is %d\n",acl_entry));
02348         DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
02349 
02350         /* Check if the extended acl bit is on.   *
02351          * If it isn't, do not show the           *
02352          * contents of the acl since AIX intends *
02353          * the extended info to remain unused     */
02354 
02355         if(file_acl->acl_mode & S_IXACL){
02356                 /* while we are not pointing to the very end */
02357                 while(acl_entry < acl_last(file_acl)) {
02358                         /* before we malloc anything, make sure this is  */
02359                         /* a valid acl entry and one that we want to map */
02360                         idp = id_nxt(acl_entry->ace_id);
02361                         if((acl_entry->ace_type == ACC_SPECIFY ||
02362                                 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
02363                                         acl_entry = acl_nxt(acl_entry);
02364                                         continue;
02365                         }
02366 
02367                         idp = acl_entry->ace_id;
02368 
02369                         /* Check if this is the first entry in the linked list. *
02370                          * The first entry needs to keep prevp pointing to NULL *
02371                          * and already has entryp allocated.                  */
02372 
02373                         if(acl_entry_link_head->count != 0) {
02374                                 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
02375 
02376                                 if(acl_entry_link->nextp == NULL) {
02377                                         SAFE_FREE(file_acl);
02378                                         errno = ENOMEM;
02379                                         DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
02380                                         return(NULL);
02381                                 }
02382 
02383                                 acl_entry_link->nextp->prevp = acl_entry_link;
02384                                 acl_entry_link = acl_entry_link->nextp;
02385                                 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
02386                                 if(acl_entry_link->entryp == NULL) {
02387                                         SAFE_FREE(file_acl);
02388                                         errno = ENOMEM;
02389                                         DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
02390                                         return(NULL);
02391                                 }
02392                                 acl_entry_link->nextp = NULL;
02393                         }
02394 
02395                         acl_entry_link->entryp->ace_len = acl_entry->ace_len;
02396 
02397                         /* Don't really need this since all types are going *
02398                          * to be specified but, it's better than leaving it 0 */
02399 
02400                         acl_entry_link->entryp->ace_type = acl_entry->ace_type;
02401  
02402                         acl_entry_link->entryp->ace_access = acl_entry->ace_access;
02403  
02404                         memcpy(acl_entry_link->entryp->ace_id,idp,sizeof(struct ace_id));
02405 
02406                         /* The access in the acl entries must be left shifted by *
02407                          * three bites, because they will ultimately be compared *
02408                          * to S_IRUSR, S_IWUSR, and S_IXUSR.                  */
02409 
02410                         switch(acl_entry->ace_type){
02411                         case ACC_PERMIT:
02412                         case ACC_SPECIFY:
02413                                 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
02414                                 acl_entry_link->entryp->ace_access <<= 6;
02415                                 acl_entry_link_head->count++;
02416                                 break;
02417                         case ACC_DENY:
02418                                 /* Since there is no way to return a DENY acl entry *
02419                                  * change to PERMIT and then shift.                 */
02420                                 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
02421                                 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
02422                                 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
02423                                 acl_entry_link->entryp->ace_access <<= 6;
02424                                 acl_entry_link_head->count++;
02425                                 break;
02426                         default:
02427                                 return(0);
02428                         }
02429 
02430                         DEBUG(10,("acl_entry = %d\n",acl_entry));
02431                         DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
02432  
02433                         acl_entry = acl_nxt(acl_entry);
02434                 }
02435         } /* end of if enabled */
02436 
02437         /* Since owner, group, other acl entries are not *
02438          * part of the acl entries in an acl, they must  *
02439          * be dummied up to become part of the list.     */
02440 
02441         for( i = 1; i < 4; i++) {
02442                 DEBUG(10,("i is %d\n",i));
02443                 if(acl_entry_link_head->count != 0) {
02444                         acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
02445                         if(acl_entry_link->nextp == NULL) {
02446                                 SAFE_FREE(file_acl);
02447                                 errno = ENOMEM;
02448                                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
02449                                 return(NULL);
02450                         }
02451 
02452                         acl_entry_link->nextp->prevp = acl_entry_link;
02453                         acl_entry_link = acl_entry_link->nextp;
02454                         acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
02455                         if(acl_entry_link->entryp == NULL) {
02456                                 SAFE_FREE(file_acl);
02457                                 errno = ENOMEM;
02458                                 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno));
02459                                 return(NULL);
02460                         }
02461                 }
02462 
02463                 acl_entry_link->nextp = NULL;
02464 
02465                 new_acl_entry = acl_entry_link->entryp;
02466                 idp = new_acl_entry->ace_id;
02467 
02468                 new_acl_entry->ace_len = sizeof(struct acl_entry);
02469                 new_acl_entry->ace_type = ACC_PERMIT;
02470                 idp->id_len = sizeof(struct ace_id);
02471                 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
02472                 memset(idp->id_data,0,sizeof(uid_t));
02473 
02474                 switch(i) {
02475                 case 2:
02476                         new_acl_entry->ace_access = file_acl->g_access << 6;
02477                         idp->id_type = SMB_ACL_GROUP_OBJ;
02478                         break;
02479 
02480                 case 3:
02481                         new_acl_entry->ace_access = file_acl->o_access << 6;
02482                         idp->id_type = SMB_ACL_OTHER;
02483                         break;
02484  
02485                 case 1:
02486                         new_acl_entry->ace_access = file_acl->u_access << 6;
02487                         idp->id_type = SMB_ACL_USER_OBJ;
02488                         break;
02489  
02490                 default:
02491                         return(NULL);
02492 
02493                 }
02494 
02495                 acl_entry_link_head->count++;
02496                 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
02497         }
02498 
02499         acl_entry_link_head->count = 0;
02500         SAFE_FREE(file_acl);
02501 
02502         return(acl_entry_link_head);
02503 }
02504 
02505 SMB_ACL_T sys_acl_get_fd(int fd)
02506 {
02507         struct acl *file_acl = (struct acl *)NULL;
02508         struct acl_entry *acl_entry;
02509         struct new_acl_entry *new_acl_entry;
02510         struct ace_id *idp;
02511         struct acl_entry_link *acl_entry_link;
02512         struct acl_entry_link *acl_entry_link_head;
02513         int i;
02514         int rc = 0;
02515         uid_t user_id;
02516 
02517         /* Get the acl using fstatacl */
02518    
02519         DEBUG(10,("Entering sys_acl_get_fd\n"));
02520         DEBUG(10,("fd is %d\n",fd));
02521         file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
02522 
02523         if(file_acl == NULL) {
02524                 errno=ENOMEM;
02525                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
02526                 return(NULL);
02527         }
02528 
02529         memset(file_acl,0,BUFSIZ);
02530 
02531         rc = fstatacl(fd,0,file_acl,BUFSIZ);
02532         if(rc == -1) {
02533                 DEBUG(0,("The fstatacl call returned %d with errno %d\n",rc,errno));
02534                 SAFE_FREE(file_acl);
02535                 return(NULL);
02536         }
02537 
02538         DEBUG(10,("Got facl and returned it\n"));
02539 
02540         /* Point to the first acl entry in the acl */
02541 
02542         acl_entry =  file_acl->acl_ext;
02543         /* Begin setting up the head of the linked list *
02544          * that will be used for the storing the acl    *
02545          * in a way that is useful for the posix_acls.c *
02546          * code.                                        */
02547 
02548         acl_entry_link_head = acl_entry_link = sys_acl_init(0);
02549         if(acl_entry_link_head == NULL){
02550                 SAFE_FREE(file_acl);
02551                 return(NULL);
02552         }
02553 
02554         acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
02555 
02556         if(acl_entry_link->entryp == NULL) {
02557                 errno = ENOMEM;
02558                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
02559                 SAFE_FREE(file_acl);
02560                 return(NULL);
02561         }
02562 
02563         DEBUG(10,("acl_entry is %d\n",acl_entry));
02564         DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl)));
02565  
02566         /* Check if the extended acl bit is on.   *
02567          * If it isn't, do not show the           *
02568          * contents of the acl since AIX intends  *
02569          * the extended info to remain unused     */
02570  
02571         if(file_acl->acl_mode & S_IXACL){
02572                 /* while we are not pointing to the very end */
02573                 while(acl_entry < acl_last(file_acl)) {
02574                         /* before we malloc anything, make sure this is  */
02575                         /* a valid acl entry and one that we want to map */
02576 
02577                         idp = id_nxt(acl_entry->ace_id);
02578                         if((acl_entry->ace_type == ACC_SPECIFY ||
02579                                 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) {
02580                                         acl_entry = acl_nxt(acl_entry);
02581                                         continue;
02582                         }
02583 
02584                         idp = acl_entry->ace_id;
02585  
02586                         /* Check if this is the first entry in the linked list. *
02587                          * The first entry needs to keep prevp pointing to NULL *
02588                          * and already has entryp allocated.                 */
02589 
02590                         if(acl_entry_link_head->count != 0) {
02591                                 acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
02592                                 if(acl_entry_link->nextp == NULL) {
02593                                         errno = ENOMEM;
02594                                         DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
02595                                         SAFE_FREE(file_acl);
02596                                         return(NULL);
02597                                 }
02598                                 acl_entry_link->nextp->prevp = acl_entry_link;
02599                                 acl_entry_link = acl_entry_link->nextp;
02600                                 acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
02601                                 if(acl_entry_link->entryp == NULL) {
02602                                         errno = ENOMEM;
02603                                         DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
02604                                         SAFE_FREE(file_acl);
02605                                         return(NULL);
02606                                 }
02607 
02608                                 acl_entry_link->nextp = NULL;
02609                         }
02610 
02611                         acl_entry_link->entryp->ace_len = acl_entry->ace_len;
02612 
02613                         /* Don't really need this since all types are going *
02614                          * to be specified but, it's better than leaving it 0 */
02615 
02616                         acl_entry_link->entryp->ace_type = acl_entry->ace_type;
02617                         acl_entry_link->entryp->ace_access = acl_entry->ace_access;
02618 
02619                         memcpy(acl_entry_link->entryp->ace_id, idp, sizeof(struct ace_id));
02620 
02621                         /* The access in the acl entries must be left shifted by *
02622                          * three bites, because they will ultimately be compared *
02623                          * to S_IRUSR, S_IWUSR, and S_IXUSR.                  */
02624 
02625                         switch(acl_entry->ace_type){
02626                         case ACC_PERMIT:
02627                         case ACC_SPECIFY:
02628                                 acl_entry_link->entryp->ace_access = acl_entry->ace_access;
02629                                 acl_entry_link->entryp->ace_access <<= 6;
02630                                 acl_entry_link_head->count++;
02631                                 break;
02632                         case ACC_DENY:
02633                                 /* Since there is no way to return a DENY acl entry *
02634                                  * change to PERMIT and then shift.                 */
02635                                 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access));
02636                                 acl_entry_link->entryp->ace_access = ~acl_entry->ace_access & 7;
02637                                 DEBUG(10,("acl_entry_link->entryp->ace_access is %d\n",acl_entry_link->entryp->ace_access));
02638                                 acl_entry_link->entryp->ace_access <<= 6;
02639                                 acl_entry_link_head->count++;
02640                                 break;
02641                         default:
02642                                 return(0);
02643                         }
02644 
02645                         DEBUG(10,("acl_entry = %d\n",acl_entry));
02646                         DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type));
02647  
02648                         acl_entry = acl_nxt(acl_entry);
02649                 }
02650         } /* end of if enabled */
02651 
02652         /* Since owner, group, other acl entries are not *
02653          * part of the acl entries in an acl, they must  *
02654          * be dummied up to become part of the list.     */
02655 
02656         for( i = 1; i < 4; i++) {
02657                 DEBUG(10,("i is %d\n",i));
02658                 if(acl_entry_link_head->count != 0){
02659                         acl_entry_link->nextp = SMB_MALLOC_P(struct acl_entry_link);
02660                         if(acl_entry_link->nextp == NULL) {
02661                                 errno = ENOMEM;
02662                                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
02663                                 SAFE_FREE(file_acl);
02664                                 return(NULL);
02665                         }
02666 
02667                         acl_entry_link->nextp->prevp = acl_entry_link;
02668                         acl_entry_link = acl_entry_link->nextp;
02669                         acl_entry_link->entryp = SMB_MALLOC_P(struct new_acl_entry);
02670 
02671                         if(acl_entry_link->entryp == NULL) {
02672                                 SAFE_FREE(file_acl);
02673                                 errno = ENOMEM;
02674                                 DEBUG(0,("Error in sys_acl_get_fd is %d\n",errno));
02675                                 return(NULL);
02676                         }
02677                 }
02678 
02679                 acl_entry_link->nextp = NULL;
02680  
02681                 new_acl_entry = acl_entry_link->entryp;
02682                 idp = new_acl_entry->ace_id;
02683  
02684                 new_acl_entry->ace_len = sizeof(struct acl_entry);
02685                 new_acl_entry->ace_type = ACC_PERMIT;
02686                 idp->id_len = sizeof(struct ace_id);
02687                 DEBUG(10,("idp->id_len = %d\n",idp->id_len));
02688                 memset(idp->id_data,0,sizeof(uid_t));
02689  
02690                 switch(i) {
02691                 case 2:
02692                         new_acl_entry->ace_access = file_acl->g_access << 6;
02693                         idp->id_type = SMB_ACL_GROUP_OBJ;
02694                         break;
02695  
02696                 case 3:
02697                         new_acl_entry->ace_access = file_acl->o_access << 6;
02698                         idp->id_type = SMB_ACL_OTHER;
02699                         break;
02700  
02701                 case 1:
02702                         new_acl_entry->ace_access = file_acl->u_access << 6;
02703                         idp->id_type = SMB_ACL_USER_OBJ;
02704                         break;
02705  
02706                 default:
02707                         return(NULL);
02708                 }
02709  
02710                 acl_entry_link_head->count++;
02711                 DEBUG(10,("new_acl_entry->ace_access = %d\n",new_acl_entry->ace_access));
02712         }
02713 
02714         acl_entry_link_head->count = 0;
02715         SAFE_FREE(file_acl);
02716  
02717         return(acl_entry_link_head);
02718 }
02719 
02720 int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset)
02721 {
02722         *permset = *permset & ~0777;
02723         return(0);
02724 }
02725 
02726 int sys_acl_add_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
02727 {
02728         if((perm != 0) &&
02729                         (perm & (S_IXUSR | S_IWUSR | S_IRUSR)) == 0)
02730                 return(-1);
02731 
02732         *permset |= perm;
02733         DEBUG(10,("This is the permset now: %d\n",*permset));
02734         return(0);
02735 }
02736 
02737 char *sys_acl_to_text( SMB_ACL_T theacl, ssize_t *plen)
02738 {
02739         return(NULL);
02740 }
02741 
02742 SMB_ACL_T sys_acl_init( int count)
02743 {
02744         struct acl_entry_link *theacl = NULL;
02745  
02746         DEBUG(10,("Entering sys_acl_init\n"));
02747 
02748         theacl = SMB_MALLOC_P(struct acl_entry_link);
02749         if(theacl == NULL) {
02750                 errno = ENOMEM;
02751                 DEBUG(0,("Error in sys_acl_init is %d\n",errno));
02752                 return(NULL);
02753         }
02754 
02755         theacl->count = 0;
02756         theacl->nextp = NULL;
02757         theacl->prevp = NULL;
02758         theacl->entryp = NULL;
02759         DEBUG(10,("Exiting sys_acl_init\n"));
02760         return(theacl);
02761 }
02762 
02763 int sys_acl_create_entry( SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
02764 {
02765         struct acl_entry_link *theacl;
02766         struct acl_entry_link *acl_entryp;
02767         struct acl_entry_link *temp_entry;
02768         int counting;
02769 
02770         DEBUG(10,("Entering the sys_acl_create_entry\n"));
02771 
02772         theacl = acl_entryp = *pacl;
02773 
02774         /* Get to the end of the acl before adding entry */
02775 
02776         for(counting=0; counting < theacl->count; counting++){
02777                 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
02778                 temp_entry = acl_entryp;
02779                 acl_entryp = acl_entryp->nextp;
02780         }
02781 
02782         if(theacl->count != 0){
02783                 temp_entry->nextp = acl_entryp = SMB_MALLOC_P(struct acl_entry_link);
02784                 if(acl_entryp == NULL) {
02785                         errno = ENOMEM;
02786                         DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
02787                         return(-1);
02788                 }
02789 
02790                 DEBUG(10,("The acl_entryp is %d\n",acl_entryp));
02791                 acl_entryp->prevp = temp_entry;
02792                 DEBUG(10,("The acl_entryp->prevp is %d\n",acl_entryp->prevp));
02793         }
02794 
02795         *pentry = acl_entryp->entryp = SMB_MALLOC_P(struct new_acl_entry);
02796         if(*pentry == NULL) {
02797                 errno = ENOMEM;
02798                 DEBUG(0,("Error in sys_acl_create_entry is %d\n",errno));
02799                 return(-1);
02800         }
02801 
02802         memset(*pentry,0,sizeof(struct new_acl_entry));
02803         acl_entryp->entryp->ace_len = sizeof(struct acl_entry);
02804         acl_entryp->entryp->ace_type = ACC_PERMIT;
02805         acl_entryp->entryp->ace_id->id_len = sizeof(struct ace_id);
02806         acl_entryp->nextp = NULL;
02807         theacl->count++;
02808         DEBUG(10,("Exiting sys_acl_create_entry\n"));
02809         return(0);
02810 }
02811 
02812 int sys_acl_set_tag_type( SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype)
02813 {
02814         DEBUG(10,("Starting AIX sys_acl_set_tag_type\n"));
02815         entry->ace_id->id_type = tagtype;
02816         DEBUG(10,("The tag type is %d\n",entry->ace_id->id_type));
02817         DEBUG(10,("Ending AIX sys_acl_set_tag_type\n"));
02818 }
02819 
02820 int sys_acl_set_qualifier( SMB_ACL_ENTRY_T entry, void *qual)
02821 {
02822         DEBUG(10,("Starting AIX sys_acl_set_qualifier\n"));
02823         memcpy(entry->ace_id->id_data,qual,sizeof(uid_t));
02824         DEBUG(10,("Ending AIX sys_acl_set_qualifier\n"));
02825         return(0);
02826 }
02827 
02828 int sys_acl_set_permset( SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset)
02829 {
02830         DEBUG(10,("Starting AIX sys_acl_set_permset\n"));
02831         if(!(*permset & S_IXUSR) &&
02832                 !(*permset & S_IWUSR) &&
02833                 !(*permset & S_IRUSR) &&
02834                 (*permset != 0))
02835                         return(-1);
02836 
02837         entry->ace_access = *permset;
02838         DEBUG(10,("entry->ace_access = %d\n",entry->ace_access));
02839         DEBUG(10,("Ending AIX sys_acl_set_permset\n"));
02840         return(0);
02841 }
02842 
02843 int sys_acl_valid( SMB_ACL_T theacl )
02844 {
02845         int user_obj = 0;
02846         int group_obj = 0;
02847         int other_obj = 0;
02848         struct acl_entry_link *acl_entry;
02849 
02850         for(acl_entry=theacl; acl_entry != NULL; acl_entry = acl_entry->nextp) {
02851                 user_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_USER_OBJ);
02852                 group_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_GROUP_OBJ);
02853                 other_obj += (acl_entry->entryp->ace_id->id_type == SMB_ACL_OTHER);
02854         }
02855 
02856         DEBUG(10,("user_obj=%d, group_obj=%d, other_obj=%d\n",user_obj,group_obj,other_obj));
02857  
02858         if(user_obj != 1 || group_obj != 1 || other_obj != 1)
02859                 return(-1); 
02860 
02861         return(0);
02862 }
02863 
02864 int sys_acl_set_file( const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
02865 {
02866         struct acl_entry_link *acl_entry_link = NULL;
02867         struct acl *file_acl = NULL;
02868         struct acl *file_acl_temp = NULL;
02869         struct acl_entry *acl_entry = NULL;
02870         struct ace_id *ace_id = NULL;
02871         uint id_type;
02872         uint ace_access;
02873         uint user_id;
02874         uint acl_length;
02875         uint rc;
02876 
02877         DEBUG(10,("Entering sys_acl_set_file\n"));
02878         DEBUG(10,("File name is %s\n",name));
02879  
02880         /* AIX has no default ACL */
02881         if(acltype == SMB_ACL_TYPE_DEFAULT)
02882                 return(0);
02883 
02884         acl_length = BUFSIZ;
02885         file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
02886 
02887         if(file_acl == NULL) {
02888                 errno = ENOMEM;
02889                 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
02890                 return(-1);
02891         }
02892 
02893         memset(file_acl,0,BUFSIZ);
02894 
02895         file_acl->acl_len = ACL_SIZ;
02896         file_acl->acl_mode = S_IXACL;
02897 
02898         for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
02899                 acl_entry_link->entryp->ace_access >>= 6;
02900                 id_type = acl_entry_link->entryp->ace_id->id_type;
02901 
02902                 switch(id_type) {
02903                 case SMB_ACL_USER_OBJ:
02904                         file_acl->u_access = acl_entry_link->entryp->ace_access;
02905                         continue;
02906                 case SMB_ACL_GROUP_OBJ:
02907                         file_acl->g_access = acl_entry_link->entryp->ace_access;
02908                         continue;
02909                 case SMB_ACL_OTHER:
02910                         file_acl->o_access = acl_entry_link->entryp->ace_access;
02911                         continue;
02912                 case SMB_ACL_MASK:
02913                         continue;
02914                 }
02915 
02916                 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
02917                         acl_length += sizeof(struct acl_entry);
02918                         file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
02919                         if(file_acl_temp == NULL) {
02920                                 SAFE_FREE(file_acl);
02921                                 errno = ENOMEM;
02922                                 DEBUG(0,("Error in sys_acl_set_file is %d\n",errno));
02923                                 return(-1);
02924                         }  
02925 
02926                         memcpy(file_acl_temp,file_acl,file_acl->acl_len);
02927                         SAFE_FREE(file_acl);
02928                         file_acl = file_acl_temp;
02929                 }
02930 
02931                 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
02932                 file_acl->acl_len += sizeof(struct acl_entry);
02933                 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
02934                 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
02935  
02936                 /* In order to use this, we'll need to wait until we can get denies */
02937                 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
02938                 acl_entry->ace_type = ACC_SPECIFY; */
02939 
02940                 acl_entry->ace_type = ACC_SPECIFY;
02941  
02942                 ace_id = acl_entry->ace_id;
02943  
02944                 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
02945                 DEBUG(10,("The id type is %d\n",ace_id->id_type));
02946                 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
02947                 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
02948                 memcpy(acl_entry->ace_id->id_data, &user_id, sizeof(uid_t));
02949         }
02950 
02951         rc = chacl(name,file_acl,file_acl->acl_len);
02952         DEBUG(10,("errno is %d\n",errno));
02953         DEBUG(10,("return code is %d\n",rc));
02954         SAFE_FREE(file_acl);
02955         DEBUG(10,("Exiting the sys_acl_set_file\n"));
02956         return(rc);
02957 }
02958 
02959 int sys_acl_set_fd( int fd, SMB_ACL_T theacl)
02960 {
02961         struct acl_entry_link *acl_entry_link = NULL;
02962         struct acl *file_acl = NULL;
02963         struct acl *file_acl_temp = NULL;
02964         struct acl_entry *acl_entry = NULL;
02965         struct ace_id *ace_id = NULL;
02966         uint id_type;
02967         uint user_id;
02968         uint acl_length;
02969         uint rc;
02970  
02971         DEBUG(10,("Entering sys_acl_set_fd\n"));
02972         acl_length = BUFSIZ;
02973         file_acl = (struct acl *)SMB_MALLOC(BUFSIZ);
02974 
02975         if(file_acl == NULL) {
02976                 errno = ENOMEM;
02977                 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
02978                 return(-1);
02979         }
02980 
02981         memset(file_acl,0,BUFSIZ);
02982  
02983         file_acl->acl_len = ACL_SIZ;
02984         file_acl->acl_mode = S_IXACL;
02985 
02986         for(acl_entry_link=theacl; acl_entry_link != NULL; acl_entry_link = acl_entry_link->nextp) {
02987                 acl_entry_link->entryp->ace_access >>= 6;
02988                 id_type = acl_entry_link->entryp->ace_id->id_type;
02989                 DEBUG(10,("The id_type is %d\n",id_type));
02990 
02991                 switch(id_type) {
02992                 case SMB_ACL_USER_OBJ:
02993                         file_acl->u_access = acl_entry_link->entryp->ace_access;
02994                         continue;
02995                 case SMB_ACL_GROUP_OBJ:
02996                         file_acl->g_access = acl_entry_link->entryp->ace_access;
02997                         continue;
02998                 case SMB_ACL_OTHER:
02999                         file_acl->o_access = acl_entry_link->entryp->ace_access;
03000                         continue;
03001                 case SMB_ACL_MASK:
03002                         continue;
03003                 }
03004 
03005                 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) {
03006                         acl_length += sizeof(struct acl_entry);
03007                         file_acl_temp = (struct acl *)SMB_MALLOC(acl_length);
03008                         if(file_acl_temp == NULL) {
03009                                 SAFE_FREE(file_acl);
03010                                 errno = ENOMEM;
03011                                 DEBUG(0,("Error in sys_acl_set_fd is %d\n",errno));
03012                                 return(-1);
03013                         }
03014 
03015                         memcpy(file_acl_temp,file_acl,file_acl->acl_len);
03016                         SAFE_FREE(file_acl);
03017                         file_acl = file_acl_temp;
03018                 }
03019 
03020                 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len);
03021                 file_acl->acl_len += sizeof(struct acl_entry);
03022                 acl_entry->ace_len = acl_entry_link->entryp->ace_len;
03023                 acl_entry->ace_access = acl_entry_link->entryp->ace_access;
03024  
03025                 /* In order to use this, we'll need to wait until we can get denies */
03026                 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT)
03027                         acl_entry->ace_type = ACC_SPECIFY; */
03028  
03029                 acl_entry->ace_type = ACC_SPECIFY;
03030  
03031                 ace_id = acl_entry->ace_id;
03032  
03033                 ace_id->id_type = acl_entry_link->entryp->ace_id->id_type;
03034                 DEBUG(10,("The id type is %d\n",ace_id->id_type));
03035                 ace_id->id_len = acl_entry_link->entryp->ace_id->id_len;
03036                 memcpy(&user_id, acl_entry_link->entryp->ace_id->id_data, sizeof(uid_t));
03037                 memcpy(ace_id->id_data, &user_id, sizeof(uid_t));
03038         }
03039  
03040         rc = fchacl(fd,file_acl,file_acl->acl_len);
03041         DEBUG(10,("errno is %d\n",errno));
03042         DEBUG(10,("return code is %d\n",rc));
03043         SAFE_FREE(file_acl);
03044         DEBUG(10,("Exiting sys_acl_set_fd\n"));
03045         return(rc);
03046 }
03047 
03048 int sys_acl_delete_def_file(const char *name)
03049 {
03050         /* AIX has no default ACL */
03051         return 0;
03052 }
03053 
03054 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
03055 {
03056         return(*permset & perm);
03057 }
03058 
03059 int sys_acl_free_text(char *text)
03060 {
03061         return(0);
03062 }
03063 
03064 int sys_acl_free_acl(SMB_ACL_T posix_acl)
03065 {
03066         struct acl_entry_link *acl_entry_link;
03067 
03068         for(acl_entry_link = posix_acl->nextp; acl_entry_link->nextp != NULL; acl_entry_link = acl_entry_link->nextp) {
03069                 SAFE_FREE(acl_entry_link->prevp->entryp);
03070                 SAFE_FREE(acl_entry_link->prevp);
03071         }
03072 
03073         SAFE_FREE(acl_entry_link->prevp->entryp);
03074         SAFE_FREE(acl_entry_link->prevp);
03075         SAFE_FREE(acl_entry_link->entryp);
03076         SAFE_FREE(acl_entry_link);
03077  
03078         return(0);
03079 }
03080 
03081 int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype)
03082 {
03083         return(0);
03084 }
03085 
03086 #else /* No ACLs. */
03087 
03088 int sys_acl_get_entry(UNUSED(SMB_ACL_T the_acl), UNUSED(int entry_id), UNUSED(SMB_ACL_ENTRY_T *entry_p))
03089 {
03090         errno = ENOSYS;
03091         return -1;
03092 }
03093 
03094 int sys_acl_get_tag_type(UNUSED(SMB_ACL_ENTRY_T entry_d), UNUSED(SMB_ACL_TAG_T *tag_type_p))
03095 {
03096         errno = ENOSYS;
03097         return -1;
03098 }
03099 
03100 int sys_acl_get_permset(UNUSED(SMB_ACL_ENTRY_T entry_d), UNUSED(SMB_ACL_PERMSET_T *permset_p))
03101 {
03102         errno = ENOSYS;
03103         return -1;
03104 }
03105 
03106 void *sys_acl_get_qualifier(UNUSED(SMB_ACL_ENTRY_T entry_d))
03107 {
03108         errno = ENOSYS;
03109         return NULL;
03110 }
03111 
03112 SMB_ACL_T sys_acl_get_file(UNUSED(const char *path_p), UNUSED(SMB_ACL_TYPE_T type))
03113 {
03114         errno = ENOSYS;
03115         return (SMB_ACL_T)NULL;
03116 }
03117 
03118 SMB_ACL_T sys_acl_get_fd(UNUSED(int fd))
03119 {
03120         errno = ENOSYS;
03121         return (SMB_ACL_T)NULL;
03122 }
03123 
03124 int sys_acl_clear_perms(UNUSED(SMB_ACL_PERMSET_T permset))
03125 {
03126         errno = ENOSYS;
03127         return -1;
03128 }
03129 
03130 int sys_acl_add_perm( UNUSED(SMB_ACL_PERMSET_T permset), UNUSED(SMB_ACL_PERM_T perm))
03131 {
03132         errno = ENOSYS;
03133         return -1;
03134 }
03135 
03136 int sys_acl_get_perm( SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm)
03137 {
03138         errno = ENOSYS;
03139         return (permset & perm) ? 1 : 0;
03140 }
03141 
03142 char *sys_acl_to_text(UNUSED(SMB_ACL_T the_acl), UNUSED(ssize_t *plen))
03143 {
03144         errno = ENOSYS;
03145         return NULL;
03146 }
03147 
03148 int sys_acl_free_text(UNUSED(char *text))
03149 {
03150         errno = ENOSYS;
03151         return -1;
03152 }
03153 
03154 SMB_ACL_T sys_acl_init(UNUSED(int count))
03155 {
03156         errno = ENOSYS;
03157         return NULL;
03158 }
03159 
03160 int sys_acl_create_entry(UNUSED(SMB_ACL_T *pacl), UNUSED(SMB_ACL_ENTRY_T *pentry))
03161 {
03162         errno = ENOSYS;
03163         return -1;
03164 }
03165 
03166 int sys_acl_set_tag_type(UNUSED(SMB_ACL_ENTRY_T entry), UNUSED(SMB_ACL_TAG_T tagtype))
03167 {
03168         errno = ENOSYS;
03169         return -1;
03170 }
03171 
03172 int sys_acl_set_qualifier(UNUSED(SMB_ACL_ENTRY_T entry), UNUSED(void *qual))
03173 {
03174         errno = ENOSYS;
03175         return -1;
03176 }
03177 
03178 int sys_acl_set_permset(UNUSED(SMB_ACL_ENTRY_T entry), UNUSED(SMB_ACL_PERMSET_T permset))
03179 {
03180         errno = ENOSYS;
03181         return -1;
03182 }
03183 
03184 int sys_acl_valid(UNUSED(SMB_ACL_T theacl))
03185 {
03186         errno = ENOSYS;
03187         return -1;
03188 }
03189 
03190 int sys_acl_set_file(UNUSED(const char *name), UNUSED(SMB_ACL_TYPE_T acltype), UNUSED(SMB_ACL_T theacl))
03191 {
03192         errno = ENOSYS;
03193         return -1;
03194 }
03195 
03196 int sys_acl_set_fd(UNUSED(int fd), UNUSED(SMB_ACL_T theacl))
03197 {
03198         errno = ENOSYS;
03199         return -1;
03200 }
03201 
03202 int sys_acl_delete_def_file(UNUSED(const char *name))
03203 {
03204         errno = ENOSYS;
03205         return -1;
03206 }
03207 
03208 int sys_acl_free_acl(UNUSED(SMB_ACL_T the_acl))
03209 {
03210         errno = ENOSYS;
03211         return -1;
03212 }
03213 
03214 int sys_acl_free_qualifier(UNUSED(void *qual), UNUSED(SMB_ACL_TAG_T tagtype))
03215 {
03216         errno = ENOSYS;
03217         return -1;
03218 }
03219 
03220 #endif /* No ACLs. */
03221 
03222 /************************************************************************
03223  Deliberately outside the ACL defines. Return 1 if this is a "no acls"
03224  errno, 0 if not.
03225 ************************************************************************/
03226 
03227 int no_acl_syscall_error(int err)
03228 {
03229 #if defined(ENOSYS)
03230         if (err == ENOSYS) {
03231                 return 1;
03232         }
03233 #endif
03234 #if defined(ENOTSUP)
03235         if (err == ENOTSUP) {
03236                 return 1;
03237         }
03238 #endif
03239         return 0;
03240 }

rsyncに対してSat Dec 5 19:45:42 2009に生成されました。  doxygen 1.4.7