1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 *
9 * $FreeBSD$
10 *
11 */
12
13#include "ctm.h"
14
15/*---------------------------------------------------------------------------*/
16void
17Fatal_(int ln, char *fn, char *kind)
18{
19    if(Verbose > 2)
20	fprintf(stderr,"Fatal error. (%s:%d)\n",fn,ln);
21    fprintf(stderr,"%s Fatal error: %s\n",FileName, kind);
22}
23#define Fatal(foo) Fatal_(__LINE__,__FILE__,foo)
24#define Assert() Fatal_(__LINE__,__FILE__,"Assert failed.")
25
26/*---------------------------------------------------------------------------*/
27/* get next field, check that the terminating whitespace is what we expect */
28u_char *
29Ffield(FILE *fd, MD5_CTX *ctx,u_char term)
30{
31    static u_char buf[BUFSIZ];
32    int i,l;
33
34    for(l=0;;) {
35	if((i=getc(fd)) == EOF) {
36	    Fatal("Truncated patch.");
37	    return 0;
38	}
39	buf[l++] = i;
40	if(isspace(i))
41	    break;
42	if(l >= sizeof buf) {
43	    Fatal("Corrupt patch.");
44	    printf("Token is too long.\n");
45	    return 0;
46	}
47    }
48    buf[l] = '\0';
49    MD5Update(ctx,buf,l);
50    if(buf[l-1] != term) {
51        Fatal("Corrupt patch.");
52	fprintf(stderr,"Expected \"%s\" but didn't find it {%02x}.\n",
53	    term == '\n' ? "\\n" : " ",buf[l-1]);
54	if(Verbose > 4)
55	    fprintf(stderr,"{%s}\n",buf);
56	return 0;
57    }
58    buf[--l] = '\0';
59    if(Verbose > 4)
60        fprintf(stderr,"<%s>\n",buf);
61    return buf;
62}
63
64int
65Fbytecnt(FILE *fd, MD5_CTX *ctx, u_char term)
66{
67    u_char *p,*q;
68    int u_chars=0;
69
70    p = Ffield(fd,ctx,term);
71    if(!p) return -1;
72    for(q=p;*q;q++) {
73	if(!isdigit(*q)) {
74	    Fatal("Bytecount contains non-digit.");
75	    return -1;
76	}
77	u_chars *= 10;
78	u_chars += (*q - '0');
79    }
80    return u_chars;
81}
82
83u_char *
84Fdata(FILE *fd, int u_chars, MD5_CTX *ctx)
85{
86    u_char *p = Malloc(u_chars+1);
87
88    if(u_chars+1 != fread(p,1,u_chars+1,fd)) {
89	Fatal("Truncated patch.");
90	return 0;
91    }
92    MD5Update(ctx,p,u_chars+1);
93    if(p[u_chars] != '\n') {
94	if(Verbose > 3)
95	    printf("FileData wasn't followed by a newline.\n");
96        Fatal("Corrupt patch.");
97	return 0;
98    }
99    p[u_chars] = '\0';
100    return p;
101}
102
103/*---------------------------------------------------------------------------*/
104/* get the filename in the next field, prepend BaseDir and give back the result
105   strings. The sustitute filename is return (the one with the suffix SUBSUFF)
106   if it exists and the qualifier contains CTM_Q_Name_Subst
107   NOTA: Buffer is already initialize with BaseDir, CatPtr is the insertion
108   point on this buffer + the length test in Ffield() is enough for Fname() */
109
110u_char *
111Fname(FILE *fd, MD5_CTX *ctx,u_char term,int qual, int verbose)
112{
113    u_char * p;
114    struct stat st;
115
116    if ((p = Ffield(fd,ctx,term)) == NULL) return(NULL);
117
118    strcpy(CatPtr, p);
119
120    if (!(qual & CTM_Q_Name_Subst)) return(Buffer);
121
122    p = Buffer + strlen(Buffer);
123
124    strcat(Buffer, SUBSUFF);
125
126    if ( -1 == stat(Buffer, &st) ) {
127	*p = '\0';
128    } else {
129	if(verbose > 2)
130	    fprintf(stderr,"Using %s as substitute file\n", Buffer);
131    }
132
133    return (Buffer);
134}
135