1 #include <config.h>
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <errno.h>
6 #include <sys/stat.h>
7
8 #ifdef HAVE_FCNTL_H
9 #include <fcntl.h>
10 #endif
11
12 #ifndef O_SYNC
13 #define O_SYNC O_FSYNC
14 #endif
15
16 #ifdef HAVE_UNISTD_H
17 #include <unistd.h>
18 #include <sys/types.h>
19 #endif
20
21 #ifdef DMALLOC
22 #include <dmalloc.h>
23 #endif
24
25 #include "suck_config.h"
26
27 #include "suck.h"
28 #include "suckutils.h"
29 #include "both.h"
30 #include "phrases.h"
31 #include "db.h"
32
33 /* ------------------------------------------------------------------------------ */
34 /* this file handles all the db routines, creating, deleting, adding records to, */
35 /* flagging as downloaded, etc. It replaces the old suck.restart and suck.sorted */
36 /* ------------------------------------------------------------------------------ */
db_delete(PMaster master)37 int db_delete(PMaster master) {
38
39 int retval = RETVAL_OK;
40 const char *ptr;
41
42 db_close(master); /* just in case */
43 ptr = full_path(FP_GET, FP_TMPDIR, N_DBFILE);
44 if(master->debug == TRUE) {
45 do_debug("Unlinking %s\n", ptr);
46 }
47 if(unlink(ptr) != 0 && errno != ENOENT) {
48 MyPerror(ptr);
49 retval = RETVAL_ERROR;
50 }
51
52 return retval;
53 }
54 /*------------------------------------------------------------------------------*/
db_write(PMaster master)55 int db_write(PMaster master) {
56
57 /* write out the entire database */
58 int retval = RETVAL_OK;
59 const char *fname;
60 int fd;
61 long itemnr, grpnr;
62 PList itemon;
63 PGroups grps;
64
65 fname = full_path(FP_GET, FP_TMPDIR, N_DBFILE);
66 if(master->debug == TRUE) {
67 do_debug("Writing entire db - %s\n", fname);
68 }
69
70 if((fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC
71 #ifdef EMX /* OS-2 */
72 | O_BINARY
73 #endif
74 , S_IRUSR | S_IWUSR)) == -1) {
75 retval = RETVAL_ERROR;
76 MyPerror(fname);
77 }
78 else {
79 /* start at the head of the list, add our dbnr */
80 itemon = master->head;
81
82 /* first write out number of items, so can read em in later*/
83 itemnr = master->nritems;
84 write(fd, &itemnr, sizeof(itemnr));
85
86 /* now write the list */
87 itemon = master->head;
88 itemnr = 0L;
89 while ( itemon != NULL && retval == RETVAL_OK) {
90 itemon->dbnr = itemnr;
91 if(write(fd, itemon, sizeof(List)) != sizeof(List)) {
92 error_log(ERRLOG_REPORT, suck_phrases[23], NULL);
93 retval = RETVAL_ERROR;
94 }
95 itemon = itemon->next;
96 itemnr++;
97 }
98
99 /* now write out the groups */
100 /* first write out the number of items, so can read em in later */
101 grps = master->groups;
102 grpnr = 0;
103 while(grps != NULL) {
104 grps = grps->next;
105 grpnr++;
106 }
107 write(fd, &grpnr, sizeof(grpnr));
108
109 grps = master->groups;
110 grpnr = 0L;
111 while (grps != NULL) {
112 if(write(fd, grps, sizeof(Groups)) != sizeof(Groups)) {
113 error_log(ERRLOG_REPORT, suck_phrases[23], NULL);
114 retval = RETVAL_ERROR;
115 }
116 grps = grps->next;
117 grpnr++;
118 }
119 close(fd);
120 }
121
122 return retval;
123 }
124 /*--------------------------------------------------------------------------------*/
db_read(PMaster master)125 int db_read(PMaster master) {
126
127 /* read in the entire database, and add it to the end of the current list */
128 int retval = RETVAL_OK;
129 const char *fname;
130 int fd;
131 PList itemon, ptr;
132 PGroups grpon, gptr;
133 long itemnr;
134
135 fname = full_path(FP_GET, FP_TMPDIR, N_DBFILE);
136 if(master->debug == TRUE) {
137 do_debug("Reading entire db - %s\n", fname);
138 }
139 if((fd = open(fname, O_RDONLY
140 #ifdef EMX /* OS-2 */
141 | O_BINARY
142 #endif
143 )) != -1) { /* read em in */
144 print_phrases(master->msgs, suck_phrases[2], NULL);
145 read(fd, &itemnr, sizeof(itemon)); /* get the number of items */
146
147 master->nritems = itemnr;
148 itemon = NULL;
149 /* have to malloc em first */
150 do {
151 if((ptr = malloc(sizeof(List))) == NULL) {
152 retval = RETVAL_ERROR;
153 error_log(ERRLOG_REPORT, suck_phrases[22], NULL);
154 }
155 else {
156 if(read(fd, ptr, sizeof(List)) == sizeof(List)) {
157 itemnr--;
158 /* add to list */
159 if( master->head == NULL) {
160 master->head = ptr;
161 }
162 else {
163 itemon->next = ptr;
164 }
165 itemon = ptr; /* so we can track where we're at */
166 if(master->debug == TRUE) {
167 do_debug("restart-read %s-%d-%ld-%d-%d-%d\n", ptr->msgnr,
168 ptr->groupnr, ptr->nr, ptr->mandatory, ptr->downloaded,
169 ptr->delete, ptr->sentcmd);
170 }
171 }
172 else {
173 retval = RETVAL_ERROR; /* didn't get in what we expected */
174 MyPerror(fname);
175 }
176 }
177
178 }
179 while(retval == RETVAL_OK && itemnr > 0);
180 /* now get the groups */
181 /* get the count first */
182 read(fd, &itemnr, sizeof(itemnr));
183 grpon = NULL;
184 do {
185 if((gptr = malloc(sizeof(Groups))) == NULL) {
186 retval = RETVAL_ERROR;
187 error_log(ERRLOG_REPORT, suck_phrases[22], NULL);
188 }
189 else
190 {
191 if(read(fd, gptr, sizeof(Groups)) == sizeof(Groups)) {
192 itemnr--;
193 if( master->groups == NULL) {
194 master->groups = gptr;
195 }
196 else {
197 grpon->next = gptr;
198 }
199 grpon = gptr;
200 }
201 else {
202 retval = RETVAL_ERROR;
203 MyPerror(fname);
204 }
205 }
206 }
207 while(retval == RETVAL_OK && itemnr > 0);
208 close(fd);
209 if(retval != RETVAL_OK) {
210 /* free up what we brought in */
211 itemon = master->head;
212 master->nritems = 0;
213 while (itemon != NULL) {
214 ptr = itemon->next;
215 free(itemon);
216 itemon = ptr;
217 }
218 grpon = master->groups;
219 while(grpon != NULL) {
220 gptr = grpon->next;
221 free(grpon);
222 grpon = gptr;
223 }
224 master->head = NULL;
225 master->groups = NULL;
226 }
227 }
228 return retval;
229 }
230 /*-----------------------------------------------------------------------------*/
db_open(PMaster master)231 int db_open(PMaster master) {
232
233 int retval = RETVAL_OK;
234 const char *fname;
235
236 if(master->db != -1) {
237 /* just to be on the safe side */
238 close(master->db);
239 }
240 fname = full_path(FP_GET, FP_TMPDIR, N_DBFILE);
241 /* we have the sync on it, so that we force the write to disk */
242 if((master->db = open (fname, O_WRONLY | O_SYNC
243 #ifdef EMX
244 | O_BINARY
245 #endif
246 )) == -1) {
247 MyPerror(fname);
248 retval = RETVAL_ERROR;
249 }
250 return retval;
251 }
252 /*-----------------------------------------------------------------------------*/
db_close(PMaster master)253 void db_close(PMaster master) {
254 if(master->db != -1) {
255 close(master->db);
256 }
257 }
258 /*------------------------------------------------------------------------------*/
db_mark_dled(PMaster master,PList itemon)259 int db_mark_dled(PMaster master, PList itemon) {
260 int retval = RETVAL_OK;
261 off_t offset;
262
263 /* first figure out where we need to be writing to */
264 offset = sizeof(long) + (itemon->dbnr * sizeof(List));
265 /* the extra long to skip the number we write out at beginning of file */
266 if(lseek(master->db, offset, SEEK_SET) == (off_t)-1) {
267 MyPerror(full_path(FP_GET, FP_TMPDIR, N_DBFILE));
268 retval = RETVAL_ERROR;
269 }
270 else {
271 itemon->downloaded = TRUE;
272 if(write(master->db, itemon, sizeof(List)) != sizeof(List)) {
273 MyPerror(full_path(FP_GET, FP_TMPDIR, N_DBFILE));
274 error_log(ERRLOG_REPORT, suck_phrases[23], NULL);
275 retval = RETVAL_ERROR;
276 }
277 }
278
279 return retval;
280 }
281
282