1 /*
2  *  Copyright (C) 1999-2004 Etymon Systems, Inc.
3  *
4  *  Authors:  Nassib Nassar
5  */
6 
7 /* new */
8 
9 #include <string.h>
10 #include "util.h"
11 
afopendbf(const char * db,int type,const char * mode)12 FILE *afopendbf(const char *db, int type, const char *mode)
13 {
14 	char fn[ETYMON_MAX_PATH_SIZE];
15 	FILE *f;
16 
17 	if (afmakefn(type, db, fn) < 0)
18 		return NULL;
19 	f = fopen(fn, mode);
20 	return f ? f : aferrn(AFEDBIO);
21 }
22 
closefile(FILE * f)23 static inline int closefile(FILE *f)
24 {
25 	if (f) {
26 		if (fclose(f) == EOF)
27 			return aferr(AFEDBIO);
28 	}
29 	return 0;
30 }
31 
afclosedbf(Affile * f)32 int afclosedbf(Affile *f)
33 {
34 	if (closefile(f->info) < 0)
35 		return -1;
36 	if (closefile(f->doctab) < 0)
37 		return -1;
38 	if (closefile(f->udict) < 0)
39 		return -1;
40 	if (closefile(f->upost) < 0)
41 		return -1;
42 	if (closefile(f->ufield) < 0)
43 		return -1;
44 	if (closefile(f->lpost) < 0)
45 		return -1;
46 	if (closefile(f->lfield) < 0)
47 		return -1;
48 	if (closefile(f->fdef) < 0)
49 		return -1;
50 	if (closefile(f->uword) < 0)
51 		return -1;
52 	if (closefile(f->lword) < 0)
53 		return -1;
54 	if (closefile(f->lock) < 0)
55 		return -1;
56 	return 0;
57 }
58 
getftfn(int type)59 static inline char *getftfn(int type)
60 {
61 	if (type < sizeof affntab)
62 		return affntab[type];
63 	else
64 		return aferrn(AFEINVAL);
65 }
66 
67 /* buf is assumed to have capacity ETYMON_MAX_PATH_SIZE */
afmakefn(int type,const char * db,char * buf)68 int afmakefn(int type, const char *db, char *buf)
69 {
70 	int dblen, extlen;
71 	char *ext;
72 
73 	dblen = strlen(db);
74 	memcpy(buf, db, dblen);
75 	buf += dblen;
76 	ext = getftfn(type);
77 	if (!ext)
78 		return -1;
79 	extlen = strlen(ext);
80 	if ((dblen + extlen) >= ETYMON_MAX_PATH_SIZE)
81 		return aferr(AFEBUFOVER);
82 	memcpy(buf, ext, extlen + 1);
83 	return 0;
84 }
85 
86 /*
87 int afgetfsize_nonansi(FILE *f, off_t *size)
88 {
89 	struct stat st;
90 
91 	if (fstat(fileno(f), &st) < 0)
92 		return aferr(AFEDBIO);
93 	*size = st.st_size;
94 	return 0;
95 }
96 */
97 
afgetfsize(FILE * f,off_t * size)98 int afgetfsize(FILE *f, off_t *size)
99 {
100 	off_t save;
101 
102 	if ((save = ftello(f)) < 0)
103 		return aferr(AFEDBIO);
104 	if (fseeko(f, 0, SEEK_END) < 0)
105 		return aferr(AFEDBIO);
106 	if ((*size = ftello(f)) < 0)
107 		return aferr(AFEDBIO);
108 	if (fseeko(f, save, SEEK_SET) < 0)
109 		return aferr(AFEDBIO);
110 	return 0;
111 }
112 
afprintvp(int verbose,int minimum)113 void afprintvp(int verbose, int minimum)
114 {
115 	int x;
116 
117 	for (x = 2; x < minimum; x++)
118 		printf("+");
119 	if (minimum > 2)
120 		printf(" ");
121 }
122 
afprintv(int verbose,int minimum,const char * msg)123 void afprintv(int verbose, int minimum, const char *msg)
124 {
125 	if (verbose >= minimum) {
126 		afprintvp(verbose, minimum);
127 		printf("%s\n", msg);
128 	}
129 }
130 
131 /* old */
132 
133 #include <stdlib.h>
134 #include <stdio.h>
135 #include <unistd.h>
136 #include <ctype.h>
137 #include <sys/types.h>
138 #include <sys/stat.h>
139 #include <fcntl.h>
140 
141 #define ETYMON_UTIL_MAX_ARG_SIZE 4096
142 
143 /**
144    Constructs a path name using a dbname as the stem and appending an
145    extension depending on the type of file requested.
146 
147    @param ftype the type of file (e.g. ETYMON_DB_INFO).
148    @param dbname the database name to use as a stem.
149    @param buf the buffer to construct the path in (assumed to have
150    capacity ETYMON_MAX_PATH_SIZE)
151 */
etymon_db_construct_path(int ftype,const char * dbname,char * buf)152 void etymon_db_construct_path(int ftype, const char* dbname, char* buf) {
153 	int leftover;  /* extra space in buf after dbname is copied in */
154 	/* start with dbname as the stem */
155 	strncpy(buf, dbname, ETYMON_MAX_PATH_SIZE - 1);
156 	buf[ETYMON_MAX_PATH_SIZE - 1] = '\0';
157 	leftover = ETYMON_MAX_PATH_SIZE - strlen(buf) - 1;
158 	/* now add the proper extension */
159 	switch (ftype) {
160 	case ETYMON_DBF_INFO:
161 		strncat(buf, ETYMON_DBF_INFO_EXT, leftover);
162 		break;
163 	case ETYMON_DBF_DOCTABLE:
164 		strncat(buf, ETYMON_DBF_DOCTABLE_EXT, leftover);
165 		break;
166 	case ETYMON_DBF_UDICT:
167 		strncat(buf, ETYMON_DBF_UDICT_EXT, leftover);
168 		break;
169 	case ETYMON_DBF_UPOST:
170 		strncat(buf, ETYMON_DBF_UPOST_EXT, leftover);
171 		break;
172 	case ETYMON_DBF_UFIELD:
173 		strncat(buf, ETYMON_DBF_UFIELD_EXT, leftover);
174 		break;
175 	case ETYMON_DBF_LPOST:
176 		strncat(buf, ETYMON_DBF_LPOST_EXT, leftover);
177 		break;
178 	case ETYMON_DBF_LFIELD:
179 		strncat(buf, ETYMON_DBF_LFIELD_EXT, leftover);
180 		break;
181 	case ETYMON_DBF_LOCK:
182 		strncat(buf, ETYMON_DBF_LOCK_EXT, leftover);
183 		break;
184 	case ETYMON_DBF_FDEF:
185 		strncat(buf, ETYMON_DBF_FDEF_EXT, leftover);
186 		break;
187 	case ETYMON_DBF_UWORD:
188 		strncat(buf, ETYMON_DBF_UWORD_EXT, leftover);
189 		break;
190 	case ETYMON_DBF_LWORD:
191 		strncat(buf, ETYMON_DBF_LWORD_EXT, leftover);
192 		break;
193 	default:
194 		break;
195 	}
196 }
197 
198 
etymon_tolower(char * s)199 void etymon_tolower(char* s) {
200 	char* p = s;
201 
202 	while (*p != '\0') {
203 		*p = tolower(*p);
204 		p++;
205 	}
206 }
207 
208 
etymon_split_options(int argc,char * argv[])209 char*** etymon_split_options(int argc, char *argv[]) {
210 	/*
211 	  we're going to create a 2-dimensional array that looks something like this:
212 	  { { "-d", "dbname" },
213 	    { "-f", "file1", "file2", "file3" } }
214 	  to do that we need to first figure out which argv[] are options flags.
215 	  the starts array keeps track of the start of each option group
216 	*/
217 	int* starts;
218 	int starts_count;
219 	int r;
220 	char*** options;
221 	starts = (int*)(malloc(sizeof(int) * argc));
222 	starts_count = 0;
223 	for (r = 1; r < argc; r++) {
224 		/* check if it's an option flag */
225 		if (argv[r][0] == '-') {
226 			if ( (argv[r][1] == '\0') || (argv[r][1] != '-') ) {
227 				/* yes, it's an option flag */
228 				starts[starts_count++] = r;
229 			}
230 		}
231 	}
232 	/* in the last element of starts we store the next (imaginary) start number */
233 	starts[starts_count] = argc;
234 	/* now the starts array contains a list of the indicies of argv[] which contain options flags
235 	   so we we next build the options array based on this information */
236 	options = (char***)(malloc(sizeof(char**) * (starts_count + 1)));
237 	for (r = 0; r < starts_count; r++) {
238 		/* size is the number of columns in this row of the array */
239 		int size = starts[r+1] - starts[r];
240 		int c;
241 		options[r] = (char**)(malloc(sizeof(char*) * (size + 1)));
242 		for (c = 0; c < size; c++) {
243 			char* s = argv[starts[r] + c];
244 			/* convert leading "--" to "-" in option arguments */
245 			if ( (c > 0) && (strncmp(s, "--", 2) == 0) ) {
246 				options[r][c] = (char*)(malloc(strlen(s)));
247 				strcpy(options[r][c], s + 1);
248 			} else {
249 				options[r][c] = (char*)(malloc(strlen(s) + 1));
250 				strcpy(options[r][c], s);
251 			}
252 		}
253 		options[r][size] = NULL;
254 	}
255 	options[starts_count] = NULL;
256 	free(starts);
257 	return options;
258 }
259 
260 
etymon_doctable_getinfo(char * dbname,ETYMON_DOCTABLE * doctable)261 void etymon_doctable_getinfo(char* dbname, ETYMON_DOCTABLE* doctable) {
262 	char fn[ETYMON_MAX_PATH_SIZE];
263 	int fd;
264 
265 	/* need to check for buffer overrun */
266 	etymon_db_construct_path(ETYMON_DBF_DOCTABLE, dbname, fn);
267 	fd = open(fn, O_RDONLY | ETYMON_AF_O_LARGEFILE, ETYMON_DB_PERM);
268 	/* need to check for missing database and transient I/O failures */
269 	if (read(fd, doctable, sizeof(ETYMON_DOCTABLE)) == -1) {
270 		perror("doctable_getinfo():read()");
271 	}
272 	close(fd);
273 }
274