#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifndef O_SYNC
#define O_SYNC O_FSYNC
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <sys/types.h>
#endif
#ifdef DMALLOC
#include <dmalloc.h>
#endif
#include "suck_config.h"
#include "suck.h"
#include "suckutils.h"
#include "both.h"
#include "phrases.h"
#include "db.h"
/* ------------------------------------------------------------------------------ */
/* this file handles all the db routines, creating, deleting, adding records to, */
/* flagging as downloaded, etc. It replaces the old suck.restart and suck.sorted */
/* ------------------------------------------------------------------------------ */
int db_delete(PMaster master) {
int retval = RETVAL_OK;
const char *ptr;
db_close(master); /* just in case */
ptr = full_path(FP_GET, FP_TMPDIR, N_DBFILE);
if(master->debug == TRUE) {
do_debug("Unlinking %s\n", ptr);
}
if(unlink(ptr) != 0 && errno != ENOENT) {
MyPerror(ptr);
retval = RETVAL_ERROR;
}
return retval;
}
/*------------------------------------------------------------------------------*/
int db_write(PMaster master) {
/* write out the entire database */
int retval = RETVAL_OK;
const char *fname;
int fd;
long itemnr, grpnr;
PList itemon;
PGroups grps;
fname = full_path(FP_GET, FP_TMPDIR, N_DBFILE);
if(master->debug == TRUE) {
do_debug("Writing entire db - %s\n", fname);
}
if((fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC
#ifdef EMX /* OS-2 */
| O_BINARY
#endif
, S_IRUSR | S_IWUSR)) == -1) {
retval = RETVAL_ERROR;
MyPerror(fname);
}
else {
/* start at the head of the list, add our dbnr */
itemon = master->head;
/* first write out number of items, so can read em in later*/
itemnr = master->nritems;
write(fd, &itemnr, sizeof(itemnr));
/* now write the list */
itemon = master->head;
itemnr = 0L;
while ( itemon != NULL && retval == RETVAL_OK) {
itemon->dbnr = itemnr;
if(write(fd, itemon, sizeof(List)) != sizeof(List)) {
error_log(ERRLOG_REPORT, suck_phrases[23], NULL);
retval = RETVAL_ERROR;
}
itemon = itemon->next;
itemnr++;
}
/* now write out the groups */
/* first write out the number of items, so can read em in later */
grps = master->groups;
grpnr = 0;
while(grps != NULL) {
grps = grps->next;
grpnr++;
}
write(fd, &grpnr, sizeof(grpnr));
grps = master->groups;
grpnr = 0L;
while (grps != NULL) {
if(write(fd, grps, sizeof(Groups)) != sizeof(Groups)) {
error_log(ERRLOG_REPORT, suck_phrases[23], NULL);
retval = RETVAL_ERROR;
}
grps = grps->next;
grpnr++;
}
close(fd);
}
return retval;
}
/*--------------------------------------------------------------------------------*/
int db_read(PMaster master) {
/* read in the entire database, and add it to the end of the current list */
int retval = RETVAL_OK;
const char *fname;
int fd;
PList itemon, ptr;
PGroups grpon, gptr;
long itemnr;
fname = full_path(FP_GET, FP_TMPDIR, N_DBFILE);
if(master->debug == TRUE) {
do_debug("Reading entire db - %s\n", fname);
}
if((fd = open(fname, O_RDONLY
#ifdef EMX /* OS-2 */
| O_BINARY
#endif
)) != -1) { /* read em in */
print_phrases(master->msgs, suck_phrases[2], NULL);
read(fd, &itemnr, sizeof(itemon)); /* get the number of items */
master->nritems = itemnr;
itemon = NULL;
/* have to malloc em first */
do {
if((ptr = malloc(sizeof(List))) == NULL) {
retval = RETVAL_ERROR;
error_log(ERRLOG_REPORT, suck_phrases[22], NULL);
}
else {
if(read(fd, ptr, sizeof(List)) == sizeof(List)) {
itemnr--;
/* add to list */
if( master->head == NULL) {
master->head = ptr;
}
else {
itemon->next = ptr;
}
itemon = ptr; /* so we can track where we're at */
if(master->debug == TRUE) {
do_debug("restart-read %s-%d-%ld-%d-%d-%d\n", ptr->msgnr,
ptr->groupnr, ptr->nr, ptr->mandatory, ptr->downloaded,
ptr->delete, ptr->sentcmd);
}
}
else {
retval = RETVAL_ERROR; /* didn't get in what we expected */
MyPerror(fname);
}
}
}
while(retval == RETVAL_OK && itemnr > 0);
/* now get the groups */
/* get the count first */
read(fd, &itemnr, sizeof(itemnr));
grpon = NULL;
do {
if((gptr = malloc(sizeof(Groups))) == NULL) {
retval = RETVAL_ERROR;
error_log(ERRLOG_REPORT, suck_phrases[22], NULL);
}
else
{
if(read(fd, gptr, sizeof(Groups)) == sizeof(Groups)) {
itemnr--;
if( master->groups == NULL) {
master->groups = gptr;
}
else {
grpon->next = gptr;
}
grpon = gptr;
}
else {
retval = RETVAL_ERROR;
MyPerror(fname);
}
}
}
while(retval == RETVAL_OK && itemnr > 0);
close(fd);
if(retval != RETVAL_OK) {
/* free up what we brought in */
itemon = master->head;
master->nritems = 0;
while (itemon != NULL) {
ptr = itemon->next;
free(itemon);
itemon = ptr;
}
grpon = master->groups;
while(grpon != NULL) {
gptr = grpon->next;
free(grpon);
grpon = gptr;
}
master->head = NULL;
master->groups = NULL;
}
}
return retval;
}
/*-----------------------------------------------------------------------------*/
int db_open(PMaster master) {
int retval = RETVAL_OK;
const char *fname;
if(master->db != -1) {
/* just to be on the safe side */
close(master->db);
}
fname = full_path(FP_GET, FP_TMPDIR, N_DBFILE);
/* we have the sync on it, so that we force the write to disk */
if((master->db = open (fname, O_WRONLY | O_SYNC
#ifdef EMX
| O_BINARY
#endif
)) == -1) {
MyPerror(fname);
retval = RETVAL_ERROR;
}
return retval;
}
/*-----------------------------------------------------------------------------*/
void db_close(PMaster master) {
if(master->db != -1) {
close(master->db);
}
}
/*------------------------------------------------------------------------------*/
int db_mark_dled(PMaster master, PList itemon) {
int retval = RETVAL_OK;
off_t offset;
/* first figure out where we need to be writing to */
offset = sizeof(long) + (itemon->dbnr * sizeof(List));
/* the extra long to skip the number we write out at beginning of file */
if(lseek(master->db, offset, SEEK_SET) == (off_t)-1) {
MyPerror(full_path(FP_GET, FP_TMPDIR, N_DBFILE));
retval = RETVAL_ERROR;
}
else {
itemon->downloaded = TRUE;
if(write(master->db, itemon, sizeof(List)) != sizeof(List)) {
MyPerror(full_path(FP_GET, FP_TMPDIR, N_DBFILE));
error_log(ERRLOG_REPORT, suck_phrases[23], NULL);
retval = RETVAL_ERROR;
}
}
return retval;
}
syntax highlighted by Code2HTML, v. 0.9.1