1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2000-2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include "rdlist.h"
30 #include "rdtable.h"
31
32 static int list_read(int listt, int elemn);
33 static int lwp_write(list_t *list);
34 static int lwp_read(int lwpn);
35
36 /*
37 * This procedure stores the current state of the lists (lwps, processes,
38 * users and project) into the file defined by 'file'.
39 * param file - the file name to be used
40 * return 0, or -1 on error and store the error message in
41 * the global buffer 'errmsg'.
42 */
43 int
list_store(char * file)44 list_store(char *file)
45 {
46 int storefd;
47 time_t tv;
48 char *tstr;
49 int ret = -1;
50
51 if ((storefd = open(file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR))
52 == -1) {
53 format_err("can't open list db: %s\n", file);
54 (void) fprintf(stderr, errmsg);
55 return (-1);
56 }
57 log_msg("writing persistence file: %s\n", file);
58
59 /*
60 * the next do {..} while (false); statement is a replacement
61 * of goto;
62 */
63 do {
64 if (open_prot(storefd, "w") == -1) {
65 format_err("can't open list db: %s\n", file);
66 (void) fprintf(stderr, errmsg);
67 break;
68 }
69 (void) time(&tv);
70 tstr = ctime(&tv);
71 if (wr_string("# RDS data base file generated on: ") == -1)
72 break;
73 if (wr_string(tstr) == -1)
74 break;
75 if (wr_value(LTDB_VERSION_KEY, LTDB_VERSION) == -1)
76 break;
77 if (wr_value(LTDB_TIMESTAMP, tv) == -1)
78 break;
79 /* we will write 4 lists */
80 if (wr_lshead(4) != 0) {
81 format_err("can't write into list db: %s\n",
82 "./listdb");
83 break;
84 }
85 if (list_write(L_LWP, 0) == -1)
86 break;
87 if (list_write(L_PRC_SI, 0) == -1)
88 break;
89 if (list_write(L_USR_SI, 0) == -1)
90 break;
91 if (list_write(L_PRJ_SI, 0) == -1)
92 break;
93 ret = 0;
94 } while (ret);
95
96 if (ret == 0) {
97 struct stat stat_buf;
98 (void) fstat(storefd, &stat_buf);
99 log_msg("wrote: %ld bytes\n", stat_buf.st_size);
100 }
101
102 /* close_prot(); */
103 (void) close(storefd);
104
105 return (ret);
106 }
107
108 /*
109 * This procedure restores the last state of the lists (lwps, processes,
110 * users and project) from the file defined by 'file'.
111 * param file - the file name to be used
112 * return 0, or -1 on error and store the error message in
113 * the global buffer 'errmsg'.
114 */
115 int
list_restore(char * file)116 list_restore(char *file)
117 {
118 int storefd;
119 int listt, elemn, listn;
120 int64_t timestamp;
121 time_t tv;
122 int version;
123 int ret = -1;
124
125 if ((storefd = open(file, O_RDONLY)) == -1)
126 return (ret);
127 log_msg("reading persistence file: %s\n", file);
128
129 /*
130 * the next do {..} while (false); statement is a replacement
131 * of goto;
132 */
133 do {
134 if (open_prot(storefd, "r") == -1)
135 break;
136 if (skip_line() == -1)
137 break;
138 if ((version = r_value(LTDB_VERSION_KEY)) == -1)
139 break;
140 if (version != LTDB_VERSION) {
141 (void) fprintf(stderr,
142 "wrong version %d of db file %s\n",
143 version, file);
144 break;
145 }
146 if ((timestamp = r_value(LTDB_TIMESTAMP)) == -1)
147 break;
148 /* check the file decay time is expired */
149 (void) time(&tv);
150 if ((tv - timestamp) > LTDB_DECAYTIME)
151 break;
152 if ((listn = r_lshead()) == -1)
153 break;
154 while (listn-- > 0) {
155 if ((elemn = r_lhead(&listt)) == -1)
156 break;
157 if (list_read(listt, elemn) != 0) {
158 break;
159 }
160 }
161 ret = 0;
162 } while (ret);
163
164 if (ret == 0) {
165 struct stat stat_buf;
166 (void) fstat(storefd, &stat_buf);
167 log_msg("read: %ld bytes\n", stat_buf.st_size);
168 }
169
170 /* close_prot(); */
171 (void) close(storefd);
172 (void) unlink(file);
173 return (ret);
174 }
175
176 /*
177 * This procedure writes a list of type 'listt' according to the
178 * rds interface protocol. It uses the already opened and initialized
179 * protocol module (see file protocol.[c,h]).
180 * param listt - the type of the list, see rdimpl.h
181 * param Po - print option, if 1 the list will be also printed on stdout.
182 * return 0, or -1 on error and store the error message in
183 * the global buffer 'errmsg'.
184 */
185 int
list_write(int listt,int Po)186 list_write(int listt, int Po)
187 {
188 char idstr[P_MAXVAL];
189 list_t *list;
190 id_info_t *id = NULL, *nextid;
191
192 if (listt == L_LWP) {
193 return (lwp_write(&lwps));
194 } else if (listt == L_SYSTEM) {
195 if (wr_lhead(listt, 1) != 0) {
196 format_err(
197 "RDS protocol error: cannot write list header");
198 return (-1);
199 }
200 (void) snprintf(idstr, sizeof (idstr), "%s", sys_info.name);
201 if (wr_element(listt, (char *)(&sys_info), idstr) != 0) {
202 format_err(
203 "RDS protocol error: cannot write list header");
204 return (-1);
205 }
206
207 } else {
208 switch (listt) {
209 case L_PRC_SI : list = &processes;
210 break;
211 case L_AC_USR :
212 case L_USR_SI : list = &users;
213 break;
214 case L_AC_PRJ :
215 case L_PRJ_SI : list = &projects;
216 break;
217 }
218 id = list->l_head;
219
220 if (wr_lhead(listt, list->l_count) != 0) {
221 format_err(
222 "RDS protocol error: cannot write list header");
223 return (-1);
224 }
225 while (id != NULL) {
226 switch (listt) {
227 case L_PRC_SI :
228 (void) sprintf(idstr, "%d", id->id_pid);
229 break;
230 case L_AC_USR :
231 case L_USR_SI :
232 (void) sprintf(idstr, "%d", id->id_uid);
233 break;
234 case L_AC_PRJ :
235 case L_PRJ_SI :
236 (void) snprintf(idstr, sizeof (idstr), "%s",
237 id->id_name);
238 break;
239 }
240 if (wr_element(listt, (char *)id, idstr) != 0) {
241 format_err(
242 "RDS protocol error: cannot write list header");
243 }
244 if (Po == 1)
245 prtelement(stderr, id);
246 nextid = id->id_next;
247 id = nextid;
248 }
249 }
250 return (0);
251 }
252
253 /*
254 * This procedure prints out all list elements on stdout. The elements
255 * int the list must be of type id_info_t.
256 * param list - the list to be printed
257 */
258 void
list_print(list_t * list,int xid)259 list_print(list_t *list, int xid)
260 {
261
262 id_info_t *id = list->l_head;
263 id_info_t *nextid;
264
265 while (id) {
266 if (xid == -1) {
267 prtelement(stdout, id);
268 } else {
269 switch (list->l_type) {
270 case LT_PROCESS : if (xid == id->id_pid)
271 prtelement(stdout, id);
272 break;
273 case LT_USERS : if (xid == id->id_uid)
274 prtelement(stdout, id);
275 break;
276 case LT_PROJECTS : if (xid == id->id_projid)
277 prtelement(stdout, id);
278 break;
279 default: prtelement(stdout, id);
280 }
281 }
282 nextid = id->id_next;
283 id = nextid;
284 }
285
286 }
287
288 static int
list_read(int listt,int elemn)289 list_read(int listt, int elemn)
290 {
291 char idstr[P_MAXVAL];
292 list_t *list;
293 id_info_t *id;
294
295 if (listt == L_LWP)
296 return (lwp_read(elemn));
297
298 while (elemn-- > 0) {
299 switch (listt) {
300 case L_PRC_SI : list = &processes;
301 break;
302 case L_USR_SI : list = &users;
303 break;
304 case L_PRJ_SI : list = &projects;
305 break;
306 }
307
308 if (list->l_head == NULL) { /* first element */
309 list->l_head = list->l_tail = id =
310 Zalloc(sizeof (id_info_t));
311 list->l_count++;
312 } else {
313 /* a new element */
314 id = list->l_tail;
315 id->id_next = Zalloc(sizeof (id_info_t));
316 id->id_next->id_prev = list->l_tail;
317 id->id_next->id_next = NULL;
318 list->l_tail = id->id_next;
319 id = list->l_tail;
320 list->l_count++;
321 }
322 if (r_element((char *)id, idstr) == -1) {
323 list_clear(list);
324 return (-1);
325 }
326 }
327 return (0);
328 }
329
330 static int
lwp_write(list_t * list)331 lwp_write(list_t *list)
332 {
333 lwpinfo_t lwpsi;
334 lwp_info_t *li = NULL, *nextli;
335
336 li = list->l_head;
337
338 if (wr_lhead(L_LWP, list->l_count) != 0) {
339 format_err(
340 "RDS protocol error: cannot write list header");
341 err_exit();
342 }
343 while (li != NULL) {
344 lwpsi.pr_pid = li->li_psinfo->pr_pid;
345 lwpsi.pr_lwpid = li->li_lwpsinfo->pr_lwpid;
346
347 if (wr_element(L_LWP__I, (char *)&lwpsi, "lwpi") != 0) {
348 format_err(
349 "RDS protocol error: cannot write list header");
350 }
351 if (wr_element(L_LWP__U, (char *)&(li->li_usage), "lwpu")
352 != 0) {
353 format_err(
354 "RDS protocol error: cannot write list header");
355 }
356 if (wr_element(L_LWP, (char *)li, "lwp") != 0) {
357 format_err(
358 "RDS protocol error: cannot write list header");
359 }
360 nextli = li->li_next;
361 li = nextli;
362 }
363 return (0);
364 }
365
366 static int
lwp_read(int lwpn)367 lwp_read(int lwpn)
368 {
369 lwp_info_t *lwp;
370 lwpinfo_t lwpsi;
371
372 char idstr[P_MAXVAL];
373
374 while (lwpn-- > 0) {
375 if (r_element((char *)&lwpsi, idstr) == -1) {
376 return (-1);
377 }
378 lwp = list_add_lwp(&lwps, lwpsi.pr_pid, lwpsi.pr_lwpid);
379 lwp->li_psinfo->pr_pid = lwpsi.pr_pid;
380 lwp->li_lwpsinfo->pr_lwpid = lwpsi.pr_lwpid;
381 if (r_element((char *)&(lwp->li_usage), idstr) == -1) {
382 return (-1);
383 }
384 if (r_element((char *)lwp, idstr) == -1) {
385 return (-1);
386 }
387
388 }
389 return (0);
390 }
391