Use a saner variant for computing the number of groups in cpuctl tests
[ltp-debian.git] / pan / zoolib.c
blob8f7bf6f07fc40b3f43c7aafea16c19b9c7b6723f
1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
26 * http://www.sgi.com
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
33 /* $Id: zoolib.c,v 1.8 2009/06/09 17:59:46 subrata_modak Exp $ */
34 /*
35 * ZooLib
37 * A Zoo is a file used to record what test tags are running at the moment.
38 * If the system crashes, we should be able to look at the zoo file to find out
39 * what was currently running. This is especially helpful when running multiple
40 * tests at the same time.
42 * The zoo file is meant to be a text file that fits on a standard console.
43 * You should be able to watch it with `cat zoofile`
45 * zoo file format:
46 * 80 characters per line, ending with a \n
47 * available lines start with '#'
48 * expected line fromat: pid_t,tag,cmdline
52 #include <stdlib.h> /* for getenv */
53 #include <string.h>
54 #include "zoolib.h"
56 char zoo_error[ZELEN];
58 #ifdef __linux__
59 /* glibc2.2 definition needs -D_XOPEN_SOURCE, which breaks other things. */
60 extern int sighold (int __sig);
61 extern int sigrelse (int __sig);
62 #endif
64 /* zoo_mark(): private function to make an entry to the zoo
65 * returns 0 on success, -1 on error */
66 static int zoo_mark(zoo_t z, char *entry);
67 static int zoo_lock(zoo_t z);
68 static int zoo_unlock(zoo_t z);
69 /* cat_args(): helper function to make cmdline from argc, argv */
70 char *cat_args(int argc, char **argv);
73 /* zoo_getname(): create a filename to use for the zoo */
74 char *
75 zoo_getname()
77 char buf[1024];
78 char *zoo;
80 zoo = getenv( "ZOO" );
81 if (zoo) {
82 snprintf(buf, 1024, "%s/%s", zoo, "active");
83 return strdup(buf);
84 } else {
85 /* if there is no environment variable, we don't know where to put it */
86 return NULL;
91 /* zoo_open(): open a zoo for use */
92 zoo_t
93 zoo_open(char *zooname)
95 zoo_t new_zoo;
97 new_zoo = (zoo_t)fopen(zooname, "r+");
98 if (!new_zoo) {
99 if (errno == ENOENT) {
100 /* file doesn't exist, try fopen(xxx, "a+") */
101 new_zoo = (zoo_t)fopen(zooname, "a+");
102 if (!new_zoo) {
103 /* total failure */
104 snprintf(zoo_error, ZELEN,
105 "Could not open zoo as \"%s\", errno:%d %s",
106 zooname, errno, strerror(errno));
107 return 0;
109 fclose(new_zoo);
110 new_zoo = fopen(zooname, "r+");
111 } else {
112 snprintf(zoo_error, ZELEN,
113 "Could not open zoo as \"%s\", errno:%d %s",
114 zooname, errno, strerror(errno));
117 return new_zoo;
121 zoo_close(zoo_t z)
123 int ret;
125 ret = fclose(z);
126 if (ret) {
127 snprintf(zoo_error, ZELEN,
128 "closing zoo caused error, errno:%d %s",
129 errno, strerror(errno));
131 return ret;
135 static int
136 zoo_mark(zoo_t z, char *entry)
138 FILE *fp = (FILE *)z;
139 int found = 0;
140 long pos;
141 char buf[BUFLEN];
143 if (fp == NULL)
144 return -1;
146 if (zoo_lock(z))
147 return -1;
149 /* first fit */
150 rewind(fp);
152 do {
153 pos = ftell(fp);
155 if (fgets(buf, BUFLEN, fp) == NULL)
156 break;
158 if (buf[0] == '#') {
159 rewind(fp);
160 if (fseek(fp, pos, SEEK_SET)) {
161 /* error */
162 snprintf(zoo_error, ZELEN,
163 "seek error while writing to zoo file, errno:%d %s",
164 errno, strerror(errno));
165 return -1;
167 /* write the entry, left justified, and padded/truncated to the
168 * same size as the previous entry */
169 fprintf(fp, "%-*.*s\n", (int)strlen(buf)-1, (int)strlen(buf)-1, entry);
170 found = 1;
171 break;
173 } while (1);
175 if (!found) {
176 if (fseek(fp, 0, SEEK_END)) {
177 snprintf(zoo_error, ZELEN,
178 "error seeking to end of zoo file, errno:%d %s",
179 errno, strerror(errno));
180 return -1;
182 fprintf(fp, "%-*.*s\n", 79, 79, entry);
184 fflush(fp);
186 if (zoo_unlock(z))
187 return -1;
188 return 0;
192 zoo_mark_cmdline(zoo_t z, pid_t p, char *tag, char *cmdline)
194 char new_entry[BUFLEN];
196 snprintf(new_entry, 80, "%d,%s,%s", p, tag, cmdline);
197 return zoo_mark(z, new_entry);
201 zoo_mark_args(zoo_t z, pid_t p, char *tag, int ac, char **av)
203 char *cmdline;
204 int ret;
206 cmdline = cat_args(ac, av);
207 ret = zoo_mark_cmdline(z, p, tag, cmdline);
209 free(cmdline);
210 return ret;
214 zoo_clear(zoo_t z, pid_t p)
216 FILE *fp = (FILE *)z;
217 long pos;
218 char buf[BUFLEN];
219 pid_t that_pid;
220 int found = 0;
223 if (fp == NULL)
224 return -1;
226 if (zoo_lock(z))
227 return -1;
228 rewind(fp);
230 do {
231 pos = ftell(fp);
233 if (fgets(buf, BUFLEN, fp) == NULL)
234 break;
236 if (buf[0] == '#')
237 continue;
239 that_pid = atoi(buf);
240 if (that_pid == p) {
241 if (fseek(fp, pos, SEEK_SET)) {
242 /* error */
243 snprintf(zoo_error, ZELEN,
244 "seek error while writing to zoo file, errno:%d %s",
245 errno, strerror(errno));
246 return -1;
248 if (ftell(fp) != pos) {
249 printf("fseek failed\n");
251 fputs("#", fp);
252 found = 1;
253 break;
255 } while (1);
257 fflush( fp );
259 /* FIXME: unlock zoo file */
260 if (zoo_unlock(z))
261 return -1;
263 if(!found) {
264 snprintf(zoo_error, ZELEN,
265 "zoo_clear() did not find pid(%d)",
267 return 1;
269 return 0;
273 pid_t
274 zoo_getpid(zoo_t z, char *tag)
276 FILE *fp = (FILE *)z;
277 char buf[BUFLEN], *s;
278 pid_t this_pid = -1;
281 if (fp == NULL)
282 return -1;
284 if (zoo_lock(z))
285 return -1;
287 rewind(fp);
288 do {
289 if (fgets(buf, BUFLEN, fp) == NULL)
290 break;
292 if (buf[0] == '#')
293 continue; /* recycled line */
295 if ((s = strchr(buf, ',')) == NULL)
296 continue; /* line was not expected format */
298 if (strncmp(s+1, tag, strlen(tag)))
299 continue; /* tag does not match */
301 this_pid = atoi(buf);
302 break;
303 } while (1);
305 if (zoo_unlock(z))
306 return -1;
307 return this_pid;
311 zoo_lock(zoo_t z)
313 FILE *fp = (FILE *)z;
314 struct flock zlock;
315 sigset_t block_these;
316 int ret;
318 if (fp == NULL)
319 return -1;
321 zlock.l_whence = zlock.l_start = zlock.l_len = 0;
322 zlock.l_type = F_WRLCK;
324 sigemptyset(&block_these);
325 sigaddset(&block_these, SIGINT);
326 sigaddset(&block_these, SIGTERM);
327 sigaddset(&block_these, SIGHUP);
328 sigaddset(&block_these, SIGUSR1);
329 sigaddset(&block_these, SIGUSR2);
330 sigprocmask(SIG_BLOCK, &block_these, NULL);
332 do {
333 ret = fcntl(fileno(fp), F_SETLKW, &zlock);
334 } while (ret == -1 && errno == EINTR);
336 sigprocmask(SIG_UNBLOCK, &block_these, NULL);
337 if (ret == -1) {
338 snprintf(zoo_error, ZELEN,
339 "failed to unlock zoo file, errno:%d %s",
340 errno, strerror(errno));
341 return -1;
343 return 0;
348 zoo_unlock(zoo_t z)
350 FILE *fp = (FILE *)z;
351 struct flock zlock;
352 sigset_t block_these;
353 int ret;
355 if (fp == NULL)
356 return -1;
358 zlock.l_whence = zlock.l_start = zlock.l_len = 0;
359 zlock.l_type = F_UNLCK;
361 sigemptyset(&block_these);
362 sigaddset(&block_these, SIGINT);
363 sigaddset(&block_these, SIGTERM);
364 sigaddset(&block_these, SIGHUP);
365 sigaddset(&block_these, SIGUSR1);
366 sigaddset(&block_these, SIGUSR2);
367 sigprocmask(SIG_BLOCK, &block_these, NULL);
369 do {
370 ret = fcntl(fileno(fp), F_SETLKW, &zlock);
371 } while (ret == -1 && errno == EINTR);
373 sigprocmask(SIG_UNBLOCK, &block_these, NULL);
375 if (ret == -1) {
376 snprintf(zoo_error, ZELEN,
377 "failed to lock zoo file, errno:%d %s",
378 errno, strerror(errno));
379 return -1;
381 return 0;
384 char *
385 cat_args(int argc, char **argv)
387 int a, size;
388 char *cmd;
390 for( size = a = 0; a < argc; a++) {
391 size += strlen(argv[a]);
392 size++;
395 if( (cmd = (char *)malloc(size)) == NULL ) {
396 snprintf(zoo_error, ZELEN,
397 "Malloc Error, %s/%d",
398 __FILE__, __LINE__);
399 return NULL;
402 *cmd='\0';
403 for(a = 0; a < argc ; a++) {
404 if(a != 0)
405 strcat(cmd, " ");
406 strcat(cmd, argv[a]);
409 return cmd;
412 #if defined(UNIT_TEST)
415 void
416 zt_add(zoo_t z, int n)
418 char cmdline[200];
419 char tag[10];
421 snprintf(tag, 10, "%s%d", "test", n);
422 snprintf(cmdline, 200, "%s%d %s %s %s", "runtest", n, "one", "two", "three");
424 zoo_mark_cmdline(z, n, tag, cmdline);
428 main(int argc, char *argv[])
431 char *zooname;
432 zoo_t test_zoo;
433 char *test_tag = "unittest";
434 int i,j;
437 zooname = zoo_getname();
439 if (!zooname) {
440 zooname = strdup("test_zoo");
442 printf("Test zoo filename is %s\n", zooname);
444 if ((test_zoo = zoo_open(zooname)) == NULL) {
445 printf("Error opennning zoo\n");
446 exit(-1);
450 zoo_mark_args(test_zoo, getpid(), test_tag, argc, argv);
453 for(j = 0; j < 5; j++) {
454 for(i = 0; i < 20; i++) {
455 zt_add(test_zoo, i);
458 for(; i >=0; i--) {
459 zoo_clear(test_zoo, i);
463 zoo_clear(test_zoo, getpid());
466 return 0;
474 #endif