/*
- * $Id: aecho.c,v 1.5 2001-08-03 22:07:22 srittau Exp $
+ * $Id: aecho.c,v 1.5.10.1 2003-07-21 05:50:53 didg Exp $
*
* Copyright (c) 1990,1991 Regents of The University of Michigan.
* All Rights Reserved.
fprintf(stderr, "Bad address.\n");
exit(1);
}
+ break;
+
case 'c' :
pings = atoi( optarg );
break;
# preexec_close -> a non-zero return code from preexec close the
# volume being mounted.
# nostat -> don't stat volume path when enumerating volumes list
+# upriv -> use unix privilege.
#
#
# codepage:filename -> load filename from nls directory.
# Note: Depending on the number of simultaneously
# connected clients and the network's speed, this can
# lead to a significant higher load on your network!
+# -sleep <number> AFP 3.x wait number hours before disconnecting
+# clients in sleep mode. Default 10 hours
# -tickleval <number> Specify the tickle timeout interval (in seconds).
# Note, this defaults to 30 seconds, and really
# shouldn't be changed. If you want to control
AFPD_MAX_CLIENTS=20
# Change this to set the machine's atalk name and zone.
-# NOTE: if you're zone has spaces in it, you're better off specifying
+# NOTE: if your zone has spaces in it, you're better off specifying
# it in afpd.conf
#ATALK_ZONE=@zone
ATALK_NAME=`echo ${HOSTNAME}|cut -d. -f1`
/*
- * $Id: afp_dsi.c,v 1.27.2.2 2003-06-23 10:25:07 didg Exp $
+ * $Id: afp_dsi.c,v 1.27.2.3 2003-07-21 05:50:53 didg Exp $
*
* Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
* Copyright (c) 1990,1993 Regents of The University of Michigan.
#define CHILD_DIE (1 << 0)
#define CHILD_RUNNING (1 << 1)
+#define CHILD_SLEEPING (1 << 2)
static struct {
AFPObj *obj;
}
}
-/* ---------------------------------
- * SIGUSR1 down in five mn.
-*/
+/* */
+static void afp_dsi_sleep(void)
+{
+ child.flags |= CHILD_SLEEPING;
+ dsi_sleep(child.obj->handle, 1);
+}
+
+/* ------------------- */
static void afp_dsi_timedown()
{
struct sigaction sv;
}
#endif /* SERVERTEXT */
-/* ---------------------- */
static void alarm_handler()
{
-int err;
+ int err;
+
/* if we're in the midst of processing something,
don't die. */
- if ((child.flags & CHILD_RUNNING) || (child.tickle++ < child.obj->options.timeout)) {
+ if ((child.flags & CHILD_SLEEPING) && child.tickle++ < child.obj->options.sleep) {
+ return;
+ } else if ((child.flags & CHILD_RUNNING) || (child.tickle++ < child.obj->options.timeout)) {
if (!(err = pollvoltime(child.obj)))
err = dsi_tickle(child.obj->handle);
if (err <= 0)
obj->reply = (int (*)()) dsi_cmdreply;
obj->attention = (int (*)(void *, AFPUserBytes)) dsi_attention;
+ obj->sleep = afp_dsi_sleep;
child.obj = obj;
child.tickle = child.flags = 0;
/* get stuck here until the end */
while ((cmd = dsi_receive(dsi))) {
child.tickle = 0;
+ child.flags &= ~CHILD_SLEEPING;
dsi_sleep(dsi, 0); /* wake up */
if (reload_request) {
reload_request = 0;
if (cmd == DSIFUNC_TICKLE) {
/* so we don't get killed on the client side. */
- if (child.flags & CHILD_DIE)
+ if ((child.flags & CHILD_DIE))
dsi_tickle(dsi);
continue;
} else if (!(child.flags & CHILD_DIE)) { /* reset tickle timer */
/*
- * $Id: afp_options.c,v 1.30.2.1 2003-05-26 11:17:25 didg Exp $
+ * $Id: afp_options.c,v 1.30.2.2 2003-07-21 05:50:53 didg Exp $
*
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* Copyright (c) 1990,1993 Regents of The University of Michigan.
options->passwdfile = _PATH_AFPDPWFILE;
options->tickleval = 30;
options->timeout = 4;
+ options->sleep = 10* 120; /* 10 h in 30 seconds tick */
options->server_notif = 1;
options->authprintdir = NULL;
options->signature = "host";
}
}
+ if ((c = getoption(buf, "-sleep"))) {
+ options->sleep = atoi(c) *120;
+ if (options->sleep <= 4) {
+ options->sleep = 4;
+ }
+ }
+
if ((c = getoption(buf, "-server_quantum")))
options->server_quantum = strtoul(c, NULL, 0);
/*
- * $Id: auth.c,v 1.44.2.2 2003-05-26 11:04:36 didg Exp $
+ * $Id: auth.c,v 1.44.2.3 2003-07-21 05:50:53 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include <pwd.h>
#include <grp.h>
#include <atalk/logger.h>
+#include <atalk/server_ipc.h>
#ifdef TRU64
#include <netdb.h>
LOG(log_info, logtype_afpd, "session from %s (%s)", hostname,
inet_ntoa( dsi->client.sin_addr ) );
+
if (setegid( pwd->pw_gid ) < 0 || seteuid( pwd->pw_uid ) < 0) {
LOG(log_error, logtype_afpd, "login: %s", strerror(errno) );
return AFPERR_BADUAM;
*rbuflen = 0;
- retdata = 1;
+ retdata = obj->options.sleep /120;
+ if (!retdata) {
+ retdata = 1;
+ }
*rbuflen = sizeof(retdata);
retdata = htonl(retdata);
memcpy(rbuf, &retdata, sizeof(retdata));
- if (obj->proto == AFPPROTO_DSI) {
- DSI *dsi = obj->handle;
- dsi_sleep(dsi, 1);
- }
+ if (obj->sleep)
+ obj->sleep();
rbuf += sizeof(retdata);
return AFP_OK;
}
unsigned int ibuflen, *rbuflen;
{
u_int16_t type;
- u_int32_t idlen;
+ u_int32_t idlen = 0;
+ u_int32_t boottime;
u_int16_t tklen; /* FIXME: spec u_int32_t? */
pid_t token;
+ char *p;
*rbuflen = 0;
break;
case 3: /* Jaguar */
case 4:
+ if (ibuflen >= 8 ) {
+ p = ibuf;
+ memcpy( &idlen, ibuf, sizeof(idlen));
+ idlen = ntohl(idlen);
+ ibuf += sizeof(idlen);
+ ibuflen -= sizeof(idlen);
+ ibuf += sizeof(boottime);
+ ibuflen -= sizeof(boottime);
+ if (ibuflen < idlen || idlen > (90-10)) {
+ return AFPERR_PARAM;
+ }
+ server_ipc_write(IPC_GETSESSION, idlen+8, p );
+ }
type = 0;
break;
}
}
memcpy(&token, ibuf, tklen);
/* killed old session, not easy */
+ server_ipc_write(IPC_KILLTOKEN, tklen, &token);
+ sleep(1);
+
return AFPERR_SESSCLOS; /* was AFP_OK */
}
if (!len || len > ibuflen)
return send_reply(obj, AFPERR_BADUAM);
- if ((afp_uam = auth_uamfind(UAM_SERVER_LOGIN, ibuf, len)) == NULL)
+ if (NULL == (afp_uam = auth_uamfind(UAM_SERVER_LOGIN, ibuf, len)) )
return send_reply(obj, AFPERR_BADUAM);
ibuf += len;
ibuflen -= len;
/*
- * $Id: desktop.c,v 1.26.2.3 2003-06-23 10:25:07 didg Exp $
+ * $Id: desktop.c,v 1.26.2.4 2003-07-21 05:50:54 didg Exp $
*
* See COPYRIGHT.
*
clen = min( clen, 199 );
upath = path->u_name;
- if (check_access(upath, OPENACC_WR ) < 0) {
+ if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
return AFPERR_ACCESS;
}
}
upath = s_path->u_name;
- if (check_access(upath, OPENACC_WR ) < 0) {
+ if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
return AFPERR_ACCESS;
}
/*
- * $Id: directory.c,v 1.71.2.3 2003-05-20 14:49:18 didg Exp $
+ * $Id: directory.c,v 1.71.2.4 2003-07-21 05:50:54 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
/* -----------------------------------------
* if did is not in the cache resolve it with cnid
*
+ * FIXME
+ * OSX call it with bogus id, ie file ID not folder ID,
+ * and we are really bad in this case.
*/
struct dir *
dirlookup( vol, did )
return 0;
}
+/* --------------------- */
+int file_access(struct path *path, int mode)
+{
+struct maccess ma;
+
+ accessmode(path->u_name, &ma, curdir, &path->st);
+ if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE))
+ return -1;
+ if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD))
+ return -1;
+ return 0;
+
+}
+
/* ------------------------------
(".", curdir)
(name, dir) with curdir:name == dir, from afp_enumerate
}
break;
+ case DIRPBIT_UNIXPR :
+ aint = htonl(st->st_uid);
+ memcpy( data, &aint, sizeof( aint ));
+ data += sizeof( aint );
+ aint = htonl(st->st_gid);
+ memcpy( data, &aint, sizeof( aint ));
+ data += sizeof( aint );
+
+ aint = st->st_mode;
+ aint = htonl ( aint & ~S_ISGID ); /* Remove SGID, OSX doesn't like it ... */
+ memcpy( data, &aint, sizeof( aint ));
+ data += sizeof( aint );
+
+ accessmode( upath, &ma, dir , st);
+
+ *data++ = ma.ma_user;
+ *data++ = ma.ma_world;
+ *data++ = ma.ma_group;
+ *data++ = ma.ma_owner;
+ break;
+
+
default :
if ( isad ) {
ad_close( &ad, ADFLAGS_HF );
buf += 6;
break;
}
+
+ case DIRPBIT_UNIXPR :
+ /* Skip UID and GID for now, there seems to be now way to set them from an OSX client anyway */
+ buf += sizeof( aint );
+ buf += sizeof( aint );
+
+ change_mdate = 1;
+ change_parent_mdate = 1;
+ memcpy( &aint, buf, sizeof( aint ));
+ buf += sizeof( aint );
+ aint = ntohl (aint);
+ if (curdir->d_did == DIRDID_ROOT)
+ setdeskmode( aint );
+#if 0 /* don't error if we can't set the desktop mode */
+ switch ( errno ) {
+ case EPERM :
+ case EACCES :
+ err = AFPERR_ACCESS;
+ goto setdirparam_done;
+ case EROFS :
+ err = AFPERR_VLOCK;
+ goto setdirparam_done;
+ default :
+ LOG(log_error, logtype_afpd, "setdirparam: setdeskmode: %s",
+ strerror(errno) );
+ break;
+ err = AFPERR_PARAM;
+ goto setdirparam_done;
+ }
+#endif /* 0 */
+
+ if ( setdirunixmode( aint, vol_noadouble(vol),
+ (vol->v_flags & AFPVOL_DROPBOX)) < 0 ) {
+ switch ( errno ) {
+ case EPERM :
+ case EACCES :
+ err = AFPERR_ACCESS;
+ goto setdirparam_done;
+ case EROFS :
+ err = AFPERR_VLOCK;
+ goto setdirparam_done;
+ default :
+ LOG(log_error, logtype_afpd, "setdirparam: setdirmode: %s",
+ strerror(errno) );
+ err = AFPERR_PARAM;
+ goto setdirparam_done;
+ }
+ }
+ break;
+
default :
err = AFPERR_BITMAP;
goto setdirparam_done;
/*
- * $Id: directory.h,v 1.13.2.3 2003-05-20 14:49:19 didg Exp $
+ * $Id: directory.h,v 1.13.2.4 2003-07-21 05:50:54 didg Exp $
*
* Copyright (c) 1990,1991 Regents of The University of Michigan.
* All Rights Reserved.
#define DIRPBIT_GID 11
#define DIRPBIT_ACCESS 12
#define DIRPBIT_PDINFO 13 /* ProDOS Info */
+#define DIRPBIT_UNIXPR 15
/* directory attribute bits (see file.h for other bits) */
#define ATTRBIT_EXPFOLDER (1 << 1) /* shared point */
extern int for_each_dirent __P((const struct vol *, char *, dir_loop , void *));
extern int check_access __P((char *name , int mode));
+extern int file_access __P((struct path *path, int mode));
extern int netatalk_unlink __P((const char *name));
/*
- * $Id: file.c,v 1.92.2.1 2003-06-05 08:48:18 didg Exp $
+ * $Id: file.c,v 1.92.2.2 2003-07-21 05:50:54 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include "file.h"
#include "filedir.h"
#include "globals.h"
+#include "unix.h"
/* the format for the finderinfo fields (from IM: Toolbox Essentials):
* field bytes subfield bytes
if (aint > 255) /* FIXME safeguard, anyway if no ascii char it's game over*/
aint = 255;
- utf8 = 0; /* mac roman hint */
+ utf8 = 0; /* htonl(utf8) */
memcpy(data, &utf8, sizeof(utf8));
data += sizeof(utf8);
u_char achar, fdType[4];
u_int32_t utf8 = 0;
struct stat *st;
+ struct maccess ma;
+
#ifdef DEBUG
LOG(log_info, logtype_afpd, "begin getmetadata:");
#endif /* DEBUG */
memcpy(data, &aint, sizeof( aint ));
data += sizeof( aint );
break;
+ case FILPBIT_UNIXPR :
+ aint = htonl(st->st_uid);
+ memcpy( data, &aint, sizeof( aint ));
+ data += sizeof( aint );
+ aint = htonl(st->st_gid);
+ memcpy( data, &aint, sizeof( aint ));
+ data += sizeof( aint );
+
+ aint = htonl(st->st_mode);
+ memcpy( data, &aint, sizeof( aint ));
+ data += sizeof( aint );
+
+ accessmode( upath, &ma, dir , st);
+
+ *data++ = ma.ma_user;
+ *data++ = ma.ma_world;
+ *data++ = ma.ma_group;
+ *data++ = ma.ma_owner;
+ break;
+
default :
return( AFPERR_BITMAP );
}
adp = &ad;
}
- if (check_access(upath, OPENACC_WR ) < 0) {
+ if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
return AFPERR_ACCESS;
}
break;
}
/* fallthrough */
+ case FILPBIT_UNIXPR :
+ /* Skip the UIG/GID, no way to set them from OSX clients */
+ buf += sizeof( aint );
+ buf += sizeof( aint );
+
+ change_mdate = 1;
+ change_parent_mdate = 1;
+ memcpy( &aint, buf, sizeof( aint ));
+ buf += sizeof( aint );
+ aint = ntohl (aint);
+
+ setfilemode(path, aint);
+ break;
default :
err = AFPERR_BITMAP;
goto setfilparam_done;
/*
- * $Id: file.h,v 1.16.2.1 2003-06-23 10:25:07 didg Exp $
+ * $Id: file.h,v 1.16.2.2 2003-07-21 05:50:54 didg Exp $
*
* Copyright (c) 1990,1991 Regents of The University of Michigan.
* All Rights Reserved.
#define FILPBIT_EXTDFLEN 11
#define FILPBIT_PDINFO 13 /* ProDOS Info/ UTF8 name */
#define FILPBIT_EXTRFLEN 14
+#define FILPBIT_UNIXPR 15
/* attribute bits. (d) = directory attribute bit as well. */
#define ATTRBIT_INVISIBLE (1<<0) /* invisible (d) */
/*
- * $Id: filedir.c,v 1.45.2.1 2003-05-10 10:33:16 didg Exp $
+ * $Id: filedir.c,v 1.45.2.2 2003-07-21 05:50:54 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
}
else
#endif /* DROPKLUDGE */
- if (!isdir) {
+ /* if unix priv don't try to match perm with dest folder */
+ if (!isdir && !vol_unix_priv(vol)) {
int admode = ad_mode("", 0777);
setfilmode(upath, admode, NULL);
/*
- * $Id: fork.c,v 1.51 2003-03-15 01:34:35 didg Exp $
+ * $Id: fork.c,v 1.51.2.1 2003-07-21 05:50:54 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
}
/* FIXME should we check it first ? */
upath = s_path->u_name;
- if (check_access(upath, access ) < 0) {
- return AFPERR_ACCESS;
+ if (!vol_unix_priv(vol)) {
+ if (check_access(upath, access ) < 0) {
+ return AFPERR_ACCESS;
+ }
+ }
+ else {
+ if (file_access(s_path, access ) < 0) {
+ return AFPERR_ACCESS;
+ }
}
st = &s_path->st;
/*
- * $Id: globals.h,v 1.18.2.1 2003-05-26 11:17:25 didg Exp $
+ * $Id: globals.h,v 1.18.2.2 2003-07-21 05:50:54 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
char *k5service, *k5realm;
mode_t umask;
mode_t save_mask;
+ int sleep;
#ifdef ADMIN_GRP
gid_t admingid;
#endif /* ADMIN_GRP */
void (*logout)(void), (*exit)(int);
int (*reply)(void *, int);
int (*attention)(void *, AFPUserBytes);
+ void (*sleep)(void);
/* to prevent confusion, only use these in afp_* calls */
char oldtmp[AFPOBJ_TMPSIZ + 1], newtmp[AFPOBJ_TMPSIZ + 1];
void *uam_cookie; /* cookie for uams */
/*
- * $Id: main.c,v 1.20.4.1 2003-05-26 11:17:25 didg Exp $
+ * $Id: main.c,v 1.20.4.2 2003-07-21 05:50:54 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include <atalk/paths.h>
#include <atalk/util.h>
#include <atalk/server_child.h>
+#include <atalk/server_ipc.h>
#include "globals.h"
#include "afp_config.h"
static AFPConfig *configs;
static server_child *server_children;
static fd_set save_rfds;
+static int Ipc_fd = -1;
#ifdef TRU64
void afp_get_cmdline( int *ac, char ***av)
exit(i);
}
+/* ------------------
+ initialize fd set we are waiting for.
+*/
+static void set_fd(int ipc_fd)
+{
+ AFPConfig *config;
+
+ FD_ZERO(&save_rfds);
+ for (config = configs; config; config = config->next) {
+ if (config->fd < 0) /* for proxies */
+ continue;
+ FD_SET(config->fd, &save_rfds);
+ }
+ if (ipc_fd >= 0) {
+ FD_SET(ipc_fd, &save_rfds);
+ }
+}
+
+/* ------------------ */
static void afp_goaway(int sig)
{
LOG(log_error, logtype_afpd, "config re-read: no servers configured");
afp_exit(1);
}
- FD_ZERO(&save_rfds);
- for (config = configs; config; config = config->next) {
- if (config->fd < 0)
- continue;
- FD_SET(config->fd, &save_rfds);
- }
+ set_fd(Ipc_fd);
} else {
LOG(log_info, logtype_afpd, "disallowing logins");
auth_unload();
{
AFPConfig *config;
fd_set rfds;
+ void *ipc;
struct sigaction sv;
sigset_t sigs;
}
sigprocmask(SIG_UNBLOCK, &sigs, NULL);
- /* watch atp and dsi sockets. */
- FD_ZERO(&save_rfds);
- for (config = configs; config; config = config->next) {
- if (config->fd < 0) /* for proxies */
- continue;
- FD_SET(config->fd, &save_rfds);
+ /* watch atp, dsi sockets and ipc parent/child file descriptor. */
+ if ((ipc = server_ipc_create())) {
+ Ipc_fd = server_ipc_parent(ipc);
}
+ set_fd(Ipc_fd);
/* wait for an appleshare connection. parent remains in the loop
* while the children get handled by afp_over_{asp,dsi}. this is
LOG(log_error, logtype_afpd, "main: can't wait for input: %s", strerror(errno));
break;
}
-
+ if (Ipc_fd >=0 && FD_ISSET(Ipc_fd, &rfds)) {
+ server_ipc_read(server_children);
+ }
for (config = configs; config; config = config->next) {
if (config->fd < 0)
continue;
/*
- * $Id: unix.c,v 1.43 2003-03-09 19:55:35 didg Exp $
+ * $Id: unix.c,v 1.43.2.1 2003-07-21 05:50:54 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include <limits.h>
#include <atalk/adouble.h>
#include <atalk/afp.h>
-
/* STDC check */
-#if STDC_HEADERS
+#ifdef STDC_HEADERS
#include <string.h>
#else /* STDC_HEADERS */
#ifndef HAVE_STRCHR
#include "directory.h"
#include "volume.h"
#include "unix.h"
+#include "fork.h"
/*
* Get the free space on a partition.
mbits = 0;
- mbits |= ( bits & ( S_IREAD >> 6 )) ? (AR_UREAD | AR_USEARCH) : 0;
+ mbits |= ( bits & ( S_IREAD >> 6 )) ? AR_UREAD : 0;
mbits |= ( bits & ( S_IWRITE >> 6 )) ? AR_UWRITE : 0;
- /* Do we really need this?
- mbits |= ( bits & ( S_IEXEC >> 6) ) ? AR_USEARCH : 0; */
+ /* Do we really need this? */
+ mbits |= ( bits & ( S_IEXEC >> 6) ) ? AR_USEARCH : 0;
return( mbits );
}
return( 0 );
}
+/* --------------------- */
+int setfilemode (path, mode)
+struct path* path;
+mode_t mode;
+{
+ if (!path->st_valid) {
+ of_stat(path);
+ }
+
+ if (path->st_errno) {
+ return -1;
+ }
+
+ if (setfilmode( path->u_name, mode, &path->st) < 0)
+ return -1;
+ /* we need to set write perm if read set for resource fork */
+ return setfilmode(ad_path( path->u_name, ADFLAGS_HF ), ad_hf_mode(mode), &path->st);
+}
+
+/* --------------------- */
int setfilmode(name, mode, st)
char * name;
mode_t mode;
return 0;
}
+/* --------------------- */
+int setdirunixmode( mode, noadouble, dropbox )
+const mode_t mode;
+const int noadouble;
+const int dropbox;
+{
+ if ( stickydirmode(".AppleDouble", DIRBITS | mode, dropbox) < 0 && !noadouble)
+ return -1 ;
+
+ if ( stickydirmode(".", DIRBITS | mode, dropbox) < 0 )
+ return -1;
+ return 0;
+}
+
+/* --------------------- */
int setdirmode( mode, noadouble, dropbox )
const mode_t mode;
const int noadouble;
/* This is equivalent of unix rename(). */
int unix_rename(const char *oldpath, const char *newpath)
{
+#if 0
char pd_name[PATH_MAX+1];
int i;
struct stat pd_stat;
uid_t uid;
+#endif
if (rename(oldpath, newpath) < 0)
return -1;
/*
- * $Id: unix.h,v 1.12 2003-01-07 15:55:22 rlewczuk Exp $
+ * $Id: unix.h,v 1.12.2.1 2003-07-21 05:50:54 didg Exp $
*/
#ifndef AFPD_UNIX_H
extern struct afp_options default_options;
-extern int gmem __P((const gid_t));
-extern int setdeskmode __P((const mode_t));
-extern int setdirmode __P((const mode_t, const int, const int));
-extern int setdeskowner __P((const uid_t, const gid_t));
-extern int setdirowner __P((const uid_t, const gid_t, const int));
-extern int setfilmode __P((char *, mode_t , struct stat *));
-extern int unix_rename __P((const char *oldpath, const char *newpath));
-
-extern void accessmode __P((char *, struct maccess *, struct dir *, struct stat *));
+extern int gmem __P((const gid_t));
+extern int setdeskmode __P((const mode_t));
+extern int setdirunixmode __P((const mode_t, const int, const int));
+extern int setdirmode __P((const mode_t, const int, const int));
+extern int setdeskowner __P((const uid_t, const gid_t));
+extern int setdirowner __P((const uid_t, const gid_t, const int));
+extern int setfilmode __P((char *, mode_t , struct stat *));
+extern int setfilemode __P((struct path*, const mode_t));
+extern int unix_rename __P((const char *oldpath, const char *newpath));
+
+extern void accessmode __P((char *, struct maccess *, struct dir *, struct stat *));
#ifdef AFS
#define accessmode afsmode
/*
- * $Id: volume.c,v 1.51.2.6 2003-06-23 10:25:08 didg Exp $
+ * $Id: volume.c,v 1.51.2.7 2003-07-21 05:50:54 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
options[VOLOPT_PREEXEC].i_value = 1;
else if (strcasecmp(p, "root_preexec_close") == 0)
options[VOLOPT_ROOTPREEXEC].i_value = 1;
+ else if (strcasecmp(p, "upriv") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_UNIX_PRIV;
+
p = strtok(NULL, ",");
}
ashort |= VOLPBIT_ATTR_CATSEARCH;
if (afp_version >= 30) {
ashort |= VOLPBIT_ATTR_UTF8;
+ if (vol->v_flags & AFPVOL_UNIX_PRIV)
+ ashort |= VOLPBIT_ATTR_UNIXPRIV;
}
ashort = htons(ashort);
memcpy(data, &ashort, sizeof( ashort ));
completely worked this out, but it's related to booting
from the server. Support for that function is a ways
off.. <shirsch@ibm.net> */
- *data++ |= (volume->v_flags & AFPVOL_A2VOL) ? AFPSRVR_CONFIGINFO : 0;
+ *data |= (volume->v_flags & AFPVOL_A2VOL) ? AFPSRVR_CONFIGINFO : 0;
+ *data++ |= 0; /* UNIX PRIVS BIT ..., OSX doesn't seem to use it, so we don't either */
len = strlen( volume->v_name );
*data++ = len;
memcpy(data, volume->v_name, len );
/*
- * $Id: volume.h,v 1.19.2.4 2003-06-23 10:25:08 didg Exp $
+ * $Id: volume.h,v 1.19.2.5 2003-07-21 05:50:54 didg Exp $
*
* Copyright (c) 1990,1994 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#define AFPVOL_NOFILEID (1 << 15) /* don't advertise createid resolveid and deleteid calls */
#define AFPVOL_UTF8 (1 << 16) /* unix name are in UTF8 */
#define AFPVOL_NOSTAT (1 << 17) /* unix name are in UTF8 */
+#define AFPVOL_UNIX_PRIV (1 << 18) /* support unix privileges */
/* FPGetSrvrParms options */
#define AFPSRVR_CONFIGINFO (1 << 0)
#define vol_utf8(vol) (0)
#define utf8_encoding() (0)
#endif
+#define vol_unix_priv(vol) (afp_version >= 30 && ((vol)->v_flags & AFPVOL_UNIX_PRIV))
extern struct vol *getvolbyvid __P((const u_int16_t));
extern int ustatfs_getvolspace __P((const struct vol *,
extern void server_child_free __P((server_child *));
extern void server_child_kill __P((server_child *, const int, const int));
+extern void server_child_kill_one __P((server_child *children, const int forkid, const pid_t pid));
+extern void server_child_kill_one_by_id __P((server_child *children, const int forkid, const pid_t pid,
+ const u_int32_t len, char *id, u_int32_t boottime));
+
extern void server_child_setup __P((server_child *, const int, void (*)()));
extern void server_child_handler __P((server_child *));
--- /dev/null
+
+#include <atalk/server_child.h>
+
+#define IPC_KILLTOKEN 1
+#define IPC_GETSESSION 2
+
+void *server_ipc_create(void);
+int server_ipc_child(void *obj);
+int server_ipc_parent(void *obj);
+int server_ipc_read(server_child *children);
+int server_ipc_write(uint16_t command, int len, void *token);
+
+
+
+
+
logger.c \
module.c \
server_child.c \
+ server_ipc.c \
server_lock.c \
strcasestr.c \
strdicasecmp.c
/*
- * $Id: server_child.c,v 1.7 2002-10-07 19:14:41 didg Exp $
+ * $Id: server_child.c,v 1.7.4.1 2003-07-21 05:50:54 didg Exp $
*
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* All rights reserved. See COPYRIGHT.
#ifndef WIFSIGNALED
#define WIFSIGNALED(status) (!WIFSTOPPED(status) && !WIFEXITED(status))
#endif
+#ifndef WTERMSIG
+#define WTERMSIG(status) ((status) & 0x7f)
+#endif
#include <atalk/server_child.h>
struct server_child_data {
pid_t pid;
+ u_int32_t time;
+ u_int32_t idlen;
+
+ char *clientid;
struct server_child_data **prevp, *next;
};
return 0;
unhash_child(child);
+ if (child->clientid) {
+ free(child->clientid);
+ }
free(child);
children->count--;
return 1;
child = fork->table[j]; /* start at the beginning */
while (child) {
tmp = child->next;
+ if (child->clientid) {
+ free(child->clientid);
+ }
free(child);
child = tmp;
}
}
}
+/* send kill to a child processes.
+ * a plain-old linked list
+ * FIXME use resolve_child ?
+ */
+void server_child_kill_one(server_child *children, const int forkid, const pid_t pid)
+{
+ server_child_fork *fork;
+ struct server_child_data *child, *tmp;
+ int i;
+
+ fork = (server_child_fork *) children->fork + forkid;
+ for (i = 0; i < CHILD_HASHSIZE; i++) {
+ child = fork->table[i];
+ while (child) {
+ tmp = child->next;
+ if (child->pid == pid) {
+ kill(child->pid, SIGTERM);
+ }
+ child = tmp;
+ }
+ }
+}
+
+
+/* see if there is a process for the same mac */
+/* if the times don't match mac has been rebooted */
+void server_child_kill_one_by_id(server_child *children, const int forkid, const pid_t pid,
+ const u_int32_t idlen, char *id, u_int32_t boottime)
+{
+ server_child_fork *fork;
+ struct server_child_data *child, *tmp;
+ int i;
+
+ fork = (server_child_fork *) children->fork + forkid;
+ for (i = 0; i < CHILD_HASHSIZE; i++) {
+ child = fork->table[i];
+ while (child) {
+ tmp = child->next;
+ if ( child->pid != pid) {
+ if ( child->idlen == idlen && !memcmp(child->clientid, id, idlen)) {
+ if ( child->time != boottime ) {
+ kill(child->pid, SIGTERM);
+ LOG(log_info, logtype_default, "Disconnecting old session %d, client rebooted.", child->pid);
+ }
+ else {
+ LOG(log_info, logtype_default, "WARNING: 2 connections (%d, %d), boottime identical, don't know if one needs to be disconnected.");
+ }
+
+ }
+ }
+ else
+ {
+ child->time = boottime;
+ /* free old token if any */
+ if (child->clientid) {
+ free(child->clientid);
+ }
+ child->idlen = idlen;
+ child->clientid = id;
+ LOG(log_info, logtype_default, "Setting clientid (len %d) for %d, boottime %X", idlen, child->pid, boottime);
+ }
+ child = tmp;
+ }
+ }
+}
+
/* for extra cleanup if necessary */
void server_child_setup(server_child *children, const int forkid,
void (*fcn)(const pid_t))
} else {
if (WIFSIGNALED(status))
{
- LOG(log_info, logtype_default, "server_child[%d] %d killed", i, pid);
+ LOG(log_info, logtype_default, "server_child[%d] %d killed by signal %d", i, pid,
+ WTERMSIG (status));
}
else
{
--- /dev/null
+/*
+ * $Id: server_ipc.c,v 1.1.4.1 2003-07-21 05:50:55 didg Exp $
+ *
+ * All rights reserved. See COPYRIGHT.
+ *
+ *
+ * ipc between parent and children.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atalk/server_child.h>
+#include <atalk/server_ipc.h>
+#include <atalk/logger.h>
+
+typedef struct ipc_header {
+ u_int16_t command;
+ pid_t child_pid;
+ u_int32_t len;
+ char *msg;
+} ipc_header;
+
+static int pipe_fd[2];
+
+void *server_ipc_create(void)
+{
+ if (pipe(pipe_fd)) {
+ return NULL;
+ }
+ return &pipe_fd;
+}
+
+/* ----------------- */
+int server_ipc_child(void *obj)
+{
+ /* close input */
+ close(pipe_fd[0]);
+ return pipe_fd[1];
+}
+
+/* ----------------- */
+int server_ipc_parent(void *obj)
+{
+ return pipe_fd[0];
+}
+
+/* ----------------- */
+int ipc_kill_token (struct ipc_header *ipc, server_child *children)
+{
+ pid_t pid;
+
+ if (ipc->len != sizeof(pid_t)) {
+ return -1;
+ }
+ /* assume signals SA_RESTART set */
+ memcpy (&pid, ipc->msg, sizeof(pid_t));
+
+ LOG(log_info, logtype_default, "child %d disconnected", pid);
+ server_child_kill_one(children, CHILD_DSIFORK, pid);
+ return 0;
+}
+
+/* ----------------- */
+int ipc_get_session (struct ipc_header *ipc, server_child *children)
+{
+ u_int32_t boottime;
+ u_int32_t idlen;
+ char *clientid, *p;
+
+
+ if (ipc->len < (sizeof(idlen) + sizeof(boottime)) ) {
+ return -1;
+ }
+ p = ipc->msg;
+ memcpy (&idlen, p, sizeof(idlen));
+ idlen = ntohl (idlen);
+ p += sizeof(idlen);
+
+ memcpy (&boottime, p, sizeof(boottime));
+ p += sizeof(boottime);
+
+ if (ipc->len < idlen + sizeof(idlen) + sizeof(boottime)) {
+ return -1;
+ }
+ if (NULL == (clientid = (char*) malloc(idlen)) ) {
+ return -1;
+ }
+ memcpy (clientid, p, idlen);
+
+ server_child_kill_one_by_id (children, CHILD_DSIFORK, ipc->child_pid, idlen, clientid, boottime);
+ /* FIXME byte to ascii if we want to log clientid */
+ LOG (log_info, logtype_afpd, "ipc_get_session: len: %u, idlen %d, time %x", ipc->len, idlen, boottime);
+ return 0;
+}
+
+#define IPC_HEADERLEN 10
+#define IPC_MAXMSGSIZE 90
+
+/* ----------------- */
+int server_ipc_read(server_child *children)
+{
+ int ret = 0;
+ struct ipc_header ipc;
+ char buf[IPC_MAXMSGSIZE], *p;
+
+ if ((ret = read(pipe_fd[0], buf, IPC_HEADERLEN)) != IPC_HEADERLEN) {
+ LOG (log_info, logtype_afpd, "Reading IPC header failed (%u of %u bytes read)", ret, IPC_HEADERLEN);
+ return -1;
+ }
+
+ p = buf;
+ memcpy(&ipc.command, p, sizeof(ipc.command));
+ p += sizeof(ipc.command);
+ memcpy(&ipc.child_pid, p, sizeof(ipc.child_pid));
+ p += sizeof(ipc.child_pid);
+ memcpy(&ipc.len, p, sizeof(ipc.len));
+
+ /* This should never happen */
+ if (ipc.len > (IPC_MAXMSGSIZE - IPC_HEADERLEN))
+ {
+ LOG (log_info, logtype_afpd, "IPC message exceeds allowed size (%u)", ipc.len);
+ return -1;
+ }
+
+ memset (buf, 0, IPC_MAXMSGSIZE);
+ if ( ipc.len != 0) {
+ if ((ret = read(pipe_fd[0], buf, ipc.len)) != ipc.len) {
+ LOG (log_info, logtype_afpd, "Reading IPC message failed (%u of %u bytes read)", ret, ipc.len);
+ return -1;
+ }
+ }
+ ipc.msg = buf;
+
+ LOG (log_info, logtype_afpd, "ipc_read: command: %u, pid: %u, len: %u", ipc.command, ipc.child_pid, ipc.len);
+
+ switch (ipc.command)
+ {
+ case IPC_KILLTOKEN:
+ return (ipc_kill_token(&ipc, children));
+ break;
+ case IPC_GETSESSION:
+ return (ipc_get_session(&ipc, children));
+ break;
+ default:
+ LOG (log_info, logtype_afpd, "ipc_read: unknown command: %d", ipc.command);
+ return -1;
+ }
+
+}
+
+/* ----------------- */
+int server_ipc_write( u_int16_t command, int len, void *msg)
+{
+ char block[IPC_MAXMSGSIZE], *p;
+ pid_t pid;
+ p = block;
+
+ memset ( p, 0 , IPC_MAXMSGSIZE);
+ if (len + IPC_HEADERLEN > IPC_MAXMSGSIZE)
+ return -1;
+
+ memcpy(p, &command, sizeof(command));
+ p += sizeof(command);
+
+ pid = getpid();
+ memcpy(p, &pid, sizeof(pid_t));
+ p += sizeof(pid_t);
+
+ memcpy(p, &len, 4);
+ p += 4;
+
+ memcpy(p, msg, len);
+
+ LOG (log_info, logtype_afpd, "ipc_write: command: %u, pid: %u, msglen: %u", command, pid, len);
+ return write(pipe_fd[1], block, len+IPC_HEADERLEN );
+}
+