Commit | Line | Data |
---|---|---|
783c5c09 BJ |
1 | /* Copyright (c) 1979 Regents of the University of California */ |
2 | #include <retrofit.h> | |
3 | #include <sys/types.h> | |
4 | #include <sys/dir.h> | |
5 | #include <sys/stat.h> | |
6 | #include <stdio.h> | |
7 | ||
8 | /* | |
9 | * Checksum the indicated directory, creating the file "check.sum" | |
10 | * with names and int sums stored inside, one per line. The -c | |
11 | * option causes the directory checksums to be verified. | |
12 | */ | |
13 | ||
14 | #define equal(a, b) (strcmp(a, b) == 0) | |
15 | ||
16 | int cflag = 1; /* Flag to verify */ | |
17 | char cname[] = "check.sum"; /* Name of checksum files */ | |
18 | int errs; /* Error count */ | |
19 | ||
20 | main(argc, argv) | |
21 | char **argv; | |
22 | { | |
23 | register char *cp; | |
24 | ||
25 | if (argc == 2 && equal(argv[1], "-c")) { | |
26 | cflag = 0; | |
27 | argc--, argv++; | |
28 | } | |
29 | if (argc < 2) { | |
30 | checkout("."); | |
31 | exit(errs); | |
32 | } | |
33 | while (--argc) { | |
34 | cp = *++argv; | |
35 | if (equal(cp, "-c")) { | |
36 | cflag++; | |
37 | continue; | |
38 | } | |
39 | checkout(cp); | |
40 | } | |
41 | exit(errs); | |
42 | } | |
43 | ||
44 | /* | |
45 | * Checkout a directory. | |
46 | * The fork is necessary to preserve the current directory. | |
47 | */ | |
48 | ||
49 | checkout(dir) | |
50 | char dir[]; | |
51 | { | |
52 | int s, pid; | |
53 | char ename[DIRSIZ+1], linebuf[BUFSIZ]; | |
54 | FILE *cf, *df, *ef; | |
55 | register int sum, c; | |
56 | struct direct dirent; | |
57 | register char *cp, *cp2; | |
58 | ||
59 | pid = fork(); | |
60 | if (pid == -1) { | |
61 | perror("fork"); | |
62 | errs++; | |
63 | return; | |
64 | } | |
65 | if (pid > 0) { | |
66 | while (wait(&s) != pid) | |
67 | ; | |
68 | if (s != 0) | |
69 | errs++; | |
70 | return; | |
71 | } | |
72 | errs = 0; | |
73 | fprintf(stderr, "%s:\n", dir); | |
74 | if (chdir(dir) < 0) { | |
75 | perror(dir); | |
76 | exit(1); | |
77 | } | |
78 | if (cflag) { | |
79 | if ((cf = fopen(cname, "r")) == NULL) { | |
80 | perror(cname); | |
81 | exit(1); | |
82 | } | |
83 | while (fgets(linebuf, BUFSIZ, cf) != NULL) { | |
84 | for (cp = linebuf, cp2 = ename; *cp != ' '; | |
85 | *cp2++ = *cp++) | |
86 | ; | |
87 | *cp2 = '\0'; | |
88 | if (equal(ename, cname)) | |
89 | continue; | |
90 | if ((ef = fopen(ename, "r")) == NULL) { | |
91 | perror(ename); | |
92 | errs++; | |
93 | continue; | |
94 | } | |
95 | c = cksum(ef); | |
96 | fclose(ef); | |
97 | sum = atoi(cp); | |
98 | if (sum != c) { | |
99 | printf("Checksum error: \"%s\" is %d not %d\n", | |
100 | ename, c, sum); | |
101 | errs++; | |
102 | } | |
103 | } | |
104 | exit(errs); | |
105 | } | |
106 | if ((cf = fopen(cname, "w")) == NULL) { | |
107 | perror(cname); | |
108 | exit(1); | |
109 | } | |
110 | if ((df = fopen("", "r")) == NULL) { | |
111 | perror(dir); | |
112 | exit(1); | |
113 | } | |
114 | while (fread((char *) &dirent, sizeof dirent, 1, df) == 1) { | |
115 | struct stat stb; | |
116 | if (dirent.d_ino == 0) | |
117 | continue; | |
118 | for (cp = dirent.d_name, cp2 = ename; *cp && | |
119 | cp-dirent.d_name < DIRSIZ; *cp2++ = *cp++) | |
120 | ; | |
121 | *cp2 = '\0'; | |
122 | if (equal(ename, cname)) | |
123 | continue; | |
124 | if ((ef = fopen(ename, "r")) == NULL) { | |
125 | perror(ename); | |
126 | errs++; | |
127 | continue; | |
128 | } | |
129 | fstat(fileno(ef), &stb); | |
130 | if ((stb.st_mode & S_IFMT) != S_IFREG) { | |
131 | fclose(ef); | |
132 | continue; | |
133 | } | |
134 | sum = cksum(ef); | |
135 | fclose(ef); | |
136 | fprintf(cf, "%s %d\n", ename, sum); | |
137 | } | |
138 | exit(errs); | |
139 | } | |
140 | ||
141 | /* | |
142 | * Checksum the passed file. Return the sum of all of its bytes. | |
143 | */ | |
144 | ||
145 | cksum(f) | |
146 | FILE *f; | |
147 | { | |
148 | register int sum, c; | |
149 | ||
150 | sum = 0; | |
151 | while ((c = getc(f)) != EOF) | |
152 | sum += c; | |
153 | if (sum < 0) | |
154 | sum = -sum; | |
155 | if (sum < 0) | |
156 | sum = 0; | |
157 | return(sum); | |
158 | } | |
159 | ||
160 | /* | |
161 | * Convert the passed string to decimal. | |
162 | */ | |
163 | ||
164 | atoi(cp) | |
165 | register char *cp; | |
166 | { | |
167 | register int sum, sign; | |
168 | ||
169 | while (any(*cp, " \t")) | |
170 | cp++; | |
171 | if (*cp == '-') | |
172 | sign = -1; | |
173 | else | |
174 | sign = 1; | |
175 | sum = 0; | |
176 | while (any(*cp, "0123456789")) | |
177 | sum = sum*10 + *cp++ - '0'; | |
178 | return(sign*sum); | |
179 | } | |
180 | ||
181 | /* | |
182 | * Is c any of *cp ? | |
183 | */ | |
184 | ||
185 | any(c, cp) | |
186 | register int c; | |
187 | register char *cp; | |
188 | { | |
189 | while (*cp) | |
190 | if (c == *cp++) | |
191 | return(1); | |
192 | return(0); | |
193 | } |