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.

470 lines
11 KiB

/*
* $Id: pilot-file.c,v 1.39 2006/10/12 14:21:21 desrod Exp $
*
* pilot-file.c - Palm File dump utility
*
* Pace Willisson <pace@blitz.com> December 1996
* Additions by Kenneth Albanowski
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program 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 General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include "pi-header.h"
#include "pi-source.h"
#include "pi-file.h"
#include "pi-userland.h"
/***********************************************************************
*
* Function: iso_time_str
*
* Summary: Build an ISO-compliant date string
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
static char *iso_time_str(time_t t)
{
struct tm tm;
static char buf[50];
tm = *localtime(&t);
sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
return (buf);
}
/***********************************************************************
*
* Function: dump
*
* Summary: Dump data as requested by other functions
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
static void dump(void *buf, int n)
{
int ch,
i,
j;
for (i = 0; i < n; i += 16) {
printf("%04x: ", i);
for (j = 0; j < 16; j++) {
if (i + j < n)
printf("%02x ",
((unsigned char *) buf)[i + j]);
else
printf(" ");
}
printf(" ");
for (j = 0; j < 16 && i + j < n; j++) {
ch = ((unsigned char *) buf)[i + j] & 0x7f;
if (ch < ' ' || ch >= 0x7f)
putchar('.');
else
putchar(ch);
}
printf("\n");
}
}
/***********************************************************************
*
* Function: dump_header
*
* Summary: Dump the header section of the database
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
static void dump_header(struct pi_file *pf, struct DBInfo *ip)
{
printf("Name..........: %s\n", ip->name);
printf("flags.........: 0x%x", ip->flags);
if (ip->flags & dlpDBFlagNewer)
printf(" NEWER");
if (ip->flags & dlpDBFlagReset)
printf(" RESET");
if (ip->flags & dlpDBFlagResource)
printf(" RESOURCE");
if (ip->flags & dlpDBFlagReadOnly)
printf(" READ_ONLY");
if (ip->flags & dlpDBFlagAppInfoDirty)
printf(" APP-INFO-DIRTY");
if (ip->flags & dlpDBFlagBackup)
printf(" BACKUP");
if (ip->flags & dlpDBFlagCopyPrevention)
printf(" COPY-PREVENTION");
if (ip->flags & dlpDBFlagStream)
printf(" STREAM");
if (ip->flags & dlpDBFlagOpen)
printf(" OPEN");
printf("\n");
printf("version.......: %d\n", ip->version);
printf("creation_time.: %s\n", iso_time_str(ip->createDate));
printf("modified_time.: %s\n", iso_time_str(ip->modifyDate));
printf("backup_time...: %s\n", iso_time_str(ip->backupDate));
printf("mod_number....: %ld\n", ip->modnum);
printf("type..........: %s\n", printlong(ip->type));
printf("CreatorID.....: %s\n", printlong(ip->creator));
printf("\n");
}
/***********************************************************************
*
* Function: dump_app_info
*
* Summary: Dump the AppInfo segment of the database(s)
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
static void dump_app_info(struct pi_file *pf, struct DBInfo *ip)
{
size_t app_info_size;
void *app_info;
pi_file_get_app_info(pf, &app_info, &app_info_size);
printf("app_info_size %zu\n", app_info_size);
dump(app_info, app_info_size);
printf("\n");
}
/***********************************************************************
*
* Function: dump_sort_info
*
* Summary: Dump the SortInfo block of the database(s)
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
static void dump_sort_info(struct pi_file *pf, struct DBInfo *ip)
{
size_t sort_info_size;
void *sort_info;
pi_file_get_sort_info(pf, &sort_info, &sort_info_size);
printf("sort_info_size %zu\n", sort_info_size);
dump(sort_info, sort_info_size);
printf("\n");
}
/***********************************************************************
*
* Function: list_records
*
* Summary: List all records in the database(s)
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
static void list_records(struct pi_file *pf, struct DBInfo *ip, int filedump, int verbose)
{
int attrs,
cat,
entnum, /* Number of the entry record */
id_,
nentries; /* Number of entries in the list */
size_t size;
void *buf;
unsigned long type, uid;
pi_file_get_entries(pf, &nentries);
if (ip->flags & dlpDBFlagResource) {
printf("entries\n");
printf("index\tsize\ttype\tid\n");
for (entnum = 0; entnum < nentries; entnum++) {
if (pi_file_read_resource
(pf, entnum, &buf, &size, &type, &id_) < 0) {
printf("error reading %d\n\n", entnum);
return;
}
printf("%d\t%zu\t%s\t%d\n", entnum, size,
printlong(type), id_);
if (verbose) {
dump(buf, size);
printf("\n");
if (filedump) {
FILE *fp;
char name[64];
sprintf(name, "%4s%04x.bin",
printlong(type), id_);
fp = fopen(name, "w");
fwrite(buf, size, 1, fp);
fclose(fp);
printf("(written to %s)\n", name);
}
}
}
} else {
printf("entries\n");
printf("index\tsize\tattrs\tcat\tuid\n");
for (entnum = 0; entnum < nentries; entnum++) {
if (pi_file_read_record(pf, entnum, &buf, &size,
&attrs, &cat, &uid) < 0) {
printf("error reading %d\n\n", entnum);
return;
}
printf("%d\t%zu\t0x%x\t%d\t0x%lx\n", entnum, size,
attrs, cat, uid);
if (verbose) {
dump(buf, size);
printf("\n");
}
}
}
printf("\n");
}
/***********************************************************************
*
* Function: dump_record
*
* Summary: Dump a record
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
static void dump_record(struct pi_file *pf, struct DBInfo *ip, char *rkey, int filedump)
{
int attrs,
cat,
id_,
record;
size_t size;
void *buf;
unsigned long type;
unsigned long uid;
if (ip->flags & dlpDBFlagResource) {
printf("entries\n");
printf("index\tsize\ttype\tid\n");
if (sscanf(rkey, "%d", &record) == 1) {
if (pi_file_read_resource
(pf, record, &buf, &size, &type, &id_) < 0) {
printf("error reading resource #%d\n\n",
record);
return;
}
} else {
type = makelong(rkey);
id_ = 0;
sscanf(&rkey[4], "%d", &id_);
if (pi_file_read_resource_by_type_id
(pf, type, id_, &buf, &size, &record) < 0) {
printf
("error reading resource %s' #%d (0x%x)\n\n",
printlong(type), id_, id_);
return;
}
}
printf("%d\t%zu\t%s\t%d\n", record, size, printlong(type),
id_);
dump(buf, size);
if (filedump) {
FILE *fp;
char name[64];
sprintf(name, "%4s%04x.bin", printlong(type), id_);
fp = fopen(name, "w");
fwrite(buf, size, 1, fp);
fclose(fp);
printf("(written to %s)\n", name);
}
} else {
printf("entries\n");
printf("index\tsize\tattrs\tcat\tuid\n");
if (sscanf(rkey, "0x%lx", &uid) == 1) {
if (pi_file_read_record_by_id(pf, uid, &buf, &size,
&record, &attrs,
&cat) < 0) {
printf
("error reading record uid 0x%lx\n\n",
uid);
return;
}
} else {
record = 0;
sscanf(rkey, "%d", &record);
if (pi_file_read_record(pf, record, &buf, &size,
&attrs, &cat, &uid) < 0) {
printf("error reading record #%d\n\n",
record);
return;
}
}
printf("%d\t%zu\t0x%x\t%d\t0x%lx\n", record, size, attrs,
cat, uid);
dump(buf, size);
}
printf("\n");
}
int main(int argc, const char **argv)
{
int c, /* switch */
hflag = 0,
aflag = 0,
sflag = 0,
dflag = 0,
lflag = 0,
rflag = 0,
filedump = 0;
char *rkey = NULL;
const char **rargv = NULL;
struct pi_file *pf;
struct DBInfo info;
poptContext po;
struct poptOption options[] = {
USERLAND_RESERVED_OPTIONS
{"header", 'H', POPT_ARG_NONE, &hflag, 0, "Dump the header of the database(s)"},
{"appinfo", 'a', POPT_ARG_NONE, &aflag, 0, "Dump app_info segment of the database(s)"},
{"sortinfo", 's', POPT_ARG_NONE, &sflag, 0, "Dump sort_info block of database(s)"},
{"list", 'l', POPT_ARG_NONE, &lflag, 0, "List all records in the database(s)"},
{"record", 'r', POPT_ARG_STRING, &rkey, 0, "Dump a record by index ('code0') or uid ('1234')"},
{"to-file", 'f', POPT_ARG_NONE, &filedump, 0, "Same as above but also dump records to files"},
{"dump", 'd', POPT_ARG_NONE, &dflag, 0, "Dump all data and all records, very verbose"},
POPT_TABLEEND
};
po = poptGetContext("pilot-file", argc, argv, options, 0);
poptSetOtherOptionHelp(po,"<filename> ...\n\n"
" Dump application and header information from your local PRC/PDB files\n\n"
" Example arguments:\n"
" -l Foo.prc\n"
" -H -a Bar.pdb\n\n");
plu_popt_alias(po,"dump-rec",0,"--bad-option --to-file --record");
plu_popt_alias(po,NULL,'R',"--bad-option --to-file --record");
plu_popt_alias(po,"dump-res",0,"--bad-option --to-file --dump");
plu_popt_alias(po,NULL,'D',"--bad-option --to-file --dump");
if (argc < 2) {
poptPrintUsage(po,stderr,0);
return 1;
}
while ((c = poptGetNextOpt(po)) >= 0) {
fprintf(stderr," ERROR: Unhandled option %d.\n",c);
return 1;
}
if (c < -1) {
plu_badoption(po,c);
}
if (rkey) {
rflag = 1;
}
rargv = poptGetArgs(po);
if (!rargv || !rargv[0]) {
fprintf(stderr," ERROR: Must provide one or more filenames.\n");
return 1;
}
while (*rargv) {
const char *name = *rargv++;
if ((pf = pi_file_open(name)) == NULL) {
fprintf(stderr, " ERROR: Can't open '%s' Does '%s' exist?\n\n",
name, name);
continue;
}
pi_file_get_info(pf, &info);
if (hflag || dflag)
dump_header(pf, &info);
if (aflag || dflag)
dump_app_info(pf, &info);
if (sflag || dflag)
dump_sort_info(pf, &info);
if (lflag || dflag)
list_records(pf, &info, filedump, dflag);
if (rflag)
dump_record(pf, &info, rkey, filedump);
}
return 0;
}
/* 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: */