#include #include #include #include #include #ifdef HAVE_FCNTL_H #include #endif #ifndef O_SYNC #define O_SYNC O_FSYNC #endif #ifdef HAVE_UNISTD_H #include #include #endif #ifdef DMALLOC #include #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; }