/*
- * $Id: afp_dsi.c,v 1.27 2003-03-12 15:07:00 didg Exp $
+ * $Id: afp_dsi.c,v 1.27.2.1 2003-05-26 11:17:25 didg Exp $
*
* Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
* Copyright (c) 1990,1993 Regents of The University of Michigan.
dsi_close(dsi);
}
-/* a little bit of code duplication. */
+/* -------------------------------
+ * SIGTERM
+ * a little bit of code duplication.
+ */
static void afp_dsi_die(int sig)
{
dsi_attention(child.obj->handle, AFPATTN_SHUTDOWN);
}
}
+/* ---------------------------------
+ * SIGUSR1 down in five mn.
+*/
static void afp_dsi_timedown()
{
struct sigaction sv;
afp_dsi_die(1);
}
- /* ignore SIGHUP */
+ /* ignore myself */
sv.sa_handler = SIG_IGN;
sigemptyset( &sv.sa_mask );
sv.sa_flags = SA_RESTART;
- if ( sigaction( SIGHUP, &sv, 0 ) < 0 ) {
+ if ( sigaction( SIGUSR1, &sv, 0 ) < 0 ) {
LOG(log_error, logtype_afpd, "afp_timedown: sigaction SIGHUP: %s", strerror(errno) );
afp_dsi_die(1);
}
}
+/* ---------------------------------
+ * SIGHUP reload configuration file
+ * FIXME here or we wait ?
+*/
+volatile reload_request = 0;
+
+static void afp_dsi_reload()
+{
+ reload_request = 1;
+}
+
+/* ---------------------- */
#ifdef SERVERTEXT
static void afp_dsi_getmesg (int sig)
{
}
#endif /* SERVERTEXT */
+/* ---------------------- */
static void alarm_handler()
{
int err;
}
-/*
- * Signal handler for SIGUSR1 - set the debug flag and
+/* ---------------------------------
+ * old signal handler for SIGUSR1 - set the debug flag and
* redirect stdout to <tmpdir>/afpd-debug-<pid>.
*/
void afp_set_debug (int sig)
return;
}
-
-/* afp over dsi. this never returns. */
+/* -------------------------------------------
+ afp over dsi. this never returns.
+*/
void afp_over_dsi(AFPObj *obj)
{
DSI *dsi = (DSI *) obj->handle;
child.obj = obj;
child.tickle = child.flags = 0;
- /* install SIGTERM and SIGHUP */
memset(&action, 0, sizeof(action));
- action.sa_handler = afp_dsi_timedown;
+
+ /* install SIGHUP */
+ action.sa_handler = afp_dsi_reload;
sigemptyset( &action.sa_mask );
sigaddset(&action.sa_mask, SIGALRM);
sigaddset(&action.sa_mask, SIGTERM);
+ sigaddset(&action.sa_mask, SIGUSR1);
action.sa_flags = SA_RESTART;
if ( sigaction( SIGHUP, &action, 0 ) < 0 ) {
LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
afp_dsi_die(1);
}
+ /* install SIGTERM */
action.sa_handler = afp_dsi_die;
sigemptyset( &action.sa_mask );
sigaddset(&action.sa_mask, SIGALRM);
sigaddset(&action.sa_mask, SIGHUP);
+ sigaddset(&action.sa_mask, SIGUSR1);
action.sa_flags = SA_RESTART;
if ( sigaction( SIGTERM, &action, 0 ) < 0 ) {
LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
}
#endif /* SERVERTEXT */
- /* SIGUSR1 - set "debug" flag on this process. */
- action.sa_handler = afp_set_debug;
+ /* SIGUSR1 - set down in 5 minutes */
+ action.sa_handler = afp_dsi_timedown;
sigemptyset( &action.sa_mask );
- sigaddset(&action.sa_mask, SIGUSR1);
+ sigaddset(&action.sa_mask, SIGALRM);
+ sigaddset(&action.sa_mask, SIGHUP);
+ sigaddset(&action.sa_mask, SIGTERM);
action.sa_flags = SA_RESTART;
if ( sigaction( SIGUSR1, &action, 0) < 0 ) {
LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
while ((cmd = dsi_receive(dsi))) {
child.tickle = 0;
dsi_sleep(dsi, 0); /* wake up */
+ if (reload_request) {
+ reload_request = 0;
+ load_volumes(child.obj);
+ }
if (cmd == DSIFUNC_TICKLE) {
/* so we don't get killed on the client side. */
/*
- * $Id: afp_options.c,v 1.30 2003-04-16 22:45:08 samnoble Exp $
+ * $Id: afp_options.c,v 1.30.2.1 2003-05-26 11:17:25 didg Exp $
*
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* Copyright (c) 1990,1993 Regents of The University of Michigan.
void afp_options_free(struct afp_options *opt,
const struct afp_options *save)
{
- if (opt->defaultvol && (opt->defaultvol != save->defaultvol))
- free(opt->defaultvol);
- if (opt->systemvol && (opt->systemvol != save->systemvol))
- free(opt->systemvol);
+ if (opt->defaultvol.name && (opt->defaultvol.name != save->defaultvol.name))
+ free(opt->defaultvol.name);
+ if (opt->defaultvol.full_name && (opt->defaultvol.full_name != save->defaultvol.full_name))
+ free(opt->defaultvol.full_name);
+
+ if (opt->systemvol.name && (opt->systemvol.name != save->systemvol.name))
+ free(opt->systemvol.name);
+ if (opt->systemvol.full_name && (opt->systemvol.full_name != save->systemvol.full_name))
+ free(opt->systemvol.full_name);
+
+ if (opt->uservol.name && (opt->uservol.name != save->uservol.name))
+ free(opt->uservol.name);
+ if (opt->uservol.full_name && (opt->uservol.full_name != save->uservol.full_name))
+ free(opt->uservol.full_name);
+
if (opt->loginmesg && (opt->loginmesg != save->loginmesg))
free(opt->loginmesg);
if (opt->guest && (opt->guest != save->guest))
memset(options, 0, sizeof(struct afp_options));
options->connections = 20;
options->pidfile = _PATH_AFPDLOCK;
- options->defaultvol = _PATH_AFPDDEFVOL;
- options->systemvol = _PATH_AFPDSYSVOL;
+ options->defaultvol.name = _PATH_AFPDDEFVOL;
+ options->systemvol.name = _PATH_AFPDSYSVOL;
options->configfile = _PATH_AFPDCONF;
options->nlspath = _PATH_AFPDNLSPATH;
options->uampath = _PATH_AFPDUAMPATH;
/* figure out options w/ values. currently, this will ignore the setting
* if memory is lacking. */
if ((c = getoption(buf, "-defaultvol")) && (opt = strdup(c)))
- options->defaultvol = opt;
+ options->defaultvol.name = opt;
if ((c = getoption(buf, "-systemvol")) && (opt = strdup(c)))
- options->systemvol = opt;
+ options->systemvol.name = opt;
if ((c = getoption(buf, "-loginmesg")) && (opt = strdup(c)))
options->loginmesg = opt;
if ((c = getoption(buf, "-guestname")) && (opt = strdup(c)))
options->server = optarg;
break;
case 'f' :
- options->defaultvol = optarg;
+ options->defaultvol.name = optarg;
break;
case 's' :
- options->systemvol = optarg;
+ options->systemvol.name = optarg;
break;
case 'u' :
options->flags |= OPTION_USERVOLFIRST;
/*
- * $Id: volume.c,v 1.51.2.1 2003-05-26 11:04:36 didg Exp $
+ * $Id: volume.c,v 1.51.2.2 2003-05-26 11:17:25 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#endif /* BYTE_ORDER == BIG_ENDIAN */
#endif /* ! NO_LARGE_VOL_SUPPORT */
-static struct vol *volumes = NULL;
+static struct vol *Volumes = NULL;
static int lastvid = 0;
#ifndef CNID_DB
static char *Trash = "\02\024Network Trash Folder";
#endif /* CNID_DB */
-static struct extmap *extmap = NULL, *defextmap = NULL;
-static int extmap_cnt;
+
+static struct extmap *Extmap = NULL, *Defextmap = NULL;
+static int Extmap_cnt;
+static void free_extmap(void);
#define VOLOPT_ALLOW 0 /* user allow list */
#define VOLOPT_DENY 1 /* user deny list */
}
}
+/* ----------------- */
+static void showvol(const char *name)
+{
+ struct vol *volume;
+ for ( volume = Volumes; volume; volume = volume->v_next ) {
+ if ( !strcasecmp( volume->v_name, name ) && volume->v_hide) {
+ volume->v_hide = 0;
+ return;
+ }
+ }
+}
+
/* ------------------------------- */
static int creatvol(AFPObj *obj, struct passwd *pwd,
char *path, char *name,
{
struct vol *volume;
int vlen;
+ int hide = 0;
if ( name == NULL || *name == '\0' ) {
if ((name = strrchr( path, '/' )) == NULL) {
return -1;
}
- for ( volume = volumes; volume; volume = volume->v_next ) {
+ for ( volume = Volumes; volume; volume = volume->v_next ) {
if ( strcasecmp( volume->v_name, name ) == 0 ) {
- return -1; /* Won't be able to access it, anyway... */
+ if (volume->v_deleted) {
+ hide = 1;
+ }
+ else {
+ return -1; /* Won't be able to access it, anyway... */
+ }
}
}
free(volume);
return -1;
}
-
+ volume->v_hide = hide;
strcpy( volume->v_name, name);
strcpy( volume->v_path, path );
}
}
- volume->v_next = volumes;
- volumes = volume;
+ volume->v_next = Volumes;
+ Volumes = volume;
return 0;
}
struct extmap *em;
int cnt;
- if (extmap == NULL) {
- if (( extmap = calloc(1, sizeof( struct extmap ))) == NULL ) {
+ if (Extmap == NULL) {
+ if (( Extmap = calloc(1, sizeof( struct extmap ))) == NULL ) {
LOG(log_error, logtype_afpd, "setextmap: calloc: %s", strerror(errno) );
return;
}
}
ext++;
- for ( em = extmap, cnt = 0; em->em_ext; em++, cnt++) {
+ for ( em = Extmap, cnt = 0; em->em_ext; em++, cnt++) {
if ( (strdiacasecmp( em->em_ext, ext )) == 0 ) {
break;
}
}
if ( em->em_ext == NULL ) {
- if (!(extmap = realloc( extmap, sizeof( struct extmap ) * (cnt +2))) ) {
+ if (!(Extmap = realloc( Extmap, sizeof( struct extmap ) * (cnt +2))) ) {
LOG(log_error, logtype_afpd, "setextmap: realloc: %s", strerror(errno) );
return;
}
- (extmap +cnt +1)->em_ext = NULL;
- em = extmap +cnt;
+ (Extmap +cnt +1)->em_ext = NULL;
+ em = Extmap +cnt;
} else if ( !user ) {
return;
}
{
struct extmap *em;
- extmap_cnt = 0;
- if ((em = extmap) == NULL) {
+ Extmap_cnt = 0;
+ if ((em = Extmap) == NULL) {
return;
}
while (em->em_ext) {
em++;
- extmap_cnt++;
+ Extmap_cnt++;
}
- if (extmap_cnt) {
- qsort(extmap, extmap_cnt, sizeof(struct extmap), extmap_cmp);
- defextmap = extmap;
+ if (Extmap_cnt) {
+ qsort(Extmap, Extmap_cnt, sizeof(struct extmap), extmap_cmp);
+ Defextmap = Extmap;
}
}
+/* ----------------------
+*/
+static void free_extmap( void)
+{
+ if (Extmap) {
+ free(Extmap);
+ Extmap = NULL;
+ Defextmap = Extmap;
+ Extmap_cnt = 0;
+ }
+}
-/*
+/* ----------------------
+*/
+static int volfile_changed(struct afp_volume_name *p)
+{
+ struct stat st;
+ char *name;
+
+ if (p->full_name)
+ name = p->full_name;
+ else
+ name = p->name;
+
+ if (!stat( name, &st) && st.st_mtime > p->mtime) {
+ p->mtime = st.st_mtime;
+ return 1;
+ }
+ return 0;
+}
+
+/* ----------------------
* Read a volume configuration file and add the volumes contained within to
* the global volume list. If p2 is non-NULL, the file that is opened is
* p1/p2
*/
static int readvolfile(obj, p1, p2, user, pwent)
AFPObj *obj;
-char *p1, *p2;
+struct afp_volume_name *p1;
+char *p2;
int user;
struct passwd *pwent;
{
struct passwd *pw;
struct vol_option options[VOLOPT_NUM], save_options[VOLOPT_NUM];
int i;
+ struct stat st;
+ int fd;
- if (!p1)
+ if (!p1->name)
return -1;
-
- strcpy( path, p1 );
+ p1->mtime = 0;
+ strcpy( path, p1->name );
if ( p2 != NULL ) {
strcat( path, "/" );
strcat( path, p2 );
+ if (p1->full_name) {
+ free(p1->full_name);
+ }
+ p1->full_name = strdup(path);
}
if (NULL == ( fp = fopen( path, "r" )) ) {
return( -1 );
}
+ fd = fileno(fp);
+ if (fd != -1 && !fstat( fd, &st) ) {
+ p1->mtime = st.st_mtime;
+ }
memset(save_options, 0, sizeof(save_options));
while ( myfgets( buf, sizeof( buf ), fp ) != NULL ) {
if ( fclose( fp ) != 0 ) {
LOG(log_error, logtype_afpd, "readvolfile: fclose: %s", strerror(errno) );
}
+ p1->loaded = 1;
return( 0 );
}
+/* ------------------------------- */
+static void volume_free(struct vol *vol)
+{
+ free(vol->v_name);
+ vol->v_name = NULL;
+ free(vol->v_path);
+ codepage_free(vol);
+ free(vol->v_password);
+ free(vol->v_veto);
+#ifdef CNID_DB
+ free(vol->v_dbpath);
+#endif /* CNID_DB */
+#ifdef FORCE_UIDGID
+ free(vol->v_forceuid);
+ free(vol->v_forcegid);
+#endif /* FORCE_UIDGID */
+}
-static void load_volumes(AFPObj *obj)
+/* ------------------------------- */
+static void free_volumes(void )
{
- struct passwd *pwent = getpwnam(obj->username);
+ struct vol *vol;
+ struct vol *nvol, *ovol;
- if ( (obj->options.flags & OPTION_USERVOLFIRST) == 0 ) {
- readvolfile(obj, obj->options.systemvol, NULL, 0, pwent);
+ for ( vol = Volumes; vol; vol = vol->v_next ) {
+ if (( vol->v_flags & AFPVOL_OPEN ) ) {
+ vol->v_deleted = 1;
+ continue;
+ }
+ volume_free(vol);
+ }
+
+ for ( vol = Volumes, ovol = NULL; vol; vol = nvol) {
+ nvol = vol->v_next;
+
+ if (vol->v_name == NULL) {
+ if (Volumes == vol) {
+ Volumes = nvol;
+ }
+ if (!ovol) {
+ ovol = Volumes;
+ }
+ else {
+ ovol->v_next = nvol;
+ }
+ free(vol);
+ }
+ else {
+ ovol = vol;
+ }
}
+}
- if ((*obj->username == '\0') || (obj->options.flags & OPTION_NOUSERVOL)) {
- readvolfile(obj, obj->options.defaultvol, NULL, 1, pwent);
- } else if (pwent) {
- /*
- * Read user's AppleVolumes or .AppleVolumes file
- * 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 &&
- readvolfile(obj, pwent->pw_dir, ".AppleVolumes", 1, pwent) < 0 &&
- readvolfile(obj, pwent->pw_dir, "applevolumes", 1, pwent) < 0 &&
- readvolfile(obj, pwent->pw_dir, ".applevolumes", 1, pwent) < 0 &&
- obj->options.defaultvol != NULL ) {
- if (readvolfile(obj, obj->options.defaultvol, NULL, 1, pwent) < 0)
- creatvol(obj, pwent, pwent->pw_dir, NULL, NULL, 1);
- }
+/* ------------------------------- */
+static void volume_unlink(struct vol *volume)
+{
+struct vol *vol, *ovol, *nvol;
+
+ if (volume == Volumes) {
+ Volumes = Volumes->v_next;
+ return;
}
- if ( obj->options.flags & OPTION_USERVOLFIRST ) {
- readvolfile(obj, obj->options.systemvol, NULL, 0, pwent );
+ for ( vol = Volumes, ovol = NULL; vol; vol = nvol) {
+ nvol = vol->v_next;
+
+ if (vol == volume) {
+ if (!ovol) {
+ ovol = Volumes;
+ }
+ else {
+ ovol->v_next = nvol;
+ }
+ break;
+ }
+ else {
+ ovol = vol;
+ }
}
}
+
static int getvolspace( vol, bfree, btotal, xbfree, xbtotal, bsize )
struct vol *vol;
u_int32_t *bfree, *btotal, *bsize;
return( AFP_OK );
}
-/* ------------------------- */
+/* ------------------------------- */
+void load_volumes(AFPObj *obj)
+{
+ struct passwd *pwent;
+
+ if (Volumes) {
+ int changed = 0;
+
+ /* check files date */
+ if (obj->options.defaultvol.loaded) {
+ changed = volfile_changed(&obj->options.defaultvol);
+ }
+ if (obj->options.systemvol.loaded) {
+ changed |= volfile_changed(&obj->options.systemvol);
+ }
+ if (obj->options.uservol.loaded) {
+ changed |= volfile_changed(&obj->options.uservol);
+ }
+ if (!changed)
+ return;
+
+ free_extmap();
+ free_volumes();
+ }
+
+ pwent = getpwnam(obj->username);
+ if ( (obj->options.flags & OPTION_USERVOLFIRST) == 0 ) {
+ readvolfile(obj, &obj->options.systemvol, NULL, 0, pwent);
+ }
+
+ if ((*obj->username == '\0') || (obj->options.flags & OPTION_NOUSERVOL)) {
+ readvolfile(obj, &obj->options.defaultvol, NULL, 1, pwent);
+ } else if (pwent) {
+ /*
+ * Read user's AppleVolumes or .AppleVolumes file
+ * If neither are readable, read the default volumes file. if
+ * that doesn't work, create a user share.
+ */
+ obj->options.uservol.name = strdup(pwent->pw_dir);
+ if ( readvolfile(obj, &obj->options.uservol, "AppleVolumes", 1, pwent) < 0 &&
+ readvolfile(obj, &obj->options.uservol, ".AppleVolumes", 1, pwent) < 0 &&
+ readvolfile(obj, &obj->options.uservol, "applevolumes", 1, pwent) < 0 &&
+ readvolfile(obj, &obj->options.uservol, ".applevolumes", 1, pwent) < 0 &&
+ obj->options.defaultvol.name != NULL ) {
+ if (readvolfile(obj, &obj->options.defaultvol, NULL, 1, pwent) < 0)
+ creatvol(pwent->pw_dir, NULL, NULL);
+ }
+ }
+ if ( obj->options.flags & OPTION_USERVOLFIRST ) {
+ readvolfile(obj, &obj->options.systemvol, NULL, 0, pwent );
+ }
+}
+
+/* ------------------------------- */
int afp_getsrvrparms(obj, ibuf, ibuflen, rbuf, rbuflen )
AFPObj *obj;
char *ibuf, *rbuf;
int vcnt, len;
- if (!volumes)
- load_volumes(obj);
+ load_volumes(obj);
data = rbuf + 5;
- for ( vcnt = 0, volume = volumes; volume; volume = volume->v_next ) {
+ for ( vcnt = 0, volume = Volumes; volume; volume = volume->v_next ) {
if ( stat( volume->v_path, &st ) < 0 ) {
LOG(log_info, logtype_afpd, "afp_getsrvrparms: stat %s: %s",
volume->v_path, strerror(errno) );
if (!S_ISDIR(st.st_mode)) {
continue; /* not a dir */
}
-
+ if (volume->v_hide) {
+ continue; /* config file changed but the volume was mounted */
+
+ }
/* set password bit if there's a volume password */
*data = (volume->v_password) ? AFPSRVR_PASSWD : 0;
if ((len + 1) & 1) /* pad to an even boundary */
ibuf++;
- if (!volumes)
- load_volumes(obj);
+ load_volumes(obj);
- for ( volume = volumes; volume; volume = volume->v_next ) {
+ for ( volume = Volumes; volume; volume = volume->v_next ) {
if ( strcasecmp( volname, volume->v_name ) == 0 ) {
break;
}
}
vol->v_flags &= ~AFPVOL_OPEN;
- for ( ovol = volumes; ovol; ovol = ovol->v_next ) {
+ for ( ovol = Volumes; ovol; ovol = ovol->v_next ) {
if ( ovol->v_flags & AFPVOL_OPEN ) {
break;
}
curdir = ovol->v_dir;
}
}
- closevol(vol);
+ dirfree( vol->v_root );
+ vol->v_dir = NULL;
+#ifdef CNID_DB
+ cnid_close(vol->v_db);
+ vol->v_db = NULL;
+#endif /* CNID_DB */
+
+#ifdef AFP3x
+ if (vol->v_utf8toucs2 != (iconv_t)(-1))
+ iconv_close(vol->v_utf8toucs2);
+ if (vol->v_ucs2toutf8 != (iconv_t)(-1))
+ iconv_close(vol->v_ucs2toutf8);
+ if (vol->v_mactoutf8 != (iconv_t)(-1))
+ iconv_close(vol->v_mactoutf8);
+ if (vol->v_ucs2tomac != (iconv_t)(-1))
+ iconv_close(vol->v_ucs2tomac);
+#endif
+
+ if (vol->v_deleted) {
+ showvol(vol->v_name);
+ volume_free(vol);
+ volume_unlink(vol);
+ }
return( AFP_OK );
}
{
struct vol *vol;
- for ( vol = volumes; vol; vol = vol->v_next ) {
+ for ( vol = Volumes; vol; vol = vol->v_next ) {
if ( vid == vol->v_vid ) {
break;
}
struct extmap *em;
if (NULL == ( p = strrchr( path, '.' )) ) {
- return( defextmap );
+ return( Defextmap );
}
p++;
- if (!*p || !extmap_cnt) {
- return( defextmap );
+ if (!*p || !Extmap_cnt) {
+ return( Defextmap );
}
- em = bsearch(p, extmap, extmap_cnt, sizeof(struct extmap), ext_cmp_key);
+ em = bsearch(p, Extmap, Extmap_cnt, sizeof(struct extmap), ext_cmp_key);
if (em) {
return( em );
} else {
- return( defextmap );
+ return( Defextmap );
}
}
/* ------------------------- */
struct extmap *getdefextmap(void)
{
- return( defextmap );
+ return( Defextmap );
}
/* --------------------------
if ( gettimeofday( &tv, 0 ) < 0 )
return 0;
- for ( vol = volumes; vol; vol = vol->v_next ) {
+ for ( vol = Volumes; vol; vol = vol->v_next ) {
if ( (vol->v_flags & AFPVOL_OPEN) && vol->v_time + 30 < tv.tv_sec) {
if ( !stat( vol->v_path, &st ) && vol->v_time != st.st_mtime ) {
vol->v_time = st.st_mtime;