Introduction
Introduction Statistics Contact Development Disclaimer Help
main.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
main.c (4447B)
---
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "diff.h"
5
6 #define DIRECTORY(s) ((s)->qid.type&QTDIR)
7 #define REGULAR_FILE(s) ((s)->type == 'M' && !DIRE…
8
9 Biobuf stdout;
10
11 static char *tmp[] = {"/tmp/diff1XXXXXXXXXXX", "/tmp/diff2XXXXXXXXXXX"};
12 static int whichtmp;
13 static char *progname;
14 static char usage[] = "diff [ -acefmnbwr ] file1 ... file2\n";
15
16 static void
17 rmtmpfiles(void)
18 {
19 while (whichtmp > 0) {
20 whichtmp--;
21 remove(tmp[whichtmp]);
22 }
23 }
24
25 void
26 done(int status)
27 {
28 rmtmpfiles();
29 switch(status)
30 {
31 case 0:
32 exits("");
33 case 1:
34 exits("some");
35 default:
36 exits("error");
37 }
38 /*NOTREACHED*/
39 }
40
41 void
42 panic(int status, char *fmt, ...)
43 {
44 va_list arg;
45
46 Bflush(&stdout);
47
48 fprint(2, "%s: ", progname);
49 va_start(arg, fmt);
50 vfprint(2, fmt, arg);
51 va_end(arg);
52 if (status)
53 done(status);
54 /*NOTREACHED*/
55 }
56
57 static int
58 catch(void *a, char *msg)
59 {
60 USED(a);
61 panic(2, msg);
62 return 1;
63 }
64
65 int
66 mkpathname(char *pathname, char *path, char *name)
67 {
68 if (strlen(path) + strlen(name) > MAXPATHLEN) {
69 panic(0, "pathname %s/%s too long\n", path, name);
70 return 1;
71 }
72 sprint(pathname, "%s/%s", path, name);
73 return 0;
74 }
75
76 static char *
77 mktmpfile(int input, Dir **sb)
78 {
79 int fd, i;
80 char *p;
81 char buf[8192];
82
83 atnotify(catch, 1);
84 /*
85 p = mktemp(tmp[whichtmp++]);
86 fd = create(p, OWRITE, 0600);
87 */
88 fd = mkstemp(p=tmp[whichtmp++]);
89 if (fd < 0) {
90 panic(mflag ? 0: 2, "cannot create %s: %r\n", p);
91 return 0;
92 }
93 while ((i = read(input, buf, sizeof(buf))) > 0) {
94 if ((i = write(fd, buf, i)) < 0)
95 break;
96 }
97 *sb = dirfstat(fd);
98 close(fd);
99 if (i < 0) {
100 panic(mflag ? 0: 2, "cannot read/write %s: %r\n", p);
101 return 0;
102 }
103 return p;
104 }
105
106 static char *
107 statfile(char *file, Dir **sb)
108 {
109 Dir *dir;
110 int input;
111
112 dir = dirstat(file);
113 if(dir == nil) {
114 if (strcmp(file, "-") || (dir = dirfstat(0)) == nil) {
115 panic(mflag ? 0: 2, "cannot stat %s: %r\n", file…
116 return 0;
117 }
118 free(dir);
119 return mktmpfile(0, sb);
120 }
121 else if (!REGULAR_FILE(dir) && !DIRECTORY(dir)) {
122 free(dir);
123 if ((input = open(file, OREAD)) == -1) {
124 panic(mflag ? 0: 2, "cannot open %s: %r\n", file…
125 return 0;
126 }
127 file = mktmpfile(input, sb);
128 close(input);
129 }
130 else
131 *sb = dir;
132 return file;
133 }
134
135 void
136 diff(char *f, char *t, int level)
137 {
138 char *fp, *tp, *p, fb[MAXPATHLEN+1], tb[MAXPATHLEN+1];
139 Dir *fsb, *tsb;
140
141 if ((fp = statfile(f, &fsb)) == 0)
142 goto Return;
143 if ((tp = statfile(t, &tsb)) == 0){
144 free(fsb);
145 goto Return;
146 }
147 if (DIRECTORY(fsb) && DIRECTORY(tsb)) {
148 if (rflag || level == 0)
149 diffdir(fp, tp, level);
150 else
151 Bprint(&stdout, "Common subdirectories: %s and %…
152 fp, tp);
153 }
154 else if (REGULAR_FILE(fsb) && REGULAR_FILE(tsb))
155 diffreg(fp, tp);
156 else {
157 if (REGULAR_FILE(fsb)) {
158 if ((p = utfrrune(f, '/')) == 0)
159 p = f;
160 else
161 p++;
162 if (mkpathname(tb, tp, p) == 0)
163 diffreg(fp, tb);
164 }
165 else {
166 if ((p = utfrrune(t, '/')) == 0)
167 p = t;
168 else
169 p++;
170 if (mkpathname(fb, fp, p) == 0)
171 diffreg(fb, tp);
172 }
173 }
174 free(fsb);
175 free(tsb);
176 Return:
177 rmtmpfiles();
178 }
179
180 void
181 main(int argc, char *argv[])
182 {
183 char *p;
184 int i;
185 Dir *fsb, *tsb;
186 extern int _p9usepwlibrary;
187
188 _p9usepwlibrary = 0;
189 Binit(&stdout, 1, OWRITE);
190 progname = *argv;
191 while (--argc && (*++argv)[0] == '-' && (*argv)[1]) {
192 for (p = *argv+1; *p; p++) {
193 switch (*p) {
194
195 case 'e':
196 case 'f':
197 case 'n':
198 case 'c':
199 case 'a':
200 mode = *p;
201 break;
202
203 case 'w':
204 bflag = 2;
205 break;
206
207 case 'b':
208 bflag = 1;
209 break;
210
211 case 'r':
212 rflag = 1;
213 mflag = 1;
214 break;
215
216 case 'm':
217 mflag = 1;
218 break;
219
220 case 'h':
221 default:
222 progname = "Usage";
223 panic(2, usage);
224 }
225 }
226 }
227 if (argc < 2)
228 panic(2, usage, progname);
229 if ((tsb = dirstat(argv[argc-1])) == nil)
230 panic(2, "can't stat %s\n", argv[argc-1]);
231 if (argc > 2) {
232 if (!DIRECTORY(tsb))
233 panic(2, usage, progname);
234 mflag = 1;
235 }
236 else {
237 if ((fsb = dirstat(argv[0])) == nil)
238 panic(2, "can't stat %s\n", argv[0]);
239 if (DIRECTORY(fsb) && DIRECTORY(tsb))
240 mflag = 1;
241 free(fsb);
242 }
243 free(tsb);
244 for (i = 0; i < argc-1; i++)
245 diff(argv[i], argv[argc-1], 0);
246 done(anychange);
247 /*NOTREACHED*/
248 }
249
250 static char noroom[] = "out of memory - try diff -h\n";
251
252 void *
253 emalloc(unsigned n)
254 {
255 register void *p;
256
257 if ((p = malloc(n)) == 0)
258 panic(2, noroom);
259 return p;
260 }
261
262 void *
263 erealloc(void *p, unsigned n)
264 {
265 register void *rp;
266
267 if ((rp = realloc(p, n)) == 0)
268 panic(2, noroom);
269 return rp;
270 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.