#include "mangle.h"
#include "hash.h"
-#ifdef HAVE_NFSv4_ACLS
+#ifdef HAVE_ACLS
extern void addir_inherit_acl(const struct vol *vol);
#endif
/* -------------------------
appledouble mkdir afp error code.
*/
-static int netatalk_mkdir(const char *name)
+static int netatalk_mkdir(const struct vol *vol, const char *name)
{
- if (ad_mkdir(name, DIRBITS | 0777) < 0) {
+ int ret;
+ struct stat st;
+
+ if (vol->v_flags & AFPVOL_UNIX_PRIV) {
+ if (lstat(".", &st) < 0)
+ return AFPERR_MISC;
+ int mode = (DIRBITS & (~S_ISGID & st.st_mode)) | (0777 & ~vol->v_umask);
+ LOG(log_maxdebug, logtype_afpd, "netatalk_mkdir(\"%s\") {parent mode: %04o, vol umask: %04o}",
+ name, st.st_mode, vol->v_umask);
+
+ ret = mkdir(name, mode);
+ } else {
+ ret = ad_mkdir(name, DIRBITS | 0777);
+ }
+
+ if (ret < 0) {
switch ( errno ) {
case ENOENT :
return( AFPERR_NOOBJ );
return AFPERR_PARAM;
/* try to create the destination directory */
- if (AFP_OK != (err = netatalk_mkdir(dst)) ) {
+ if (AFP_OK != (err = netatalk_mkdir(vol, dst)) ) {
closedir(dp);
return err;
}
*
* Resolve a DID, allocate a struct dir for it
* 1. Check for special CNIDs 0 (invalid), 1 and 2.
- * 2. Check if the DID is in the cache.
+ * 2a. Check if the DID is in the cache.
+ * 2b. Check if it's really a dir (d_fullpath != NULL) because we cache files too.
* 3. If it's not in the cache resolve it via the database.
* 4. Build complete server-side path to the dir.
* 5. Check if it exists and is a directory.
}
/* Search the cache */
- if ((ret = dircache_search_by_did(vol, did)) != NULL) { /* 2 */
+ if ((ret = dircache_search_by_did(vol, did)) != NULL) { /* 2a */
+ if (ret->d_fullpath == NULL) { /* 2b */
+ afp_errno = AFPERR_BADTYPE;
+ return NULL;
+ }
if (lstat(cfrombstring(ret->d_fullpath), &st) != 0) {
LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {lstat: %s}", ntohl(did), strerror(errno));
switch (errno) {
* @param vol (r) pointer to struct vol
* @param pdid (r) Parent CNID
* @param did (r) CNID
- * @param fullpath (r) Full unix path to dir
+ * @param fullpath (r) Full unix path to dir or NULL for files
*
* @returns pointer to new struct dir or NULL on error
*
upath = s_path->u_name;
- if (AFP_OK != (err = netatalk_mkdir( upath))) {
+ if (AFP_OK != (err = netatalk_mkdir(vol, upath))) {
return err;
}
ad_close_metadata( &ad);
createdir_done:
-#ifdef HAVE_NFSv4_ACLS
+#ifdef HAVE_ACLS
/* FIXME: are we really inside the created dir? */
addir_inherit_acl(vol);
-#endif
+#endif /* HAVE_ACLS */
memcpy( rbuf, &dir->d_did, sizeof( u_int32_t ));
*rbuflen = sizeof( u_int32_t );
name = NULL;
}
break;
-#ifdef HAVE_NFSv4_ACLS
+#ifdef HAVE_ACLS
case 5 : /* UUID -> username */
case 6 : /* UUID -> groupname */
if ((afp_version < 32) || !(obj->options.flags & OPTION_UUID ))
*rbuflen = 2 * sizeof( id );
}
break;
-#endif
+#endif /* HAVE_ACLS */
default :
return( AFPERR_PARAM );
}
case 4 :
len = (unsigned char) *ibuf++;
break;
-#ifdef HAVE_NFSv4_ACLS
+#ifdef HAVE_ACLS
case 5 : /* username -> UUID */
case 6 : /* groupname -> UUID */
if ((afp_version < 32) || !(obj->options.flags & OPTION_UUID ))
len = ntohs(ulen);
ibuf += 2;
break;
-#endif
+#endif /* HAVE_ACLS */
default :
return( AFPERR_PARAM );
}
memcpy( rbuf, &id, sizeof( id ));
*rbuflen = sizeof( id );
break;
-#ifdef HAVE_NFSv4_ACLS
+#ifdef HAVE_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;
-#endif
+#endif /* HAVE_ACLS */
}
}
return( AFP_OK );