dsi_attention(AFPobj->handle, AFPATTN_SHUTDOWN);
afp_dsi_close(AFPobj);
- if (sig) /* if no signal, assume dieing because logins are disabled &
+ if (sig) /* if no signal, assume dieing because logins are disabled &
don't log it (maintenance mode)*/
LOG(log_info, logtype_afpd, "Connection terminated");
if (sig == SIGTERM || sig == SIGALRM) {
}
/* Some error on the client connection, enter disconnected state */
dsi->flags |= DSI_DISCONNECTED;
+
+ /* the client sometimes logs out (afp_logout) but doesn't close the DSI session */
+ if (dsi->flags & DSI_AFP_LOGGED_OUT) {
+ afp_dsi_close(obj);
+ exit(0);
+ }
+
pause(); /* gets interrupted by SIGALARM or SIGURG tickle */
continue; /* continue receiving until disconnect timer expires
* or a primary reconnect succeeds */
LOG(log_debug, logtype_afpd, "DSI: close session request");
afp_dsi_close(obj);
LOG(log_note, logtype_afpd, "done");
- return;
+ exit(0);
case DSIFUNC_TICKLE:
dsi->flags &= ~DSI_DATA; /* thats no data in the sense we use it in alarm_handler */
int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
+ DSI *dsi = (DSI *)(obj->handle);
+
LOG(log_note, logtype_afpd, "AFP logout by %s", obj->username);
+ of_close_all_forks();
close_all_vol();
+ dsi->flags = DSI_AFP_LOGGED_OUT;
*rbuflen = 0;
return AFP_OK;
}
extern int of_statdir (struct vol *vol, struct path *);
extern int of_closefork (struct ofork *ofork);
extern void of_closevol (const struct vol *vol);
+extern void of_close_all_forks(void);
extern struct adouble *of_ad (const struct vol *, struct path *, struct adouble *);
#ifdef HAVE_ATFUNCS
return;
}
+/* ----------------------
+ close all forks for a volume
+*/
+void of_close_all_forks(void)
+{
+ int refnum;
+
+ if (!oforks)
+ return;
+
+ for ( refnum = 0; refnum < nforks; refnum++ ) {
+ if (oforks[ refnum ] != NULL) {
+ if (of_closefork( oforks[ refnum ]) < 0 ) {
+ LOG(log_error, logtype_afpd, "of_close_all_forks: %s", strerror(errno) );
+ }
+ }
+ }
+ return;
+}
+
#define DSI_NOREPLY (1 << 6) /* in dsi_write we generate our own replies */
#define DSI_RECONSOCKET (1 << 7) /* we have a new socket from primary reconnect */
#define DSI_RECONINPROG (1 << 8) /* used in the new session in reconnect */
+#define DSI_AFP_LOGGED_OUT (1 << 9) /* client called afp_logout, quit on next EOF from socket */
/* basic initialization: dsi_init.c */
extern DSI *dsi_init (const dsi_proto /*protocol*/,
void dsi_close(DSI *dsi)
{
/* server generated. need to set all the fields. */
- if (!(dsi->flags & DSI_SLEEPING)) {
+ if (!(dsi->flags & DSI_SLEEPING) && !(dsi->flags & DSI_DISCONNECTED)) {
dsi->header.dsi_flags = DSIFL_REQUEST;
dsi->header.dsi_command = DSIFUNC_CLOSE;
dsi->header.dsi_requestID = htons(dsi_serverID(dsi));