/*
- * $Id: directory.c,v 1.80 2005-05-14 12:54:50 didg Exp $
+ * $Id: directory.c,v 1.111 2009-10-16 00:15:53 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include <sys/param.h>
#include <errno.h>
#include <utime.h>
-#include <atalk/adouble.h>
+#include <atalk/adouble.h>
+#include <atalk/vfs.h>
#include <atalk/afp.h>
#include <atalk/util.h>
#include <atalk/cnid.h>
#include <atalk/logger.h>
+#include <atalk/uuid.h>
+#include <atalk/unix.h>
#include "directory.h"
#include "desktop.h"
#include "globals.h"
#include "unix.h"
#include "mangle.h"
+#include "hash.h"
+
+#ifdef HAVE_NFSv4_ACLS
+extern void addir_inherit_acl(const struct vol *vol);
+#endif
struct dir *curdir;
int afp_errno;
* how exciting.
*/
struct dir *
- dirsearch( vol, did )
- const struct vol *vol;
-u_int32_t did;
+ dirsearch(const struct vol *vol, u_int32_t did)
{
struct dir *dir;
}
/* ------------------- */
-#ifdef ATACC
-int path_isadir(struct path *o_path)
-{
- return o_path->d_dir != NULL;
-#if 0
- return o_path->m_name == '\0' || /* we are in a it */
- !o_path->st_valid || /* in cache but we can't chdir in it */
- (!o_path->st_errno && S_ISDIR(o_path->st.st_mode)); /* not in cache an can't chdir */
-#endif
-}
-#endif
-
int get_afp_errno(const int param)
{
if (afp_errno != AFPERR_DID1)
* and we are really bad in this case.
*/
struct dir *
- dirlookup( vol, did )
- const struct vol *vol;
-u_int32_t did;
+ dirlookup( struct vol *vol, u_int32_t did)
{
struct dir *ret;
char *upath;
/* --------------------------- */
/* rotate the tree to the left */
-static void dir_leftrotate(vol, dir)
-struct vol *vol;
-struct dir *dir;
+static void dir_leftrotate(struct vol *vol, struct dir *dir)
{
struct dir *right = dir->d_right;
/* rotate the tree to the right */
-static void dir_rightrotate(vol, dir)
-struct vol *vol;
-struct dir *dir;
+static void dir_rightrotate(struct vol *vol, struct dir *dir)
{
struct dir *left = dir->d_left;
#if 0
/* recolor after a removal */
-static struct dir *dir_rmrecolor(vol, dir)
- struct vol *vol;
-struct dir *dir;
+static struct dir *dir_rmrecolor(struct vol *vol, struct dir *dir)
{
struct dir *leaf;
/* remove the node from the tree. this is just like insertion, but
* different. actually, it has to worry about a bunch of things that
* insertion doesn't care about. */
-static void dir_remove( vol, dir )
-struct vol *vol;
-struct dir *dir;
+
+static void dir_remove( const struct vol *vol _U_, struct dir *dir)
{
#ifdef REMOVE_NODES
struct ofork *of, *last;
* process. It's fixable within afpd if fnctl_lock, doable with smb and
* next to impossible for nfs and local filesystem access.
*/
-static void dir_invalidate( vol, dir )
-const struct vol *vol;
-struct dir *dir;
+static void dir_invalidate( const struct vol *vol, struct dir *dir)
{
if (curdir == dir) {
/* v_root can't be deleted */
}
/* ------------------------------------ */
-static struct dir *dir_insert(vol, dir)
- const struct vol *vol;
-struct dir *dir;
+static struct dir *dir_insert(const struct vol *vol, struct dir *dir)
{
struct dir *pdir;
ucs2_t u2_dename[MAXPATHLEN];
char *tmp, *savepath;
+ if (!(vol->v_flags & AFPVOL_CASEINSEN))
+ return -1;
+
if (veto_file(ENUMVETO, path->u_name))
return -1;
if (ret) {
/* invalidate cache */
- memset(cname, 0, sizeof(cname));
+ cname[0] = 0;
did = 0;
path->u_name = savepath;
}
* as a side-effect, movecwd to that point and return the new dir
*/
static struct dir *
- extenddir( vol, dir, path )
-struct vol *vol;
-struct dir *dir;
-struct path *path;
+ extenddir(struct vol *vol, struct dir *dir, struct path *path)
{
path->d_dir = NULL;
afp_errno = AFPERR_PARAM;
return NULL;
}
+
+ if (check_name(vol, path->u_name)) {
+ /* the name is illegal */
+ LOG(log_info, logtype_afpd, "extenddir: illegal path: '%s'", path->u_name);
+ path->u_name = NULL;
+ afp_errno = AFPERR_PARAM;
+ return NULL;
+ }
+
if (of_stat( path ) != 0 ) {
if (!(vol->v_flags & AFPVOL_CASEINSEN))
return NULL;
return( dir );
}
-/* -------------------
- system rmdir with afp error code.
- ENOENT is not an error.
- */
-int netatalk_rmdir(const char *name)
-{
- if (rmdir(name) < 0) {
- switch ( errno ) {
- case ENOENT :
- break;
- case ENOTEMPTY :
- return AFPERR_DIRNEMPT;
- case EPERM:
- case EACCES :
- return AFPERR_ACCESS;
- case EROFS:
- return AFPERR_VLOCK;
- default :
- return AFPERR_PARAM;
- }
- }
- return AFP_OK;
-}
-
/* -------------------------
appledouble mkdir afp error code.
*/
return AFP_OK;
}
-/* -------------------
- system unlink with afp error code.
- ENOENT is not an error.
- */
-int netatalk_unlink(const char *name)
-{
- if (unlink(name) < 0) {
- switch (errno) {
- case ENOENT :
- break;
- case EROFS:
- return AFPERR_VLOCK;
- case EPERM:
- case EACCES :
- return AFPERR_ACCESS;
- default :
- return AFPERR_PARAM;
- }
- }
- return AFP_OK;
-}
-
/* ------------------- */
static int deletedir(char *dir)
{
/* --- public functions follow --- */
/* NOTE: we start off with at least one node (the root directory). */
-static struct dir *dirinsert( vol, dir )
- struct vol *vol;
-struct dir *dir;
+static struct dir *dirinsert(struct vol *vol, struct dir *dir)
{
struct dir *node;
/* ---------------------------- */
struct dir *
- adddir( vol, dir, path)
-struct vol *vol;
-struct dir *dir;
-struct path *path;
+ adddir(struct vol *vol, struct dir *dir, struct path *path)
{
struct dir *cdir, *edir;
int upathlen;
return NULL;
}
if ((size_t)-1 == convert_string_allocate((utf8_encoding())?CH_UTF8_MAC:vol->v_maccharset, CH_UCS2, path->m_name, strlen(path->m_name), &cdir->d_m_name_ucs2)) {
- LOG(log_error, logtype_afpd, "Couldn't set UCS2 name for %s", name);
- cdir->d_m_name_ucs2 = NULL;
+ LOG(log_error, logtype_afpd, "Couldn't set UCS2 name for %s", name);
+ cdir->d_m_name_ucs2 = NULL;
}
cdir->d_did = id;
free(dir->d_m_name);
}
-void dirfree( dir )
-struct dir *dir;
+void dirfree(struct dir *dir)
{
if (!dir || (dir == SENTINEL))
return;
*/
struct path *
-cname( vol, dir, cpath )
-const struct vol *vol;
-struct dir *dir;
-char **cpath;
+cname(struct vol *vol, struct dir *dir, char **cpath)
{
struct dir *cdir, *scdir=NULL;
static char path[ MAXPATHLEN + 1];
int size = 0;
char sep;
int toUTF8 = 0;
-
+
data = *cpath;
afp_errno = AFPERR_NOOBJ;
memset(&ret, 0, sizeof(ret));
if (toUTF8) {
static char temp[ MAXPATHLEN + 1];
- /* not an UTF8 name */
- if (mtoUTF8(vol, path, strlen(path), temp, MAXPATHLEN) == (size_t)-1) {
- afp_errno = AFPERR_PARAM;
- return( NULL );
+ if (dir->d_did == DIRDID_ROOT_PARENT) {
+ /*
+ With uft8 volume name is utf8-mac, but requested path may be a mangled longname. See #2611981.
+ So we compare it with the longname from the current volume and if they match
+ we overwrite the requested path with the utf8 volume name so that the following
+ strcmp can match.
+ */
+ ucs2_to_charset(vol->v_maccharset, vol->v_macname, temp, AFPVOL_MACNAMELEN + 1);
+ if (strcasecmp( path, temp) == 0)
+ ucs2_to_charset(CH_UTF8_MAC, vol->v_u8mname, path, AFPVOL_U8MNAMELEN);
+ } else {
+ /* toUTF8 */
+ if (mtoUTF8(vol, path, strlen(path), temp, MAXPATHLEN) == (size_t)-1) {
+ afp_errno = AFPERR_PARAM;
+ return( NULL );
+ }
+ strcpy(path, temp);
}
- strcpy(path, temp);
}
/* check for OS X mangled filename :( */
else {
noucsfallback:
if (dir->d_did == DIRDID_ROOT_PARENT) {
- /* root parent has only one child and d_m_name is *NOT* utm (d_u_name)
- * d_m_name is the Mac volume name
- * d_u_name is the volume unix directory name
- *
- */
- cdir = NULL;
- if (!strcmp(vol->v_dir->d_m_name, ret.m_name)) {
- cdir = vol->v_dir;
- }
+ /*
+ root parent (did 1) has one child: the volume. Requests for did=1 with some <name>
+ must check against the volume name.
+ */
+ if (!strcmp(vol->v_dir->d_m_name, ret.m_name))
+ cdir = vol->v_dir;
+ else
+ cdir = NULL;
}
- else {
- cdir = dirsearch_byname(vol, dir, ret.u_name);
+ else {
+ cdir = dirsearch_byname(vol, dir, ret.u_name);
}
}
-
+
if (cdir == NULL && scdir != NULL) {
cdir = scdir;
/* LOG(log_debug, logtype_afpd, "cname: using casediff for %s, (%s = %s)", fullpathname(cdir->d_u_name), cdir->d_m_name, path ); */
if ( cdir == NULL ) {
- if ( len > 0) {
+ if ( len > 0 || !ret.u_name ) {
return NULL;
}
/*
* Move curdir to dir, with a possible chdir()
*/
-int movecwd( vol, dir)
-const struct vol *vol;
-struct dir *dir;
+int movecwd(const struct vol *vol, struct dir *dir)
{
char path[MAXPATHLEN + 1];
struct dir *d;
* is our cached offspring count valid?
*/
-int diroffcnt(struct dir *dir, struct stat *st)
+static int diroffcnt(struct dir *dir, struct stat *st)
{
return st->st_ctime == dir->ctime;
}
return st->st_ctime == dir->ctime && (dir->d_flags & DIRF_CNID);
}
+/* --------------------- */
+static int invisible_dots(const struct vol *vol, const char *name)
+{
+ return vol_inv_dots(vol) && *name == '.' && strcmp(name, ".") && strcmp(name, "..");
+}
+
/* ------------------------------
(".", curdir)
(name, dir) with curdir:name == dir, from afp_enumerate
case DIRPBIT_ATTR :
if ( isad ) {
ad_getattr(&ad, &ashort);
- } else if (*dir->d_u_name == '.' && strcmp(dir->d_u_name, ".")
- && strcmp(dir->d_u_name, "..")) {
+ } else if (invisible_dots(vol, dir->d_u_name)) {
ashort = htons(ATTRBIT_INVISIBLE);
} else
ashort = 0;
ashort = htons(FINDERINFO_CLOSEDVIEW);
memcpy(data + FINDERINFO_FRVIEWOFF, &ashort, sizeof(ashort));
- /* dot files are by default invisible */
- if (*dir->d_u_name == '.' && strcmp(dir->d_u_name , ".") &&
- strcmp(dir->d_u_name , "..")) {
+ /* dot files are by default visible */
+ if (invisible_dots(vol, dir->d_u_name)) {
ashort = htons(FINDERINFO_INVISIBLE);
- memcpy(data + FINDERINFO_FRFLAGOFF,
- &ashort, sizeof(ashort));
+ memcpy(data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
}
}
data += 32;
}
/* ----------------------------- */
-int afp_setdirparams(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf _U_;
-int ibuflen _U_, *rbuflen;
+int afp_setdirparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct vol *vol;
struct dir *dir;
char *upath;
struct dir *dir;
- int bit, aint, isad = 1;
+ int bit, isad = 1;
int cdate, bdate;
int owner, group;
u_int16_t ashort, bshort;
u_int16_t bitmap = d_bitmap;
u_char finder_buf[32];
u_int32_t upriv;
- mode_t mpriv; /* uninitialized, OK 310105 */
+ mode_t mpriv = 0;
u_int16_t upriv_bit = 0;
bit = 0;
ma.ma_world = *buf++;
ma.ma_group = *buf++;
ma.ma_owner = *buf++;
- mpriv = mtoumode( &ma );
+ mpriv = mtoumode( &ma ) | vol->v_dperm;
if (dir_rx_set(mpriv) && setdirmode( vol, upath, mpriv) < 0 ) {
err = set_dir_errors(path, "setdirmode", errno);
bitmap = 0;
break;
case DIRPBIT_UNIXPR :
if (vol_unix_priv(vol)) {
- /* Skip UID and GID for now, there seems to be no way to set them from an OSX client anyway */
- buf += sizeof( aint );
- buf += sizeof( aint );
+ memcpy( &owner, buf, sizeof(owner)); /* FIXME need to change owner too? */
+ buf += sizeof( owner );
+ memcpy( &group, buf, sizeof( group ));
+ buf += sizeof( group );
change_mdate = 1;
change_parent_mdate = 1;
memcpy( &upriv, buf, sizeof( upriv ));
buf += sizeof( upriv );
- upriv = ntohl (upriv);
+ upriv = ntohl (upriv) | vol->v_dperm;
if (dir_rx_set(upriv)) {
/* maybe we are trying to set perms back */
if ( setdirunixmode(vol, upath, upriv) < 0 ) {
bitmap = 0;
- err = set_dir_errors(path, "setdirmode", errno);
+ err = set_dir_errors(path, "setdirunixmode", errno);
}
}
else {
break;
case DIRPBIT_FINFO :
if (isad) {
+ /* Fixes #2802236 */
+ u_int16_t *fflags = (u_int16_t *)(finder_buf + FINDERINFO_FRFLAGOFF);
+ *fflags &= htons(~FINDERINFO_ISHARED);
+ /* #2802236 end */
if ( dir->d_did == DIRDID_ROOT ) {
/*
* Alright, we admit it, this is *really* sick!
goto setdirparam_done;
}
break;
-
case DIRPBIT_GID :
if (dir->d_did == DIRDID_ROOT)
setdeskowner( -1, ntohl(group) );
-
-#if 0 /* don't error if we can't set the desktop owner. */
- err = set_dir_errors(path, "setdeskowner", errno);
- if (isad && err == AFPERR_PARAM) {
- err = AFP_OK; /* ???*/
- }
- else {
- goto setdirparam_done;
- }
-#endif /* 0 */
-
if ( setdirowner(vol, upath, -1, ntohl(group) ) < 0 ) {
err = set_dir_errors(path, "setdirowner", errno);
goto setdirparam_done;
}
break;
-
case DIRPBIT_ACCESS :
if (dir->d_did == DIRDID_ROOT) {
setdeskmode(mpriv);
case DIRPBIT_UNIXPR :
if (vol_unix_priv(vol)) {
if (dir->d_did == DIRDID_ROOT) {
- setdeskmode( upriv );
if (!dir_rx_set(upriv)) {
/* we can't remove read and search for owner on volume root */
err = AFPERR_ACCESS;
goto setdirparam_done;
}
+ setdeskowner( -1, ntohl(group) );
+ setdeskmode( upriv );
+ }
+ if ( setdirowner(vol, upath, -1, ntohl(group) ) < 0 ) {
+ err = set_dir_errors(path, "setdirowner", errno);
+ goto setdirparam_done;
}
if ( upriv_bit && setdirunixmode(vol, upath, upriv) < 0 ) {
- err = set_dir_errors(path, "setdirmode", errno);
+ err = set_dir_errors(path, "setdirunixmode", errno);
goto setdirparam_done;
}
- break;
}
- /* fall through */
+ else {
+ err = AFPERR_BITMAP;
+ goto setdirparam_done;
+ }
+ break;
default :
err = AFPERR_BITMAP;
goto setdirparam_done;
ad_setid(&ad, st->st_dev, st->st_ino, dir->d_did, dir->d_parent->d_did, vol->v_stamp);
}
}
- ad_flush_metadata( &ad);
+ ad_flush( &ad);
ad_close_metadata( &ad);
}
return err;
}
-int afp_createdir(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf;
-int ibuflen _U_, *rbuflen;
+int afp_syncdir(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
+{
+#ifdef HAVE_DIRFD
+ DIR *dp;
+#endif
+ int dfd;
+ struct vol *vol;
+ struct dir *dir;
+ u_int32_t did;
+ u_int16_t vid;
+
+ *rbuflen = 0;
+ ibuf += 2;
+
+ memcpy( &vid, ibuf, sizeof( vid ));
+ ibuf += sizeof( vid );
+ if (NULL == (vol = getvolbyvid( vid )) ) {
+ return( AFPERR_PARAM );
+ }
+
+ memcpy( &did, ibuf, sizeof( did ));
+ ibuf += sizeof( did );
+
+ /*
+ * Here's the deal:
+ * if it's CNID 2 our only choice to meet the specs is call sync.
+ * For any other CNID just sync that dir. To my knowledge the
+ * intended use of FPSyncDir is to sync the volume so all we're
+ * ever going to see here is probably CNID 2. Anyway, we' prepared.
+ */
+
+ if ( ntohl(did) == 2 ) {
+ sync();
+ } else {
+ if (NULL == ( dir = dirlookup( vol, did )) ) {
+ return afp_errno; /* was AFPERR_NOOBJ */
+ }
+
+ if (movecwd( vol, dir ) < 0 )
+ return ( AFPERR_NOOBJ );
+
+ /*
+ * Assuming only OSens that have dirfd also may require fsyncing directories
+ * in order to flush metadata e.g. Linux.
+ */
+
+#ifdef HAVE_DIRFD
+ if (NULL == ( dp = opendir( "." )) ) {
+ switch( errno ) {
+ case ENOENT :
+ return( AFPERR_NOOBJ );
+ case EACCES :
+ return( AFPERR_ACCESS );
+ default :
+ return( AFPERR_PARAM );
+ }
+ }
+
+ LOG(log_debug, logtype_afpd, "afp_syncdir: dir: '%s'", dir->d_u_name);
+
+ dfd = dirfd( dp );
+ if ( fsync ( dfd ) < 0 )
+ LOG(log_error, logtype_afpd, "afp_syncdir(%s): %s",
+ dir->d_u_name, strerror(errno) );
+ closedir(dp); /* closes dfd too */
+#endif
+
+ if ( -1 == (dfd = open(vol->ad_path(".", ADFLAGS_DIR), O_RDWR))) {
+ switch( errno ) {
+ case ENOENT:
+ return( AFPERR_NOOBJ );
+ case EACCES:
+ return( AFPERR_ACCESS );
+ default:
+ return( AFPERR_PARAM );
+ }
+ }
+
+ LOG(log_debug, logtype_afpd, "afp_syncdir: ad-file: '%s'",
+ vol->ad_path(".", ADFLAGS_DIR) );
+
+ if ( fsync(dfd) < 0 )
+ LOG(log_error, logtype_afpd, "afp_syncdir(%s): %s",
+ vol->ad_path(dir->d_u_name, ADFLAGS_DIR), strerror(errno) );
+ close(dfd);
+ }
+
+ return ( AFP_OK );
+}
+
+int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
struct adouble ad;
struct vol *vol;
return AFPERR_EXIST;
upath = s_path->u_name;
- if (0 != (err = check_name(vol, upath))) {
- return err;
- }
if (AFP_OK != (err = netatalk_mkdir( upath))) {
return err;
ad_setname(&ad, s_path->m_name);
ad_setid( &ad, s_path->st.st_dev, s_path->st.st_ino, dir->d_did, did, vol->v_stamp);
- ad_flush_metadata( &ad);
+ ad_flush( &ad);
ad_close_metadata( &ad);
createdir_done:
+#ifdef HAVE_NFSv4_ACLS
+ /* FIXME: are we really inside the created dir? */
+ addir_inherit_acl(vol);
+#endif
+
memcpy( rbuf, &dir->d_did, sizeof( u_int32_t ));
*rbuflen = sizeof( u_int32_t );
setvoltime(obj, vol );
* newparent curdir
*
*/
-int renamedir(vol, src, dst, dir, newparent, newname)
-const struct vol *vol;
-char *src, *dst, *newname;
-struct dir *dir, *newparent;
+int renamedir(const struct vol *vol, char *src, char *dst,
+ struct dir *dir,
+ struct dir *newparent,
+ char *newname)
{
struct adouble ad;
struct dir *parent;
}
}
- vol->vfs->rf_renamedir(vol, src, dst);
+ vol->vfs->vfs_renamedir(vol, src, dst);
len = strlen( newname );
/* rename() succeeded so we need to update our tree even if we can't open
if (!ad_open_metadata( dst, ADFLAGS_DIR, 0, &ad)) {
ad_setname(&ad, newname);
- ad_flush_metadata( &ad);
+ ad_flush( &ad);
ad_close_metadata( &ad);
}
}
/* delete an empty directory */
-int deletecurdir( vol)
-const struct vol *vol;
+int deletecurdir(const struct vol *vol)
{
struct dirent *de;
struct stat st;
return AFPERR_OLOCK;
}
}
- err = vol->vfs->rf_deletecurdir(vol);
+ err = vol->vfs->vfs_deletecurdir(vol);
if (err) {
return err;
}
return err;
}
-int afp_mapid(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf;
-int ibuflen _U_, *rbuflen;
+int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
struct passwd *pw;
struct group *gr;
u_int32_t id;
int len, sfunc;
int utf8 = 0;
-
+ uuidtype_t type;
+
ibuf++;
sfunc = (unsigned char) *ibuf++;
- memcpy( &id, ibuf, sizeof( id ));
-
- id = ntohl(id);
*rbuflen = 0;
- if (sfunc == 3 || sfunc == 4) {
+
+ if (sfunc >= 3 && sfunc <= 6) {
if (afp_version < 30) {
return( AFPERR_PARAM );
}
utf8 = 1;
}
- if ( id != 0 ) {
+
switch ( sfunc ) {
case 1 :
case 3 :/* unicode */
+ memcpy( &id, ibuf, sizeof( id ));
+ id = ntohl(id);
+ if ( id != 0 ) {
if (( pw = getpwuid( id )) == NULL ) {
return( AFPERR_NOITEM );
}
len = convert_string_allocate( obj->options.unixcharset, ((!utf8)?obj->options.maccharset:CH_UTF8_MAC),
pw->pw_name, strlen(pw->pw_name), &name);
+ } else {
+ len = 0;
+ name = NULL;
+ }
break;
-
case 2 :
case 4 : /* unicode */
+ memcpy( &id, ibuf, sizeof( id ));
+ id = ntohl(id);
+ if ( id != 0 ) {
if (NULL == ( gr = (struct group *)getgrgid( id ))) {
return( AFPERR_NOITEM );
}
len = convert_string_allocate( obj->options.unixcharset, (!utf8)?obj->options.maccharset:CH_UTF8_MAC,
gr->gr_name, strlen(gr->gr_name), &name);
+ } else {
+ len = 0;
+ name = NULL;
+ }
break;
-
+#ifdef HAVE_NFSv4_ACLS
+ case 5 : /* UUID -> username */
+ case 6 : /* UUID -> groupname */
+ if ((afp_version < 32) || !(obj->options.flags & OPTION_UUID ))
+ return AFPERR_PARAM;
+ LOG(log_debug, logtype_afpd, "afp_mapid: valid UUID request");
+ len = getnamefromuuid( ibuf, &name, &type);
+ if (len != 0) /* its a error code, not len */
+ return AFPERR_NOITEM;
+ if (type == UUID_USER) {
+ if (( pw = getpwnam( name )) == NULL )
+ return( AFPERR_NOITEM );
+ LOG(log_debug, logtype_afpd, "afp_mapid: name:%s -> uid:%d", name, pw->pw_uid);
+ id = htonl(UUID_USER);
+ memcpy( rbuf, &id, sizeof( id ));
+ id = htonl( pw->pw_uid);
+ rbuf += sizeof( id );
+ memcpy( rbuf, &id, sizeof( id ));
+ rbuf += sizeof( id );
+ *rbuflen = 2 * sizeof( id );
+ } else { /* type == UUID_GROUP */
+ if (( gr = getgrnam( name )) == NULL )
+ return( AFPERR_NOITEM );
+ LOG(log_debug, logtype_afpd, "afp_mapid: group:%s -> gid:%d", name, gr->gr_gid);
+ id = htonl(UUID_GROUP);
+ memcpy( rbuf, &id, sizeof( id ));
+ rbuf += sizeof( id );
+ id = htonl( gr->gr_gid);
+ memcpy( rbuf, &id, sizeof( id ));
+ rbuf += sizeof( id );
+ *rbuflen = 2 * sizeof( id );
+ }
+ break;
+#endif
default :
return( AFPERR_PARAM );
}
- len = strlen( name );
- } else {
- len = 0;
- name = NULL;
- }
+ if (name)
+ len = strlen( name );
+
if (utf8) {
u_int16_t tp = htons(len);
memcpy(rbuf, &tp, sizeof(tp));
return( AFP_OK );
}
-int afp_mapname(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj _U_;
-char *ibuf, *rbuf;
-int ibuflen _U_, *rbuflen;
+int afp_mapname(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
struct passwd *pw;
struct group *gr;
ibuf++;
sfunc = (unsigned char) *ibuf++;
*rbuflen = 0;
+ LOG(log_debug, logtype_afpd, "afp_mapname: sfunc: %d, afp_version: %d", sfunc, afp_version);
switch ( sfunc ) {
case 1 :
case 2 : /* unicode */
memcpy(&ulen, ibuf, sizeof(ulen));
len = ntohs(ulen);
ibuf += 2;
+ LOG(log_debug, logtype_afpd, "afp_mapname: alive");
break;
case 3 :
case 4 :
len = (unsigned char) *ibuf++;
break;
+#ifdef HAVE_NFSv4_ACLS
+ case 5 : /* username -> UUID */
+ case 6 : /* groupname -> UUID */
+ if ((afp_version < 32) || !(obj->options.flags & OPTION_UUID ))
+ return AFPERR_PARAM;
+ memcpy(&ulen, ibuf, sizeof(ulen));
+ len = ntohs(ulen);
+ ibuf += 2;
+ break;
+#endif
default :
return( AFPERR_PARAM );
}
ibuf[ len ] = '\0';
- if ( len != 0 ) {
+ if ( len == 0 )
+ return AFPERR_PARAM;
+ else {
switch ( sfunc ) {
case 1 : /* unicode */
case 3 :
return( AFPERR_NOITEM );
}
id = pw->pw_uid;
+ id = htonl(id);
+ memcpy( rbuf, &id, sizeof( id ));
+ *rbuflen = sizeof( id );
break;
case 2 : /* unicode */
case 4 :
+ LOG(log_debug, logtype_afpd, "afp_mapname: gettgrnam for name: %s",ibuf);
if (NULL == ( gr = (struct group *)getgrnam( ibuf ))) {
return( AFPERR_NOITEM );
}
id = gr->gr_gid;
- break;
- }
- } else {
- id = 0;
- }
+ LOG(log_debug, logtype_afpd, "afp_mapname: gettgrnam for name: %s -> id: %d",ibuf, id);
id = htonl(id);
memcpy( rbuf, &id, sizeof( id ));
*rbuflen = sizeof( id );
+ break;
+#ifdef HAVE_NFSv4_ACLS
+ case 5 : /* username -> UUID */
+ LOG(log_debug, logtype_afpd, "afp_mapname: name: %s",ibuf);
+ if (0 != getuuidfromname(ibuf, UUID_USER, rbuf))
+ return AFPERR_NOITEM;
+ *rbuflen = UUID_BINSIZE;
+ break;
+ case 6 : /* groupname -> UUID */
+ LOG(log_debug, logtype_afpd, "afp_mapname: name: %s",ibuf);
+ if (0 != getuuidfromname(ibuf, UUID_GROUP, rbuf))
+ return AFPERR_NOITEM;
+ *rbuflen = UUID_BINSIZE;
+ break;
+#endif
+ }
+ }
return( AFP_OK );
}
/* ------------------------------------
variable DID support
*/
-int afp_closedir(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj _U_;
-char *ibuf _U_, *rbuf _U_;
-int ibuflen _U_, *rbuflen;
+int afp_closedir(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
#if 0
struct vol *vol;
/* did creation gets done automatically
* there's a pb again with case but move it to cname
*/
-int afp_opendir(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj _U_;
-char *ibuf, *rbuf;
-int ibuflen _U_, *rbuflen;
+int afp_opendir(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
struct vol *vol;
struct dir *parentdir;