home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
bin
/
p205.zip
/
exesrc
/
callback.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-18
|
26KB
|
1,003 lines
/*****************************************************************************/
/* Copyright (c) 1994 by Jyrki Salmi <jytasa@jyu.fi> */
/* You may modify, recompile and distribute this file freely. */
/*****************************************************************************/
/*
Callback functions called by P.DLL
*/
#include <stdio.h>
#define INCL_DOSPROCESS
#include <os2.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <sys\utime.h>
#include <share.h>
#include <time.h>
#include <ctype.h>
#include <errno.h>
#include "typedefs.h"
#include "p.h"
#include "callback.h"
#include "common.h"
#include "brw.h"
#include "error.h"
#include "global.h"
#include "modules.h"
U8 *z_header[] = {
"TIMEOUT",
"ZRQINIT",
"ZRINIT",
"ZSINIT",
"ZACK",
"ZFILE",
"ZSKIP",
"ZNAK",
"ZABORT",
"ZFIN",
"ZRPOS",
"ZDATA",
"ZEOF",
"ZFERR",
"ZCRC",
"ZCHALLENGE",
"ZCOMPL",
"ZCAN",
"ZFREECNT",
"ZCOMMAND",
"ZSTDERR"
};
U8 *z_frame_end[] = {
"TIMEOUT",
"ZCRCE",
"ZCRCG",
"ZCRCQ",
"ZCRCW",
"ZERROR",
"ZCAN"
};
/* Makes an array of va_list */
void make_arg_list(U32 *arg_list, va_list arg_ptr, U32 cnt) {
U32 idx;
for (idx = 0; idx < cnt; idx++)
arg_list[idx] = va_arg(arg_ptr, int);
}
BOOLEAN _System status_func(U32 type, ...) {
static U32 checking_method = 0;
static U32 receiver_flags = 0;
static S32 receiver_window_size = -1;
va_list arg_ptr;
U32 arg_list[10]; /* No more than 10 parameters for status */
/* message possible */
/* Make an array from arg_ptr */
va_start(arg_ptr, type);
make_arg_list(arg_list, arg_ptr, 10);
va_end(arg_ptr);
switch (type) {
case PS_ERROR:
if (is_os2_error(arg_list[0])) {
os2_error(arg_list[0], /* Error num */
arg_list[1], /* Return code */
arg_list[2], /* Module */
arg_list[3], /* Line num */
(U8 *)arg_list[4]); /* Optional argument */
} else if (is_tcpip_error(arg_list[0])) {
tcpip_error(arg_list[0], /* Error num */
arg_list[1], /* Return code */
arg_list[2], /* Module */
arg_list[3], /* Line num */
(U8 *)arg_list[4]); /* Optional argument */
}
break;
case PS_CARRIER_LOST:
carrier_lost = 1;
msg(MSG_LF, "Carrier lost");
break;
case PS_TIMEOUT:
msg(MSG_LF, "Timeout (%lu secs)",
arg_list[0]);
break;
case PS_TRANSFER_DONE:
msg(MSG_LF, "Transfer done!");
break;
case PS_PROGRESS:
msg(MSG_CR, "%lu",
arg_list[0]);
break;
case PS_CANNOT_SEND_BLOCK:
msg(MSG_LF, "Can't send block");
break;
case PS_CHECKING_METHOD:
if (checking_method != arg_list[0]) { /* Has the checking method */
/* changed since last displayed? */
checking_method = arg_list[0];
switch (checking_method) {
case CHECKING_CHECKSUM:
msg(MSG_CR | MSG_LF, "Checksum checking will be used");
break;
case CHECKING_CRC16:
msg(MSG_CR | MSG_LF, "CRC-16 checking will be used");
break;
case CHECKING_CRC32:
default: /* To shut up the compiler */
msg(MSG_CR | MSG_LF, "CRC-32 checking will be used");
break;
}
}
break;
case PS_INVALID_FILE_INFO:
msg(MSG_LF, "Got invalid file info");
break;
case PS_NON_STD_FILE_INFO:
msg(MSG_LF, "Got non-standard file info");
break;
case PS_XY_FALLBACK_TO_CHECKSUM:
msg(MSG_LF, "Falling back to checksum checking...");
break;
case PS_CHECK_FAILED:
switch (arg_list[0]) {
case CHECKING_CHECKSUM:
msg(MSG_LF, "Checksum mismatch");
break;
case CHECKING_CRC16:
msg(MSG_LF, "CRC-16 mismatch");
break;
case CHECKING_CRC32:
msg(MSG_LF, "CRC-32 mismatch");
break;
}
break;
case PS_REMOTE_ABORTED:
msg(MSG_LF, "Remote aborted");
break;
case PS_G_ABORTED:
msg(MSG_LF, "Cancelling Ymodem-g transfer");
break;
case PS_XYG_NAK:
msg(MSG_LF, "Got NAK on byte %lu",
arg_list[0]);
break;
case PS_XYG_BLK_NUM_MISMATCH:
msg(MSG_LF, "Block numbers mismatch (%lu:%lu <> %lu:%lu)",
arg_list[0], arg_list[1],
arg_list[2], arg_list[3]);
break;
case PS_Z_HEADER:
if (opt_headers) {
msg(MSG_LF, "%s %lu",
z_header[arg_list[0]], arg_list[1]);
}
break;
case PS_Z_UNEXPECTED_HEADER:
msg(MSG_LF, "Unexpected %s %lu",
z_header[arg_list[0]], arg_list[1]);
break;
case PS_Z_FRAME_END:
if (opt_frameends)
msg(MSG_LF, "%s", z_frame_end[arg_list[0]]);
break;
case PS_Z_INVALID_FRAME_END:
msg(MSG_LF, "Invalid frame end: %s",
z_frame_end[arg_list[0]]);
break;
case PS_Z_PHONY_ZEOF:
msg(MSG_LF, "Got phony ZEOF");
break;
case PS_Z_RETRY_CNT_EXCEEDED:
msg(MSG_LF, "Retry count exceeded");
break;
case PS_Z_DATA_FROM_INVALID_POS:
msg(MSG_LF, "Got data from invalid position: %lu, expected from %lu",
arg_list[0], arg_list[1]);
break;
case PS_Z_COMMAND:
msg(MSG_LF, "Zcommand: \"%s\"", arg_list[0]);
break;
case PS_Z_CTRL_CHAR_IGNORED:
msg(MSG_LF, "Unexpected control character ignored: %lu",
arg_list[0]);
break;
case PS_Z_INVALID_ZDLE_SEQUENCE:
msg(MSG_LF, "Invalid ZDLE sequence received");
break;
case PS_Z_CHECK_FAILED_FOR_HEADER:
switch (arg_list[0]) {
case CHECKING_CHECKSUM:
/* This never happens... Checksum checking isn't used for headers! */
break;
case CHECKING_CRC16:
msg(MSG_LF, "CRC-16 mismatch for a header");
break;
case CHECKING_CRC32:
msg(MSG_LF, "CRC-32 mismatch for a header");
break;
}
break;
case PS_Z_INVALID_HEX_HEADER:
msg(MSG_LF, "Invalid zmodem hex header received");
break;
case PS_Z_SUBPACKET_TOO_LONG:
msg(MSG_LF, "Too long zmodem subpacket received (> %lu)",
arg_list[0]);
break;
case PS_Z_CRASH_RECOVERY:
msg(MSG_LF, "Crash recovery at %lu",
arg_list[0]);
break;
case PS_Z_RECEIVER_FLAGS:
if (receiver_flags != arg_list[0]) {
if (receiver_flags != 0) /* We have parsed zrinit */
/* at least once before */
msg(MSG_CR | MSG_LF, "Receiver has changed its parameters");
receiver_flags = arg_list[0];
if (receiver_flags & RZ_FLAG_CANFDX)
msg(MSG_CR | MSG_LF, "Receiver is capable of true full duplex");
if (receiver_flags & RZ_FLAG_CANOVIO)
msg(MSG_CR | MSG_LF, "Receiver can receive data during disk I/O");
if (receiver_flags & RZ_FLAG_CANBRK)
msg(MSG_CR | MSG_LF, "Receiver can send break signal");
if (receiver_flags & RZ_FLAG_CANCRY)
msg(MSG_CR | MSG_LF, "Receiver can decrypt");
if (receiver_flags & RZ_FLAG_CANLZW)
msg(MSG_CR | MSG_LF, "Receiver can uncompress");
if (receiver_flags & RZ_FLAG_CANFC32) {
msg(MSG_CR | MSG_LF, "Receiver can use 32-bit frame checking");
if (p_cfg.attr & CFG_ALTERNATIVE_CHECKING)
msg(MSG_CR | MSG_LF, "Our parameters override, 16-bit frame checking will be used");
}
if (receiver_flags & RZ_FLAG_ESC_CTRL)
msg(MSG_CR | MSG_LF, "Receiver wants control characters to be escaped");
if (receiver_flags & RZ_FLAG_ESC_8TH)
msg(MSG_CR | MSG_LF, "Receiver wants 8th bit to be escaped");
}
break;
case PS_Z_RECEIVER_WINDOW_SIZE:
if (receiver_window_size != arg_list[0]) {
if (receiver_window_size != -1)
msg(MSG_CR | MSG_LF, "Receiver has changed its window parameters");
receiver_window_size = arg_list[0];
if (receiver_window_size == 0)
msg(MSG_CR | MSG_LF, "Receiver can accept full streaming");
else
msg(MSG_CR | MSG_LF, "Receiver wants a frame window of %lu bytes to be used", receiver_window_size);
if (p_cfg.blk_size &&
p_cfg.blk_size != receiver_window_size)
msg(MSG_CR | MSG_LF, "Our parameters override, a frame window of %lu bytes will be used", p_cfg.blk_size);
}
break;
case PS_Z_SENDER_FLAGS:
if (arg_list[0] & RZ_FLAG_ESC_CTRL)
msg(MSG_LF, "Sender wants control characters to be escaped");
if (arg_list[0] & RZ_FLAG_ESC_8TH)
msg(MSG_LF, "Sender wants 8th bit to be escaped");
break;
case PS_SERVER_WAITING:
if (arg_list[0] == opt_wait) {
if (opt_wait) {
msg(MSG_LF, "Timeout");
DosBeep(750, 1000);
} else
msg(MSG_LF, "No connection, try specifying a waiting time (with -wait option)");
aborted = 1;
} else {
msg(MSG_CR, "Waiting for connect (%lu secs)", arg_list[0] + 1);
if (!opt_quiet)
DosBeep(250, 20);
DosSleep(1000);
}
break;
case PS_FILE_SKIPPED:
msg(MSG_LF, "File skipped by receiver request");
break;
case PS_Z_SERIAL_NUM:
if (p_cfg.attr & CFG_QUERY_SERIAL_NUM) /* Let's not show it, if not */
/* explicitly asked to */
msg(MSG_LF, "Serial number of the receiver is %lu", arg_list[0]);
remote_serial_num = arg_list[0];
break;
default:
msg(MSG_LF, "Got unknown P_STATUS: %lu", type);
break;
}
if (aborted) { /* User has pressed CTRL-C */
we_aborted = 1;
aborted = 0; /* Once is enough */
return(1);
}
return(0);
}
BOOLEAN s_open_func(U8 **path, U32 *length, U32 *date, U32 *mode,
U32 *f_left, U32 *b_left,
U8 *zconv, U8 *zmanag, U8 *ztrans) {
APIRET rc;
struct stat statbuf;
while (1) {
if (tl->c == NULL) {
*path = NULL;
return(0);
}
rc = DosAllocMem((void **)path, 4096, PAG_COMMIT | PAG_WRITE | PAG_READ);
if (rc)
os2_error(P_ERROR_DOSALLOCMEM, rc,
MODULE_CALLBACK, __LINE__,
(U8 *)4096);
full_path = tl->c->path;
if (opt_paths)
strcpy(*path, tl->c->path);
else
strcpy(*path, tl->c->name);
tl->c = tl->c->n;
if ((brwf = brw_open(full_path,
opt_filebuf, opt_filebuf,
O_RDONLY | O_BINARY, SH_DENYNO)) == NULL) {
perror(full_path);
} else {
*length = filelength(brwf->fd);
fstat(brwf->fd, &statbuf);
*date = statbuf.st_mtime;
*mode = statbuf.st_mode;
*f_left = files_left;
*b_left = bytes_left;
if (p_cfg.protocol_type == PROTOCOL_Z) {
/**********************/
/* Conversion options */
/**********************/
*zconv = 0;
if (opt_text)
*zconv |= Z_CONVERSION_TEXT;
else
*zconv |= Z_CONVERSION_BINARY;
if (opt_resume)
*zconv = Z_CONVERSION_RESUME;
/**********************/
/* Management options */
/**********************/
*zmanag = 0;
if (opt_existing)
*zmanag |= Z_MANAGEMENT_MUST_EXIST;
*zmanag |= opt_management;
/*********************/
/* Transport options */
/*********************/
*ztrans = 0;
}
if (opt_mileage) {
if (opt_speed)
msg(MSG_LF,
"Total of %lu files and %lu bytes (%s) left to transfer",
files_left, bytes_left, d_time(bytes_left / (opt_speed / 10)));
else
msg(MSG_LF, "Total of %lu files and %lu bytes left to transfer",
files_left, bytes_left);
}
if (opt_speed)
msg(MSG_CR | MSG_LF, "Sending %s, %lu bytes, %s",
full_path, *length, d_time(*length / (opt_speed / 10)));
else
msg(MSG_CR | MSG_LF, "Sending %s, %lu bytes", full_path, *length);
time(&t_started);
return(0);
}
}
}
/* Finds an unique name for the file */
BOOLEAN solve_name_for_file(U8 **path, U32 open_mode) {
U32 i;
U32 org_i;
U32 n = 0;
U32 m = 10;
BOOLEAN extending = 1;
org_i = strlen(*path);
i = org_i;
while (1) {
if (extending) {
sprintf(&(*path)[i], "-%lu", n);
n++;
} else {
sprintf(&(*path)[i], "%lu", n);
n++;
if (n == m) {
i--;
m = n * 10;
}
}
if ((brwf = brw_open(*path,
opt_filebuf, opt_filebuf,
O_CREAT | O_WRONLY | O_EXCL | open_mode,
SH_DENYWR, S_IWRITE)) != NULL)
break;
#ifdef __EMX__
if (errno == ENAMETOOLONG) {
extending = 0;
i = org_i - 1; /* We'll start from the beginning */
n = 0;
m = 10;
} else if (errno != EEXIST) {
/* error, the reason for brw_open to fail was */
/* something else than that the file already exists */
return(1);
}
#else /* __EMX__ */
/* Renaming on FAT doesn't work with ICC this way, haven't bothered to */
/* kludge it to work... */
return(0);
#endif /* __EMX__ */
}
msg(MSG_LF, "File already exists, renaming to %s", *path);
return(0);
}
U32 r_open_func(U8 **path, U32 length, U32 date, U32 mode,
U32 f_left, U32 b_left,
U8 zconv, U8 zmanag, U8 ztrans,
U32 *offset) {
BOOLEAN path_was_null;
U32 management = 0;
U32 open_mode = 0;
APIRET rc;
struct stat statbuf;
if (*path == NULL) { /* Xmodem receive? */
rc = DosAllocMem((void **)path, 4096,
PAG_COMMIT | PAG_WRITE | PAG_READ);
if (rc)
os2_error(P_ERROR_DOSALLOCMEM, rc,
MODULE_CALLBACK, __LINE__,
(U8 *)4096);
strcpy(*path, tl->c->path);
tl->c = tl->c->n;
path_was_null = 1;
} else
path_was_null = 0;
if (!opt_paths)
strip_drive_and_dir(*path);
else {
if (opt_create && create_dirs(*path)) {
msg(MSG_LF, "%s: %s, %s...", *path, strerror(errno),
p_cfg.protocol_type == PROTOCOL_Z ? "skipping" : "aborting");
rc = DosFreeMem((void *)*path);
if (rc)
os2_error(P_ERROR_DOSFREEMEM, rc,
MODULE_CALLBACK, __LINE__,
NULL);
*path = NULL;
return(0);
}
}
if (opt_mileage) {
if (f_left || b_left) {
if (opt_speed)
msg(MSG_LF,
"Total of %lu files and %lu bytes (%s) left to transfer",
f_left, b_left, d_time(b_left / (opt_speed / 10)));
else
msg(MSG_LF, "Total of %lu files and %lu bytes left to transfer",
f_left, b_left);
}
}
if (p_cfg.protocol_type == PROTOCOL_Z && opt_options) {
switch (zconv) {
case Z_CONVERSION_UNDEFINED:
break;
case Z_CONVERSION_BINARY:
msg(MSG_LF, "Sender suggests a binary conversion to be used");
break;
case Z_CONVERSION_TEXT:
msg(MSG_LF, "Sender suggests a text conversion to be used");
break;
case Z_CONVERSION_RESUME:
msg(MSG_LF, "Sender suggests that the file transfer should be resumed");
break;
default:
msg(MSG_LF, "Unknown conversion option received: %lu", zconv);
break;
}
switch (zmanag & Z_MANAGEMENT_MASK) {
case Z_MANAGEMENT_UNDEFINED:
break;
case Z_MANAGEMENT_UPDATE:
msg(MSG_LF, "Sender wants to update older and shorter files");
break;
case Z_MANAGEMENT_COMPARE:
msg(MSG_LF,
"Sender wants to compare possibly existing files before replacing");
break;
case Z_MANAGEMENT_APPEND:
msg(MSG_LF, "Sender wants to append to already existing files");
break;
case Z_MANAGEMENT_REPLACE:
msg(MSG_LF, "Sender wants to replace already existing files");
break;
case Z_MANAGEMENT_NEWER:
msg(MSG_LF, "Sender wants to update older files");
break;
case Z_MANAGEMENT_DIFFERENT:
msg(MSG_LF,
"Sender wants to replace files with different dates and lengths");
break;
case Z_MANAGEMENT_PROTECT:
msg(MSG_LF, "Sender does not want to replace already existing files");
break;
default:
msg(MSG_LF, "Unknown management option received: %lu", zmanag);
break;
}
if (zmanag & Z_MANAGEMENT_MUST_EXIST)
msg(MSG_LF, "Sender wants to transfer only already existing files");
switch (ztrans) {
case Z_TRANSPORT_UNDEFINED:
break;
case Z_TRANSPORT_LZW:
msg(MSG_LF, "Sender wants to use Lempel-Ziv compression");
break;
case Z_TRANSPORT_CRYPT:
msg(MSG_LF, "Sender wants to use encryption");
break;
case Z_TRANSPORT_RLE:
msg(MSG_LF, "Sender wants to use RLE compression");
break;
default:
msg(MSG_LF, "Unknown transport option received: %lu", ztrans);
break;
}
}
/******************************/
/* Process conversion options */
/******************************/
if (zconv == Z_CONVERSION_TEXT || opt_text)
open_mode |= O_TEXT;
else
open_mode |= O_BINARY;
/******************************/
/* Process management options */
/******************************/
if (!(zmanag & Z_MANAGEMENT_MUST_EXIST) && !opt_existing)
open_mode |= O_CREAT;
management = (zmanag & Z_MANAGEMENT_MASK);
if (opt_management) /* If management option specified */
/* on the command-line */
management = opt_management; /* Command-line overrides remote's */
/* options */
if (!management && zconv != Z_CONVERSION_RESUME && !opt_resume) {
/* If no management option or resume specified, we'll default to */
/* protecting existing files... */
management = Z_MANAGEMENT_PROTECT;
}
if (length != -1) {
if (opt_speed != 0) {
msg(MSG_CR | MSG_LF, "Receiving %s, %lu bytes, %s",
*path, length, d_time(length / (opt_speed / 10)));
} else
msg(MSG_CR | MSG_LF, "Receiving %s, %lu bytes", *path, length);
} else
msg(MSG_CR | MSG_LF, "Receiving %s", *path);
if (!path_was_null && tl != NULL) {
if (!tl_exists(tl, *path)) {
msg(MSG_LF, "File not specified on command-line, %s...",
p_cfg.protocol_type == PROTOCOL_Z ? "skipping" : "aborting");
rc = DosFreeMem((void *)*path);
if (rc)
os2_error(P_ERROR_DOSFREEMEM, rc,
MODULE_CALLBACK, __LINE__,
NULL);
*path = NULL;
return(0);
}
}
add_recv_dir_to_path(path);
if ((brwf = brw_open(*path,
opt_filebuf, opt_filebuf,
O_WRONLY | O_EXCL | open_mode,
SH_DENYWR, S_IWRITE)) == NULL) {
if (errno != EEXIST) { /* The reason for brw_open() to fail was */
/* something else than that the file */
/* already exists */
msg(MSG_LF, "%s: %s, %s...", *path, strerror(errno),
p_cfg.protocol_type == PROTOCOL_Z ? "skipping" : "aborting");
rc = DosFreeMem((void *)*path);
if (rc)
os2_error(P_ERROR_DOSFREEMEM, rc,
MODULE_CALLBACK, __LINE__,
NULL);
*path = NULL;
return(0);
}
switch (management) {
case Z_MANAGEMENT_UNDEFINED:
/* Do nothing */
break;
case Z_MANAGEMENT_UPDATE: /* Only if newer or longer */
stat(*path, &statbuf);
if (statbuf.st_size >= length && statbuf.st_mtime >= date) {
msg(MSG_LF, "Up to date file already exists, %s...",
p_cfg.protocol_type == PROTOCOL_Z ? "skipping" : "aborting");
rc = DosFreeMem((void *)*path);
if (rc)
os2_error(P_ERROR_DOSFREEMEM, rc,
MODULE_CALLBACK, __LINE__,
NULL);
*path = NULL;
return(0);
}
break;
case Z_MANAGEMENT_NEWER: /* Only if newer */
stat(*path, &statbuf);
if (statbuf.st_mtime >= date) {
msg(MSG_LF, "Up to date file already exists, %s...",
p_cfg.protocol_type == PROTOCOL_Z ? "skipping" : "aborting");
rc = DosFreeMem((void *)*path);
if (rc)
os2_error(P_ERROR_DOSFREEMEM, rc,
MODULE_CALLBACK, __LINE__,
NULL);
*path = NULL;
return(0);
}
break;
case Z_MANAGEMENT_DIFFERENT: /* Only if date if different */
stat(*path, &statbuf);
if (statbuf.st_mtime == date) {
msg(MSG_LF, "File with an identical date exists, %s...",
p_cfg.protocol_type == PROTOCOL_Z ? "skipping" : "aborting");
rc = DosFreeMem((void *)*path);
if (rc)
os2_error(P_ERROR_DOSFREEMEM, rc,
MODULE_CALLBACK, __LINE__,
NULL);
*path = NULL;
return(0);
}
if (statbuf.st_size == length) {
msg(MSG_LF, "File with an identical size exists, %s...",
p_cfg.protocol_type == PROTOCOL_Z ? "skipping" : "aborting");
rc = DosFreeMem((void *)*path);
if (rc)
os2_error(P_ERROR_DOSFREEMEM, rc,
MODULE_CALLBACK, __LINE__,
NULL);
*path = NULL;
return(0);
}
break;
case Z_MANAGEMENT_APPEND:
msg(MSG_LF, "File already exists, appending...");
open_mode |= O_APPEND;
break;
case Z_MANAGEMENT_REPLACE:
msg(MSG_LF, "File already exists, overwriting...");
open_mode |= O_TRUNC;
break;
case Z_MANAGEMENT_PROTECT:
msg(MSG_LF, "File already exists, %s...",
p_cfg.protocol_type == PROTOCOL_Z ? "skipping" : "aborting");
rc = DosFreeMem((void *)*path);
if (rc)
os2_error(P_ERROR_DOSFREEMEM, rc,
MODULE_CALLBACK, __LINE__,
NULL);
*path = NULL;
return(0);
case Z_MANAGEMENT_RENAME:
if (solve_name_for_file(path, open_mode)) { /* brwf gets opened here */
msg(MSG_LF, "%s: %s, %s...", *path, strerror(errno),
p_cfg.protocol_type == PROTOCOL_Z ? "skipping" : "aborting");
rc = DosFreeMem((void *)*path);
if (rc)
os2_error(P_ERROR_DOSFREEMEM, rc,
MODULE_CALLBACK, __LINE__,
NULL);
*path = NULL;
return(0);
}
/* brwf is open now! */
break;
case Z_MANAGEMENT_COMPARE:
/* Do nothing */
break;
}
if (zconv == Z_CONVERSION_RESUME || opt_resume)
open_mode |= O_APPEND;
if (brwf == NULL) { /* brwf is not yet opened */
if ((brwf = brw_open(*path,
opt_filebuf, opt_filebuf,
O_CREAT | O_WRONLY | open_mode,
SH_DENYWR, S_IWRITE)) == NULL) {
msg(MSG_LF, "%s: %s, %s...", *path, strerror(errno),
p_cfg.protocol_type == PROTOCOL_Z ? "skipping" : "aborting");
rc = DosFreeMem((void *)*path);
if (rc)
os2_error(P_ERROR_DOSFREEMEM, rc,
MODULE_CALLBACK, __LINE__,
NULL);
*path = NULL;
return(0);
}
if (open_mode & O_APPEND) {
if (p_cfg.protocol_type == PROTOCOL_Z &&
(zconv == Z_CONVERSION_RESUME || opt_resume)) { /* Are we crash- */
/* recovering? */
*offset = filelength(brwf->fd);
if (*offset != length)
msg(MSG_LF, "Crash recovery at %lu", *offset);
else {
msg(MSG_LF, "We have the whole file already, skipping...");
brw_close(&brwf);
rc = DosFreeMem((void *)*path);
if (rc)
os2_error(P_ERROR_DOSFREEMEM, rc,
MODULE_CALLBACK, __LINE__,
NULL);
*path = NULL;
return(0);
}
} else { /* Not resuming => appending */
msg(MSG_LF, "Appending at %lu", filelength(brwf->fd));
if (offset != NULL) /* If offset is non-null, we're using Zmodem */
*offset = 0; /* Tell the remote to start sending from the */
/* beginning of the file */
}
}
}
} else {
if (offset != NULL) /* Zmodem receive? */
*offset = 0;
}
time(&t_started);
return(0);
}
U32 close_func(U8 **path,
U32 length,
U32 date,
U32 retransmits,
BOOLEAN successful,
U32 offset) {
U8 id;
S32 rw_ret;
time_t t_now;
U32 cps;
U32 ret_val = 0;
struct utimbuf times;
APIRET rc;
time(&t_now);
if ((rw_ret = brw_flush(brwf))) {
if (rw_ret == -1)
fprintf(stderr, "\rFailed to write to file, %s\n", strerror(errno));
else
fprintf(stderr, "\rFailed to write to file, disk full?\n");
ret_val = 1;
}
brw_close(&brwf);
if (!opt_touch && date != -1) { /* Set the file date */
time(×.actime);
times.modtime = date;
#ifdef __EMX__
utime(*path, ×);
#else /* __EMX__ */
_utime(*path, ×);
#endif /* __EMX__ */
}
if (p_cfg.transfer_direction == DIR_SEND) {
files_left--;
bytes_left -= length;
}
if (offset) {
cps = (t_now == t_started ?
offset : offset / (t_now - t_started));
msg(MSG_CR | MSG_LF, "%lu bytes, %s, %lu CPS%s",
offset, d_time(t_now - t_started), cps,
!successful ? ", Transfer incomplete" : "");
if (opt_dszlog != NULL) {
if (dszlog_stream == NULL &&
(dszlog_stream = fopen(opt_dszlog, "w")) == NULL) {
perror(opt_dszlog);
ret_val = 1;
} else {
if (successful) {
switch (p_cfg.protocol_type) {
case PROTOCOL_X:
id = 'x';
break;
case PROTOCOL_Y:
id = 'y';
break;
case PROTOCOL_G:
id = 'g';
break;
case PROTOCOL_Z:
default: /* Just to shut up the compiler */
id = 'z';
break;
}
if (p_cfg.transfer_direction == DIR_RECV) /* The protocol id */
/* should be in */
/* uppercase when */
/* receiving...*/
id = toupper(id);
} else if (carrier_lost)
id = 'L'; /* Carrier lost */
else
id = 'E'; /* Other error */
fprintf(dszlog_stream,
"%c %6lu %5lu bps %4lu cps %3lu errors 0 %4lu %12s %ld\n",
id,
successful ? length : offset,
opt_speed,
cps,
retransmits,
1024L, /* block_size */
full_path != NULL ? full_path : *path,
remote_serial_num);
}
}
}
if (p_cfg.transfer_direction == DIR_RECV &&
opt_clean &&
!successful) {
msg(MSG_LF, "Deleting: %s", *path);
unlink(*path);
}
rc = DosFreeMem(*path);
if (rc)
os2_error(P_ERROR_DOSFREEMEM, rc,
MODULE_CALLBACK, __LINE__,
NULL);
*path = NULL;
return(ret_val);
}
U32 seek_func(U32 pos) {
if (brw_seek(brwf, pos) == -1) {
fprintf(stderr, "\rFailed to seek in file, %s\n", strerror(errno));
return(1);
} else
return(0);
}
U32 read_func(U8 *buf, U32 bytes_wanted, U32 *bytes_got) {
if ((*bytes_got = brw_read(brwf, buf, bytes_wanted)) == -1) {
fprintf(stderr, "\rFailed to read from file, %s\n", strerror(errno));
return(1);
} else
return(0);
}
U32 write_func(U8 *buf, U32 bytes) {
U32 rw_ret;
if ((rw_ret = brw_write(brwf, buf, bytes)) == -1) {
fprintf(stderr, "\rFailed to write to file, %s\n", strerror(errno));
return(1);
} else if (rw_ret) {
fprintf(stderr, "\rFailed to write to file, disk full?\n");
return(1);
} else
return(0);
}