/*
+ * $Id: volume.c,v 1.13 2001-09-06 20:00:59 rufustfirefly Exp $
+ *
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
+#endif /* HAVE_CONFIG_H */
#include <sys/time.h>
#include <sys/syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <netatalk/endian.h>
#include <atalk/asp.h>
#include <atalk/dsi.h>
#include <atalk/adouble.h>
#include <atalk/afp.h>
#include <atalk/util.h>
+#ifdef CNID_DB
#include <atalk/cnid.h>
+#endif /* CNID_DB*/
#include <dirent.h>
+#ifdef HAVE_FCNTL_H
#include <fcntl.h>
+#endif /* HAVE_FCNTL_H */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
+
+/* STDC check */
+#if STDC_HEADERS
#include <string.h>
+#else /* STDC_HEADERS */
+#ifndef HAVE_STRCHR
+#define strchr index
+#define strrchr index
+#endif /* HAVE_STRCHR */
+char *strchr (), *strrchr ();
+#ifndef HAVE_MEMCPY
+#define memcpy(d,s,n) bcopy ((s), (d), (n))
+#define memmove(d,s,n) bcopy ((s), (d), (n))
+#endif /* ! HAVE_MEMCPY */
+#endif /* STDC_HEADERS */
+
#include <pwd.h>
#include <grp.h>
#include <utime.h>
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
+#endif /* ! MIN */
#ifndef NO_LARGE_VOL_SUPPORT
#if BYTE_ORDER == BIG_ENDIAN
#define hton64(x) (x)
#define ntoh64(x) (x)
-#else
+#else /* BYTE_ORDER == BIG_ENDIAN */
#define hton64(x) ((u_int64_t) (htonl(((x) >> 32) & 0xffffffffLL)) | \
(u_int64_t) ((htonl(x) & 0xffffffffLL) << 32))
#define ntoh64(x) (hton64(x))
-#endif
-#endif
+#endif /* BYTE_ORDER == BIG_ENDIAN */
+#endif /* ! NO_LARGE_VOL_SUPPORT */
static struct vol *volumes = NULL;
static int lastvid = 0;
-#if AD_VERSION == AD_VERSION1
+#ifndef CNID_DB
static char *Trash = "\02\024Network Trash Folder";
-#endif
+#endif /* CNID_DB */
static struct extmap *extmap = NULL, *defextmap = NULL;
#define VOLOPT_ALLOW 0 /* user allow list */
~u -> make u illegal only as the first
part of a double-byte character.
*/
-#define VOLOPT_MAX 9
+#define VOLOPT_VETO 10 /* list of veto filespec */
+
+#ifdef FORCE_UIDGID
+#define VOLOPT_FORCEUID 11 /* force uid for username x */
+#define VOLOPT_FORCEGID 12 /* force gid for group x */
+#define VOLOPT_MAX 12
+#else /* normally, there are only 9 possible options */
+#define VOLOPT_MAX 10
+#endif /* FORCE_UIDGID */
+
#define VOLOPT_NUM (VOLOPT_MAX + 1)
#define VOLPASSLEN 8
destlen -= len;
}
} else if (is_var(p, "$f")) {
- if (q = strchr(pwd->pw_gecos, ','))
+ if ((q = strchr(pwd->pw_gecos, ',')))
*q = '\0';
q = pwd->pw_gecos;
} else if (is_var(p, "$g")) {
page = strdup(name);
}
+ /* debug: show which codepage directory we are using */
+ syslog(LOG_DEBUG, "using codepage directory: %s", page);
+
return page;
}
free(options[VOLOPT_CODEPAGE].c_value);
options[VOLOPT_CODEPAGE].c_value = get_codepage_path(nlspath, val + 1);
+ } else if (optionok(tmp, "veto:", val)) {
+ if (options[VOLOPT_VETO].c_value)
+ free(options[VOLOPT_VETO].c_value);
+ options[VOLOPT_VETO].c_value = strdup(val + 1);
+
} else if (optionok(tmp, "casefold:", val)) {
if (strcasecmp(val + 1, "tolower") == 0)
options[VOLOPT_CASEFOLD].i_value = AFPVOL_UMLOWER;
options[VOLOPT_FLAGS].i_value |= AFPVOL_USEDOTS;
else if (strcasecmp(p, "limitsize") == 0)
options[VOLOPT_FLAGS].i_value |= AFPVOL_LIMITSIZE;
+ /* support for either "dropbox" or "dropkludge" */
+ else if (strcasecmp(p, "dropbox") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_DROPBOX;
+ else if (strcasecmp(p, "dropkludge") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_DROPBOX;
p = strtok(NULL, ",");
}
-#if AD_VERSION > AD_VERSION1
+#ifdef CNID_DB
} else if (optionok(tmp, "dbpath:", val)) {
if (options[VOLOPT_DBPATH].c_value)
free(options[VOLOPT_DBPATH].c_value);
-
+
options[VOLOPT_DBPATH].c_value = strdup(val + 1);
-#endif
+#endif /* CNID_DB */
} else if (optionok(tmp, "mapchars:",val)) {
if (options[VOLOPT_MAPCHARS].c_value)
free(options[VOLOPT_MAPCHARS].c_value);
if (options[VOLOPT_PASSWORD].c_value)
free(options[VOLOPT_PASSWORD].c_value);
options[VOLOPT_PASSWORD].c_value = strdup(val + 1);
+
+#ifdef FORCE_UIDGID
+
+ /* this code allows forced uid/gid per volume settings */
+ } else if (optionok(tmp, "forceuid:", val)) {
+ if (options[VOLOPT_FORCEUID].c_value)
+ free(options[VOLOPT_FORCEUID].c_value);
+ options[VOLOPT_FORCEUID].c_value = strdup(val + 1);
+ } else if (optionok(tmp, "forcegid:", val)) {
+ if (options[VOLOPT_FORCEGID].c_value)
+ free(options[VOLOPT_FORCEGID].c_value);
+ options[VOLOPT_FORCEGID].c_value = strdup(val + 1);
+
+#endif /* FORCE_UIDGID */
+
} else if (val) {
/* ignore unknown options */
syslog(LOG_DEBUG, "ignoring unknown volume option: %s", tmp);
} else {
/* we'll assume it's a volume name. */
- strncpy(volname, tmp, vlen);
+ strncpy(volname, tmp, vlen);
}
}
if (( volume =
(struct vol *)calloc(1, sizeof( struct vol ))) == NULL ) {
- syslog( LOG_ERR, "creatvol: malloc: %m" );
+ syslog( LOG_ERR, "creatvol: malloc: %s", strerror(errno) );
return -1;
}
if (( volume->v_name =
(char *)malloc( vlen + 1 )) == NULL ) {
- syslog( LOG_ERR, "creatvol: malloc: %m" );
+ syslog( LOG_ERR, "creatvol: malloc: %s", strerror(errno) );
free(volume);
return -1;
}
if (( volume->v_path =
(char *)malloc( strlen( path ) + 1 )) == NULL ) {
- syslog( LOG_ERR, "creatvol: malloc: %m" );
+ syslog( LOG_ERR, "creatvol: malloc: %s", strerror(errno) );
free(volume->v_name);
free(volume);
return -1;
#ifdef __svr4__
volume->v_qfd = -1;
-#endif
+#endif /* __svr4__ */
volume->v_vid = lastvid++;
volume->v_lastdid = 3;
if (options[VOLOPT_PASSWORD].c_value)
volume->v_password = strdup(options[VOLOPT_PASSWORD].c_value);
-#if AD_VERSION > AD_VERSION1
+ if (options[VOLOPT_VETO].c_value)
+ volume->v_veto = strdup(options[VOLOPT_VETO].c_value);
+
+#ifdef CNID_DB
if (options[VOLOPT_DBPATH].c_value)
volume->v_dbpath = strdup(options[VOLOPT_DBPATH].c_value);
-#endif
+#endif /* CNID_DB */
+
+#ifdef FORCE_UIDGID
+
+ if (options[VOLOPT_FORCEUID].c_value) {
+ volume->v_forceuid = strdup(options[VOLOPT_FORCEUID].c_value);
+ } else {
+ volume->v_forceuid = NULL; /* set as null so as to return 0 later on */
+ }
+
+ if (options[VOLOPT_FORCEGID].c_value) {
+ volume->v_forcegid = strdup(options[VOLOPT_FORCEGID].c_value);
+ } else {
+ volume->v_forcegid = NULL; /* set as null so as to return 0 later on */
+ }
+
+#endif /* FORCE_UIDGID */
+
}
volume->v_next = volumes;
if ( em == NULL ) {
if (( em =
(struct extmap *)malloc( sizeof( struct extmap ))) == NULL ) {
- syslog( LOG_ERR, "setextmap: malloc: %m" );
+ syslog( LOG_ERR, "setextmap: malloc: %s", strerror(errno) );
return;
}
em->em_next = extmap;
if (strncmp(path, VOLOPT_DEFAULT, VOLOPT_DEFAULT_LEN) == 0) {
*tmp = '\0';
for (i = 0; i < VOLOPT_NUM; i++) {
- if (parseline( sizeof( path ) - VOLOPT_DEFAULT_LEN - 1,
+ if (parseline( sizeof( path ) - VOLOPT_DEFAULT_LEN - 1,
path + VOLOPT_DEFAULT_LEN) < 0)
break;
- volset(save_options, tmp, sizeof(tmp) - 1,
+ volset(save_options, tmp, sizeof(tmp) - 1,
obj->options.nlspath, path + VOLOPT_DEFAULT_LEN);
}
}
if (((options[VOLOPT_FLAGS].i_value & AFPVOL_RO) == 0) &&
((accessvol(options[VOLOPT_ROLIST].c_value,
obj->username) == 1) ||
- !accessvol(options[VOLOPT_RWLIST].c_value,
+ !accessvol(options[VOLOPT_RWLIST].c_value,
obj->username)))
options[VOLOPT_FLAGS].i_value |= AFPVOL_RO;
}
volfree(save_options, NULL);
if ( fclose( fp ) != 0 ) {
- syslog( LOG_ERR, "readvolfile: fclose: %m" );
+ syslog( LOG_ERR, "readvolfile: fclose: %s", strerror(errno) );
}
return( 0 );
}
} else if (pwent) {
/*
* Read user's AppleVolumes or .AppleVolumes file
- * If neither are readable, read the default volumes file. if
+ * If neither are readable, read the default volumes file. if
* that doesn't work, create a user share.
*/
if ( readvolfile(obj, pwent->pw_dir, "AppleVolumes", 1, pwent) < 0 &&
u_int32_t maxsize;
#ifndef NO_QUOTA_SUPPORT
VolSpace qfree, qtotal;
-#endif
+#endif /* ! NO_QUOTA_SUPPORT */
spaceflag = AFPVOL_GVSMASK & vol->v_flags;
/* report up to 2GB if afp version is < 2.2 (4GB if not) */
goto getvolspace_done;
}
}
-#endif AFS
+#endif /* AFS */
if (( rc = ustatfs_getvolspace( vol, xbfree, xbtotal,
bsize)) != AFP_OK ) {
goto getvolspace_done;
}
}
-#endif
+#endif /* ! NO_QUOTA_SUPPORT */
vol->v_flags = ( ~AFPVOL_GVSMASK & vol->v_flags ) | AFPVOL_USTATFS;
getvolspace_done:
int *buflen;
{
struct adouble ad;
- int bit = 0, aint, isad = 1;
+ int bit = 0, isad = 1;
+ u_int32_t aint;
u_short ashort;
u_int32_t bfree, btotal, bsize;
VolSpace xbfree, xbtotal; /* extended bytes */
* .Parent file here if it doesn't exist. */
memset(&ad, 0, sizeof(ad));
- if ( ad_open( vol->v_path, vol_noadouble(vol) |
+ if ( ad_open( vol->v_path, vol_noadouble(vol) |
ADFLAGS_HF|ADFLAGS_DIR, O_RDWR | O_CREAT,
0666, &ad) < 0 ) {
isad = 0;
switch ( bit ) {
case VOLPBIT_ATTR :
-#if AD_VERSION > AD_VERSION1
+#ifdef CNID_DB
ashort = VOLPBIT_ATTR_FILEID;
-#else
+#else /* CNID_DB */
ashort = 0;
-#endif
+#endif /* CNID_DB */
/* check for read-only.
* NOTE: we don't actually set the read-only flag unless
* it's passed in that way as it's possible to mount
xbfree = hton64( xbfree );
#if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
bcopy(&xbfree, data, sizeof(xbfree));
-#else
+#else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
memcpy(data, &xbfree, sizeof( xbfree ));
-#endif
+#endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
data += sizeof( xbfree );
break;
xbtotal = hton64( xbtotal );
#if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
bcopy(&xbtotal, data, sizeof(xbtotal));
-#else
+#else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
memcpy(data, &xbtotal, sizeof( xbtotal ));
-#endif
+#endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
data += sizeof( xbfree );
break;
-#endif
+#endif /* ! NO_LARGE_VOL_SUPPORT */
case VOLPBIT_NAME :
nameoff = data;
data = rbuf + 5;
for ( vcnt = 0, volume = volumes; volume; volume = volume->v_next ) {
if ( stat( volume->v_path, &st ) < 0 ) {
- syslog( LOG_INFO, "afp_getsrvrparms: stat %s: %m",
- volume->v_path );
+ syslog( LOG_INFO, "afp_getsrvrparms: stat %s: %s",
+ volume->v_path, strerror(errno) );
continue; /* can't access directory */
}
if (!S_ISDIR(st.st_mode)) {
*rbuflen = data - rbuf;
data = rbuf;
if ( gettimeofday( &tv, 0 ) < 0 ) {
- syslog( LOG_ERR, "afp_getsrvrparms: gettimeofday: %m" );
+ syslog( LOG_ERR, "afp_getsrvrparms: gettimeofday: %s", strerror(errno) );
*rbuflen = 0;
return AFPERR_PARAM;
}
{
struct stat st;
char *volname;
-#if AD_VERSION == AD_VERSION1
+#ifndef CNID_DB
char *p;
-#endif
+#endif /* CNID_DB */
struct vol *volume;
struct dir *dir;
int len, ret, buflen;
if (( volume->v_flags & AFPVOL_OPEN ) == 0 ) {
if ((dir = dirnew(strlen(volume->v_name) + 1)) == NULL) {
- syslog( LOG_ERR, "afp_openvol: malloc: %m" );
+ syslog( LOG_ERR, "afp_openvol: malloc: %s", strerror(errno) );
ret = AFPERR_MISC;
goto openvol_err;
}
ret = AFPERR_PARAM;
goto openvol_err;
}
-#if AD_VERSION == AD_VERSION1
+
+#ifdef CNID_DB
+ if (volume->v_dbpath)
+ volume->v_db = cnid_open (volume->v_dbpath);
+ if (volume->v_db == 0)
+ volume->v_db = cnid_open (volume->v_path);
+#endif /* CNID_DB */
+
+#ifndef CNID_DB
/*
* If you mount a volume twice, the second time the trash appears on
* the desk-top. That's because the Mac remembers the DID for the
*/
p = Trash;
cname( volume, volume->v_dir, &p );
-#endif
+#endif /* CNID_DB */
return( AFP_OK );
dirfree( vol->v_root );
vol->v_dir = NULL;
-#if AD_VERSION > AD_VERSION1
+#ifdef CNID_DB
cnid_close(vol->v_db);
vol->v_db = NULL;
-#endif
+#endif /* CNID_DB */
return( AFP_OK );
}
{
struct timeval tv;
- /* fail w/out dying */
+ /* just looking at vol->v_time is broken seriously since updates
+ * from other users afpd processes never are seen.
+ * This is not the most elegant solution (a shared memory between
+ * the afpd processes would come closer)
+ * [RS] */
+
if ( gettimeofday( &tv, 0 ) < 0 ) {
- syslog( LOG_ERR, "setvoltime: gettimeofday: %m" );
+ syslog( LOG_ERR, "setvoltime: gettimeofday: %s", strerror(errno) );
return;
}
-
+ if( utime( vol->v_path, NULL ) < 0 ) {
+ /* write of time failed ... probably a read only filesys,
+ * where no other users can interfere, so there's no issue here
+ */
+ }
+
/* a little granularity */
if (vol->v_time < tv.tv_sec) {
vol->v_time = tv.tv_sec;