home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magazyn Amiga Shareware Floppies
/
ma64.dms
/
ma64.adf
/
FTPMount-1.0
/
Source
/
site.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-10
|
51KB
|
2,229 lines
/*
* This source file is Copyright 1995 by Evan Scott.
* All rights reserved.
* Permission is granted to distribute this file provided no
* fees beyond distribution costs are levied.
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/alerts.h>
#include <devices/timer.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <workbench/workbench.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/icon.h>
#include <proto/gadtools.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "evtypes.h"
#include "verify.h"
#include "tcp.h"
#include "site.h"
#include "ftp.h"
#include "split.h"
#include "ftpinfo.h"
#include "connect.h"
#include "request.h"
#include "globals.h"
#include "strings.h"
struct MsgPort *get_site(b8 *s)
{
site *sp;
struct Process *child;
struct StandardPacket *std_pkt;
struct DiskObject *dobj;
BPTR ocd;
b8 *tmp;
sp = sites;
while (sp) {
if (stricmp(sp->name, s) == 0) return sp->port;
sp = sp->next;
}
sp = (site *)allocate(sizeof(*sp) + strlen(s) + 1, V_site);
if (!sp) return nil;
ensure(sp, V_site);
/* first sort out default login information */
sp->user = nil;
sp->password = nil;
sp->needs_user = false;
sp->needs_password = false;
sp->root = nil;
sp->user = nil;
sp->password = nil;
sp->host = nil;
sp->open_status = false;
sp->quick = true;
sp->case_sensitive = false;
sp->all_messages = true;
sp->error_messages = true;
sp->port_number = ftp_port_number;
tmp = s;
while (*tmp && *tmp != '@') tmp++;
if (*tmp == '@') {
sp->host = (b8 *)allocate(strlen(tmp + 1) + 1, V_cstr);
if (sp->host) {
strcpy(sp->host, tmp + 1);
}
sp->needs_user = true;
sp->needs_password = true;
if (tmp != s) {
sp->user = (b8 *)allocate(tmp - s + 1, V_cstr);
if (sp->user) {
strncpy(sp->user, s, tmp - s);
sp->user[tmp - s] = 0;
sp->needs_user = false;
}
}
} else {
sp->host = (b8 *)allocate(strlen(s) + 1, V_cstr);
if (sp->host) {
strcpy(sp->host, s);
}
}
/* now try to get info from icon */
if (IconBase) {
ocd = CurrentDir(ftphosts_lock);
dobj = GetDiskObject(s);
if (!dobj)
{
dobj = GetDiskObject(strings[MSG_DEFAULT]);
}
CurrentDir(ocd);
} else {
dobj = nil;
}
if (dobj) {
/*
* HOST overrides the "title", whereas USER doesn't ...
* is this inconsistent or is it valid?
*/
if (!sp->user) {
tmp = FindToolType(dobj->do_ToolTypes, strings[MSG_USER_TT]);
if (tmp) {
sp->user = (b8 *)allocate(strlen(tmp) + 1, V_cstr);
if (sp->user) {
strcpy(sp->user, tmp);
sp->needs_user = false;
}
}
}
tmp = FindToolType(dobj->do_ToolTypes, strings[MSG_PASSWORD_TT]);
if (tmp) {
sp->password = (b8 *)allocate(strlen(tmp) + 1, V_cstr);
if (sp->password) {
strcpy(sp->password, tmp);
sp->needs_password = false;
}
}
tmp = FindToolType(dobj->do_ToolTypes, strings[MSG_STATUS_TT]);
if (tmp) {
if (stricmp(tmp, strings[MSG_OFF]) != 0 &&
stricmp(tmp, strings[MSG_FALSE]) != 0) {
sp->open_status = true;
}
}
tmp = FindToolType(dobj->do_ToolTypes, strings[MSG_QUICK_TT]);
if (tmp) {
if (stricmp(tmp, strings[MSG_OFF]) == 0 ||
stricmp(tmp, strings[MSG_FALSE]) == 0) {
sp->quick = false;
} else {
sp->quick = true;
}
}
tmp = FindToolType(dobj->do_ToolTypes, strings[MSG_SLOW_TT]);
if (tmp) {
if (stricmp(tmp, strings[MSG_OFF]) != 0 &&
stricmp(tmp, strings[MSG_FALSE]) != 0) {
sp->quick = false;
} else {
sp->quick = true;
}
}
tmp = FindToolType(dobj->do_ToolTypes, strings[MSG_CASE_TT]);
if (tmp) {
if (stricmp(tmp, strings[MSG_OFF]) != 0 &&
stricmp(tmp, strings[MSG_FALSE]) != 0) {
sp->case_sensitive = true;
}
}
tmp = FindToolType(dobj->do_ToolTypes, strings[MSG_HOST_TT]);
if (tmp) {
if (sp->host) deallocate(sp->host, V_cstr);
sp->host = allocate(strlen(tmp) + 1, V_cstr);
if (sp->host) {
strcpy(sp->host, tmp);
}
}
tmp = FindToolType(dobj->do_ToolTypes, strings[MSG_ROOT_TT]);
if (tmp)
{
sp->root = allocate(strlen(tmp) + 1, V_cstr);
if (sp->root)
{
strcpy(sp->root, tmp);
}
}
tmp = FindToolType(dobj->do_ToolTypes, strings[MSG_MESSAGES_TT]);
if (tmp) {
if (stricmp(tmp, strings[MSG_ALL]) == 0)
{
sp->error_messages = true;
sp->all_messages = true;
}
else if (stricmp(tmp, strings[MSG_ERROR]) == 0)
{
sp->all_messages = false;
sp->error_messages = true;
}
else if (stricmp(tmp, strings[MSG_NONE]) == 0)
{
sp->all_messages = false;
sp->error_messages = false;
}
}
tmp = FindToolType(dobj->do_ToolTypes, strings[MSG_PORT_TT]);
if (tmp) {
sp->port_number = atoi(tmp);
}
FreeDiskObject(dobj);
}
if (!sp->host) {
if (sp->user) deallocate(sp->user, V_cstr);
if (sp->password) deallocate(sp->password, V_cstr);
if (sp->root) deallocate(sp->root, V_cstr);
deallocate(sp, V_site);
return nil;
}
std_pkt = (struct StandardPacket *)allocate(sizeof(*std_pkt), V_StandardPacket);
if (!std_pkt) {
deallocate(sp->host, V_cstr);
if (sp->user) deallocate(sp->user, V_cstr);
if (sp->password) deallocate(sp->password, V_cstr);
if (sp->root) deallocate(sp->root, V_cstr);
deallocate(sp, V_site);
return nil;
}
std_pkt->sp_Msg.mn_Node.ln_Name = (void *)&std_pkt->sp_Pkt;
std_pkt->sp_Pkt.dp_Link = &std_pkt->sp_Msg;
std_pkt->sp_Pkt.dp_Type = ACTION_DIE; /* ignored when used at startup */
std_pkt->sp_Pkt.dp_Arg1 = (b32)sp;
std_pkt->sp_Pkt.dp_Port = startup_sync;
strcpy(sp->name, s);
sp->lock_list = nil;
sp->file_list = nil;
sp->infos = nil;
sp->control = nil;
sp->intr = nil;
sp->cwd = nil;
sp->connected = false;
sp->read_banners = false;
sp->unix_paths = true;
sp->cfile = nil;
sp->cfile_type = 0;
sp->abort_signals = sp->disconnect_signals = 0;
sp->site_state = SS_DISCONNECTED;
sp->status_window = nil;
child = CreateNewProcTags(
NP_Entry, site_handler,
NP_Name, sp->name,
NP_StackSize, 6000,
NP_Priority, 0,
TAG_END, 0
);
if (!child) {
deallocate(sp->host, V_cstr);
if (sp->user) deallocate(sp->user, V_cstr);
if (sp->password) deallocate(sp->password, V_cstr);
if (sp->root) deallocate(sp->root, V_cstr);
deallocate(std_pkt, V_StandardPacket);
deallocate(sp, V_site);
return nil;
}
sp->port = &child->pr_MsgPort;
PutMsg(sp->port, &std_pkt->sp_Msg);
WaitPort(startup_sync); GetMsg(startup_sync);
if (std_pkt->sp_Pkt.dp_Res1) {
sp->death_packet = std_pkt;
sp->next = sites;
sites = sp;
return sp->port;
} else {
deallocate(sp->host, V_cstr);
if (sp->user) deallocate(sp->user, V_cstr);
if (sp->password) deallocate(sp->password, V_cstr);
if (sp->root) deallocate(sp->root, V_cstr);
deallocate(std_pkt, V_StandardPacket);
deallocate(sp, V_site);
return nil;
}
}
void remove_site(site *sp)
{
site **sps;
verify(sp, V_site);
sps = &sites;
while (*sps && *sps != sp) {
sps = &(*sps)->next;
}
if (*sps) {
*sps = sp->next;
if (sp->host) deallocate(sp->host, V_cstr);
if (sp->root) deallocate(sp->root, V_cstr);
deallocate(sp->death_packet, V_StandardPacket);
deallocate(sp, V_site);
}
return;
}
void shutdown_sites(void)
{
site *sp, *spn;
struct DosPacket *dp;
lock *l;
sp = sites;
while (sp) {
verify(sp, V_site);
spn = sp->next;
dp = &sp->death_packet->sp_Pkt;
dp->dp_Type = ACTION_DIE;
dp->dp_Port = startup_sync;
PutMsg(sp->port, dp->dp_Link);
WaitPort(startup_sync); GetMsg(startup_sync);
l = (lock *)dp->dp_Res2;
while (l) {
adopt(l, V_lock);
l = l->next;
}
if (sp->host) deallocate(sp->host, V_cstr);
if (sp->root) deallocate(sp->root, V_cstr);
deallocate(sp->death_packet, V_StandardPacket);
deallocate(sp, V_site);
sp = spn;
}
sites = nil;
}
void suspend_sites(void)
{
site *sp;
struct DosPacket *dp;
sp = sites;
while (sp) {
verify(sp, V_site);
dp = &sp->death_packet->sp_Pkt;
dp->dp_Type = action_SUSPEND;
dp->dp_Port = startup_sync;
PutMsg(sp->port, dp->dp_Link);
WaitPort(startup_sync); GetMsg(startup_sync);
sp = sp->next;
}
}
struct info_header *get_dir(site *sp, b8 *name)
{
struct info_header *ih;
verify(sp, V_site);
truth(name != nil);
ih = find_info_header(sp, name);
if (ih) return ih;
/* oh kay */
if (sp->cfile) {
verify(sp->file_list, V_file_info);
if (sp->file_list->closed) {
close_file(sp, true);
} else {
return nil;
}
}
if (!change_dir(sp, name)) return nil;
ih = new_info_header(sp, name);
if (!ih) return nil; /* just out of memory ... but wth */
get_list(sp, ih);
return ih;
}
ftpinfo *get_info(site *ftp_site, b8 *name)
{
b8 *s;
struct info_header *ih;
verify(ftp_site, V_site);
truth(name != nil);
/* get parent dir name */
s = name + strlen(name) - 1;
while (s >= name && *s != '/') s--;
if (s >= name) {
*s = 0;
ih = get_dir(ftp_site, name);
*s++ = '/';
} else {
s = name;
ih = get_dir(ftp_site, "");
}
if (!ih) return nil;
return find_info(ih, s);
}
void flush_info(site *ftp_site, b8 *name)
{
b8 *s;
struct info_header *ih;
verify(ftp_site, V_site);
truth(name != nil);
/* get parent dir name */
s = name + strlen(name) - 1;
while (s >= name && *s != '/') s--;
if (s >= name) {
*s = 0;
ih = find_info_header(ftp_site, name);
*s++ = '/';
} else {
s = name;
ih = find_info_header(ftp_site, "");
}
if (ih) {
free_info_header(ih);
}
return;
}
status_message *get_sm(site *sp)
{
status_message *sm;
verify(sp, V_site);
if (sm = (status_message *)GetMsg(sp->rank)) return sm;
sm = (status_message *)allocate(sizeof(*sm), V_status_message);
if (!sm) return nil;
ensure(sm, V_status_message);
sm->header.mn_ReplyPort = sp->rank;
sm->header.mn_Length = sizeof(*sm);
sm->header.mn_Node.ln_Type = NT_MESSAGE;
sm->header.mn_Node.ln_Name = "site status message";
sm->header.mn_Node.ln_Pri = 0;
sm->this_site = sp;
return sm;
}
void state_change(site *sp, b16 state)
{
status_message *sm;
verify(sp, V_site);
if (sp->site_state == state) return;
sp->site_state = state;
sm = get_sm(sp);
if (sm) {
sm->command = SM_STATE_CHANGE;
PutMsg(status_port, &sm->header);
}
}
void __saveds site_handler(void)
{
struct Process *me;
struct Message *msg;
struct DosPacket *dp;
struct MsgPort *local, *reply, *sync, *timeport, *rank;
struct StandardPacket *idle_packet;
struct timerequest *timer;
status_message *sm, *tsm;
lock *new_lock, *slock, **locks;
site *ftp_site;
b32 signals;
int idlecount, n;
split sd, sd2;
b8 *s;
struct info_header *ih;
ftpinfo *fi;
file_info *fip;
struct FileHandle *fh;
struct FileInfoBlock *fib;
b32 o1, o2, o3;
me = (struct Process *)FindTask(0);
local = &me->pr_MsgPort;
WaitPort(local);
msg = GetMsg(local);
dp = (struct DosPacket *)msg->mn_Node.ln_Name;
reply = dp->dp_Port;
dp->dp_Port = local;
ftp_site = (site *)dp->dp_Arg1;
verify(ftp_site, V_site);
local->mp_Node.ln_Name = ftp_site->name;
idlecount = 0;
mem_tracking_on();
ftp_site->IBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 36);
if (ftp_site->IBase) {
ftp_site->GTBase = OpenLibrary("gadtools.library", 0);
if (ftp_site->GTBase) {
ftp_site->GBase = (struct GfxBase *)OpenLibrary("graphics.library", 36);
if (ftp_site->GBase) {
sync = CreatePort(0, 0);
if (sync) {
ftp_site->sync = sync;
timeport = CreatePort(0, 0);
if (timeport) {
timer = (struct timerequest *)CreateExtIO(timeport, sizeof(*timer));
if (timer) {
idle_packet = (struct StandardPacket *)allocate(sizeof(*idle_packet), V_StandardPacket);
if (idle_packet) {
idle_packet->sp_Msg.mn_Node.ln_Name =
(void *)&idle_packet->sp_Pkt;
idle_packet->sp_Pkt.dp_Link = &idle_packet->sp_Msg;
idle_packet->sp_Pkt.dp_Type = action_IDLE;
idle_packet->sp_Pkt.dp_Arg1 = (b32)ftp_site;
prime->header.mn_ReplyPort = sync;
prime->command = TCP_NEWMESSAGE;
PutMsg(tcp, &prime->header);
WaitPort(sync); GetMsg(sync);
if (prime->result) {
ftp_site->control = prime->data;
PutMsg(tcp, &prime->header);
WaitPort(sync); GetMsg(sync);
if (prime->result) {
ftp_site->intr = prime->data;
ftp_site->intr->interrupt = ftp_site->control;
ftp_site->intr->header.mn_ReplyPort = sync;
ftp_site->intr->command = TCP_INTERRUPT;
if (OpenDevice("timer.device", UNIT_VBLANK, (struct IORequest *)timer, 0) == 0) {
sm = (status_message *)allocate(sizeof(*sm), V_status_message);
if (sm) {
rank = CreatePort(0, 0);
if (rank) {
ftp_site->rank = rank;
goto begin;
} else dp->dp_Res2 = ERROR_NO_FREE_STORE;
deallocate(sm, V_status_message);
} else dp->dp_Res2 = ERROR_NO_FREE_STORE;
CloseDevice((struct IORequest *)timer);
} else dp->dp_Res2 = ERROR_DEVICE_NOT_MOUNTED;
ftp_site->intr->command = TCP_DISPOSE;
PutMsg(tcp, &ftp_site->intr->header);
} else dp->dp_Res2 = ERROR_NO_FREE_STORE;
ftp_site->control->command = TCP_DISPOSE;
PutMsg(tcp, &ftp_site->control->header);
} else dp->dp_Res2 = ERROR_NO_FREE_STORE;
deallocate(idle_packet, V_StandardPacket);
} else dp->dp_Res2 = ERROR_NO_FREE_STORE;
DeleteExtIO((struct IORequest *)timer);
} else dp->dp_Res2 = ERROR_NO_FREE_STORE;
DeletePort(timeport);
} else dp->dp_Res2 = ERROR_NO_FREE_STORE;
DeletePort(sync);
} else dp->dp_Res2 = ERROR_NO_FREE_STORE;
CloseLibrary((struct Library *)ftp_site->GBase);
} else dp->dp_Res2 = ERROR_INVALID_RESIDENT_LIBRARY;
CloseLibrary(ftp_site->GTBase);
} else dp->dp_Res2 = ERROR_INVALID_RESIDENT_LIBRARY;
CloseLibrary((struct Library *)ftp_site->IBase);
} else dp->dp_Res2 = ERROR_INVALID_RESIDENT_LIBRARY;
dp->dp_Res1 = DOSFALSE;
check_memory();
Forbid();
PutMsg(reply, dp->dp_Link);
return;
begin:
timer->tr_node.io_Command = TR_ADDREQUEST;
timer->tr_time.tv_secs = IDLE_INTERVAL;
timer->tr_time.tv_micro = 0;
SendIO((struct IORequest *)timer);
ensure(sm, V_status_message);
sm->header.mn_ReplyPort = sync;
sm->header.mn_Length = sizeof(*sm);
sm->header.mn_Node.ln_Type = NT_MESSAGE;
sm->header.mn_Node.ln_Pri = 0;
sm->header.mn_Node.ln_Name = "site status message";
sm->command = SM_NEW_SITE;
sm->data = ftp_site->open_status;
sm->this_site = ftp_site;
PutMsg(status_port, &sm->header);
WaitPort(sync); GetMsg(sync);
ftp_site->abort_signals = (1 << AllocSignal(-1));
ftp_site->disconnect_signals = (1 << AllocSignal(-1));
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
PutMsg(reply, dp->dp_Link); /* send it back to signal we are away */
signals = (1 << local->mp_SigBit) | (1 << timeport->mp_SigBit) | (ftp_site->disconnect_signals);
while (1) {
if (ftp_site->connected) {
if (!ftp_site->cfile) {
state_change(ftp_site, SS_IDLE);
}
} else {
state_change(ftp_site, SS_DISCONNECTED);
}
if (Wait(signals) & ftp_site->disconnect_signals) {
disconnect(ftp_site);
}
if (GetMsg(timeport)) {
timer->tr_node.io_Command = TR_ADDREQUEST;
timer->tr_time.tv_secs = IDLE_INTERVAL;
timer->tr_time.tv_micro = 0;
idlecount++;
SendIO((struct IORequest *)timer);
if (ftp_site->lock_list == nil && ftp_site->file_list == nil) {
if (ftp_site->connected) {
if (idlecount > NO_LOCK_CONN_IDLE) {
idle_packet->sp_Pkt.dp_Port = sync;
PutMsg(ftp_port, &idle_packet->sp_Msg);
WaitPort(sync); GetMsg(sync);
}
} else if (!ftp_site->connected) {
if (idlecount > NO_LOCK_NO_CONN_IDLE) {
idle_packet->sp_Pkt.dp_Port = sync;
PutMsg(ftp_port, &idle_packet->sp_Msg);
WaitPort(sync); GetMsg(sync);
}
}
}
}
while (msg = GetMsg(local)) {
idlecount = 0;
dp = (struct DosPacket *)msg->mn_Node.ln_Name;
reply = dp->dp_Port;
switch (dp->dp_Type) {
case action_IDLE_DEATH:
if (ftp_site->file_list && ftp_site->file_list->closed) {
close_file(ftp_site, true);
}
if (ftp_site->lock_list || ftp_site->file_list) {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = 0;
break;
}
/* fall through to DIE */
case ACTION_DIE:
state_change(ftp_site, SS_DISCONNECTING);
slock = ftp_site->lock_list;
while (slock) {
new_lock = slock->next;
disown(slock, V_lock);
slock = new_lock;
}
deallocate(idle_packet, V_StandardPacket);
AbortIO((struct IORequest *)timer);
WaitPort(timeport); GetMsg(timeport);
CloseDevice((struct IORequest *)timer);
if (ftp_site->connected) {
ftp_site->control->command = TCP_CLOSE;
PutMsg(tcp, &ftp_site->control->header);
WaitPort(sync); GetMsg(sync);
ftp_site->connected = false;
}
ftp_site->control->command = TCP_DISPOSE;
PutMsg(tcp, &ftp_site->control->header);
ftp_site->intr->command = TCP_DISPOSE;
PutMsg(tcp, &ftp_site->intr->header);
sm->command = SM_DEAD_SITE;
PutMsg(status_port, &sm->header);
WaitPort(sync); GetMsg(sync);
while (tsm = (status_message *)GetMsg(rank)) {
verify(tsm, V_status_message);
deallocate(tsm, V_status_message);
}
DeletePort(rank);
deallocate(sm, V_status_message);
DeleteExtIO((struct IORequest *)timer);
DeletePort(timeport);
DeletePort(sync);
CloseLibrary((struct Library *)ftp_site->GBase);
CloseLibrary(ftp_site->GTBase);
CloseLibrary((struct Library *)ftp_site->IBase);
while (ftp_site->infos) free_info_header(ftp_site->infos);
if (ftp_site->cwd) deallocate(ftp_site->cwd, V_cstr);
if (ftp_site->root) {
/* this one might have been allocated from main task ... but */
deallocate(ftp_site->root, V_cstr);
ftp_site->root = nil;
}
/* again, these may have been allocated in either the main task or
the site task ... too complicated to work it out ... this works for now */
if (ftp_site->user) deallocate(ftp_site->user, V_cstr);
if (ftp_site->password) deallocate(ftp_site->password, V_cstr);
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = (b32)(ftp_site->lock_list); /* so they can adopt the locks */
check_memory();
Forbid();
PutMsg(reply, dp->dp_Link);
return;
case ACTION_LOCATE_OBJECT:
if (!split_data((lock *)(dp->dp_Arg1 << 2), (b8 *)(dp->dp_Arg2 << 2), &sd)) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
if (!ftp_site->connected) {
init_connect(ftp_site);
if (!ftp_site->connected) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
end_split(&sd);
break;
}
}
if (!sd.path || sd.path[0] == 0) {
/* the root ... this is ok */
if (dp->dp_Arg3 == EXCLUSIVE_LOCK) {
dp->dp_Res1 = 0;
/* can't exclusive lock root */
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
break;
}
new_lock = (lock *)allocate(sizeof(*new_lock) + 1, V_lock);
if (!new_lock) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
ensure(new_lock, V_lock);
new_lock->next = ftp_site->lock_list;
ftp_site->lock_list = new_lock;
new_lock->port = local;
new_lock->rfsl = 0;
new_lock->lastkey = 0;
new_lock->fname[0] = 0;
new_lock->fl.fl_Link = 0;
new_lock->fl.fl_Key = 0;
new_lock->fl.fl_Access = SHARED_LOCK;
new_lock->fl.fl_Task = ftp_port;
new_lock->fl.fl_Volume = (b32)ftp_volume >> 2;
dp->dp_Res1 = (b32)new_lock >> 2;
dp->dp_Res2 = 0;
} else {
new_lock = (lock *)allocate(sizeof(*new_lock) + strlen(sd.path) + 1, V_lock);
if (!new_lock) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
ensure(new_lock, V_lock);
strcpy(new_lock->fname, sd.path);
new_lock->port = local;
new_lock->rfsl = 0;
new_lock->lastkey = 0;
new_lock->fl.fl_Link = 0;
new_lock->fl.fl_Key = 0;
new_lock->fl.fl_Access = SHARED_LOCK;
new_lock->fl.fl_Task = ftp_port;
new_lock->fl.fl_Volume = (b32)ftp_volume >> 2;
/* search for a conflicting lock */
slock = ftp_site->lock_list;
while (slock) {
if (strcmp(sd.path, slock->fname) == 0) {
if (dp->dp_Arg3 == EXCLUSIVE_LOCK || slock->fl.fl_Access == EXCLUSIVE_LOCK) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
deallocate(new_lock, V_lock);
end_split(&sd);
goto reply_msg;
}
/* ok, this one is guaranteed to work */
new_lock->next = ftp_site->lock_list;
ftp_site->lock_list = new_lock;
dp->dp_Res1 = (b32)new_lock >> 2;
dp->dp_Res2 = 0;
end_split(&sd);
goto reply_msg;
}
slock = slock->next;
}
/* ok, it doesn't conflict ... check if it actually exists */
fi = get_info(ftp_site, sd.path);
if (!fi) {
deallocate(new_lock, V_lock);
end_split(&sd);
dp->dp_Res1 = 0;
if (ftp_site->cfile)
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
else
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
goto reply_msg;
}
/* well, we found it! */
new_lock->next = ftp_site->lock_list;
ftp_site->lock_list = new_lock;
dp->dp_Res1 = (b32)new_lock >> 2;
dp->dp_Res2 = 0;
}
end_split(&sd);
break;
case ACTION_FREE_LOCK:
slock = (lock *)(dp->dp_Arg1 << 2);
if (!slock) {
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
break;
}
verify(slock, V_lock);
locks = &ftp_site->lock_list;
while (*locks && *locks != slock) {
locks = &(*locks)->next;
}
if (!*locks) {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_INVALID_LOCK;
} else {
*locks = slock->next;
deallocate(slock, V_lock);
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
}
break;
case ACTION_DELETE_OBJECT:
if (!split_data((lock *)(dp->dp_Arg1 << 2), (b8 *)(dp->dp_Arg2 << 2), &sd)) {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
if (ftp_site->file_list) {
if (ftp_site->file_list->closed) {
close_file(ftp_site, true);
} else {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
end_split(&sd);
goto reply_msg;
}
}
/* search for a conflicting lock */
slock = ftp_site->lock_list;
while (slock) {
if (strcmp(sd.path, slock->fname) == 0) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
end_split(&sd);
goto reply_msg;
}
slock = slock->next;
}
fi = get_info(ftp_site, sd.path);
if (fi && fi->flags & MYFLAG_DIR) {
dp->dp_Res2 = delete_directory(ftp_site, sd.path);
} else {
dp->dp_Res2 = delete_file(ftp_site, sd.path);
}
if (dp->dp_Res2) {
dp->dp_Res1 = DOSFALSE;
} else {
if (fi) fi->flags |= MYFLAG_DELETED;
dp->dp_Res1 = DOSTRUE;
}
end_split(&sd);
break;
case ACTION_RENAME_OBJECT:
if (!split_data((lock *)(dp->dp_Arg1 << 2), (b8 *)(dp->dp_Arg2 << 2), &sd)) {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
if (!split_data((lock *)(dp->dp_Arg3 << 2), (b8 *)(dp->dp_Arg4 << 2), &sd2)) {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
end_split(&sd);
break;
}
fi = get_info(ftp_site, sd.path);
dp->dp_Res2 = rename_object(ftp_site, sd.path, sd2.path);
if (dp->dp_Res2) {
dp->dp_Res1 = DOSFALSE;
} else {
if (fi) fi->flags |= MYFLAG_DELETED;
flush_info(ftp_site, sd2.path);
dp->dp_Res1 = DOSTRUE;
}
end_split(&sd);
end_split(&sd2);
break;
case ACTION_COPY_DIR:
slock = (lock *)(dp->dp_Arg1 << 2);
if (!slock) {
dp->dp_Res1 = 0;
dp->dp_Res2 = 0;
break;
}
verify(slock, V_lock);
if (slock->fl.fl_Access == EXCLUSIVE_LOCK) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
break;
}
new_lock = (lock *)allocate(sizeof(*new_lock) + strlen(slock->fname) + 1, V_lock);
if (!new_lock) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
*new_lock = *slock;
strcpy(new_lock->fname, slock->fname);
new_lock->next = slock->next;
slock->next = new_lock;
dp->dp_Res1 = (b32)new_lock >> 2;
dp->dp_Res2 = 0;
break;
case ACTION_CREATE_DIR:
if (!split_data((lock *)(dp->dp_Arg1 << 2), (b8 *)(dp->dp_Arg2 << 2), &sd)) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
if (ftp_site->file_list) {
if (ftp_site->file_list->closed) {
close_file(ftp_site, true);
} else {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
end_split(&sd);
goto reply_msg;
}
}
new_lock = (lock *)allocate(sizeof(*new_lock) + strlen(sd.path) + 1, V_lock);
if (!new_lock) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
end_split(&sd);
break;
}
dp->dp_Res2 = make_directory(ftp_site, sd.path);
flush_info(ftp_site, sd.path);
if (dp->dp_Res2) {
dp->dp_Res1 = 0;
deallocate(new_lock, V_lock);
} else {
dp->dp_Res1 = (b32)new_lock >> 2;
ensure(new_lock, V_lock);
new_lock->next = ftp_site->lock_list;
ftp_site->lock_list = new_lock;
strcpy(new_lock->fname, sd.path);
new_lock->port = local;
new_lock->rfsl = 0;
new_lock->lastkey = 0;
new_lock->fl.fl_Link = 0;
new_lock->fl.fl_Key = 0;
new_lock->fl.fl_Access = SHARED_LOCK;
new_lock->fl.fl_Task = ftp_port;
new_lock->fl.fl_Volume = (b32)ftp_volume >> 2;
}
end_split(&sd);
break;
case ACTION_EXAMINE_OBJECT:
slock = (lock *)(dp->dp_Arg1 << 2);
fib = (struct FileInfoBlock *)(dp->dp_Arg2 << 2);
verify(slock, V_lock);
truth(fib != nil);
if (slock->fname[0] == 0) {
/* root of this site */
fib->fib_DiskKey = 0;
fib->fib_DirEntryType = ST_USERDIR;
fib->fib_EntryType = ST_USERDIR;
strcpy(&fib->fib_FileName[1], ftp_site->name);
fib->fib_FileName[0] = strlen(ftp_site->name);
fib->fib_Protection = 0xf;
fib->fib_Size = 0;
fib->fib_NumBlocks = 0;
fib->fib_Date = ftp_volume->dol_misc.dol_volume.dol_VolumeDate;
fib->fib_Comment[0] = 0;
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
break;
}
s = slock->fname + strlen(slock->fname) - 1;
while (s > slock->fname && *s != '/') s--;
if (s == slock->fname) {
ih = get_dir(ftp_site, "");
} else {
*s = 0;
ih = get_dir(ftp_site, slock->fname);
*s++ = '/';
}
if (!ih) {
dp->dp_Res1 = DOSFALSE;
if (ftp_site->cfile)
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
else
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
/* general "connection buggered" */
break;
}
fi = find_info(ih, s);
if (!fi) {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
break;
}
if (fi->flags & MYFLAG_DIR) {
fib->fib_DirEntryType = ST_USERDIR;
} else {
fib->fib_DirEntryType = ST_FILE;
}
fib->fib_EntryType = fib->fib_DirEntryType;
fib->fib_DiskKey = 0;
slock->lastkey = 0;
fib->fib_FileName[0] = strlen(fi->name);
strcpy(&fib->fib_FileName[1], fi->name);
fib->fib_Protection = fi->flags & 0xff;
fib->fib_Size = fi->size;
fib->fib_NumBlocks = fi->blocks;
fib->fib_Date = fi->modified;
fib->fib_Comment[0] = 0;
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
break;
case ACTION_EXAMINE_NEXT:
slock = (lock *)(dp->dp_Arg1 << 2);
fib = (struct FileInfoBlock *)(dp->dp_Arg2 << 2);
verify(slock, V_lock);
truth(fib != nil);
ih = get_dir(ftp_site, slock->fname);
if (!ih) {
dp->dp_Res1 = DOSFALSE;
if (ftp_site->cfile)
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
else
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
break;
}
// n = fib->fib_DiskKey;
n = slock->lastkey;
slock->lastkey++;
fi = ih->infos;
while (fi && n) {
fi = fi->next;
n--;
}
while (fi && fi->flags & MYFLAG_DELETED) {
fi = fi->next;
slock->lastkey++;
}
fib->fib_DiskKey = slock->lastkey;
if (!fi) {
slock->lastkey = 0;
fib->fib_DiskKey = 0;
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_NO_MORE_ENTRIES;
break;
}
if (fi->flags & MYFLAG_DIR) {
fib->fib_DirEntryType = ST_USERDIR;
} else {
fib->fib_DirEntryType = ST_FILE;
}
fib->fib_EntryType = fib->fib_DirEntryType;
fib->fib_FileName[0] = strlen(fi->name);
strcpy(&fib->fib_FileName[1], fi->name);
fib->fib_Protection = fi->flags & 0xff;
fib->fib_Size = fi->size;
fib->fib_NumBlocks = fi->blocks;
fib->fib_Date = fi->modified;
fib->fib_Comment[0] = 0;
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
break;
case ACTION_PARENT:
slock = (lock *)(dp->dp_Arg1 << 2);
if (!slock) {
dp->dp_Res1 = 0;
dp->dp_Res2 = 0;
break;
}
if (slock->fname[0] == 0) {
/* need root of FTP: (the slimy way) */
dp->dp_Port = ftp_site->sync;
dp->dp_Type = ACTION_LOCATE_OBJECT;
o1 = dp->dp_Arg1;
o2 = dp->dp_Arg2;
o3 = dp->dp_Arg3;
dp->dp_Arg1 = 0;
dp->dp_Arg2 = (b32)(&("\0\0\0\0"[3])) >> 2;
dp->dp_Arg3 = SHARED_LOCK;
PutMsg(local_port, dp->dp_Link);
WaitPort(ftp_site->sync); GetMsg(ftp_site->sync);
dp->dp_Arg1 = o1;
dp->dp_Arg2 = o2;
dp->dp_Arg3 = o3;
dp->dp_Type = ACTION_PARENT;
break;
}
s = slock->fname + strlen(slock->fname) - 1;
while (s > slock->fname && *s != '/') s--;
if (s == slock->fname) {
new_lock = (lock *)allocate(sizeof(*new_lock) + 1, V_lock);
if (!new_lock) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
ensure(new_lock, V_lock);
new_lock->next = ftp_site->lock_list;
ftp_site->lock_list = new_lock;
new_lock->port = local;
new_lock->rfsl = 0;
new_lock->fname[0] = 0;
new_lock->fl.fl_Link = 0;
new_lock->fl.fl_Key = 0;
new_lock->fl.fl_Access = SHARED_LOCK;
new_lock->fl.fl_Task = ftp_port;
new_lock->fl.fl_Volume = (b32)ftp_volume >> 2;
dp->dp_Res1 = (b32)new_lock >> 2;
dp->dp_Res2 = 0;
} else {
*s = 0;
new_lock = (lock *)allocate(sizeof(*new_lock) + strlen(slock->fname) + 1, V_lock);
if (!new_lock) {
*s = '/';
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
ensure(new_lock, V_lock);
strcpy(new_lock->fname, slock->fname);
*s = '/';
new_lock->port = local;
new_lock->rfsl = 0;
new_lock->fl.fl_Link = 0;
new_lock->fl.fl_Key = 0;
new_lock->fl.fl_Access = SHARED_LOCK;
new_lock->fl.fl_Task = ftp_port;
new_lock->fl.fl_Volume = (b32)ftp_volume >> 2;
/* search for a conflicting lock */
slock = ftp_site->lock_list;
while (slock) {
if (strcmp(new_lock->fname, slock->fname) == 0) {
if (slock->fl.fl_Access == EXCLUSIVE_LOCK) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
deallocate(new_lock, V_lock);
goto reply_msg;
}
/* ok, this one is guaranteed to work */
new_lock->next = ftp_site->lock_list;
ftp_site->lock_list = new_lock;
dp->dp_Res1 = (b32)new_lock >> 2;
dp->dp_Res2 = 0;
goto reply_msg;
}
slock = slock->next;
}
/* ok, it doesn't conflict ... it must exist*/
new_lock->next = ftp_site->lock_list;
ftp_site->lock_list = new_lock;
dp->dp_Res1 = (b32)new_lock >> 2;
dp->dp_Res2 = 0;
}
break;
case ACTION_SAME_LOCK:
slock = (lock *)(dp->dp_Arg1 << 2);
new_lock = (lock *)(dp->dp_Arg2 << 2);
verify(slock, V_lock);
verify(new_lock, V_lock);
if (strcmp(slock->fname, new_lock->fname) == 0) {
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
} else {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = 0;
}
break;
case ACTION_READ:
fip = (file_info *)dp->dp_Arg1;
verify(fip, V_file_info);
if (!ftp_site->connected || ftp_site->cfile == nil) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
break;
}
if (ftp_site->cfile_type != ACTION_FINDINPUT) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_READ_PROTECTED;
break;
}
if (fip->seek_end) { /* artificially at end */
dp->dp_Res1 = 0;
dp->dp_Res2 = 0;
break;
}
state_change(ftp_site, SS_READING);
o1 = dp->dp_Arg3;
s = (b8 *)dp->dp_Arg2;
if (o1 == 0) {
dp->dp_Res1 = 0;
dp->dp_Res2 = 0;
break;
}
if (fip->vpos < FIRST_BLOCK_SIZE && fip->vpos < fip->rpos) {
o2 = o1;
if (o2 > FIRST_BLOCK_SIZE - fip->vpos) o2 = FIRST_BLOCK_SIZE - fip->vpos;
if (o2 > fip->rpos - fip->vpos) o2 = fip->rpos - fip->vpos;
memcpy(s, &fip->first_block[fip->vpos], o2);
fip->vpos += o2;
if (o2 == o1) {
dp->dp_Res1 = o1;
dp->dp_Res2 = 0;
break;
} else {
s += o2;
o1 -= o2;
}
}
if (fip->vpos != fip->rpos) {
dp->dp_Res1 = -1;
dp->dp_Res2 = ERROR_SEEK_ERROR;
break;
}
while (o1) {
if (o1 > MAX_READ_SIZE) {
o2 = MAX_READ_SIZE;
o1 -= o2;
} else {
o2 = o1;
o1 = 0;
}
switch (read_file(ftp_site, s, &o2)) {
case NO_ERROR:
s += o2;
break;
case ERROR_EOF:
s += o2;
dp->dp_Res1 = s - (b8 *)dp->dp_Arg2;
dp->dp_Res2 = 0;
o1 = 0;
fip->eof = true;
break;
default:
dp->dp_Res1 = -1;
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
o1 = 0;
break;
}
fip->rpos += o2;
fip->vpos = fip->rpos;
tsm = get_sm(ftp_site);
if (tsm) {
tsm->command = SM_PROGRESS;
PutMsg(status_port, &tsm->header);
}
}
dp->dp_Res1 = s - (b8 *)dp->dp_Arg2;
dp->dp_Res2 = 0;
break;
case ACTION_WRITE:
fip = (file_info *)dp->dp_Arg1;
verify(fip, V_file_info);
if (!ftp_site->connected || ftp_site->cfile == nil) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
break;
}
if (ftp_site->cfile_type != ACTION_FINDOUTPUT) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_WRITE_PROTECTED;
break;
}
state_change(ftp_site, SS_WRITING);
o1 = dp->dp_Arg3;
s = (b8 *)dp->dp_Arg2;
if (o1 == 0) {
dp->dp_Res1 = 0;
dp->dp_Res2 = 0;
break;
}
if (fip->vpos != fip->rpos) {
dp->dp_Res1 = -1;
dp->dp_Res2 = ERROR_SEEK_ERROR;
break;
}
while (o1) {
if (o1 > MAX_READ_SIZE) {
o2 = MAX_READ_SIZE;
o1 -= o2;
} else {
o2 = o1;
o1 = 0;
}
switch (write_file(ftp_site, s, &o2)) {
case NO_ERROR:
s += o2;
break;
case ERROR_EOF:
s += o2;
dp->dp_Res1 = s - (b8 *)dp->dp_Arg2;
dp->dp_Res2 = 0;
o1 = 0;
fip->eof = true;
break;
default:
dp->dp_Res1 = -1;
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
o1 = 0;
break;
}
fip->rpos += o2;
fip->vpos = fip->rpos;
tsm = get_sm(ftp_site);
if (tsm) {
tsm->command = SM_PROGRESS;
PutMsg(status_port, &tsm->header);
}
}
dp->dp_Res1 = s - (b8 *)dp->dp_Arg2;
dp->dp_Res2 = 0;
break;
case ACTION_FINDINPUT:
case ACTION_FINDOUTPUT:
if (!split_data((lock *)(dp->dp_Arg2 << 2),
(b8 *)(dp->dp_Arg3 << 2), &sd)) {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
if (!ftp_site->connected)
init_connect(ftp_site);
if (!ftp_site->connected) {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
end_split(&sd);
break;
}
if (ftp_site->cfile) {
fip = ftp_site->file_list;
verify(fip, V_file_info);
if (fip->closed) {
if (strcmp(sd.path, fip->fname) == 0 &&
dp->dp_Type == ACTION_FINDINPUT) {
/* "reopen" this file */
fh = (struct FileHandle *)(dp->dp_Arg1 << 2);
truth(fh != nil);
fh->fh_Type = ftp_port;
fh->fh_Args = (b32)fip;
fip->closed = false;
fip->vpos = 0;
fip->seek_end = false;
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
end_split(&sd);
break;
}
close_file(ftp_site, true);
} else {
/* only one file at a time! :( */
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
end_split(&sd);
break;
}
}
/* search for a conflicting lock */
slock = ftp_site->lock_list;
while (slock) {
if (strcmp(sd.path, slock->fname) == 0) {
if (dp->dp_Type == ACTION_FINDOUTPUT || slock->fl.fl_Access == EXCLUSIVE_LOCK) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
end_split(&sd);
goto reply_msg;
}
}
slock = slock->next;
}
/* make sure we have information on this file BEFORE we start */
if (dp->dp_Type == ACTION_FINDINPUT) {
fi = get_info(ftp_site, sd.path);
// if (!fi) {
// dp->dp_Res1 = 0;
// dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
//
// end_split(&sd);
//
// break;
// }
} else {
fi = nil;
}
if (dp->dp_Type == ACTION_FINDINPUT) {
if (fi) {
dp->dp_Res2 = open_file(ftp_site, sd.path, false, fi->name);
} else {
dp->dp_Res2 = open_file(ftp_site, sd.path, false, nil);
}
} else {
dp->dp_Res2 = open_file(ftp_site, sd.path, true, nil);
flush_info(ftp_site, sd.path);
}
if (dp->dp_Res2 != 0) {
end_split(&sd);
dp->dp_Res1 = 0;
break;
}
fip = ftp_site->file_list;
if (fi) {
fip->end = fi->size;
} else {
fip->end = 0;
}
fip->port = local;
fip->type = ftp_site->cfile_type = dp->dp_Type;
end_split(&sd);
fh = (struct FileHandle *)(dp->dp_Arg1 << 2);
truth(fh != nil);
fh->fh_Type = ftp_port;
fh->fh_Args = (b32)fip;
if (dp->dp_Type == ACTION_FINDINPUT) {
o1 = FIRST_BLOCK_SIZE;
switch (read_file(ftp_site, fip->first_block, &o1)) {
case ERROR_EOF:
fip->eof = true;
case NO_ERROR:
fip->rpos = o1;
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
break;
default:
close_file(ftp_site, true);
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
break;
}
} else {
dp->dp_Res1= DOSTRUE;
dp->dp_Res2 = 0;
}
break;
case ACTION_END:
fip = (file_info *)dp->dp_Arg1;
verify(fip, V_file_info);
if (fip->type == ACTION_FINDINPUT && fip->rpos <= FIRST_BLOCK_SIZE) {
fip->closed = true;
} else {
close_file(ftp_site, true);
}
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
break;
case ACTION_SEEK:
fip = (file_info *)dp->dp_Arg1;
verify(fip, V_file_info);
if (dp->dp_Arg3 == OFFSET_END && dp->dp_Arg2 == 0) {
/* go to the end of the file ... really we are :) */
if (fip->seek_end) {
dp->dp_Res1 = fip->end;
dp->dp_Res2 = 0;
break;
}
if (fip->type == ACTION_FINDINPUT)
fip->seek_end = true;
dp->dp_Res1 = fip->vpos;
dp->dp_Res2 = 0;
break;
}
if (dp->dp_Arg3 == OFFSET_BEGINNING) {
o1 = dp->dp_Arg2;
} else if (dp->dp_Arg3 == OFFSET_END) {
o1 = fip->end + dp->dp_Arg2;
} else if (dp->dp_Arg3 == OFFSET_CURRENT) {
o1 = fip->vpos + dp->dp_Arg2;
}
if (o1 == fip->vpos) {
/* not actually moving */
if (fip->seek_end) {
dp->dp_Res1 = fip->end;
dp->dp_Res2 = 0;
fip->seek_end = false;
} else {
dp->dp_Res1 = fip->vpos;
dp->dp_Res2 = 0;
}
break;
}
if (o1 == fip->rpos) {
/* not _really_ moving */
if (fip->seek_end) {
dp->dp_Res1 = fip->end;
dp->dp_Res2 = 0;
fip->seek_end = false;
} else {
dp->dp_Res1 = fip->vpos;
dp->dp_Res2 = 0;
}
fip->vpos = fip->rpos;
break;
}
if (o1 < fip->rpos && o1 < FIRST_BLOCK_SIZE) {
/* seeking into our stored first block */
if (fip->seek_end) {
dp->dp_Res1 = fip->end;
dp->dp_Res2 = 0;
fip->seek_end = false;
} else {
dp->dp_Res1 = fip->vpos;
dp->dp_Res2 = 0;
}
fip->vpos = o1;
break;
}
show_string("SEEK:");
show_int(dp->dp_Arg2);
show_int(dp->dp_Arg3);
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
break;
case ACTION_FH_FROM_LOCK:
fh = (struct FileHandle *)(dp->dp_Arg1 << 2);
slock = (lock *)(dp->dp_Arg2 << 2);
truth(fh != nil);
verify(slock, V_lock);
if (!ftp_site->connected)
init_connect(ftp_site);
if (!ftp_site->connected) {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
break;
}
if (ftp_site->cfile) {
fip = ftp_site->file_list;
verify(fip, V_file_info);
if (fip->closed) {
if (strcmp(slock->fname, fip->fname) == 0 &&
slock->fl.fl_Access == SHARED_LOCK) {
/* "reopen" this file */
fh->fh_Type = ftp_port;
fh->fh_Args = (b32)fip;
fip->closed = false;
fip->vpos = 0;
fip->seek_end = false;
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
break;
}
close_file(ftp_site, true);
} else {
/* only one file at a time! :( */
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
break;
}
}
if (slock->fl.fl_Access == SHARED_LOCK) {
fi = get_info(ftp_site, slock->fname);
} else {
fi = nil;
}
if (slock->fl.fl_Access == SHARED_LOCK) {
if (fi) {
dp->dp_Res2 = open_file(ftp_site, slock->fname, false, fi->name);
} else {
dp->dp_Res2 = open_file(ftp_site, slock->fname, false, nil);
}
} else {
dp->dp_Res2 = open_file(ftp_site, slock->fname, true, nil);
flush_info(ftp_site, slock->fname);
}
if (dp->dp_Res2 != 0) {
dp->dp_Res1 = 0;
break;
}
fip = ftp_site->file_list;
if (fi) {
fip->end = fi->size;
} else {
fip->end = 0;
}
fip->port = local;
if (slock->fl.fl_Access == SHARED_LOCK) {
fip->type = ftp_site->cfile_type = ACTION_FINDINPUT;
} else {
fip->type = ftp_site->cfile_type = ACTION_FINDOUTPUT;
}
fh->fh_Type = ftp_port;
fh->fh_Args = (b32)fip;
if (slock->fl.fl_Access == SHARED_LOCK) {
o1 = FIRST_BLOCK_SIZE;
switch (read_file(ftp_site, fip->first_block, &o1)) {
case ERROR_EOF:
fip->eof = true;
case NO_ERROR:
fip->rpos = o1;
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
break;
default:
close_file(ftp_site, true);
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
break;
}
} else {
dp->dp_Res1= DOSTRUE;
dp->dp_Res2 = 0;
}
if (dp->dp_Res1) {
/* close the lock */
ensure(slock, 0);
locks = &ftp_site->lock_list;
while (*locks && *locks != slock) {
locks = &(*locks)->next;
}
if (*locks) {
*locks = slock->next;
deallocate(slock, V_lock);
}
}
break;
case ACTION_COPY_DIR_FH:
fh = (struct FileHandle *)(dp->dp_Arg1 << 2);
if (!fh) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
break;
}
fip = (file_info *)fh->fh_Args;
verify(fip, V_file_info);
if (fip->type == ACTION_FINDOUTPUT) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
break;
}
new_lock = (lock *)allocate(sizeof(*new_lock) + strlen(fip->fname) + 1, V_lock);
if (!new_lock) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
new_lock->port = local;
new_lock->rfsl = 0;
new_lock->lastkey = 0;
new_lock->fl.fl_Link = 0;
new_lock->fl.fl_Key = 0;
new_lock->fl.fl_Access = SHARED_LOCK;
new_lock->fl.fl_Task = ftp_port;
new_lock->fl.fl_Volume = (b32)ftp_volume >> 2;
strcpy(new_lock->fname, fip->fname);
new_lock->next = ftp_site->lock_list;
ftp_site->lock_list = new_lock;
dp->dp_Res1 = (b32)new_lock >> 2;
dp->dp_Res2 = 0;
break;
case ACTION_PARENT_FH:
fh = (struct FileHandle *)(dp->dp_Arg1 << 2);
if (!fh) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
break;
}
fip = (file_info *)fh->fh_Args;
verify(fip, V_file_info);
s = fip->fname + strlen(fip->fname) - 1;
while (s > fip->fname && *s != '/') s--;
if (s == fip->fname) {
new_lock = (lock *)allocate(sizeof(*new_lock) + 1, V_lock);
if (!new_lock) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
ensure(new_lock, V_lock);
new_lock->next = ftp_site->lock_list;
ftp_site->lock_list = new_lock;
new_lock->port = local;
new_lock->rfsl = 0;
new_lock->fname[0] = 0;
new_lock->fl.fl_Link = 0;
new_lock->fl.fl_Key = 0;
new_lock->fl.fl_Access = SHARED_LOCK;
new_lock->fl.fl_Task = ftp_port;
new_lock->fl.fl_Volume = (b32)ftp_volume >> 2;
dp->dp_Res1 = (b32)new_lock >> 2;
dp->dp_Res2 = 0;
} else {
*s = 0;
new_lock = (lock *)allocate(sizeof(*new_lock) + strlen(fip->fname) + 1, V_lock);
if (!new_lock) {
*s = '/';
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_NO_FREE_STORE;
break;
}
ensure(new_lock, V_lock);
strcpy(new_lock->fname, fip->fname);
*s = '/';
new_lock->port = local;
new_lock->rfsl = 0;
new_lock->fl.fl_Link = 0;
new_lock->fl.fl_Key = 0;
new_lock->fl.fl_Access = SHARED_LOCK;
new_lock->fl.fl_Task = ftp_port;
new_lock->fl.fl_Volume = (b32)ftp_volume >> 2;
/* search for a conflicting lock */
slock = ftp_site->lock_list;
while (slock) {
if (strcmp(new_lock->fname, slock->fname) == 0) {
if (slock->fl.fl_Access == EXCLUSIVE_LOCK) {
dp->dp_Res1 = 0;
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
deallocate(new_lock, V_lock);
goto reply_msg;
}
/* ok, this one is guaranteed to work */
new_lock->next = ftp_site->lock_list;
ftp_site->lock_list = new_lock;
dp->dp_Res1 = (b32)new_lock >> 2;
dp->dp_Res2 = 0;
goto reply_msg;
}
slock = slock->next;
}
/* ok, it doesn't conflict ... it must exist*/
new_lock->next = ftp_site->lock_list;
ftp_site->lock_list = new_lock;
dp->dp_Res1 = (b32)new_lock >> 2;
dp->dp_Res2 = 0;
}
break;
case ACTION_EXAMINE_FH:
fh = (struct FileHandle *)(dp->dp_Arg1 << 2);
fip = (file_info *)fh->fh_Args;
verify(fip, V_file_info);
fib = (struct FileInfoBlock *)(dp->dp_Arg2 << 2);
truth(fib != nil);
s = fip->fname + strlen(fip->fname) - 1;
while (s > fip->fname && *s != '/') s--;
if (s == fip->fname) {
ih = get_dir(ftp_site, "");
} else {
*s = 0;
ih = get_dir(ftp_site, fip->fname);
*s++ = '/';
}
if (!ih) {
dp->dp_Res1 = DOSFALSE;
if (ftp_site->cfile)
dp->dp_Res2 = ERROR_OBJECT_IN_USE;
else
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
/* general "connection buggered" */
break;
}
fi = find_info(ih, s);
if (!fi) {
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
break;
}
if (fi->flags & MYFLAG_DIR) {
fib->fib_DirEntryType = ST_USERDIR;
} else {
fib->fib_DirEntryType = ST_FILE;
}
fib->fib_EntryType = fib->fib_DirEntryType;
fib->fib_DiskKey = 0;
fib->fib_FileName[0] = strlen(fi->name);
strcpy(&fib->fib_FileName[1], fi->name);
fib->fib_Protection = fi->flags & 0xff;
fib->fib_Size = fi->size;
fib->fib_NumBlocks = fi->blocks;
fib->fib_Date = fi->modified;
fib->fib_Comment[0] = 0;
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
break;
case action_SUSPEND:
if (ftp_site->connected) {
disconnect(ftp_site);
}
dp->dp_Res1 = DOSTRUE;
dp->dp_Res2 = 0;
dp->dp_Port = ftp_port;
PutMsg(reply, dp->dp_Link);
idle_packet->sp_Pkt.dp_Port = sync;
PutMsg(ftp_port, &idle_packet->sp_Msg);
WaitPort(sync); GetMsg(sync);
continue;
default:
show_int(dp->dp_Type);
dp->dp_Res1 = DOSFALSE;
dp->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
break;
}
reply_msg:
dp->dp_Port = ftp_port;
PutMsg(reply, dp->dp_Link);
}
}
}