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