You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4912 lines
122 KiB
4912 lines
122 KiB
/*
|
|
* $Id: dlp.c,v 1.139 2006/11/07 20:42:36 adridg Exp $
|
|
*
|
|
* dlp.c: Palm DLP protocol
|
|
*
|
|
* Copyright (c) 1996, 1997, Kenneth Albanowski
|
|
* Copyright (c) 1998-2003, David Desrosiers, JP Rosevear and others
|
|
* Copyright (c) 2004, 2005, 2006, Florent Pillet
|
|
*
|
|
* This library is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Library General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or (at
|
|
* your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#ifdef HAVE_ERRNO_H
|
|
#include <errno.h>
|
|
#ifndef ENOMSG
|
|
#define ENOMSG EINVAL /* For systems that don't provide ENOMSG. Use EINVAL instead. */
|
|
#endif
|
|
#endif
|
|
#include <sys/types.h>
|
|
#include <netinet/in.h>
|
|
|
|
#include "pi-debug.h"
|
|
#include "pi-source.h"
|
|
#include "pi-dlp.h"
|
|
#include "pi-syspkt.h"
|
|
|
|
#define DLP_REQUEST_DATA(req, arg, offset) &req->argv[arg]->data[offset]
|
|
#define DLP_RESPONSE_DATA(res, arg, offset) &res->argv[arg]->data[offset]
|
|
|
|
#define get_date(ptr) (dlp_ptohdate((ptr)))
|
|
#define set_date(ptr,val) (dlp_htopdate((val),(ptr)))
|
|
|
|
#define RequireDLPVersion(sd,major,minor) \
|
|
if (pi_version(sd) < (((major)<<8) | (minor))) \
|
|
return dlpErrNotSupp
|
|
|
|
/* This constant is being used during dlp_ReadResourceByType, dlp_ReadResourceByIndex, dlp_ReadRecordById, and dlp_ReadRecordByIndex
|
|
* Scott Gruby discovered that on some devices, reading a record that has the maximum record size can lock up the device.
|
|
* We'll read large records in two steps, getting the small amount of remaining data the second time.
|
|
* Scott's tests showed that the value above (100 bytes) was enough of a safeguard to prevent device lockup
|
|
*/
|
|
#define RECORD_READ_SAFEGUARD_SIZE 100
|
|
|
|
/* Define prototypes */
|
|
#ifdef PI_DEBUG
|
|
static void record_dump (unsigned long recID, unsigned int recIndex,
|
|
int flags, int catID, const char *data, int data_len);
|
|
#endif
|
|
|
|
char *dlp_errorlist[] = {
|
|
"No error",
|
|
"General System error",
|
|
"Illegal Function",
|
|
"Out of memory",
|
|
"Invalid parameter",
|
|
"Not found",
|
|
"None Open",
|
|
"Already Open",
|
|
"Too many Open",
|
|
"Already Exists",
|
|
"Cannot Open",
|
|
"Record deleted",
|
|
"Record busy",
|
|
"Operation not supported",
|
|
"-Unused-",
|
|
"Read only",
|
|
"Not enough space",
|
|
"Limit exceeded",
|
|
"Sync cancelled",
|
|
"Bad arg wrapper",
|
|
"Argument missing",
|
|
"Bad argument size"
|
|
};
|
|
|
|
/* Look at "Error codes" in VFSMgr.h in the Palm SDK for their
|
|
implementation */
|
|
char * vfs_errorlist[] = {
|
|
"No error",
|
|
"Buffer Overflow",
|
|
"Generic file error",
|
|
"File reference is invalid",
|
|
"File still open",
|
|
"Permission denied",
|
|
"File or folder already exists",
|
|
"FileEOF",
|
|
"File not found",
|
|
"volumereference is invalid",
|
|
"Volume still mounted",
|
|
"No filesystem",
|
|
"Bad data",
|
|
"Non-empty directory",
|
|
"Invalid path or filename",
|
|
"Volume full - not enough space",
|
|
"Unimplemented",
|
|
"Not a directory",
|
|
"Is a directory",
|
|
"Directory not found",
|
|
"Name truncated"
|
|
};
|
|
|
|
/* Look at "Error codes" in ExpansionMgr.h in the Palm SDK for their
|
|
implementation */
|
|
char * exp_errorlist[] = {
|
|
"No error",
|
|
"Unsupported Operation",
|
|
"Not enough Power",
|
|
"Card not present",
|
|
"Invalid slotreference number",
|
|
"Slot deallocated",
|
|
"Card no sector read/write",
|
|
"Card read only",
|
|
"Card bad sector",
|
|
"Protected sector",
|
|
"Not open (slot driver)",
|
|
"still open (slot driver)",
|
|
"Unimplemented",
|
|
"Enumeration empty",
|
|
"Incompatible API version"
|
|
};
|
|
|
|
#ifdef DLP_TRACE
|
|
static int dlp_trace = 0;
|
|
#endif
|
|
static int dlp_version_major = PI_DLP_VERSION_MAJOR;
|
|
static int dlp_version_minor = PI_DLP_VERSION_MINOR;
|
|
|
|
#ifdef PI_DEBUG
|
|
#define Trace(name) \
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO, "DLP sd=%d %s\n", sd, #name));
|
|
#ifdef __GNUC__
|
|
#define TraceX(name,format,...) \
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO, "DLP sd=%d %s " #format "\n", sd, #name, __VA_ARGS__));
|
|
#else
|
|
#define TraceX(name,format,...) \
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO, "DLP sd=%d %s\n", sd, #name));
|
|
#endif
|
|
#else
|
|
#define Trace(name)
|
|
#define TraceX(name,format,...)
|
|
#endif
|
|
|
|
#ifdef PI_DEBUG
|
|
static void record_dump (unsigned long recID, unsigned int recIndex, int flags,
|
|
int catID, const char *data, int data_len)
|
|
{
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" ID: 0x%8.8lX, Index: %u, Category: %d\n"
|
|
" Flags:%s%s%s%s%s%s (0x%2.2X), and %d bytes:\n",
|
|
(unsigned long) recID,
|
|
recIndex,
|
|
catID,
|
|
(flags & dlpRecAttrDeleted) ? " Deleted" : "",
|
|
(flags & dlpRecAttrDirty) ? " Dirty" : "",
|
|
(flags & dlpRecAttrBusy) ? " Busy" : "",
|
|
(flags & dlpRecAttrSecret) ? " Secret" : "",
|
|
(flags & dlpRecAttrArchived) ? " Archive" : "",
|
|
(!flags) ? " None" : "",
|
|
flags, data_len));
|
|
pi_dumpdata(data, (size_t)data_len);
|
|
}
|
|
#endif
|
|
|
|
void
|
|
dlp_set_protocol_version(int major, int minor)
|
|
{
|
|
dlp_version_major = major;
|
|
dlp_version_minor = minor;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function: dlp_strerror
|
|
*
|
|
* Summary: lookup text for dlp error
|
|
*
|
|
* Parameters: error number
|
|
*
|
|
* Returns: char* to error text string
|
|
*
|
|
***************************************************************************/
|
|
char
|
|
*dlp_strerror(int error)
|
|
{
|
|
if (error < 0)
|
|
error = -error;
|
|
|
|
if ((unsigned int) error >= (sizeof(dlp_errorlist)/(sizeof(char *))))
|
|
return "Unknown error";
|
|
|
|
return dlp_errorlist[error];
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function: dlp_arg_new
|
|
*
|
|
* Summary: create a dlpArg instance
|
|
*
|
|
* Parameters: id_, length of data
|
|
*
|
|
* Returns: dlpArg* or NULL on failure
|
|
*
|
|
***************************************************************************/
|
|
struct dlpArg
|
|
*dlp_arg_new (int argID, size_t len)
|
|
{
|
|
struct dlpArg *arg;
|
|
|
|
arg = (struct dlpArg *)malloc(sizeof (struct dlpArg));
|
|
|
|
if (arg != NULL) {
|
|
arg->id_ = argID;
|
|
arg->len = len;
|
|
arg->data = NULL;
|
|
if (len > 0) {
|
|
arg->data = (char *)malloc (len);
|
|
if (arg->data == NULL) {
|
|
free(arg);
|
|
arg = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return arg;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function: dlp_arg_free
|
|
*
|
|
* Summary: frees a dlpArg instance
|
|
*
|
|
* Parameters: dlpArg*
|
|
*
|
|
* Returns: void
|
|
*
|
|
***************************************************************************/
|
|
void
|
|
dlp_arg_free (struct dlpArg *arg)
|
|
{
|
|
if (arg != NULL) {
|
|
if (arg->data != NULL)
|
|
free (arg->data);
|
|
free (arg);
|
|
}
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function: dlp_arg_len
|
|
*
|
|
* Summary: computes aggregate length of data members associated with an
|
|
* array of dlpArg instances
|
|
*
|
|
* Parameters: number of dlpArg instances, dlpArg**
|
|
*
|
|
* Returns: aggregate length or -1 on error
|
|
*
|
|
***************************************************************************/
|
|
int
|
|
dlp_arg_len (int argc, struct dlpArg **argv)
|
|
{
|
|
int i, len = 0;
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
struct dlpArg *arg = argv[i];
|
|
|
|
/* FIXME: shapiro: should these be < or <= ??? */
|
|
if (arg->len < PI_DLP_ARG_TINY_LEN &&
|
|
(arg->id_ & (PI_DLP_ARG_FLAG_SHORT | PI_DLP_ARG_FLAG_LONG)) == 0)
|
|
len += 2;
|
|
else if (arg->len < PI_DLP_ARG_SHORT_LEN &&
|
|
(arg->id_ & PI_DLP_ARG_FLAG_LONG) == 0)
|
|
len += 4;
|
|
else
|
|
len += 6;
|
|
|
|
len += arg->len;
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function: dlp_request_new
|
|
*
|
|
* Summary: creates a new dlpRequest instance
|
|
*
|
|
* Parameters: dlpFunction command, number of dlpArgs, lengths of dlpArgs
|
|
* data member
|
|
*
|
|
* Returns: dlpRequest* or NULL if failure
|
|
*
|
|
***************************************************************************/
|
|
struct dlpRequest*
|
|
dlp_request_new (enum dlpFunctions cmd, int argc, ...)
|
|
{
|
|
struct dlpRequest *req;
|
|
va_list ap;
|
|
int i,
|
|
j;
|
|
|
|
req = (struct dlpRequest *)malloc (sizeof (struct dlpRequest));
|
|
|
|
if (req != NULL) {
|
|
req->cmd = cmd;
|
|
req->argc = argc;
|
|
req->argv = NULL;
|
|
|
|
if (argc) {
|
|
req->argv = (struct dlpArg **) malloc (sizeof (struct dlpArg *) * argc);
|
|
if (req->argv == NULL) {
|
|
free(req);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
va_start (ap, argc);
|
|
for (i = 0; i < argc; i++) {
|
|
size_t len;
|
|
|
|
len = va_arg (ap, size_t);
|
|
req->argv[i] = dlp_arg_new (PI_DLP_ARG_FIRST_ID + i,
|
|
len);
|
|
if (req->argv[i] == NULL) {
|
|
for (j = 0; j < i; j++)
|
|
dlp_arg_free(req->argv[j]);
|
|
free(req->argv);
|
|
free(req);
|
|
req = NULL;
|
|
break;
|
|
}
|
|
}
|
|
va_end (ap);
|
|
}
|
|
|
|
return req;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function: dlp_request_new_with_argid
|
|
*
|
|
* Summary: creates a new dlpRequest instance with argid
|
|
*
|
|
* Parameters: dlpFunction command, number of dlpArgs, argid, lengths of
|
|
* dlpArgs data member
|
|
*
|
|
* Returns: dlpRequest* or NULL if failure
|
|
*
|
|
***************************************************************************/
|
|
struct dlpRequest*
|
|
dlp_request_new_with_argid (enum dlpFunctions cmd, int argid, int argc, ...)
|
|
{
|
|
struct dlpRequest *req;
|
|
va_list ap;
|
|
int i,
|
|
j;
|
|
|
|
req = (struct dlpRequest *) malloc (sizeof (struct dlpRequest));
|
|
|
|
if (req != NULL) {
|
|
req->cmd = cmd;
|
|
req->argc = argc;
|
|
req->argv = NULL;
|
|
|
|
if (argc) {
|
|
req->argv = (struct dlpArg **) malloc (sizeof (struct dlpArg *) * argc);
|
|
if (req->argv == NULL) {
|
|
free(req);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
va_start (ap, argc);
|
|
for (i = 0; i < argc; i++) {
|
|
size_t len;
|
|
|
|
len = va_arg (ap, size_t);
|
|
req->argv[i] = dlp_arg_new (argid + i, len);
|
|
if (req->argv[i] == NULL) {
|
|
for (j = 0; j < i; j++)
|
|
dlp_arg_free(req->argv[j]);
|
|
free(req->argv);
|
|
free(req);
|
|
req = NULL;
|
|
break;
|
|
}
|
|
}
|
|
va_end (ap);
|
|
}
|
|
|
|
return req;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function: dlp_response_new
|
|
*
|
|
* Summary: creates a new dlpResponse instance
|
|
*
|
|
* Parameters: dlpFunction command, number of dlpArg instances
|
|
*
|
|
* Returns: dlpResponse* or NULL if failure
|
|
*
|
|
***************************************************************************/
|
|
struct dlpResponse
|
|
*dlp_response_new (enum dlpFunctions cmd, int argc)
|
|
{
|
|
struct dlpResponse *res;
|
|
|
|
res = (struct dlpResponse *) malloc (sizeof (struct dlpResponse));
|
|
|
|
if (res != NULL) {
|
|
|
|
res->cmd = cmd;
|
|
res->err = dlpErrNoError;
|
|
res->argc = argc;
|
|
res->argv = NULL;
|
|
|
|
if (argc) {
|
|
res->argv = (struct dlpArg **) malloc (sizeof (struct dlpArg *) * argc);
|
|
if (res->argv == NULL) {
|
|
free(res);
|
|
return NULL;
|
|
}
|
|
/* zero-out argv so that in case of error during
|
|
response read, dlp_response_free() won't try to
|
|
free uninitialized ptrs */
|
|
memset(res->argv, 0, sizeof (struct dlpArg *) * argc);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function: dlp_response_read
|
|
*
|
|
* Summary: reads dlp response
|
|
*
|
|
* Parameters: dlpResonse**, sd
|
|
*
|
|
* Returns: first dlpArg response length or -1 on error
|
|
*
|
|
***************************************************************************/
|
|
ssize_t
|
|
dlp_response_read (struct dlpResponse **res, int sd)
|
|
{
|
|
struct dlpResponse *response;
|
|
unsigned char *buf;
|
|
short argid;
|
|
int i;
|
|
ssize_t bytes;
|
|
size_t len;
|
|
pi_buffer_t *dlp_buf;
|
|
|
|
dlp_buf = pi_buffer_new (DLP_BUF_SIZE);
|
|
if (dlp_buf == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
bytes = pi_read (sd, dlp_buf, dlp_buf->allocated); /* buffer will grow as needed */
|
|
if (bytes < 0) {
|
|
pi_buffer_free (dlp_buf);
|
|
return bytes;
|
|
}
|
|
if (bytes < 4) {
|
|
/* packet is probably incomplete */
|
|
#ifdef DEBUG
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
|
|
"dlp_response_read: response too short (%d bytes)\n",
|
|
bytes));
|
|
if (bytes)
|
|
pi_dumpdata(dlp_buf->data, (size_t)dlp_buf->used);
|
|
#endif
|
|
return pi_set_error(sd, PI_ERR_DLP_COMMAND);
|
|
}
|
|
|
|
response = dlp_response_new ((enum dlpFunctions)(dlp_buf->data[0] & 0x7f), dlp_buf->data[1]);
|
|
*res = response;
|
|
|
|
/* note that in case an error occurs, we do not deallocate the response
|
|
since callers already do it under all circumstances */
|
|
if (response == NULL) {
|
|
pi_buffer_free (dlp_buf);
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
}
|
|
|
|
response->err = (enum dlpErrors) get_short (&dlp_buf->data[2]);
|
|
pi_set_palmos_error(sd, (int)response->err);
|
|
|
|
/* FIXME: add bounds checking to make sure we don't access past
|
|
* the end of the buffer in case the data is corrupt */
|
|
buf = dlp_buf->data + 4;
|
|
for (i = 0; i < response->argc; i++) {
|
|
argid = get_byte (buf) & 0x3f;
|
|
if (get_byte(buf) & PI_DLP_ARG_FLAG_LONG) {
|
|
if (pi_version(sd) < 0x0104) {
|
|
/* we received a response from a device indicating that
|
|
it would have transmitted a >64k data block but DLP
|
|
versions prior to 1.4 don't have this capacity. In
|
|
this case (as observed on a T3), there is NO length
|
|
stored after the argid, it goes straigt to the data
|
|
contents. We need to report that the data is too large
|
|
to be transferred.
|
|
*/
|
|
pi_buffer_free (dlp_buf);
|
|
return pi_set_error(sd, PI_ERR_DLP_DATASIZE);
|
|
}
|
|
len = get_long (&buf[2]);
|
|
buf += 6;
|
|
} else if (get_byte(buf) & PI_DLP_ARG_FLAG_SHORT) {
|
|
len = get_short (&buf[2]);
|
|
buf += 4;
|
|
} else {
|
|
argid = get_byte(buf);
|
|
len = get_byte(&buf[1]);
|
|
buf += 2;
|
|
}
|
|
|
|
response->argv[i] = dlp_arg_new (argid, len);
|
|
if (response->argv[i] == NULL) {
|
|
pi_buffer_free (dlp_buf);
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
}
|
|
memcpy (response->argv[i]->data, buf, len);
|
|
buf += len;
|
|
}
|
|
|
|
pi_buffer_free (dlp_buf);
|
|
|
|
return response->argc ? response->argv[0]->len : 0;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function: dlp_request_write
|
|
*
|
|
* Summary: writes dlp request
|
|
*
|
|
* Parameters: dlpRequest**, sd
|
|
*
|
|
* Returns: response length or -1 on error
|
|
*
|
|
***************************************************************************/
|
|
ssize_t
|
|
dlp_request_write (struct dlpRequest *req, int sd)
|
|
{
|
|
unsigned char *exec_buf, *buf;
|
|
int i;
|
|
size_t len;
|
|
|
|
len = dlp_arg_len (req->argc, req->argv) + 2;
|
|
exec_buf = (unsigned char *) malloc (sizeof (unsigned char) * len);
|
|
if (exec_buf == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte (&exec_buf[PI_DLP_OFFSET_CMD], req->cmd);
|
|
set_byte (&exec_buf[PI_DLP_OFFSET_ARGC], req->argc);
|
|
|
|
buf = &exec_buf[PI_DLP_OFFSET_ARGV];
|
|
for (i = 0; i < req->argc; i++) {
|
|
struct dlpArg *arg = req->argv[i];
|
|
short argid = arg->id_;
|
|
|
|
if (arg->len < PI_DLP_ARG_TINY_LEN &&
|
|
(argid & (PI_DLP_ARG_FLAG_SHORT | PI_DLP_ARG_FLAG_LONG)) == 0) {
|
|
set_byte(&buf[0], argid | PI_DLP_ARG_FLAG_TINY);
|
|
set_byte(&buf[1], arg->len);
|
|
|
|
memcpy(&buf[2], arg->data, arg->len);
|
|
buf += arg->len + 2;
|
|
} else if (arg->len < PI_DLP_ARG_SHORT_LEN &&
|
|
(argid & PI_DLP_ARG_FLAG_LONG) == 0) {
|
|
set_byte(&buf[0], argid | PI_DLP_ARG_FLAG_SHORT);
|
|
set_byte(&buf[1], 0);
|
|
set_short(&buf[2], arg->len);
|
|
|
|
memcpy (&buf[4], arg->data, arg->len);
|
|
buf += arg->len + 4;
|
|
} else {
|
|
set_byte (&buf[0], argid | PI_DLP_ARG_FLAG_LONG);
|
|
set_byte(&buf[1], 0);
|
|
set_long (&buf[2], arg->len);
|
|
|
|
memcpy (&buf[6], arg->data, arg->len);
|
|
buf += arg->len + 6;
|
|
}
|
|
}
|
|
|
|
pi_flush(sd, PI_FLUSH_INPUT);
|
|
|
|
if ((i = pi_write(sd, exec_buf, len)) < (ssize_t)len) {
|
|
errno = -EIO;
|
|
if (i >= 0 && i < (ssize_t)len)
|
|
i = -1;
|
|
}
|
|
|
|
free (exec_buf);
|
|
|
|
return i;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function: dlp_request_free
|
|
*
|
|
* Summary: frees a dlpRequest instance
|
|
*
|
|
* Parameters: dlpRequest*
|
|
*
|
|
* Returns: void
|
|
*
|
|
***************************************************************************/
|
|
void
|
|
dlp_request_free (struct dlpRequest *req)
|
|
{
|
|
int i;
|
|
|
|
if (req == NULL)
|
|
return;
|
|
|
|
if (req->argv != NULL) {
|
|
for (i = 0; i < req->argc; i++) {
|
|
if (req->argv[i] != NULL)
|
|
dlp_arg_free (req->argv[i]);
|
|
}
|
|
free (req->argv);
|
|
}
|
|
|
|
free (req);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function: dlp_response_free
|
|
*
|
|
* Summary: frees a dlpResponse instance
|
|
*
|
|
* Parameters: dlpResponse*
|
|
*
|
|
* Returns: void
|
|
*
|
|
***************************************************************************/
|
|
void
|
|
dlp_response_free (struct dlpResponse *res)
|
|
{
|
|
int i;
|
|
|
|
if (res == NULL)
|
|
return;
|
|
|
|
if (res->argv != NULL) {
|
|
for (i = 0; i < res->argc; i++) {
|
|
if (res->argv[i] != NULL)
|
|
dlp_arg_free (res->argv[i]);
|
|
}
|
|
free (res->argv);
|
|
}
|
|
|
|
free (res);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function: dlp_exec
|
|
*
|
|
* Summary: writes a dlp request and reads the response
|
|
*
|
|
* Parameters: dlpResponse*
|
|
*
|
|
* Returns: the number of response bytes, or -1 on error
|
|
*
|
|
***************************************************************************/
|
|
int
|
|
dlp_exec(int sd, struct dlpRequest *req, struct dlpResponse **res)
|
|
{
|
|
int bytes, result;
|
|
*res = NULL;
|
|
|
|
if ((result = dlp_request_write (req, sd)) < req->argc) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
|
|
"DLP sd:%i dlp_request_write returned %i\n",
|
|
sd, result));
|
|
errno = -EIO;
|
|
return result;
|
|
}
|
|
|
|
if ((bytes = dlp_response_read (res, sd)) < 0) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
|
|
"DLP sd:%i dlp_response_read returned %i\n",
|
|
sd, bytes));
|
|
errno = -EIO;
|
|
return bytes;
|
|
}
|
|
|
|
/* Check to make sure the response is for this command */
|
|
if ((*res)->cmd != req->cmd) {
|
|
/* The Palm m130 and Tungsten T return the wrong code for VFSVolumeInfo */
|
|
/* Tungsten T5 (and maybe Treo 650) return dlpFuncEndOfSync for dlpFuncWriteResource */
|
|
/* In some cases, the Tapwave Zodiac returns dlpFuncReadRecord instead of dlpFuncReadRecordEx */
|
|
if ((req->cmd != dlpFuncVFSVolumeInfo || (*res)->cmd != dlpFuncVFSVolumeSize)
|
|
&& req->cmd != dlpFuncWriteResource /* T5 */
|
|
&& req->cmd != dlpFuncReadRecord /* Zodiac */
|
|
&& req->cmd != dlpFuncReadRecordEx) /* Zodiac */
|
|
{
|
|
errno = -ENOMSG;
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
"dlp_exec: result CMD 0x%02x doesn't match requested cmd 0x%02x\n",
|
|
(unsigned)((*res)->cmd), (unsigned)req->cmd));
|
|
|
|
return pi_set_error(sd, PI_ERR_DLP_COMMAND);
|
|
}
|
|
}
|
|
|
|
/* Check to make sure there was no error */
|
|
if ((*res)->err != dlpErrNoError) {
|
|
errno = -ENOMSG;
|
|
pi_set_palmos_error(sd, (int)((*res)->err));
|
|
return pi_set_error(sd, PI_ERR_DLP_PALMOS);
|
|
}
|
|
|
|
return bytes;
|
|
}
|
|
|
|
/* These conversion functions are strictly for use within the DLP layer.
|
|
This particular date/time format does not occur anywhere else within the
|
|
Palm or its communications. */
|
|
|
|
/* Notice:
|
|
The dates in the DLP protocol are expressed as absolute dates/times,
|
|
without any time zone information. For example if a file was created
|
|
on the device at 19:32:48, the time members will be 19, 32 and 48.
|
|
This simplifies things a lot since we don't need to to time zone
|
|
conversions. The functions below convert a breakdown DLP date to and
|
|
from a time_t expressed in the machine's local timezone.
|
|
-- FP */
|
|
|
|
time_t
|
|
dlp_ptohdate(const unsigned char *data)
|
|
{
|
|
struct tm t;
|
|
|
|
/* Seems like year comes back as all zeros if the date is "empty"
|
|
(but other fields can vary). And mktime() chokes on 1900 B.C.
|
|
(result of 0 minus 1900), returning -1, which the higher level
|
|
code can't deal with (passes it straight on to utime(), which
|
|
simply leaves the file's timestamp "as-is").
|
|
|
|
So, since year 0 appears to mean "no date", we'll return an odd
|
|
number that works out to precisely one day before the start of
|
|
the Palm's clock (thus little chance of being run into by any
|
|
Palm-based time stamp). */
|
|
|
|
if (data[0] == 0 && data[1] == 0) {
|
|
|
|
/* This original calculation was wrong, and reported one day
|
|
earlier than it was supposed to report. You can verify
|
|
this with the following:
|
|
|
|
perl -e '$date=localtime(0x83D8FE00); print $date,"\n"'
|
|
|
|
return (time_t) 0x83D8FE00; // Wed Dec 30 16:00:00 1903 GMT
|
|
|
|
Here are others, depending on what your system requirements are:
|
|
|
|
return (time_t) 0x83D96E80; // Thu Dec 31 00:00:00 1903 GMT
|
|
return (time_t) 0x00007080; // Thu Jan 1 00:00:00 1970 GMT
|
|
|
|
Palm's own Conduit Development Kit references using 1/1/1904,
|
|
so that's what we'll use here until something else breaks
|
|
it.
|
|
*/
|
|
|
|
return (time_t) 0x83DAC000; /* Fri Jan 1 00:00:00 1904 GMT */
|
|
}
|
|
|
|
memset(&t, 0, sizeof(t));
|
|
t.tm_sec = (int) data[6];
|
|
t.tm_min = (int) data[5];
|
|
t.tm_hour = (int) data[4];
|
|
t.tm_mday = (int) data[3];
|
|
t.tm_mon = (int) data[2] - 1;
|
|
t.tm_year = (((int)data[0] << 8) | (int)data[1]) - 1900;
|
|
t.tm_isdst = -1;
|
|
|
|
return mktime(&t);
|
|
}
|
|
|
|
void
|
|
dlp_htopdate(time_t time_interval, unsigned char *data)
|
|
{ /* @+ptrnegate@ */
|
|
int year;
|
|
const struct tm *t;
|
|
|
|
/* Fri Jan 1 00:00:00 1904 GMT */
|
|
time_t palm_epoch = 0x83DAC000;
|
|
|
|
if (time_interval == palm_epoch) {
|
|
memset(data, 0, 8);
|
|
return;
|
|
}
|
|
|
|
t = localtime(&time_interval);
|
|
ASSERT(t != NULL);
|
|
|
|
year = t->tm_year + 1900;
|
|
|
|
data[7] = (unsigned char) 0; /* packing spacer */
|
|
data[6] = (unsigned char) t->tm_sec;
|
|
data[5] = (unsigned char) t->tm_min;
|
|
data[4] = (unsigned char) t->tm_hour;
|
|
data[3] = (unsigned char) t->tm_mday;
|
|
data[2] = (unsigned char) (t->tm_mon + 1);
|
|
data[0] = (unsigned char) (year >> 8);
|
|
data[1] = (unsigned char) year;
|
|
}
|
|
|
|
int
|
|
dlp_GetSysDateTime(int sd, time_t *t)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_GetSysDateTime);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncGetSysDateTime, 0);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
*t = dlp_ptohdate((const unsigned char *)DLP_RESPONSE_DATA (res, 0, 0));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP GetSysDateTime %s", ctime(t)));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_SetSysDateTime(int sd, time_t t)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_SetSysDateTime,"time=0x%08lx",t);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncSetSysDateTime, 1, 8);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
dlp_htopdate(t, (unsigned char *)DLP_REQUEST_DATA(req, 0, 0));
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ReadStorageInfo(int sd, int cardno, struct CardInfo *c)
|
|
{
|
|
int result;
|
|
size_t len1, len2;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_ReadStorageInfo,"cardno=%d",cardno);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncReadStorageInfo, 1, 2);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), cardno);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
c->more = get_byte(DLP_RESPONSE_DATA(res, 0, 0))
|
|
|| (get_byte(DLP_RESPONSE_DATA(res, 0, 3)) > 1);
|
|
c->card = get_byte(DLP_RESPONSE_DATA(res, 0, 5));
|
|
c->version = get_byte(DLP_RESPONSE_DATA(res, 0, 6));
|
|
c->creation = get_date((const unsigned char *)DLP_RESPONSE_DATA(res, 0, 8));
|
|
c->romSize = get_long(DLP_RESPONSE_DATA(res, 0, 16));
|
|
c->ramSize = get_long(DLP_RESPONSE_DATA(res, 0, 20));
|
|
c->ramFree = get_long(DLP_RESPONSE_DATA(res, 0, 24));
|
|
|
|
len1 = get_byte(DLP_RESPONSE_DATA(res, 0, 28));
|
|
memcpy(c->name, DLP_RESPONSE_DATA(res, 0, 30), len1);
|
|
c->name[len1] = '\0';
|
|
|
|
len2 = get_byte(DLP_RESPONSE_DATA(res, 0, 29));
|
|
memcpy(c->manufacturer, DLP_RESPONSE_DATA(res, 0, 30 + len1),
|
|
len2);
|
|
c->manufacturer[len2] = '\0';
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP Read Cardno: %d, Card Version: %d, Creation time: %s",
|
|
c->card, c->version, ctime(&c->creation)));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Total ROM: %lu, Total RAM: %lu, Free RAM: %lu\n",
|
|
c->romSize, c->ramSize, c->ramFree));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Card name: '%s'\n", c->name));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Manufacturer name: '%s'\n", c->manufacturer));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" More: %s\n", c->more ? "Yes" : "No"));
|
|
}
|
|
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ReadSysInfo(int sd, struct SysInfo *s)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_ReadSysInfo);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncReadSysInfo, 1, 4);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short (DLP_REQUEST_DATA (req, 0, 0), dlp_version_major);
|
|
set_short (DLP_REQUEST_DATA (req, 0, 2), dlp_version_minor);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result > 0) {
|
|
s->romVersion = get_long (DLP_RESPONSE_DATA (res, 0, 0));
|
|
s->locale = get_long (DLP_RESPONSE_DATA (res, 0, 4));
|
|
/* The 8th byte is a filler byte */
|
|
s->prodIDLength = get_byte (DLP_RESPONSE_DATA (res, 0, 9));
|
|
memcpy(s->prodID, DLP_RESPONSE_DATA(res, 0, 10),
|
|
s->prodIDLength);
|
|
|
|
if (res->argc > 1) {
|
|
/* response added in DLP 1.2 */
|
|
pi_socket_t *ps = find_pi_socket(sd);
|
|
|
|
s->dlpMajorVersion =
|
|
get_short (DLP_RESPONSE_DATA (res, 1, 0));
|
|
s->dlpMinorVersion =
|
|
get_short (DLP_RESPONSE_DATA (res, 1, 2));
|
|
s->compatMajorVersion =
|
|
get_short (DLP_RESPONSE_DATA (res, 1, 4));
|
|
s->compatMinorVersion =
|
|
get_short (DLP_RESPONSE_DATA (res, 1, 6));
|
|
s->maxRecSize =
|
|
get_long (DLP_RESPONSE_DATA (res, 1, 8));
|
|
|
|
/* update socket information */
|
|
ps->dlpversion = (s->dlpMajorVersion << 8) | s->dlpMinorVersion;
|
|
ps->maxrecsize = s->maxRecSize;
|
|
} else {
|
|
s->dlpMajorVersion = 0;
|
|
s->dlpMinorVersion = 0;
|
|
s->compatMajorVersion = 0;
|
|
s->compatMinorVersion = 0;
|
|
s->maxRecSize = 0;
|
|
}
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadSysInfo ROM Ver=0x%8.8lX Locale=0x%8.8lX\n",
|
|
s->romVersion, s->locale));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Product ID=0x%8.8lX\n", s->prodID));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" DLP Major Ver=0x%4.4lX DLP Minor Ver=0x%4.4lX\n",
|
|
s->dlpMajorVersion, s->dlpMinorVersion));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Compat Major Ver=0x%4.4lX Compat Minor Vers=0x%4.4lX\n",
|
|
s->compatMajorVersion, s->compatMinorVersion));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Max Rec Size=%ld\n", s->maxRecSize));
|
|
}
|
|
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ReadDBList(int sd, int cardno, int flags, int start, pi_buffer_t *info)
|
|
{
|
|
int result,
|
|
i,
|
|
count;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
unsigned char *p;
|
|
struct DBInfo db;
|
|
|
|
TraceX(dlp_ReadDBList,"cardno=%d flags=0x%04x start=%d",cardno,flags,start);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncReadDBList, 1, 4);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
pi_buffer_clear (info);
|
|
|
|
/* `multiple' only supported in DLP 1.2 and above */
|
|
if (pi_version(sd) < 0x0102)
|
|
flags &= ~dlpDBListMultiple;
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), (unsigned char) flags);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), (unsigned char) cardno);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), start);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
p = (unsigned char *)DLP_RESPONSE_DATA(res, 0, 0);
|
|
db.more = get_byte(p + 2);
|
|
count = get_byte(p + 3);
|
|
|
|
for (i=0; i < count; i++) {
|
|
/* PalmOS 2.0 has additional flag */
|
|
if (pi_version(sd) > 0x0100)
|
|
db.miscFlags = get_byte(p + 5);
|
|
else
|
|
db.miscFlags = 0;
|
|
|
|
db.flags = get_short(p + 6);
|
|
db.type = get_long(p + 8);
|
|
db.creator = get_long(p + 12);
|
|
db.version = get_short(p + 16);
|
|
db.modnum = get_long(p + 18);
|
|
db.createDate = get_date(p + 22);
|
|
db.modifyDate = get_date(p + 30);
|
|
db.backupDate = get_date(p + 38);
|
|
db.index = get_short(p + 46);
|
|
|
|
memset(db.name, 0, sizeof(db.name));
|
|
strncpy(db.name, (char *)(p + 48), 32);
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadDBList Name: '%s', Version: %d, More: %s\n",
|
|
db.name, db.version, db.more ? "Yes" : "No"));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Creator: '%s'", printlong(db.creator)));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Type: '%s' Flags: %s%s%s%s%s%s%s%s%s%s",
|
|
printlong(db.type),
|
|
(db.flags & dlpDBFlagResource) ? "Resource " : "",
|
|
(db.flags & dlpDBFlagReadOnly) ? "ReadOnly " : "",
|
|
(db.flags & dlpDBFlagAppInfoDirty) ?
|
|
"AppInfoDirty " : "",
|
|
(db.flags & dlpDBFlagBackup) ? "Backup " : "",
|
|
(db.flags & dlpDBFlagReset) ? "Reset " : "",
|
|
(db.flags & dlpDBFlagNewer) ? "Newer " : "",
|
|
(db.flags & dlpDBFlagCopyPrevention) ?
|
|
"CopyPrevention " : "",
|
|
(db.flags & dlpDBFlagStream) ? "Stream " : "",
|
|
(db.flags & dlpDBFlagOpen) ? "Open " : "",
|
|
(!db.flags) ? "None" : ""));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO, " (0x%2.2X)\n", db.flags));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Modnum: %ld, Index: %d, Creation date: 0x%08lx, %s",
|
|
db.modnum, db.index, db.createDate, ctime(&db.createDate)));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Modification date: 0x%08lx, %s", db.modifyDate, ctime(&db.modifyDate)));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Backup date: 0x%08lx, %s", db.backupDate, ctime(&db.backupDate)));
|
|
|
|
if (pi_buffer_append(info, &db, sizeof(db)) == NULL) {
|
|
result = pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
break;
|
|
}
|
|
|
|
p += get_byte(p + 4);
|
|
}
|
|
} else {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"Error in dlp_ReadDBList: %d\n", result));
|
|
}
|
|
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_FindDBInfo(int sd, int cardno, int start, const char *dbname,
|
|
unsigned long type, unsigned long creator,
|
|
struct DBInfo *info)
|
|
{
|
|
int i,
|
|
j;
|
|
pi_buffer_t *buf;
|
|
|
|
TraceX(dlp_FindDBInfo,"cardno=%d start=%d",cardno,start);
|
|
pi_reset_errors(sd);
|
|
|
|
buf = pi_buffer_new (sizeof (struct DBInfo));
|
|
if (buf == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
if (start < 0x1000) {
|
|
i = start;
|
|
while (dlp_ReadDBList(sd, cardno, 0x80 | dlpDBListMultiple, i, buf) >= 0) {
|
|
for (j=0; j < (int)(buf->used / sizeof(struct DBInfo)); j++) {
|
|
memcpy (info, buf->data + j * sizeof(struct DBInfo), sizeof(struct DBInfo));
|
|
if ((!dbname || strcmp(info->name, dbname) == 0)
|
|
&& (!type || info->type == type)
|
|
&& (!creator || info->creator == creator))
|
|
goto found;
|
|
i = info->index + 1;
|
|
}
|
|
}
|
|
start = 0x1000;
|
|
}
|
|
|
|
i = start & 0xFFF;
|
|
while (dlp_ReadDBList(sd, cardno, 0x40 | dlpDBListMultiple, i, buf) >= 0) {
|
|
for (j=0; j < (int)(buf->used / sizeof(struct DBInfo)); j++) {
|
|
memcpy (info, buf->data + j * sizeof(struct DBInfo), sizeof(struct DBInfo));
|
|
if ((!dbname || strcmp(info->name, dbname) == 0)
|
|
&& (!type || info->type == type)
|
|
&& (!creator || info->creator == creator))
|
|
{
|
|
info->index |= 0x1000;
|
|
goto found;
|
|
}
|
|
i = info->index + 1;
|
|
}
|
|
}
|
|
|
|
pi_buffer_free (buf);
|
|
return -1;
|
|
|
|
found:
|
|
pi_buffer_free (buf);
|
|
return 0;
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* Function: dlp_decode_finddb_response
|
|
*
|
|
* Summary: Response decoding for the three variants of dlp_FindDB
|
|
*
|
|
* Parameters: None
|
|
*
|
|
* Returns: Nothing
|
|
*
|
|
***************************************************************************/
|
|
static void
|
|
dlp_decode_finddb_response(struct dlpResponse *res, int *cardno, unsigned long *localid,
|
|
int *dbhandle, struct DBInfo *info, struct DBSizeInfo *size)
|
|
{
|
|
int arg, argid;
|
|
for (arg = 0; arg < res->argc; arg++) {
|
|
argid = (res->argv[arg]->id_ & 0x7f) - PI_DLP_ARG_FIRST_ID;
|
|
if (argid == 0) {
|
|
if (cardno)
|
|
*cardno = get_byte(DLP_RESPONSE_DATA(res, arg, 0));
|
|
if (localid)
|
|
*localid = get_long(DLP_RESPONSE_DATA(res, arg, 2));
|
|
if (dbhandle)
|
|
*dbhandle = get_long(DLP_RESPONSE_DATA(res, arg, 6));
|
|
|
|
if (info) {
|
|
info->more = 0;
|
|
info->miscFlags =
|
|
get_byte(DLP_RESPONSE_DATA(res, arg, 11));
|
|
info->flags =
|
|
get_short(DLP_RESPONSE_DATA(res, arg, 12));
|
|
info->type =
|
|
get_long(DLP_RESPONSE_DATA(res, arg, 14));
|
|
info->creator =
|
|
get_long(DLP_RESPONSE_DATA(res, arg, 18));
|
|
info->version =
|
|
get_short(DLP_RESPONSE_DATA(res, arg, 22));
|
|
info->modnum =
|
|
get_long(DLP_RESPONSE_DATA(res, arg, 24));
|
|
info->createDate =
|
|
get_date((const unsigned char *)DLP_RESPONSE_DATA(res, arg, 28));
|
|
info->modifyDate =
|
|
get_date((const unsigned char *)DLP_RESPONSE_DATA(res, arg, 36));
|
|
info->backupDate =
|
|
get_date((const unsigned char *)DLP_RESPONSE_DATA(res, arg, 44));
|
|
info->index =
|
|
get_short(DLP_RESPONSE_DATA(res, arg, 52));
|
|
|
|
strncpy(info->name, DLP_RESPONSE_DATA(res, arg, 54), 32);
|
|
info->name[32] = '\0';
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP FindDB Name: '%s', "
|
|
"Version: %d, More: %s\n",
|
|
info->name, info->version,
|
|
info->more ? "Yes" : "No"));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Creator: '%s'", printlong(info->creator)));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Type: '%s' Flags: %s%s%s%s%s%s%s%s%s%s",
|
|
printlong(info->type),
|
|
(info->flags & dlpDBFlagResource) ?
|
|
"Resource " : "",
|
|
(info->flags & dlpDBFlagReadOnly) ?
|
|
"ReadOnly " : "",
|
|
(info->flags & dlpDBFlagAppInfoDirty) ?
|
|
"AppInfoDirty " : "",
|
|
(info->flags & dlpDBFlagBackup) ?
|
|
"Backup " : "",
|
|
(info->flags & dlpDBFlagReset) ?
|
|
"Reset " : "",
|
|
(info->flags & dlpDBFlagNewer) ?
|
|
"Newer " : "",
|
|
(info->flags & dlpDBFlagCopyPrevention) ?
|
|
"CopyPrevention " : "",
|
|
(info->flags & dlpDBFlagStream) ?
|
|
"Stream " : "",
|
|
(info->flags & dlpDBFlagOpen) ?
|
|
"Open " : "",
|
|
(!info->flags) ? "None" : ""));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" (0x%2.2X)\n", info->flags));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Modnum: %ld, Index: %d, "
|
|
"Creation date: %s",
|
|
info->modnum, info->index,
|
|
ctime(&info->createDate)));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Modification date: %s",
|
|
ctime(&info->modifyDate)));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Backup date: %s",
|
|
ctime(&info->backupDate)));
|
|
}
|
|
}
|
|
else if (argid == 1) {
|
|
if (size) {
|
|
size->numRecords =
|
|
get_long(DLP_RESPONSE_DATA(res, arg, 0));
|
|
size->totalBytes =
|
|
get_long(DLP_RESPONSE_DATA(res, arg, 4));
|
|
size->dataBytes =
|
|
get_long(DLP_RESPONSE_DATA(res, arg, 8));
|
|
size->appBlockSize =
|
|
get_long(DLP_RESPONSE_DATA(res, arg, 12));
|
|
size->sortBlockSize =
|
|
get_long(DLP_RESPONSE_DATA(res, arg, 16));
|
|
size->maxRecSize =
|
|
get_long(DLP_RESPONSE_DATA(res, arg, 20));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
dlp_FindDBByName (int sd, int cardno, PI_CONST char *name, unsigned long *localid,
|
|
int *dbhandle, struct DBInfo *info, struct DBSizeInfo *size)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
int flags = 0;
|
|
|
|
TraceX(dlp_FindDBByName,"cardno=%d name='%s'",cardno,name);
|
|
pi_reset_errors(sd);
|
|
|
|
if (pi_version(sd) < 0x0102)
|
|
return pi_set_error(sd, PI_ERR_DLP_UNSUPPORTED);
|
|
|
|
req = dlp_request_new(dlpFuncFindDB, 1, 2 + (strlen(name) + 1));
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
if (localid || dbhandle || info)
|
|
flags |= dlpFindDBOptFlagGetAttributes;
|
|
if (size)
|
|
flags |= dlpFindDBOptFlagGetSize;
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), flags);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), cardno);
|
|
strcpy(DLP_REQUEST_DATA(req, 0, 2), name);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0)
|
|
dlp_decode_finddb_response(res, NULL, localid, dbhandle, info, size);
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_FindDBByOpenHandle (int sd, int dbhandle, int *cardno,
|
|
unsigned long *localid, struct DBInfo *info, struct DBSizeInfo *size)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
int flags = 0;
|
|
|
|
Trace(dlp_FindDBByOpenHandle);
|
|
pi_reset_errors(sd);
|
|
|
|
if (pi_version(sd) < 0x0102)
|
|
return pi_set_error(sd, PI_ERR_DLP_UNSUPPORTED);
|
|
|
|
req = dlp_request_new_with_argid(dlpFuncFindDB, 0x21, 1, 2);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
/* Note: there is a bug in HotSync -- requesting the maxRecSize
|
|
* crashes the device, so we don't. This is supposed to work only
|
|
* for this variant of FindDB anyway.
|
|
*/
|
|
if (cardno || localid || info)
|
|
flags |= dlpFindDBOptFlagGetAttributes;
|
|
if (size)
|
|
flags |= dlpFindDBOptFlagGetSize;
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), flags);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), dbhandle);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0)
|
|
dlp_decode_finddb_response(res, cardno, localid, NULL, info, size);
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_FindDBByTypeCreator (int sd, unsigned long type, unsigned long creator,
|
|
int start, int latest, int *cardno, unsigned long *localid,
|
|
int *dbhandle, struct DBInfo *info, struct DBSizeInfo *size)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
int flags = 0, search_flags = 0;
|
|
|
|
TraceX(dlp_FindDBByTypeCreator,"type='%4.4s' creator='%4.4s' start=%d latest=%d",
|
|
(const char *)&type,(const char *)&creator,start,latest);
|
|
pi_reset_errors(sd);
|
|
|
|
if (pi_version(sd) < 0x0102)
|
|
return pi_set_error(sd, PI_ERR_DLP_UNSUPPORTED);
|
|
|
|
req = dlp_request_new_with_argid(dlpFuncFindDB, 0x22, 1, 10);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
if (cardno || localid || dbhandle || info)
|
|
flags |= dlpFindDBOptFlagGetAttributes;
|
|
if (size)
|
|
flags |= (dlpFindDBOptFlagGetSize |
|
|
dlpFindDBOptFlagMaxRecSize);
|
|
|
|
if (start)
|
|
search_flags |= dlpFindDBSrchFlagNewSearch;
|
|
if (latest)
|
|
search_flags |= dlpFindDBSrchFlagOnlyLatest;
|
|
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), flags);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), search_flags);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 2), type);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 6), creator);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0)
|
|
dlp_decode_finddb_response(res, cardno, localid, dbhandle, info, size);
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_OpenDB(int sd, int cardno, int mode, PI_CONST char *name, int *dbhandle)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_OpenDB,"'%s'",name);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncOpenDB, 1, 2 + strlen(name) + 1);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), cardno);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), mode);
|
|
strcpy(DLP_REQUEST_DATA(req, 0, 2), name);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
*dbhandle = get_byte(DLP_RESPONSE_DATA(res, 0, 0));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"-> dlp_OpenDB dbhandle=%d\n", *dbhandle));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_DeleteDB(int sd, int card, const char *name)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_DeleteDB,"%s",name);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncDeleteDB, 1, 2 + (strlen(name) + 1));
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), card);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
strcpy(DLP_REQUEST_DATA(req, 0, 2), name);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_CreateDB(int sd, unsigned long creator, unsigned long type, int cardno,
|
|
int flags, unsigned int version, const char *name, int *dbhandle)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_CreateDB,"'%s' type='%4.4s' creator='%4.4s' flags=0x%04x version=%d",
|
|
name,(const char *)&type,(const char *)&creator,flags,version);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncCreateDB, 1, 14 + (strlen(name) + 1));
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long(DLP_REQUEST_DATA(req, 0, 0), creator);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 4), type);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 8), cardno);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 9), 0);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 10), flags);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 12), version);
|
|
strcpy(DLP_REQUEST_DATA(req, 0, 14), name);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0 && dbhandle) {
|
|
*dbhandle = get_byte(DLP_RESPONSE_DATA(res, 0, 0));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP CreateDB Handle=%d\n", *dbhandle));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_CloseDB(int sd, int dbhandle)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_CloseDB);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncCloseDB, 1, 1);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), (unsigned char) dbhandle);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_CloseDB_All(int sd)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_CloseDB_All);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new_with_argid(dlpFuncCloseDB, 0x21, 0);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_CallApplication(int sd, unsigned long creator, unsigned long type,
|
|
int action, size_t length, const void *data,
|
|
unsigned long *retcode, pi_buffer_t *retbuf)
|
|
{
|
|
int result,
|
|
version = pi_version(sd),
|
|
previous_honor_rx_timeout,
|
|
no_rx_timeout = 0;
|
|
size_t data_len;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_CallApplication,"type='%4.4s' creator='%4.4s' action=0x%04x dataLength=%d",
|
|
(const char *)&type,(const char *)&creator,action,(int)length);
|
|
pi_reset_errors(sd);
|
|
if (retbuf)
|
|
pi_buffer_clear(retbuf);
|
|
|
|
/* we are going to temporarily disable PI_SOCK_HONOR_RX_TIMEOUT
|
|
* so that lengthy tasks on the device side don't cause a
|
|
* connection timeout
|
|
*/
|
|
data_len = sizeof(previous_honor_rx_timeout);
|
|
pi_getsockopt(sd, PI_LEVEL_SOCK, PI_SOCK_HONOR_RX_TIMEOUT,
|
|
&previous_honor_rx_timeout, &data_len);
|
|
|
|
if (version >= 0x0101) { /* PalmOS 2.0 call encoding */
|
|
|
|
if (length + 22 > DLP_BUF_SIZE) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
|
|
"DLP CallApplication: data too large (>64k)"));
|
|
pi_set_error(sd, PI_ERR_DLP_DATASIZE);
|
|
return -131;
|
|
}
|
|
|
|
req = dlp_request_new_with_argid(
|
|
dlpFuncCallApplication, 0x21, 1, 22 + length);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long(DLP_REQUEST_DATA(req, 0, 0), creator);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 4), type);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 8), action);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 10), length);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 14), 0);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 18), 0);
|
|
if (length)
|
|
memcpy(DLP_REQUEST_DATA(req, 0, 22), data, length);
|
|
|
|
data_len = sizeof(no_rx_timeout);
|
|
pi_setsockopt(sd, PI_LEVEL_SOCK, PI_SOCK_HONOR_RX_TIMEOUT,
|
|
&no_rx_timeout, &data_len);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
pi_setsockopt(sd, PI_LEVEL_SOCK, PI_SOCK_HONOR_RX_TIMEOUT,
|
|
&previous_honor_rx_timeout, &data_len);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
data_len = res->argv[0]->len - 16;
|
|
|
|
if (retcode)
|
|
*retcode = get_long(DLP_RESPONSE_DATA(res, 0, 0));
|
|
if (retbuf)
|
|
pi_buffer_append(retbuf, DLP_RESPONSE_DATA(res, 0, 16), data_len);
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP CallApplication Result: %lu (0x%08lx), "
|
|
"and %d bytes:\n",
|
|
get_long(DLP_RESPONSE_DATA(res, 0, 0)),
|
|
get_long(DLP_RESPONSE_DATA(res, 0, 0)),
|
|
data_len));
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 16),
|
|
(size_t)data_len));
|
|
}
|
|
|
|
} else { /* PalmOS 1.0 call encoding */
|
|
|
|
if (length + 8 > DLP_BUF_SIZE) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
|
|
"DLP CallApplication: data too large (>64k)"));
|
|
pi_set_error(sd, PI_ERR_DLP_DATASIZE);
|
|
return -131;
|
|
}
|
|
|
|
req = dlp_request_new (dlpFuncCallApplication, 1, 8 + length);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long(DLP_REQUEST_DATA(req, 0, 0), creator);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 4), action);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), length);
|
|
memcpy(DLP_REQUEST_DATA(req, 0, 8), data, length);
|
|
|
|
data_len = sizeof(no_rx_timeout);
|
|
pi_setsockopt(sd, PI_LEVEL_SOCK, PI_SOCK_HONOR_RX_TIMEOUT,
|
|
&no_rx_timeout, &data_len);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
pi_setsockopt(sd, PI_LEVEL_SOCK, PI_SOCK_HONOR_RX_TIMEOUT,
|
|
&previous_honor_rx_timeout, &data_len);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
data_len = res->argv[0]->len - 6;
|
|
if (retcode)
|
|
*retcode = get_short(DLP_RESPONSE_DATA(res, 0, 2));
|
|
if (retbuf)
|
|
pi_buffer_append(retbuf, DLP_RESPONSE_DATA(res, 0, 6), data_len);
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP CallApplication Action: %d Result:"
|
|
" %u (0x%04x), and %d bytes:\n",
|
|
(int)get_short(DLP_RESPONSE_DATA(res, 0, 0)),
|
|
(unsigned int)get_short(DLP_RESPONSE_DATA(res, 0, 2)),
|
|
(unsigned int)get_short(DLP_RESPONSE_DATA(res, 0, 2)),
|
|
data_len));
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 6),
|
|
(size_t)data_len));
|
|
}
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ResetSystem(int sd)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_ResetSystem);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncResetSystem, 0);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_AddSyncLogEntry(int sd, char *entry)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_AddSyncLogEntry,"%s",entry);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncAddSyncLogEntry, 1, strlen(entry) + 1);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
strcpy(DLP_REQUEST_DATA(req, 0, 0), entry);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
if (result > 0) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP AddSyncLogEntry Entry: \n %s\n", entry));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ReadOpenDBInfo(int sd, int dbhandle, int *records)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_ReadOpenDBInfo);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncReadOpenDBInfo, 1, 1);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
if (records)
|
|
*records = get_short(DLP_RESPONSE_DATA(res, 0, 0));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadOpenDBInfo %d records\n",
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 0))));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_SetDBInfo (int sd, int dbhandle, int flags, int clearFlags,
|
|
unsigned int version, time_t createDate, time_t modifyDate,
|
|
time_t backupDate, unsigned long type, unsigned long creator)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_SetDBInfo);
|
|
pi_reset_errors(sd);
|
|
|
|
if (pi_version(sd) < 0x0102)
|
|
return pi_set_error(sd, PI_ERR_DLP_UNSUPPORTED);
|
|
|
|
req = dlp_request_new(dlpFuncSetDBInfo, 1, 40);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), clearFlags);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 4), flags);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), version);
|
|
set_date((unsigned char *)DLP_REQUEST_DATA(req, 0, 8), createDate);
|
|
set_date((unsigned char *)DLP_REQUEST_DATA(req, 0, 16), modifyDate);
|
|
set_date((unsigned char *)DLP_REQUEST_DATA(req, 0, 24), backupDate);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 32), type);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 36), creator);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_MoveCategory(int sd, int handle, int fromcat, int tocat)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_MoveCategory,"from %d to %d",fromcat,tocat);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncMoveCategory, 1, 4);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), handle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), fromcat);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 2), tocat);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 3), 0);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
if (result >= 0) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP MoveCategory Handle: %d, From: %d, To: %d\n",
|
|
handle, fromcat, tocat));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_OpenConduit(int sd)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_OpenConduit);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncOpenConduit, 0);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
/* if this was not done yet, this will read and cache the DLP version
|
|
that the Palm is running. We need this when reading responses during
|
|
record/resource transfers */
|
|
if (result >= 0)
|
|
pi_version(sd);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_EndOfSync(int sd, int status)
|
|
{
|
|
int result;
|
|
pi_socket_t *ps;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_EndOfSync);
|
|
pi_reset_errors(sd);
|
|
|
|
ps = find_pi_socket(sd);
|
|
if (ps == NULL) {
|
|
errno = ESRCH;
|
|
return PI_ERR_SOCK_INVALID;
|
|
}
|
|
|
|
req = dlp_request_new(dlpFuncEndOfSync, 1, 2);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short(DLP_REQUEST_DATA(req, 0, 0), status);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
/* Messy code to set end-of-sync flag on socket
|
|
so pi_close won't do it for us */
|
|
if (result == 0)
|
|
ps->state = PI_SOCK_CONN_END;
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_AbortSync(int sd)
|
|
{
|
|
pi_socket_t *ps;
|
|
|
|
Trace(dlp_AbortSync);
|
|
pi_reset_errors(sd);
|
|
|
|
/* Pretend we sent the sync end */
|
|
if ((ps = find_pi_socket(sd)) == NULL) {
|
|
errno = ESRCH;
|
|
return PI_ERR_SOCK_INVALID;
|
|
}
|
|
|
|
ps->state = PI_SOCK_CONN_END;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
dlp_WriteUserInfo(int sd, const struct PilotUser *User)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
int len;
|
|
|
|
Trace(dlp_WriteUserInfo);
|
|
pi_reset_errors(sd);
|
|
|
|
len = strlen (User->username) + 1;
|
|
|
|
req = dlp_request_new (dlpFuncWriteUserInfo, 1, 22 + len);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long(DLP_REQUEST_DATA(req, 0, 0), User->userID);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 4), User->viewerID);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 8), User->lastSyncPC);
|
|
set_date((unsigned char *)DLP_REQUEST_DATA(req, 0, 12), User->lastSyncDate);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 20), 0xff);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 21), len);
|
|
strcpy(DLP_REQUEST_DATA(req, 0, 22), User->username);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ReadUserInfo(int sd, struct PilotUser *User)
|
|
{
|
|
int result;
|
|
size_t userlen;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_ReadUserInfo);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncReadUserInfo, 0);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result > 0) {
|
|
User->userID =
|
|
get_long(DLP_RESPONSE_DATA (res, 0, 0));
|
|
User->viewerID =
|
|
get_long(DLP_RESPONSE_DATA (res, 0, 4));
|
|
User->lastSyncPC =
|
|
get_long(DLP_RESPONSE_DATA (res, 0, 8));
|
|
User->successfulSyncDate =
|
|
get_date((const unsigned char *)DLP_RESPONSE_DATA (res, 0, 12));
|
|
User->lastSyncDate =
|
|
get_date((const unsigned char *)DLP_RESPONSE_DATA (res, 0, 20));
|
|
userlen =
|
|
get_byte(DLP_RESPONSE_DATA (res, 0, 28));
|
|
User->passwordLength =
|
|
get_byte(DLP_RESPONSE_DATA (res, 0, 29));
|
|
|
|
memcpy(User->username,
|
|
DLP_RESPONSE_DATA (res, 0, 30), userlen);
|
|
memcpy(User->password,
|
|
DLP_RESPONSE_DATA (res, 0, 30 + userlen),
|
|
User->passwordLength);
|
|
|
|
if (userlen < sizeof(User->username))
|
|
User->username[userlen] = '\0';
|
|
if (User->passwordLength < sizeof(User->password))
|
|
User->password[User->passwordLength] = '\0';
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadUserInfo UID=0x%8.8lX VID=0x%8.8lX "
|
|
"PCID=0x%8.8lX\n",
|
|
User->userID, User->viewerID, User->lastSyncPC));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Last Sync=%s Last Successful Sync=%s",
|
|
ctime (&User->lastSyncDate),
|
|
ctime (&User->successfulSyncDate)));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" Username=%s\n", User->username));
|
|
}
|
|
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ReadNetSyncInfo(int sd, struct NetSyncInfo *i)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_ReadNetSyncInfo);
|
|
pi_reset_errors(sd);
|
|
|
|
if (pi_version(sd) < 0x0101)
|
|
return pi_set_error(sd, PI_ERR_DLP_UNSUPPORTED);
|
|
|
|
req = dlp_request_new(dlpFuncReadNetSyncInfo, 0);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result >= 0) {
|
|
size_t str_offset = 24;
|
|
|
|
i->lanSync = get_byte(DLP_RESPONSE_DATA(res, 0, 0));
|
|
|
|
i->hostName[0] = '\0';
|
|
memcpy(i->hostName, DLP_RESPONSE_DATA(res, 0, str_offset),
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 18)));
|
|
str_offset += get_short(DLP_RESPONSE_DATA(res, 0, 18));
|
|
|
|
i->hostAddress[0] = '\0';
|
|
memcpy(i->hostAddress, DLP_RESPONSE_DATA(res, 0, str_offset),
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 20)));
|
|
str_offset += get_short(DLP_RESPONSE_DATA(res, 0, 20));
|
|
|
|
i->hostSubnetMask[0] = '\0';
|
|
memcpy(i->hostSubnetMask, DLP_RESPONSE_DATA(res, 0, str_offset),
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 22)));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadNetSyncInfo Active: %d\n", i->lanSync ? 1 : 0));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" PC hostname: '%s', address '%s', mask '%s'\n",
|
|
i->hostName, i->hostAddress, i->hostSubnetMask));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_WriteNetSyncInfo(int sd, const struct NetSyncInfo *i)
|
|
{
|
|
int result,
|
|
str_offset = 24;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_WriteNetSyncInfo);
|
|
pi_reset_errors(sd);
|
|
|
|
if (pi_version(sd) < 0x0101)
|
|
return pi_set_error(sd, PI_ERR_DLP_UNSUPPORTED);
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadNetSyncInfo Active: %d\n", i->lanSync ? 1 : 0));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" PC hostname: '%s', address '%s', mask '%s'\n",
|
|
i->hostName, i->hostAddress, i->hostSubnetMask));
|
|
|
|
req = dlp_request_new(dlpFuncWriteNetSyncInfo, 1,
|
|
24 + strlen(i->hostName) +
|
|
strlen(i->hostAddress) + strlen(i->hostSubnetMask) + 3);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
/* Change all settings */
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), 0x80 | 0x40 | 0x20 | 0x10);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), i->lanSync);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 2), 0); /* Reserved1 */
|
|
set_long(DLP_REQUEST_DATA(req, 0, 6), 0); /* Reserved2 */
|
|
set_long(DLP_REQUEST_DATA(req, 0, 10), 0); /* Reserved3 */
|
|
set_long(DLP_REQUEST_DATA(req, 0, 14), 0); /* Reserved4 */
|
|
set_short(DLP_REQUEST_DATA(req, 0, 18), strlen(i->hostName) + 1);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 20), strlen(i->hostAddress) + 1);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 22), strlen(i->hostSubnetMask) + 1);
|
|
|
|
strcpy(DLP_REQUEST_DATA(req, 0, str_offset), i->hostName);
|
|
str_offset += strlen(i->hostName) + 1;
|
|
strcpy(DLP_REQUEST_DATA(req, 0, str_offset), i->hostAddress);
|
|
str_offset += strlen(i->hostAddress) + 1;
|
|
strcpy(DLP_REQUEST_DATA(req, 0, str_offset), i->hostSubnetMask);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
#ifdef _PILOT_SYSPKT_H
|
|
int
|
|
dlp_RPC(int sd, struct RPC_params *p, unsigned long *result)
|
|
{
|
|
int i,
|
|
err = 0;
|
|
long D0 = 0,
|
|
A0 = 0;
|
|
unsigned char *c;
|
|
pi_buffer_t *dlp_buf;
|
|
|
|
Trace(dlp_RPC);
|
|
pi_reset_errors(sd);
|
|
|
|
/* RPC through DLP breaks all the rules and isn't well documented to
|
|
boot */
|
|
dlp_buf = pi_buffer_new (DLP_BUF_SIZE);
|
|
if (dlp_buf == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
dlp_buf->data[0] = 0x2D;
|
|
dlp_buf->data[1] = 1;
|
|
dlp_buf->data[2] = 0; /* Unknown filler */
|
|
dlp_buf->data[3] = 0;
|
|
|
|
InvertRPC(p);
|
|
|
|
set_short(dlp_buf->data + 4, p->trap);
|
|
set_long(dlp_buf->data + 6, D0);
|
|
set_long(dlp_buf->data + 10, A0);
|
|
set_short(dlp_buf->data + 14, p->args);
|
|
|
|
c = dlp_buf->data + 16;
|
|
for (i = p->args - 1; i >= 0; i--) {
|
|
set_byte(c, p->param[i].byRef);
|
|
c++;
|
|
set_byte(c, p->param[i].size);
|
|
c++;
|
|
if (p->param[i].data)
|
|
memcpy(c, p->param[i].data, p->param[i].size);
|
|
c += p->param[i].size;
|
|
if (p->param[i].size & 1)
|
|
*c++ = 0;
|
|
}
|
|
|
|
if (pi_write(sd, dlp_buf->data, (size_t)(c - dlp_buf->data)) > 0) {
|
|
err = 0;
|
|
if (p->reply) {
|
|
int l = pi_read(sd, dlp_buf, (size_t)(c - dlp_buf->data + 2));
|
|
|
|
if (l < 0)
|
|
err = l;
|
|
else if (l < 6)
|
|
err = -1;
|
|
else if (dlp_buf->data[0] != 0xAD)
|
|
err = -2;
|
|
else if (get_short(dlp_buf->data + 2)) {
|
|
err = -get_short(dlp_buf->data + 2);
|
|
pi_set_palmos_error(sd, -err);
|
|
} else {
|
|
D0 = get_long(dlp_buf->data + 8);
|
|
A0 = get_long(dlp_buf->data + 12);
|
|
c = dlp_buf->data + 18;
|
|
for (i = p->args - 1; i >= 0; i--) {
|
|
if (p->param[i].byRef && p->param[i].data)
|
|
memcpy(p->param[i].data, c + 2,
|
|
p->param[i].size);
|
|
c += 2 + ((p->param[i].size + 1) &
|
|
(unsigned)~1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pi_buffer_free (dlp_buf);
|
|
|
|
UninvertRPC(p);
|
|
|
|
if (result) {
|
|
if (p->reply == RPC_PtrReply) {
|
|
*result = A0;
|
|
} else if (p->reply == RPC_IntReply) {
|
|
*result = D0;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
int
|
|
dlp_ReadFeature(int sd, unsigned long creator, int num,
|
|
unsigned long *feature)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_ReadFeature,"creator='%4.4s' num=%d",(const char *)&creator,num);
|
|
pi_reset_errors(sd);
|
|
|
|
if (pi_version(sd) < 0x0101) {
|
|
struct RPC_params p;
|
|
int val;
|
|
unsigned long errCode;
|
|
|
|
if (feature == NULL)
|
|
return 0;
|
|
|
|
*feature = 0x12345678;
|
|
|
|
PackRPC(&p, 0xA27B, RPC_IntReply, RPC_Long(creator), RPC_Short(num), RPC_LongPtr(feature), RPC_End);
|
|
|
|
val = dlp_RPC(sd, &p, &errCode);
|
|
|
|
if (val < 0) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadFeature Error: %s (%d)\n",
|
|
dlp_errorlist[-val], val));
|
|
|
|
return val;
|
|
}
|
|
|
|
if (errCode) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadFeature FtrGet error 0x%8.8lX\n",
|
|
res));
|
|
pi_set_palmos_error(sd, (int)errCode);
|
|
return pi_set_error(sd, PI_ERR_DLP_PALMOS);
|
|
}
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" DLP ReadFeature Feature: 0x%8.8lX\n",
|
|
(unsigned long) *feature));
|
|
|
|
return 0;
|
|
}
|
|
|
|
Trace(dlp_ReadFeatureV2);
|
|
|
|
req = dlp_request_new(dlpFuncReadFeature, 1, 6);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long(DLP_REQUEST_DATA(req, 0, 0), creator);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 4), num);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
if (feature)
|
|
*feature = (unsigned long)
|
|
get_long(DLP_RESPONSE_DATA(res, 0, 0));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadFeature Feature: 0x%8.8lX\n",
|
|
(unsigned long)
|
|
get_long(DLP_RESPONSE_DATA(res, 0, 0))));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
#endif /* IFDEF _PILOT_SYSPKT_H */
|
|
|
|
int
|
|
dlp_GetROMToken(int sd, unsigned long token, void *buffer, size_t *size)
|
|
{
|
|
unsigned long result;
|
|
|
|
struct RPC_params p;
|
|
|
|
int val;
|
|
unsigned long buffer_ptr;
|
|
|
|
Trace(dlp_GetROMToken);
|
|
pi_reset_errors(sd);
|
|
|
|
#ifdef DLP_TRACE
|
|
if (dlp_trace) {
|
|
fprintf(stderr,
|
|
" Wrote: Token: '%s'\n",
|
|
printlong(token));
|
|
}
|
|
#endif
|
|
|
|
PackRPC(&p, 0xa340, RPC_IntReply, /* sysTrapHwrGetROMToken */
|
|
RPC_Short(0),
|
|
RPC_Long(token),
|
|
RPC_LongPtr(&buffer_ptr),
|
|
RPC_ShortPtr(size), RPC_End);
|
|
|
|
val = dlp_RPC(sd, &p, &result);
|
|
|
|
#ifdef DLP_TRACE
|
|
if (dlp_trace) {
|
|
if (val < 0)
|
|
fprintf(stderr,
|
|
"Result: Error: %s (%d)\n",
|
|
dlp_errorlist[-val], val);
|
|
else if (result)
|
|
fprintf(stderr,
|
|
"FtrGet error 0x%8.8lX\n",
|
|
(unsigned long) result);
|
|
else
|
|
fprintf(stderr,
|
|
" Read: Buffer Ptr: 0x%8.8lX Size: %d\n",
|
|
(unsigned long) buffer_ptr, *size);
|
|
}
|
|
#endif
|
|
|
|
if (buffer) {
|
|
((unsigned char *)buffer)[*size] = 0;
|
|
|
|
PackRPC(&p, 0xa026, RPC_IntReply, /* sysTrapMemMove */
|
|
RPC_Ptr(buffer, *size),
|
|
RPC_Long(buffer_ptr),
|
|
RPC_Long((unsigned long) *size),
|
|
RPC_End);
|
|
|
|
val = dlp_RPC(sd, &p, &result);
|
|
}
|
|
|
|
#ifdef DLP_TRACE
|
|
if (dlp_trace) {
|
|
if (val < 0)
|
|
fprintf(stderr,
|
|
"Result: Error: %s (%d)\n",
|
|
dlp_errorlist[-val], val);
|
|
else if (result)
|
|
fprintf(stderr,
|
|
"FtrGet error 0x%8.8lX\n",
|
|
(unsigned long) result);
|
|
else
|
|
fprintf(stderr,
|
|
" Read: Buffer: %s\n", buffer);
|
|
}
|
|
#endif
|
|
|
|
if (val < 0)
|
|
return val;
|
|
|
|
if (result)
|
|
return -((int)result);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ResetLastSyncPC(int sd)
|
|
{
|
|
int err;
|
|
struct PilotUser User;
|
|
|
|
Trace(dlp_ResetLastSyncPC);
|
|
|
|
if ((err = dlp_ReadUserInfo(sd, &User)) < 0)
|
|
return err;
|
|
|
|
User.lastSyncPC = 0;
|
|
|
|
return dlp_WriteUserInfo(sd, &User);
|
|
}
|
|
|
|
int
|
|
dlp_ResetDBIndex(int sd, int dbhandle)
|
|
{
|
|
int result;
|
|
pi_socket_t *ps;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_ResetDBIndex);
|
|
pi_reset_errors(sd);
|
|
|
|
if ((ps = find_pi_socket(sd)) == NULL) {
|
|
errno = ESRCH;
|
|
return PI_ERR_SOCK_INVALID;
|
|
}
|
|
|
|
ps->dlprecord = 0;
|
|
|
|
req = dlp_request_new(dlpFuncResetRecordIndex, 1, 1);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ReadRecordIDList(int sd, int dbhandle, int sort, int start, int max,
|
|
recordid_t * IDs, int *count)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_ReadRecordIDList,"sort=%d start=%d max=%d",
|
|
sort,start,max);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncReadRecordIDList, 1, 6);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), sort ? 0x80 : 0);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), start);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 4), max);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
int ret, i;
|
|
|
|
ret = get_short(DLP_RESPONSE_DATA(res, 0, 0));
|
|
for (i = 0; i < ret; i++)
|
|
IDs[i] =
|
|
get_long(DLP_RESPONSE_DATA(res, 0, 2 + (i * 4)));
|
|
|
|
if (count)
|
|
*count = ret;
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadRecordIDList %d IDs:\n", ret));
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 2),
|
|
(size_t)(ret * 4)));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_WriteRecord(int sd, int dbhandle, int flags, recordid_t recID,
|
|
int catID, const void *data, size_t length, recordid_t *pNewRecID)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_WriteRecord);
|
|
pi_reset_errors(sd);
|
|
|
|
if (length == (size_t)-1)
|
|
length = strlen((char *) data) + 1;
|
|
|
|
if (pi_version(sd) >= 0x0104) {
|
|
req = dlp_request_new(dlpFuncWriteRecordEx, 1, 12 + length);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0x80); /* "data included" */
|
|
set_long(DLP_REQUEST_DATA(req, 0, 2), recID);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 6), flags);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 7), catID);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 8), 0);
|
|
|
|
memcpy(DLP_REQUEST_DATA(req, 0, 12), data, length);
|
|
} else {
|
|
if ((length + 8) > DLP_BUF_SIZE) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
|
|
"DLP WriteRecord: data too large (>64k)"));
|
|
return PI_ERR_DLP_DATASIZE;
|
|
}
|
|
|
|
req = dlp_request_new(dlpFuncWriteRecord, 1, 8 + length);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0x80); /* "data included" */
|
|
set_long(DLP_REQUEST_DATA(req, 0, 2), recID);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 6), flags);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 7), catID);
|
|
|
|
memcpy(DLP_REQUEST_DATA(req, 0, 8), data, length);
|
|
}
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
if (pNewRecID)
|
|
*pNewRecID = get_long(DLP_RESPONSE_DATA(res, 0, 0));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP WriteRecord Record ID: 0x%8.8lX\n",
|
|
get_long(DLP_RESPONSE_DATA(res, 0, 0))));
|
|
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
record_dump(
|
|
get_long(DLP_RESPONSE_DATA(res, 0, 0)), /* recID */
|
|
0xffff, /* index */
|
|
flags,
|
|
catID,
|
|
(const char *)data, (int)length));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_DeleteRecord(int sd, int dbhandle, int all, recordid_t recID)
|
|
{
|
|
int result,
|
|
flags = all ? 0x80 : 0;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_DeleteRecord);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncDeleteRecord, 1, 6);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), flags);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 2), recID);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_DeleteCategory(int sd, int dbhandle, int category)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_DeleteCategory,"category=%d",category);
|
|
pi_reset_errors(sd);
|
|
|
|
if (pi_version(sd) < 0x0101) {
|
|
/* Emulate if not connected to PalmOS 2.0 */
|
|
int i, cat, attr;
|
|
recordid_t id_;
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP DeleteCategory Emulating with: Handle: %d, "
|
|
"Category: %d\n",
|
|
dbhandle, category & 0xff));
|
|
|
|
for (i = 0;
|
|
(result = dlp_ReadRecordByIndex(sd, dbhandle, i, NULL, &id_,
|
|
&attr, &cat)) >= 0; i++) {
|
|
if (cat != category
|
|
|| (attr & dlpRecAttrDeleted)
|
|
|| (attr & dlpRecAttrArchived))
|
|
continue;
|
|
result = dlp_DeleteRecord(sd, dbhandle, 0, id_);
|
|
if (result < 0)
|
|
break;
|
|
i--; /* Sigh, deleting record moves it to the end. */
|
|
}
|
|
|
|
return result;
|
|
} else {
|
|
int flags = 0x40;
|
|
|
|
req = dlp_request_new(dlpFuncDeleteRecord, 1, 6);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), flags);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 2), category & 0xff);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
int
|
|
dlp_ReadResourceByType(int sd, int dbhandle, unsigned long type, int resID,
|
|
pi_buffer_t *buffer, int *resindex)
|
|
{
|
|
int result,
|
|
data_len;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
int maxBufferSize = pi_maxrecsize(sd) - RECORD_READ_SAFEGUARD_SIZE;
|
|
|
|
TraceX(dlp_ReadResourceByType,"type='%4.4s' resID=%d",(const char *)&type,resID);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new_with_argid(dlpFuncReadResource, 0x21, 1, 12);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 2), type);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), resID);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 8), 0);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 10), buffer ? maxBufferSize : 0);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
data_len = res->argv[0]->len - 10;
|
|
if (resindex)
|
|
*resindex = get_short(DLP_RESPONSE_DATA(res, 0, 6));
|
|
if (buffer) {
|
|
pi_buffer_clear (buffer);
|
|
pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10),
|
|
(size_t)data_len);
|
|
|
|
/* Some devices such as the Tungsten TX, Treo 650 and Treo 700p lock up if you try to read the entire record if the
|
|
** record is almost at the maximum record size. The following mitigates this and allows the record
|
|
** to be read in two chunks.
|
|
*/
|
|
if (data_len == maxBufferSize) {
|
|
dlp_response_free(res);
|
|
req = dlp_request_new_with_argid(dlpFuncReadResource, 0x21, 1, 12);
|
|
if (req != NULL) {
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 2), type);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), resID);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 8), maxBufferSize); /* Offset in record */
|
|
set_short(DLP_REQUEST_DATA(req, 0, 10), RECORD_READ_SAFEGUARD_SIZE);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
data_len = res->argv[0]->len - 10; /* number of bytes returned by the second read... */
|
|
pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10), (size_t)data_len);
|
|
data_len += maxBufferSize; /* ...that add up to the bytes received in the first read */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadResourceByType Type: '%s', ID: %d, "
|
|
"Index: %d, and %d bytes:\n",
|
|
printlong(type), resID,
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 6)),(size_t)data_len));
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 10),(size_t)data_len));
|
|
} else {
|
|
data_len = result;
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return data_len;
|
|
}
|
|
|
|
int
|
|
dlp_ReadResourceByIndex(int sd, int dbhandle, unsigned int resindex, pi_buffer_t *buffer,
|
|
unsigned long *type, int *resID)
|
|
{
|
|
int result,
|
|
data_len,
|
|
large = 0;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
int maxBufferSize = pi_maxrecsize(sd) - RECORD_READ_SAFEGUARD_SIZE;
|
|
|
|
TraceX(dlp_ReadResourceByIndex,"resindex=%d",resindex);
|
|
pi_reset_errors(sd);
|
|
|
|
/* TapWave (DLP 1.4) implements a `large' version of dlpFuncReadResource,
|
|
* which can return resources >64k
|
|
*/
|
|
if (pi_version(sd) >= 0x0104) {
|
|
req = dlp_request_new (dlpFuncReadResourceEx, 1, 12);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), resindex);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 4), 0);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 8), pi_maxrecsize(sd));
|
|
large = 1;
|
|
} else {
|
|
req = dlp_request_new (dlpFuncReadResource, 1, 8);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), resindex);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 4), maxBufferSize);
|
|
}
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
data_len = res->argv[0]->len - (large ? 12 : 10);
|
|
if (type)
|
|
*type = get_long(DLP_RESPONSE_DATA(res, 0, 0));
|
|
if (resID)
|
|
*resID = get_short(DLP_RESPONSE_DATA(res, 0, 4));
|
|
if (buffer) {
|
|
pi_buffer_clear (buffer);
|
|
pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, large ? 12 : 10),
|
|
(size_t)data_len);
|
|
|
|
/* Some devices such as the Tungsten TX, Treo 650 and Treo 700p lock up if you try to read the entire record if the
|
|
** record is almost at the maximum record size. The following mitigates this and allows the record
|
|
** to be read in two chunks.
|
|
*/
|
|
if (data_len == maxBufferSize && !large) {
|
|
dlp_response_free(res);
|
|
req = dlp_request_new (dlpFuncReadResource, 1, 8);
|
|
if (req != NULL) {
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), resindex);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 4), maxBufferSize); /* Offset in record */
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), RECORD_READ_SAFEGUARD_SIZE);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
data_len = res->argv[0]->len - (large ? 12 : 10); /* number of bytes returned by the second read... */
|
|
pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, large ? 12 : 10),
|
|
(size_t)data_len);
|
|
data_len += maxBufferSize; /* ...that add up to the bytes received in the first read */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadResourceByIndex Type: '%s', ID: %d, "
|
|
"Index: %d, and %d bytes:\n",
|
|
printlong(get_long(DLP_RESPONSE_DATA(res, 0, 0))),
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 4)),
|
|
resindex, data_len));
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
pi_dumpdata(DLP_RESPONSE_DATA(res, 0, (large ? 12 : 10)),
|
|
(size_t)data_len));
|
|
} else {
|
|
data_len = result;
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return data_len;
|
|
}
|
|
|
|
int
|
|
dlp_WriteResource(int sd, int dbhandle, unsigned long type, int resID,
|
|
const void *data, size_t length)
|
|
{
|
|
int result,
|
|
large = 0;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_WriteResource,"'%4.4s' #%d",(const char *)&type,resID);
|
|
pi_reset_errors(sd);
|
|
|
|
/* TapWave (DLP 1.4) implements a `large' version of dlpFuncWriteResource,
|
|
* which can store records >64k
|
|
*/
|
|
if (pi_version(sd) >= 0x0104) {
|
|
req = dlp_request_new_with_argid(dlpFuncWriteResourceEx,
|
|
PI_DLP_ARG_FIRST_ID | PI_DLP_ARG_FLAG_LONG, 1, 12 + length);
|
|
large = 1;
|
|
} else {
|
|
if (length > 0xffff)
|
|
length = 0xffff;
|
|
req = dlp_request_new(dlpFuncWriteResource, 1, 10 + length);
|
|
}
|
|
if (req == NULL) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
|
|
"DLP sd:%i large:%i dlp_request_new failed\n",
|
|
sd, large));
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
}
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 2), type);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), resID);
|
|
if (large)
|
|
set_long (DLP_REQUEST_DATA(req, 0, 8), 0); /* device doesn't want length here (it computes it) */
|
|
else
|
|
set_short(DLP_REQUEST_DATA(req, 0, 8), length);
|
|
|
|
memcpy(DLP_REQUEST_DATA(req, 0, large ? 12 : 10), data, length);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
int
|
|
dlp_DeleteResource(int sd, int dbhandle, int all, unsigned long restype,
|
|
int resID)
|
|
{
|
|
int result,
|
|
flags = all ? 0x80 : 0;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_DeleteResource,"restype='%4.4s' resID=%d all=%d",
|
|
(const char *)&restype,resID,all);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncDeleteResource, 1, 8);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), flags);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 2), restype);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), resID);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ReadAppBlock(int sd, int dbhandle, int offset, int reqbytes, pi_buffer_t *retbuf)
|
|
{
|
|
int result,
|
|
data_len;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_ReadAppBlock,"offset=%d reqbytes=%ld",offset,reqbytes);
|
|
pi_reset_errors(sd);
|
|
|
|
if (retbuf)
|
|
pi_buffer_clear(retbuf);
|
|
|
|
req = dlp_request_new(dlpFuncReadAppBlock, 1, 6);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), offset);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 4), reqbytes);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result >= 0) {
|
|
if (result < 2)
|
|
data_len = PI_ERR_DLP_COMMAND;
|
|
else {
|
|
data_len = res->argv[0]->len - 2;
|
|
if (retbuf && data_len)
|
|
pi_buffer_append(retbuf, DLP_RESPONSE_DATA(res, 0, 2),
|
|
(size_t)data_len);
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadAppBlock %d bytes\n", data_len));
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 2),
|
|
(size_t)data_len));
|
|
}
|
|
} else {
|
|
data_len = result;
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return data_len;
|
|
}
|
|
|
|
int
|
|
dlp_WriteAppBlock(int sd, int dbhandle, const /* @unique@ */ void *data,
|
|
size_t length)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_WriteAppBlock,"length=%ld",length);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncWriteAppBlock, 1, 4 + length);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), length);
|
|
|
|
if (length + 10 > DLP_BUF_SIZE) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
|
|
"DLP WriteAppBlock: data too large (>64k)"));
|
|
pi_set_error(sd, PI_ERR_DLP_DATASIZE);
|
|
return -131;
|
|
}
|
|
if (length)
|
|
memcpy(DLP_REQUEST_DATA(req, 0, 4), data, length);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ReadSortBlock(int sd, int dbhandle, int offset, int reqbytes, pi_buffer_t *retbuf)
|
|
{
|
|
int result,
|
|
data_len;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_ReadSortBlock,"offset=%d reqbytes=%d",offset,reqbytes);
|
|
pi_reset_errors(sd);
|
|
|
|
if (retbuf)
|
|
pi_buffer_clear(retbuf);
|
|
|
|
req = dlp_request_new(dlpFuncReadSortBlock, 1, 6);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), offset);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 4), reqbytes);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result >= 0) {
|
|
if (result < 2)
|
|
data_len = PI_ERR_DLP_COMMAND;
|
|
else {
|
|
data_len = res->argv[0]->len - 2;
|
|
if (retbuf)
|
|
pi_buffer_append(retbuf, DLP_RESPONSE_DATA(res, 0, 2),
|
|
(size_t)data_len);
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadSortBlock %d bytes\n", data_len));
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 2),
|
|
(size_t)data_len));
|
|
}
|
|
} else {
|
|
data_len = result;
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return data_len;
|
|
}
|
|
|
|
int
|
|
dlp_WriteSortBlock(int sd, int dbhandle, const /* @unique@ */ void *data,
|
|
size_t length)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_WriteSortBlock,"length=%ld",length);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncWriteSortBlock, 1, 4 + length);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), length);
|
|
|
|
if (length + 10 > DLP_BUF_SIZE) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
|
|
"DLP WriteSortBlock: data too large (>64k)"));
|
|
pi_set_error(sd, PI_ERR_DLP_DATASIZE);
|
|
return -131;
|
|
}
|
|
memcpy(DLP_REQUEST_DATA(req, 0, 4), data, length);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_CleanUpDatabase(int sd, int dbhandle)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_CleanUpDatabase);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncCleanUpDatabase, 1, 1);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ResetSyncFlags(int sd, int dbhandle)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dpl_ResetSyncFlags);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncResetSyncFlags, 1, 1);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ReadNextRecInCategory(int sd, int dbhandle, int category,
|
|
pi_buffer_t *buffer, recordid_t *recuid, int *recindex,
|
|
int *attr)
|
|
{
|
|
int result,
|
|
data_len,
|
|
flags;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_ReadNextRecInCategory,"category=%d",category);
|
|
pi_reset_errors(sd);
|
|
|
|
if (pi_version(sd) < 0x0101) {
|
|
/* Emulate for PalmOS 1.0 */
|
|
int cat,
|
|
rec;
|
|
pi_socket_t *ps;
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadNextRecInCategory Emulating with: Handle: %d, "
|
|
"Category: %d\n",
|
|
dbhandle, category));
|
|
|
|
if ((ps = find_pi_socket(sd)) == 0) {
|
|
errno = ESRCH;
|
|
return -130;
|
|
}
|
|
|
|
for (;;) {
|
|
/* Fetch next modified record (in any category) */
|
|
rec = dlp_ReadRecordByIndex(sd, dbhandle,
|
|
ps->dlprecord, 0, 0,
|
|
0, &cat);
|
|
|
|
if (rec < 0)
|
|
break;
|
|
|
|
if (cat != category) {
|
|
ps->dlprecord++;
|
|
continue;
|
|
}
|
|
|
|
rec = dlp_ReadRecordByIndex(sd, dbhandle,
|
|
ps->dlprecord, buffer,
|
|
recuid, attr, &cat);
|
|
|
|
if (rec >= 0) {
|
|
if (recindex)
|
|
*recindex = ps->dlprecord;
|
|
ps->dlprecord++;
|
|
} else {
|
|
/* If none found, reset modified pointer so
|
|
that another search on a different (or
|
|
the same!) category will work */
|
|
|
|
/* Freeow! Do _not_ reset, as the Palm
|
|
itself does not!
|
|
|
|
ps->dlprecord = 0; */
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return rec;
|
|
}
|
|
|
|
req = dlp_request_new(dlpFuncReadNextRecInCategory, 1, 2);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), category);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
data_len = res->argv[0]->len - 10;
|
|
if (recuid)
|
|
*recuid = get_long(DLP_RESPONSE_DATA(res, 0, 0));
|
|
if (recindex)
|
|
*recindex = get_short(DLP_RESPONSE_DATA(res, 0, 4));
|
|
if (attr)
|
|
*attr = get_byte(DLP_RESPONSE_DATA(res, 0, 8));
|
|
if (buffer) {
|
|
pi_buffer_clear (buffer);
|
|
pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10),
|
|
(size_t)data_len);
|
|
}
|
|
|
|
flags = get_byte(DLP_RESPONSE_DATA(res, 0, 8));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadNextRecInCategory ID: 0x%8.8lX, "
|
|
"Index: %d, Category: %d\n"
|
|
" Flags: %s%s%s%s%s%s (0x%2.2X) and %d bytes:\n",
|
|
(unsigned long) get_long(DLP_RESPONSE_DATA(res,
|
|
0, 0)),
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 4)),
|
|
(int) get_byte(DLP_RESPONSE_DATA(res, 0, 9)),
|
|
(flags & dlpRecAttrDeleted) ? " Deleted" : "",
|
|
(flags & dlpRecAttrDirty) ? " Dirty" : "",
|
|
(flags & dlpRecAttrBusy) ? " Busy" : "",
|
|
(flags & dlpRecAttrSecret) ? " Secret" : "",
|
|
(flags & dlpRecAttrArchived) ? " Archive" : "",
|
|
(!flags) ? " None" : "",
|
|
flags, data_len));
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 10),
|
|
(size_t)data_len));
|
|
} else {
|
|
data_len = result;
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return data_len;
|
|
}
|
|
|
|
int
|
|
dlp_ReadAppPreference(int sd, unsigned long creator, int prefID, int backup,
|
|
int maxsize, void *buffer, size_t *size, int *version)
|
|
{
|
|
int result,
|
|
data_len;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_ReadAppPreference,"creator='%4.4s' prefID=%d backup=%d maxsize=%d",
|
|
(const char *)creator,prefID,backup,maxsize);
|
|
pi_reset_errors(sd);
|
|
|
|
if (pi_version(sd) < 0x0101) {
|
|
/* Emulate on PalmOS 1.0 */
|
|
int db;
|
|
pi_buffer_t *buf;
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadAppPreference Emulating with: Creator: '%s', "
|
|
"Id: %d, Size: %d, Backup: %d\n",
|
|
printlong(creator), prefID,
|
|
buffer ? maxsize : 0, backup ? 0x80 : 0));
|
|
|
|
result = dlp_OpenDB(sd, 0, dlpOpenRead, "System Preferences", &db);
|
|
if (result < 0)
|
|
return result;
|
|
|
|
buf = pi_buffer_new (1024);
|
|
|
|
result = dlp_ReadResourceByType(sd, db, creator, prefID, buf,NULL);
|
|
|
|
if (result < 0) {
|
|
/* have to keep the previous error codes to properly return it */
|
|
int err1 = pi_error(sd);
|
|
int err2 = pi_palmos_error(sd);
|
|
|
|
pi_buffer_free (buf);
|
|
if (err1 != PI_ERR_SOCK_DISCONNECTED)
|
|
dlp_CloseDB(sd, db);
|
|
|
|
pi_set_error(sd, err1);
|
|
pi_set_palmos_error(sd, err2);
|
|
return result;
|
|
}
|
|
|
|
if (size)
|
|
*size = buf->used - 2;
|
|
|
|
if (version)
|
|
*version = get_short(buf->data);
|
|
|
|
if (result > 2) {
|
|
result -= 2;
|
|
memcpy(buffer, buf->data + 2, (size_t)result);
|
|
} else {
|
|
result = 0;
|
|
}
|
|
|
|
pi_buffer_free (buf);
|
|
dlp_CloseDB(sd, db);
|
|
return result;
|
|
}
|
|
|
|
req = dlp_request_new(dlpFuncReadAppPreference, 1, 10);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long(DLP_REQUEST_DATA(req, 0, 0), creator);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 4), prefID);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), buffer ? maxsize : 0);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 8), backup ? 0x80 : 0);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 9), 0); /* Reserved */
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
data_len = get_short(DLP_RESPONSE_DATA(res, 0, 4));
|
|
if (version)
|
|
*version = get_short(DLP_RESPONSE_DATA(res, 0, 0));
|
|
if (size && !buffer) *size =
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 2)); /* Total sz */
|
|
if (size && buffer)
|
|
*size = data_len; /* Size returned */
|
|
if (buffer)
|
|
memcpy(buffer, DLP_RESPONSE_DATA(res, 0, 6),
|
|
(size_t)data_len);
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadAppPref Version: %d, "
|
|
"Total size: %d, Read %d bytes:\n",
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 0)),
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 2)),
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 4))));
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
pi_dumpdata(DLP_RESPONSE_DATA(res, 0, 6),
|
|
(size_t)data_len));
|
|
} else {
|
|
data_len = result;
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return data_len;
|
|
}
|
|
|
|
int
|
|
dlp_WriteAppPreference(int sd, unsigned long creator, int prefID, int backup,
|
|
int version, const void *buffer, size_t size)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_WriteAppPreference,"creator='%4.4s' prefID=%d backup=%d version=%d size=%ld",
|
|
(const char *)&creator,prefID,backup,version,size);
|
|
pi_reset_errors(sd);
|
|
|
|
if (pi_version(sd) < 0x0101) {
|
|
/* Emulate on PalmOS 1.0 */
|
|
int db,
|
|
err1,
|
|
err2;
|
|
|
|
if ((result = dlp_OpenDB(sd, 0, dlpOpenWrite, "System Preferences",
|
|
&db)) < 0)
|
|
return result;
|
|
|
|
if (buffer && size) {
|
|
unsigned char dlp_buf[DLP_BUF_SIZE];
|
|
memcpy(dlp_buf + 2, buffer, size);
|
|
set_short(dlp_buf, version);
|
|
result = dlp_WriteResource(sd, db, creator, prefID, dlp_buf,
|
|
size);
|
|
} else {
|
|
result = dlp_WriteResource(sd, db, creator, prefID, NULL,
|
|
0);
|
|
}
|
|
err1 = pi_error(sd);
|
|
err2 = pi_palmos_error(sd);
|
|
|
|
if (err1 != PI_ERR_SOCK_DISCONNECTED)
|
|
dlp_CloseDB(sd, db);
|
|
|
|
if (result < 0) {
|
|
/* restore previous error after DB close */
|
|
pi_set_error(sd, err1);
|
|
pi_set_palmos_error(sd, err2);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
req = dlp_request_new(dlpFuncWriteAppPreference, 1, 12 + size);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long(DLP_REQUEST_DATA(req, 0, 0), creator);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 4), prefID);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), version);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 8), size);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 10), backup ? 0x80 : 0);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 11), 0); /* Reserved */
|
|
|
|
if ((size + 12) > DLP_BUF_SIZE) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_ERR,
|
|
"DLP WriteAppPreferenceV2: data too large (>64k)"));
|
|
return PI_ERR_DLP_DATASIZE;
|
|
}
|
|
memcpy(DLP_REQUEST_DATA(req, 0, 12), buffer, size);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ReadNextModifiedRecInCategory(int sd, int dbhandle, int category,
|
|
pi_buffer_t *buffer, recordid_t *recID,
|
|
int *recindex, int *attr)
|
|
{
|
|
int result,
|
|
data_len;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
TraceX(dlp_ReadNextModifiedRecInCategory,"category=%d",category);
|
|
pi_reset_errors(sd);
|
|
|
|
if (pi_version(sd) < 0x0101) {
|
|
/* Emulate for PalmOS 1.0 */
|
|
int cat;
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ReadNextModifiedRecInCategory"
|
|
" Emulating with: Handle: %d, Category: %d\n",
|
|
dbhandle, category));
|
|
|
|
do {
|
|
/* Fetch next modified record (in any category) */
|
|
result = dlp_ReadNextModifiedRec(sd, dbhandle, buffer,
|
|
recID, recindex, attr, &cat);
|
|
|
|
/* If none found, reset modified pointer so that
|
|
another search on a different (or the same!) category
|
|
will start from the beginning */
|
|
|
|
/* Working on same assumption as ReadNextRecInCat,
|
|
elide this:
|
|
if (r < 0)
|
|
dlp_ResetDBIndex(sd, fHandle);
|
|
*/
|
|
|
|
/* Loop until we fail to get a record or a record
|
|
is found in the proper category */
|
|
}
|
|
while (result >= 0 && cat != category);
|
|
|
|
return result;
|
|
}
|
|
|
|
req = dlp_request_new(dlpFuncReadNextModifiedRecInCategory, 1, 2);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), category);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
data_len = res->argv[0]->len - 10;
|
|
|
|
if (recID)
|
|
*recID = get_long(DLP_RESPONSE_DATA(res, 0, 0));
|
|
if (recindex)
|
|
*recindex = get_short(DLP_RESPONSE_DATA(res, 0, 4));
|
|
if (attr)
|
|
*attr = get_byte(DLP_RESPONSE_DATA(res, 0, 8));
|
|
|
|
if (buffer) {
|
|
pi_buffer_clear (buffer);
|
|
pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10),
|
|
(size_t)data_len);
|
|
}
|
|
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
record_dump(
|
|
get_long(DLP_RESPONSE_DATA(res, 0, 0)), /* recID */
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 4)), /* index */
|
|
get_byte(DLP_RESPONSE_DATA(res, 0, 8)), /* flags */
|
|
get_byte(DLP_RESPONSE_DATA(res, 0, 9)), /* catID */
|
|
DLP_RESPONSE_DATA(res, 0, 10), data_len));
|
|
} else {
|
|
data_len = result;
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return data_len;
|
|
}
|
|
|
|
int
|
|
dlp_ReadNextModifiedRec(int sd, int dbhandle, pi_buffer_t *buffer, recordid_t * recID,
|
|
int *recindex, int *attr, int *category)
|
|
{
|
|
int result,
|
|
data_len;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
Trace(dlp_ReadNextModifiedRec);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncReadNextModifiedRec, 1, 1);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result >= 0) {
|
|
data_len = res->argv[0]->len -10;
|
|
if (recID)
|
|
*recID = get_long(DLP_RESPONSE_DATA(res, 0, 0));
|
|
if (recindex)
|
|
*recindex = get_short(DLP_RESPONSE_DATA(res, 0, 4));
|
|
if (attr)
|
|
*attr = get_byte(DLP_RESPONSE_DATA(res, 0, 8));
|
|
if (category)
|
|
*category = get_byte(DLP_RESPONSE_DATA(res, 0, 9));
|
|
|
|
if (buffer) {
|
|
pi_buffer_clear (buffer);
|
|
pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10),
|
|
(size_t)data_len);
|
|
}
|
|
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
record_dump(
|
|
get_long(DLP_RESPONSE_DATA(res, 0, 0)), /* recID */
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 4)), /* index */
|
|
get_byte(DLP_RESPONSE_DATA(res, 0, 8)), /* flags */
|
|
get_byte(DLP_RESPONSE_DATA(res, 0, 9)), /* catID */
|
|
DLP_RESPONSE_DATA(res, 0, 10), data_len));
|
|
} else {
|
|
data_len = result;
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return data_len;
|
|
}
|
|
|
|
int
|
|
dlp_ReadRecordById(int sd, int dbhandle, recordid_t recuid, pi_buffer_t *buffer,
|
|
int *recindex, int *attr, int *category)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
int maxBufferSize = pi_maxrecsize(sd) - RECORD_READ_SAFEGUARD_SIZE;
|
|
|
|
TraceX(dlp_ReadRecordById,"recuid=0x%08lx",recuid);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncReadRecord, 1, 10);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 2), recuid);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), 0); /* Offset into record */
|
|
set_short(DLP_REQUEST_DATA(req, 0, 8), buffer ? maxBufferSize : 0); /* length to return */
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
result = res->argv[0]->len - 10;
|
|
if (recindex)
|
|
*recindex = get_short(DLP_RESPONSE_DATA(res, 0, 4));
|
|
if (attr)
|
|
*attr = get_byte(DLP_RESPONSE_DATA(res, 0, 8));
|
|
if (category)
|
|
*category = get_byte(DLP_RESPONSE_DATA(res, 0, 9));
|
|
if (buffer) {
|
|
pi_buffer_clear (buffer);
|
|
pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10),
|
|
(size_t)result);
|
|
|
|
/* Some devices such as the Tungsten TX, Treo 650 and Treo 700p lock up if you try to read the entire record if the
|
|
** record is almost at the maximum record size. The following mitigates this and allows the record
|
|
** to be read in two chunks.
|
|
*/
|
|
if (result == maxBufferSize) {
|
|
dlp_response_free(res);
|
|
req = dlp_request_new(dlpFuncReadRecord, 1, 10);
|
|
if (req != NULL) {
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 2), recuid);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), maxBufferSize); /* Offset into record */
|
|
set_short(DLP_REQUEST_DATA(req, 0, 8), buffer ? RECORD_READ_SAFEGUARD_SIZE : 0); /* length to return */
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
result = res->argv[0]->len - 10;
|
|
pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, 10),
|
|
(size_t)result);
|
|
result += maxBufferSize;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
record_dump(
|
|
get_long(DLP_RESPONSE_DATA(res, 0, 0)), /* recID */
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 4)), /* index */
|
|
get_byte(DLP_RESPONSE_DATA(res, 0, 8)), /* flags */
|
|
get_byte(DLP_RESPONSE_DATA(res, 0, 9)), /* catID */
|
|
DLP_RESPONSE_DATA(res, 0, 10), result));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ReadRecordByIndex(int sd, int dbhandle, int recindex, pi_buffer_t *buffer,
|
|
recordid_t * recuid, int *attr, int *category)
|
|
{
|
|
int result,
|
|
large = 0;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
int maxBufferSize = pi_maxrecsize(sd) - RECORD_READ_SAFEGUARD_SIZE;
|
|
|
|
TraceX(dlp_ReadRecordByIndex,"recindex=%d",recindex);
|
|
pi_reset_errors(sd);
|
|
|
|
/* TapWave (DLP 1.4) implements a `large' version of dlpFuncReadRecord,
|
|
* which can return records >64k
|
|
*/
|
|
if (pi_version(sd) >= 0x0104) {
|
|
req = dlp_request_new_with_argid(dlpFuncReadRecordEx, 0x21, 1, 12);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0x00);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), recindex);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 4), 0); /* Offset into record */
|
|
set_long(DLP_REQUEST_DATA(req, 0, 8), pi_maxrecsize(sd)); /* length to return */
|
|
large = 1;
|
|
} else {
|
|
req = dlp_request_new_with_argid(dlpFuncReadRecord, 0x21, 1, 8);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0x00);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), recindex);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 4), 0); /* Offset into record */
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), buffer ? maxBufferSize : 0); /* length to return */
|
|
}
|
|
result = dlp_exec(sd, req, &res);
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
result = res->argv[0]->len - (large ? 14 : 10);
|
|
if (recuid)
|
|
*recuid = get_long(DLP_RESPONSE_DATA(res, 0, 0));
|
|
if (attr)
|
|
*attr = get_byte(DLP_RESPONSE_DATA(res, 0, large ? 12 : 8));
|
|
if (category)
|
|
*category = get_byte(DLP_RESPONSE_DATA(res, 0, large ? 13 : 9));
|
|
if (buffer) {
|
|
pi_buffer_clear (buffer);
|
|
pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, large ? 14 : 10),
|
|
(size_t)result);
|
|
|
|
/* Some devices such as the Tungsten TX, Treo 650 and Treo 700p lock up if you try to read the entire record if the
|
|
** record is almost at the maximum record size. The following mitigates this and allows the record
|
|
** to be read in two chunks.
|
|
*/
|
|
if (result == maxBufferSize && !large) {
|
|
dlp_response_free(res);
|
|
req = dlp_request_new_with_argid(dlpFuncReadRecord, 0x21, 1, 8);
|
|
if (req != NULL) {
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 0), dbhandle);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 1), 0x00);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), recindex);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 4), maxBufferSize); /* Offset into record */
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), buffer ? RECORD_READ_SAFEGUARD_SIZE : 0); /* length to return */
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
result = res->argv[0]->len - (large ? 14 : 10);
|
|
pi_buffer_append (buffer, DLP_RESPONSE_DATA(res, 0, large ? 14 : 10),
|
|
(size_t)result);
|
|
|
|
result += maxBufferSize;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CHECK(PI_DBG_DLP, PI_DBG_LVL_DEBUG,
|
|
record_dump(
|
|
get_long(DLP_RESPONSE_DATA(res, 0, 0)), /* recUID */
|
|
get_short(DLP_RESPONSE_DATA(res, 0, 4)), /* index */
|
|
get_byte(DLP_RESPONSE_DATA(res, 0, large ? 12 : 8)), /* flags */
|
|
get_byte(DLP_RESPONSE_DATA(res, 0, large ? 13 : 9)), /* catID */
|
|
DLP_RESPONSE_DATA(res, 0, large ? 14 : 10), result));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ExpSlotEnumerate(int sd, int *numSlots, int *slotRefs)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
Trace(dlp_ExpSlotEnumerate);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncExpSlotEnumerate, 0);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
int slots, i;
|
|
|
|
slots = get_short(DLP_RESPONSE_DATA (res, 0, 0));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ExpSlotEnumerate %d\n", slots));
|
|
|
|
if (slots) {
|
|
for (i = 0; i < slots && i < *numSlots; i++) {
|
|
slotRefs[i] =
|
|
get_short(DLP_RESPONSE_DATA (res, 0,
|
|
2 + (2 * i)));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" %d Slot-Refnum %d\n", i, slotRefs[i]));
|
|
}
|
|
}
|
|
|
|
*numSlots = slots;
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ExpCardPresent(int sd, int slotRef)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_ExpCardPresent,"slotRef=%d",slotRef);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncExpCardPresent, 1, 2);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short(DLP_REQUEST_DATA(req, 0, 0), slotRef);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ExpCardInfo(int sd, int slotRef, unsigned long *flags, int *numStrings,
|
|
char **strings)
|
|
{
|
|
int result;
|
|
struct dlpRequest* req;
|
|
struct dlpResponse* res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_ExpCardInfo,"slotRef=%d",slotRef);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncExpCardInfo, 1, 2);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short(DLP_REQUEST_DATA(req, 0, 0), slotRef);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
*flags = get_long(DLP_RESPONSE_DATA (res, 0, 0));
|
|
*numStrings = get_byte(DLP_RESPONSE_DATA (res, 0, 4));
|
|
|
|
if (strings && *numStrings) {
|
|
int i, len, sz = 0;
|
|
char *p = DLP_RESPONSE_DATA (res, 0, 8);
|
|
|
|
for (i=0; i < *numStrings; i++, sz+=len, p+=len)
|
|
len = strlen (p) + 1;
|
|
|
|
*strings = (char *) malloc ((size_t)sz);
|
|
if (*strings)
|
|
memcpy (*strings, DLP_RESPONSE_DATA (res, 0, 8), (size_t)sz);
|
|
else
|
|
result = pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
}
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP ExpCardInfo flags: 0x%08lx numStrings: %d\n",
|
|
*flags, *numStrings));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSGetDefaultDir(int sd, int volRefNum, const char *type, char *dir,
|
|
int *len)
|
|
{
|
|
int result, buflen;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSGetDefaultDir,"volRefNum=%d",volRefNum);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncVFSGetDefaultDir,
|
|
1, 2 + (strlen(type) + 1));
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short(DLP_REQUEST_DATA(req, 0, 0), volRefNum);
|
|
strcpy(DLP_REQUEST_DATA(req, 0, 2), type);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
buflen = get_short(DLP_RESPONSE_DATA (res, 0, 0));
|
|
|
|
if (*len < buflen + 1)
|
|
result = pi_set_error(sd, PI_ERR_DLP_BUFSIZE);
|
|
else {
|
|
if (buflen)
|
|
strncpy(dir, DLP_RESPONSE_DATA (res, 0, 2),
|
|
(size_t)buflen);
|
|
else
|
|
dir[0] = '\0';
|
|
|
|
*len = buflen;
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"Default dir is %s\n", dir));
|
|
}
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSImportDatabaseFromFile(int sd, int volRefNum, const char *path,
|
|
int *cardno, unsigned long *localid)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSImportDatabaseFromFile,"volRefNum=%d path='%s'",volRefNum,path);
|
|
pi_reset_errors(sd);
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"Import file <%s>%d\n", path));
|
|
|
|
req = dlp_request_new(dlpFuncVFSImportDatabaseFromFile,
|
|
1, 2 + (strlen(path) + 1));
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short(DLP_REQUEST_DATA(req, 0, 0), volRefNum);
|
|
strcpy(DLP_REQUEST_DATA(req, 0, 2), path);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
|
|
if (result > 0) {
|
|
if (cardno)
|
|
*cardno = get_short(DLP_RESPONSE_DATA (res, 0, 0));
|
|
if (localid)
|
|
*localid = get_short(DLP_RESPONSE_DATA (res, 0, 2));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"Database imported as: cardNo:%d dbID:%d\n",
|
|
get_short(DLP_RESPONSE_DATA (res, 0, 0)),
|
|
get_short(DLP_RESPONSE_DATA (res, 0, 2))));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSExportDatabaseToFile(int sd, int volRefNum, const char *path,
|
|
int cardno, unsigned int localid)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSExportDatabaseToFile,"cardno=%d localid=0x%08lx volRefNum=%d path='%s'",
|
|
cardno,(long)localid,volRefNum,path);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncVFSExportDatabaseToFile,
|
|
1, 8 + (strlen(path) + 1));
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short(DLP_REQUEST_DATA(req, 0, 0), volRefNum);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2), cardno);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 4), localid);
|
|
strcpy(DLP_REQUEST_DATA(req, 0, 8), path);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileCreate(int sd, int volRefNum, const char *name)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileCreate,"volRefNum=%d name='%s'",volRefNum,name);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSFileCreate, 1, 2 + (strlen(name) + 1));
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
|
|
strcpy (DLP_REQUEST_DATA (req, 0, 2), name);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileOpen(int sd, int volRefNum, const char *path, int openMode,
|
|
FileRef *fileRef)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileOpen,"volRefNum=%d mode=0x%04x path='%s'",
|
|
volRefNum,openMode,path);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSFileOpen, 1, 4 + (strlen (path) + 1));
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
|
|
set_short (DLP_REQUEST_DATA (req, 0, 2), openMode);
|
|
strcpy (DLP_REQUEST_DATA (req, 0, 4), path);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result > 0) {
|
|
*fileRef = get_long(DLP_RESPONSE_DATA (res, 0, 0));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"OpenFileRef: 0x%x\n", *fileRef));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileClose(int sd, FileRef fileRef)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileClose,"fileRef=%ld",fileRef);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSFileClose, 1, 4);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
dlp_response_free (res);
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"Closed FileRef: %x\n", fileRef));
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileWrite(int sd, FileRef fileRef, const void *data, size_t len)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res = NULL;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileWrite,"fileRef=%ld len=%ld",(long)fileRef,(long)len);
|
|
pi_reset_errors(sd);
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"Write to FileRef: %x bytes %d\n", fileRef, len));
|
|
|
|
req = dlp_request_new (dlpFuncVFSFileWrite, 1, 8);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
|
|
set_long (DLP_REQUEST_DATA (req, 0, 4), len);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result >= 0) {
|
|
int bytes = pi_write (sd, data, len);
|
|
result = bytes;
|
|
if (result < (int)len) {
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"send failed %d\n", result));
|
|
} else {
|
|
dlp_response_free (res);
|
|
res = NULL;
|
|
|
|
result = dlp_response_read (&res, sd);
|
|
|
|
if (result > 0) {
|
|
pi_set_palmos_error(sd, get_short(DLP_RESPONSE_DATA (res, 0, 2)));
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"send success (%d) res 0x%04x!\n", len, pi_palmos_error(sd)));
|
|
result = bytes;
|
|
}
|
|
}
|
|
}
|
|
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileRead(int sd, FileRef fileRef, pi_buffer_t *data, size_t len)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
size_t bytes = 0;
|
|
int freeze_txid = 1;
|
|
size_t opt_size = sizeof(int);
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileRead,"fileRef=%ld len=%ld",(long)fileRef,(long)len);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSFileRead, 1, 8);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
|
|
set_long (DLP_REQUEST_DATA (req, 0, 4), len);
|
|
|
|
/* if we're using PADP, this socket option is required so that
|
|
* the transfer can complete without error
|
|
*/
|
|
pi_setsockopt(sd, PI_LEVEL_PADP, PI_PADP_FREEZE_TXID, &freeze_txid, &opt_size);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
pi_buffer_clear (data);
|
|
|
|
if (result >= 0) {
|
|
|
|
do {
|
|
result = pi_read(sd, data, len);
|
|
if (result > 0) {
|
|
len -= result;
|
|
bytes += result;
|
|
}
|
|
} while (result > 0 && len > 0);
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"dlp_VFSFileRead: read %u bytes (last pi_read was %d)\n",
|
|
(unsigned)bytes, result));
|
|
|
|
if (result >= 0)
|
|
result = bytes;
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
freeze_txid = 0;
|
|
pi_setsockopt(sd, PI_LEVEL_PADP, PI_PADP_FREEZE_TXID, &freeze_txid, &opt_size);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileDelete(int sd, int volRefNum, const char *path)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileDelete,"volRefNum=%d path='%s'",volRefNum,path);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSFileDelete, 1, 2 + (strlen (path) + 1));
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
|
|
strcpy (DLP_REQUEST_DATA (req, 0, 2), path);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileRename(int sd, int volRefNum, const char *path,
|
|
const char *newname)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileRename,"volRefNum=%d file '%s' renamed '%s'",
|
|
volRefNum,path,rename);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSFileRename,
|
|
1, 4 + (strlen (path) + 1) + (strlen (newname) + 1));
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
|
|
set_short (DLP_REQUEST_DATA (req, 0, 2), 2);
|
|
strcpy (DLP_REQUEST_DATA (req, 0, 4), path);
|
|
strcpy (DLP_REQUEST_DATA (req, 0, 4 + (strlen(path) + 1)), newname);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileEOF(int sd, FileRef fileRef)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileEOF,"fileRef=%ld",fileRef);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSFileEOF, 1, 4);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileTell(int sd, FileRef fileRef,int *position)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileTell,"fileRef=%ld",fileRef);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncVFSFileTell, 1, 4);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result > 0) {
|
|
*position = get_long (DLP_RESPONSE_DATA (res, 0, 0));
|
|
}
|
|
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileGetAttributes (int sd, FileRef fileRef, unsigned long *attributes)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileGetAttributes,"fileRef=%ld",fileRef);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSFileGetAttributes, 1, 4);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result > 0) {
|
|
*attributes = get_long (DLP_RESPONSE_DATA (res, 0, 0));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileSetAttributes(int sd, FileRef fileRef, unsigned long attributes)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileSetAttributes,"fileRef=%ld attributes=0x%08lx",
|
|
fileRef,attributes);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSFileSetAttributes, 1, 8);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
|
|
set_long (DLP_REQUEST_DATA (req, 0, 4), attributes);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileGetDate(int sd, FileRef fileRef, int which, time_t *date)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileGetDate,"fileRef=%ld which=%d",fileRef,which);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSFileGetDate, 1, 6);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
|
|
set_short (DLP_REQUEST_DATA (req, 0, 4), which);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result > 0) {
|
|
*date = get_long (DLP_RESPONSE_DATA (res, 0, 0)) - 2082852000;
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"Requested date(%d): %d / %x calc %d / %x\n",which,
|
|
get_long(DLP_RESPONSE_DATA (res, 0, 0)),
|
|
get_long(DLP_RESPONSE_DATA (res, 0, 0)),
|
|
*date,*date));
|
|
}
|
|
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileSetDate(int sd, FileRef fileRef, int which, time_t date)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileSetDate,"fileRef=%ld which=%d date=0x%08lx",
|
|
(long)fileRef,which,(long)date);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncVFSFileSetDate, 1, 10);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long (DLP_REQUEST_DATA(req, 0, 0), fileRef);
|
|
set_short (DLP_REQUEST_DATA(req, 0, 4), which);
|
|
set_long (DLP_REQUEST_DATA(req, 0, 6), date + 2082852000);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSDirCreate(int sd, int volRefNum, const char *path)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSDirCreate,"volRefNum=%d path='%s'",volRefNum,path);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSDirCreate, 1, 2 + (strlen(path) + 1));
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
|
|
strcpy (DLP_REQUEST_DATA (req, 0, 2), path);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSDirEntryEnumerate(int sd, FileRef dirRefNum,
|
|
unsigned long *dirIterator, int *maxDirItems, struct VFSDirInfo *data)
|
|
{
|
|
unsigned int result,
|
|
entries,
|
|
from,
|
|
at,
|
|
slen,
|
|
count;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSDirEntryEnumerate,"dirRef=%ld",dirRefNum);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSDirEntryEnumerate, 1, 12);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long (DLP_REQUEST_DATA (req, 0, 0), dirRefNum);
|
|
set_long (DLP_REQUEST_DATA (req, 0, 4), *dirIterator);
|
|
set_long (DLP_REQUEST_DATA (req, 0, 8), 8 + *maxDirItems * (4 + vfsMAXFILENAME));
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result > 0) {
|
|
if (result) {
|
|
*dirIterator = get_long (DLP_RESPONSE_DATA (res, 0, 0));
|
|
entries = get_long (DLP_RESPONSE_DATA (res, 0, 4));
|
|
} else {
|
|
*dirIterator = vfsIteratorStop;
|
|
entries = 0;
|
|
}
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"%d results returnd (ilterator: %d)\n", entries,
|
|
*dirIterator));
|
|
|
|
from = 8;
|
|
count = 0;
|
|
|
|
for (at = 0; at < entries; at++) {
|
|
if (*maxDirItems > at) {
|
|
data[at].attr =
|
|
get_long(DLP_RESPONSE_DATA (res, 0, from));
|
|
|
|
/* fix for Sony sims (and probably devices too): they return
|
|
the attributes in the high word of attr instead of the low
|
|
word. We can safely shift it since the high 16 bits are not
|
|
used for VFS flags */
|
|
if ((data[at].attr & 0x0000FFFF) == 0 &&
|
|
(data[at].attr & 0xFFFF0000) != 0)
|
|
data[at].attr >>= 16;
|
|
|
|
strncpy (data[at].name,
|
|
DLP_RESPONSE_DATA(res, 0, from + 4),
|
|
vfsMAXFILENAME);
|
|
data[at].name[vfsMAXFILENAME-1] = 0;
|
|
count++;
|
|
}
|
|
|
|
/* Zero terminated string. Strings that have an
|
|
even length will be null terminated and have a
|
|
pad byte. */
|
|
slen = strlen (DLP_RESPONSE_DATA(res, 0, from + 4)) + 1;
|
|
if (slen & 1)
|
|
slen++; /* make even stringlen + NULL */
|
|
|
|
/* 6 = 4 (attr) + 1 (NULL) -+ 1 (PADDING) */
|
|
from += slen + 4;
|
|
}
|
|
*maxDirItems = count;
|
|
}
|
|
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSVolumeFormat(int sd, unsigned char flags,
|
|
int fsLibRef, struct VFSSlotMountParam *param)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
Trace(dlp_VFSVolumeFormat);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncVFSVolumeFormat, 1, 4);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
/* FIXME check sizes, list the mount params properly */
|
|
set_short(DLP_REQUEST_DATA(req, 0, 0), fsLibRef);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 2),
|
|
sizeof(struct VFSSlotMountParam));
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 4), flags);
|
|
set_byte(DLP_REQUEST_DATA(req, 0, 4), 0); /* unused */
|
|
|
|
set_short(DLP_REQUEST_DATA(req, 0, 6), param->vfsMountParam.volRefNum);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 8), param->vfsMountParam.reserved);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 10), param->vfsMountParam.mountClass);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 14), param->slotLibRefNum);
|
|
set_short(DLP_REQUEST_DATA(req, 0, 16), param->slotRefNum);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free(req);
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSVolumeEnumerate(int sd, int *numVols, int *volRefs)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
Trace(dlp_VFSVolumeEnumerate);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSVolumeEnumerate, 0);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result > 0) {
|
|
int vols, i;
|
|
|
|
vols = get_short (DLP_RESPONSE_DATA (res, 0, 0));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP VFSVolumeEnumerate %d\n", vols));
|
|
|
|
if (vols) {
|
|
for (i = 0; i < vols && i < *numVols; i++) {
|
|
volRefs[i] =
|
|
get_short (DLP_RESPONSE_DATA (res,
|
|
0, 2 + (2 * i)));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
" %d Volume-Refnum %d\n", i, volRefs[i]));
|
|
}
|
|
}
|
|
*numVols = vols;
|
|
}
|
|
else
|
|
*numVols = 0;
|
|
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSVolumeInfo(int sd, int volRefNum, struct VFSInfo *volInfo)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSVolumeInfo,"volRefNum=%d",volRefNum);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSVolumeInfo, 1, 2);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short (DLP_REQUEST_DATA(req, 0, 0), volRefNum);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result > 0) {
|
|
volInfo->attributes = get_long (DLP_RESPONSE_DATA (res, 0, 0));
|
|
volInfo->fsType = get_long (DLP_RESPONSE_DATA (res, 0, 4));
|
|
volInfo->fsCreator = get_long (DLP_RESPONSE_DATA (res, 0, 8));
|
|
volInfo->mountClass = get_long (DLP_RESPONSE_DATA (res, 0, 12));
|
|
volInfo->slotLibRefNum = get_short (DLP_RESPONSE_DATA (res, 0, 16));
|
|
volInfo->slotRefNum = get_short (DLP_RESPONSE_DATA (res, 0, 18));
|
|
volInfo->mediaType = get_long (DLP_RESPONSE_DATA (res, 0, 20));
|
|
volInfo->reserved = get_long (DLP_RESPONSE_DATA (res, 0, 24));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"VFSVolumeInfo: fstype '%s' ", printlong(volInfo->fsType)));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"fscreator: '%s'\nSlotlibref %d Slotref %d\n",
|
|
printlong(volInfo->fsCreator),
|
|
volInfo->slotLibRefNum,
|
|
volInfo->slotRefNum));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"Media: '%s'\n", printlong(volInfo->mediaType)));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSVolumeGetLabel(int sd, int volRefNum, int *len, char *name)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSVolumeGetLabel,"volRefNum=%d",volRefNum);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSVolumeGetLabel, 1, 2);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result > 0) {
|
|
strncpy(name, DLP_RESPONSE_DATA(res, 0, 0),
|
|
(size_t)(*len - 1));
|
|
*len = strlen(name);
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP VFSVolumeGetLabel %s\n", name));
|
|
}
|
|
|
|
dlp_response_free(res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSVolumeSetLabel(int sd, int volRefNum, const char *name)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSVolumeSetLabel,"volRefNum=%d name='%s'",volRefNum,name);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSVolumeSetLabel, 1,
|
|
2 + (strlen(name) + 1));
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
|
|
strcpy (DLP_REQUEST_DATA (req, 0, 2), name);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_response_free (res);
|
|
dlp_request_free (req);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSVolumeSize(int sd, int volRefNum, long *volSizeUsed,
|
|
long *volSizeTotal)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSVolumeSize,"volRefNum=%d",volRefNum);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSVolumeSize, 1, 2);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short (DLP_REQUEST_DATA (req, 0, 0), volRefNum);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result > 0) {
|
|
*volSizeUsed = get_long (DLP_RESPONSE_DATA (res, 0, 0));
|
|
*volSizeTotal = get_long (DLP_RESPONSE_DATA (res, 0, 4));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP VFS Volume Size total: %d used: %d\n",
|
|
*volSizeTotal, *volSizeUsed));
|
|
}
|
|
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileSeek(int sd, FileRef fileRef, int origin, int offset)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileSeek,"fileRef=%ld origin=%d offset=%d",
|
|
fileRef,origin,offset);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSFileSeek, 1, 10);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
|
|
set_short (DLP_REQUEST_DATA (req, 0, 4), origin);
|
|
set_long (DLP_REQUEST_DATA (req, 0, 6), offset);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileResize(int sd, FileRef fileRef, int newSize)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileResize,"fileRef=%ld newSize=%d",fileRef,newSize);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new(dlpFuncVFSFileResize, 1, 8);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long(DLP_REQUEST_DATA(req, 0, 0), fileRef);
|
|
set_long(DLP_REQUEST_DATA(req, 0, 4), newSize);
|
|
|
|
result = dlp_exec(sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_VFSFileSize(int sd, FileRef fileRef, int *size)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1,2);
|
|
TraceX(dlp_VFSFileSize,"fileRef=%ld",fileRef);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncVFSFileSize, 1, 4);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_long (DLP_REQUEST_DATA (req, 0, 0), fileRef);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result > 0) {
|
|
*size = get_long (DLP_RESPONSE_DATA (res, 0, 0));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP VFS File Size: %d\n", *size));
|
|
}
|
|
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
dlp_ExpSlotMediaType(int sd, int slotNum, unsigned long *mediaType)
|
|
{
|
|
int result;
|
|
struct dlpRequest *req;
|
|
struct dlpResponse *res;
|
|
|
|
RequireDLPVersion(sd,1, 4);
|
|
TraceX(dlp_ExpSlotMediaType,"slotNum=%d",slotNum);
|
|
pi_reset_errors(sd);
|
|
|
|
req = dlp_request_new (dlpFuncExpSlotMediaType, 1, 2);
|
|
if (req == NULL)
|
|
return pi_set_error(sd, PI_ERR_GENERIC_MEMORY);
|
|
|
|
set_short (DLP_REQUEST_DATA (req, 0, 0), slotNum);
|
|
|
|
result = dlp_exec (sd, req, &res);
|
|
|
|
dlp_request_free (req);
|
|
|
|
if (result > 0) {
|
|
*mediaType = get_long (DLP_RESPONSE_DATA (res, 0, 0));
|
|
|
|
LOG((PI_DBG_DLP, PI_DBG_LVL_INFO,
|
|
"DLP Media Type for slot %d: %4.4s\n",
|
|
slotNum, mediaType));
|
|
}
|
|
|
|
dlp_response_free (res);
|
|
|
|
return result;
|
|
}
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
|
|
/* ex: set tabstop=4 expandtab: */
|
|
/* Local Variables: */
|
|
/* indent-tabs-mode: t */
|
|
/* c-basic-offset: 8 */
|
|
/* End: */
|