2 * SPDX-License-Identifier: Beerware
4 * ----------------------------------------------------------------------------
5 * "THE BEER-WARE LICENSE" (Revision 42):
6 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
7 * can do whatever you want with this stuff. If we meet some day, and you think
8 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
9 * ----------------------------------------------------------------------------
18 /*---------------------------------------------------------------------------*/
19 /* Pass2 -- Validate the incoming CTM-file.
27 int i,j,sep,cnt,fdesc;
28 u_char *trash=0,*name=0;
29 struct CTM_Syntax *sp;
34 struct CTM_Filter *filter;
36 static char *template = NULL;
39 printf("Pass2 -- Checking if CTM-patch will apply\n");
42 GETFIELD(p,' '); if(strcmp("CTM_BEGIN",p)) WRONG
43 GETFIELD(p,' '); if(strcmp(Version,p)) WRONG
44 GETFIELD(p,' '); if(strcmp(Name,p)) WRONG
45 /* XXX Lookup name in /etc/ctm,conf, read stuff */
46 GETFIELD(p,' '); if(strcmp(Nbr,p)) WRONG
47 /* XXX Verify that this is the next patch to apply */
48 GETFIELD(p,' '); if(strcmp(TimeStamp,p)) WRONG
49 GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG
50 /* XXX drop or use ? */
58 /* if a filter list was specified, check file name against
60 if no filter was given operate on all files. */
62 !(FilterList->Action) : CTM_FILTER_ENABLE);
66 if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG
68 if(!strcmp(p+3,"_END"))
71 for(sp=Syntax;sp->Key;sp++)
72 if(!strcmp(p+3,sp->Key))
76 for(i=0;(j = sp->List[i]);i++) {
77 if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes)
82 switch (j & CTM_F_MASK) {
84 GETNAMECOPY(name,sep,j,0);
85 /* If `keep' was specified, we won't remove any files,
86 so don't check if the file exists */
88 (!strcmp(sp->Key,"FR") || !strcmp(sp->Key,"DR"))) {
89 match = CTM_FILTER_DISABLE;
93 for (filter = FilterList; filter; filter = filter->Next) if (0 == regexec(&filter->CompiledRegex, name,
95 match = filter->Action;
98 if (CTM_FILTER_DISABLE == match)
99 break; /* should ignore this file */
101 /* XXX Check DR DM rec's for parent-dir */
102 if(j & CTM_Q_Name_New) {
103 /* XXX Check DR FR rec's for item */
104 if(-1 != stat(name,&st)) {
105 fprintf(stderr," %s: %s exists.\n",
107 ret |= Exit_Forcible;
111 if(-1 == stat(name,&st)) {
112 fprintf(stderr," %s: %s doesn't exist.\n",
114 if (sp->Key[1] == 'R')
115 ret |= Exit_Forcible;
120 if (SetTime && getuid() && (getuid() != st.st_uid)) {
122 " %s: %s not mine, cannot set time.\n",
126 if (j & CTM_Q_Name_Dir) {
127 if((st.st_mode & S_IFMT) != S_IFDIR) {
129 " %s: %s exist, but isn't dir.\n",
135 if (j & CTM_Q_Name_File) {
136 if((st.st_mode & S_IFMT) != S_IFREG) {
138 " %s: %s exist, but isn't file.\n",
152 if(j & CTM_Q_MD5_Before) {
155 if(match && (st.st_mode & S_IFMT) == S_IFREG &&
156 (tmp = MD5File(name,md5_1)) != NULL &&
158 fprintf(stderr," %s: %s md5 mismatch.\n",
160 GETFIELDCOPY(md5,sep);
161 if(md5 != NULL && strcmp(tmp,md5) == 0) {
162 fprintf(stderr," %s: %s already applied.\n",
164 match = CTM_FILTER_DISABLE;
165 } else if(j & CTM_Q_MD5_Force) {
167 fprintf(stderr," Can and will force.\n");
169 fprintf(stderr," Could have forced.\n");
170 ret |= Exit_Forcible;
176 } else if(j & CTM_Q_MD5_After) {
178 GETFIELDCOPY(md5,sep);
182 /* Unqualified MD5 */
194 if (asprintf(&template, "%s/CTMclientXXXXXX",
196 fprintf(stderr, " %s: malloc failed.\n",
202 if(!strcmp(sp->Key,"FN")) {
203 if ((p = strdup(template)) == NULL) {
204 fprintf(stderr, " %s: malloc failed.\n",
209 if ((fdesc = mkstemp(p)) == -1) {
210 fprintf(stderr, " %s: mkstemp failed.\n",
216 if (close(fdesc) == -1) {
217 fprintf(stderr, " %s: close failed.\n",
224 j = ctm_edit(trash,cnt,name,p);
226 fprintf(stderr," %s: %s edit returned %d.\n",
232 } else if(strcmp(md5,MD5File(p,md5_1))) {
233 fprintf(stderr," %s: %s edit fails.\n",
242 } else if (!strcmp(sp->Key,"FE")) {
243 if ((p = strdup(template)) == NULL) {
244 fprintf(stderr, " %s: malloc failed.\n",
249 if ((fdesc = mkstemp(p)) == -1) {
250 fprintf(stderr, " %s: mkstemp failed.\n",
256 if (close(fdesc) == -1) {
257 fprintf(stderr, " %s: close failed.\n",
264 ed = popen("ed","w");
268 fprintf(ed,"e %s\n", name);
269 if (cnt != fwrite(trash,1,cnt,ed)) {
274 fprintf(ed,"w %s\n",p);
279 if(strcmp(md5,MD5File(p,md5_1))) {
280 fprintf(stderr,"%s %s MD5 didn't come out right\n",
298 q = MD5End (&ctx,md5_1);
299 GETFIELD(p,'\n'); /* <MD5> */
300 if(strcmp(q,p)) WRONG
301 if (-1 != getc(fd)) WRONG