[Cfengine-3] / trunk / src / files_interfaces.c Repository:
ViewVC logotype

Annotation of /trunk/src/files_interfaces.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 38 - (view) (download) (as text)

1 : mark 38 /*
2 :     Copyright (C) 2008 - Mark Burgess
3 :    
4 :     This file is part of Cfengine 3 - written and maintained by Mark Burgess.
5 :    
6 :     This program is free software; you can redistribute it and/or modify it
7 :     under the terms of the GNU General Public License as published by the
8 :     Free Software Foundation; either version 3, or (at your option) any
9 :     later version.
10 :     This program is distributed in the hope that it will be useful,
11 :     but WITHOUT ANY WARRANTY; without even the implied warranty of
12 :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 :     GNU General Public License for more details.
14 :    
15 :     You should have received a copy of the GNU General Public License
16 :     along with this program; if not, write to the Free Software
17 :     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 :    
19 :     */
20 :    
21 :     /*****************************************************************************/
22 :     /* */
23 :     /* File: files_interfaces.c */
24 :     /* */
25 :     /*****************************************************************************/
26 :    
27 :     #include "cf3.defs.h"
28 :     #include "cf3.extern.h"
29 :    
30 :     /*****************************************************************************/
31 :    
32 :     /* File copying is a special case, particularly complex - cannot be integrated */
33 :    
34 :     void SourceSearchAndCopy(char *from,char *to,int maxrecurse,struct FileAttr attr,struct Promise *pp)
35 :    
36 :     { struct stat statbuf, deststatbuf;
37 :     char newfrom[CF_BUFSIZE];
38 :     char newto[CF_BUFSIZE];
39 :     struct Item *namecache = NULL;
40 :     struct cfdirent *dirp;
41 :     CFDIR *dirh;
42 :    
43 :     if (maxrecurse == 0) /* reached depth limit */
44 :     {
45 :     Debug("MAXRECURSE ran out, quitting at level %s\n",from);
46 :     return;
47 :     }
48 :    
49 :     Debug("RecursiveCopy(%s,lev=%d)\n",from,maxrecurse);
50 :    
51 :     if (strlen(from) == 0) /* Check for root dir */
52 :     {
53 :     from = "/";
54 :     }
55 :    
56 :     /* Check that dest dir exists before starting */
57 :    
58 :     strncpy(newto,to,CF_BUFSIZE-2);
59 :     AddSlash(newto);
60 :    
61 :     if (attr.transaction.action == cfa_warn)
62 :     {
63 :     if (!MakeParentDirectory(newto,attr.move_obstructions))
64 :     {
65 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to make directory for %s in file-copy %s to %s\n",newto,attr.copy.source,attr.copy.destination);
66 :     CfLog(cferror,OUTPUT,"");
67 :     return;
68 :     }
69 :     }
70 :    
71 :     if ((dirh = cf_opendir(from,attr,pp)) == NULL)
72 :     {
73 :     snprintf(OUTPUT,CF_BUFSIZE*2,"copy can't open directory [%s]\n",from);
74 :     CfLog(cfverbose,OUTPUT,"");
75 :     return;
76 :     }
77 :    
78 :     for (dirp = cf_readdir(dirh,attr,pp); dirp != NULL; dirp = cf_readdir(dirh,attr,pp))
79 :     {
80 :     if (!ConsiderFile(dirp->d_name,from,attr,pp))
81 :     {
82 :     continue;
83 :     }
84 :    
85 :     if (attr.copy.purge) /* Do not purge this file */
86 :     {
87 :     AppendItem(&namecache,dirp->d_name,NULL);
88 :     }
89 :    
90 :     strncpy(newfrom,from,CF_BUFSIZE-2); /* Assemble pathname */
91 :     AddSlash(newfrom);
92 :     strncpy(newto,to,CF_BUFSIZE-2);
93 :     AddSlash(newto);
94 :    
95 :     if (!JoinPath(newfrom,dirp->d_name))
96 :     {
97 :     cf_closedir(dirh);
98 :     return;
99 :     }
100 :    
101 :     if (!JoinPath(newto,dirp->d_name))
102 :     {
103 :     cf_closedir(dirh);
104 :     return;
105 :     }
106 :    
107 :     if (attr.recursion.travlinks || attr.copy.link_type == cfa_notlinked)
108 :     {
109 :     /* No point in checking if there are untrusted symlinks here,
110 :     since this is from a trusted source, by defintion */
111 :    
112 :     if (cf_stat(newfrom,&statbuf,attr,pp) == -1)
113 :     {
114 :     Verbose("%s: (Can't stat %s)\n",VPREFIX,newfrom);
115 :     continue;
116 :     }
117 :     }
118 :     else
119 :     {
120 :     if (cf_lstat(newfrom,&statbuf,attr,pp) == -1)
121 :     {
122 :     Verbose("%s: (Can't stat %s)\n",VPREFIX,newfrom);
123 :     continue;
124 :     }
125 :     }
126 :    
127 :     if (attr.recursion.xdev && DeviceBoundary(&statbuf,pp))
128 :     {
129 :     Verbose("Skipping %s on different device\n",newfrom);
130 :     continue;
131 :     }
132 :    
133 :     if (S_ISDIR(statbuf.st_mode))
134 :     {
135 :     if (attr.recursion.travlinks)
136 :     {
137 :     CfLog(cfverbose,"Traversing directory links during copy is too dangerous, pruned","");
138 :     continue;
139 :     }
140 :    
141 :     if (SkipDirLinks(newfrom,dirp->d_name,attr.recursion))
142 :     {
143 :     continue;
144 :     }
145 :    
146 :     memset(&deststatbuf,0,sizeof(struct stat));
147 :    
148 :     if (stat(newto,&deststatbuf) == -1)
149 :     {
150 :     mkdir(newto,statbuf.st_mode);
151 :    
152 :     if (stat(newto,&deststatbuf) == -1)
153 :     {
154 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",newto);
155 :     CfLog(cferror,OUTPUT,"stat");
156 :     continue;
157 :     }
158 :     }
159 :    
160 :     VerifyCopiedFileAttributes(newto,&deststatbuf,&statbuf,attr,pp);
161 :    
162 :     SourceSearchAndCopy(newfrom,newto,maxrecurse-1,attr,pp);
163 :     }
164 :     else
165 :     {
166 :     VerifyCopy(newfrom,newto,attr,pp);
167 :     }
168 :     }
169 :    
170 :     if (attr.copy.purge)
171 :     {
172 :     /* inclusions not exclusions, since exclude from purge means include */
173 :     // PurgeFiles(namecache,to,attr.select.inclusions,AUTHENTICATED);
174 :     DeleteItemList(namecache);
175 :     }
176 :    
177 :     DeleteCompressedArray(pp->inode_cache);
178 :     pp->inode_cache = NULL;
179 :     cf_closedir(dirh);
180 :     }
181 :    
182 :     /*********************************************************************/
183 :    
184 :     void VerifyCopy(char *source,char *destination,struct FileAttr attr,struct Promise *pp)
185 :    
186 :     { CFDIR *dirh;
187 :     char sourcefile[CF_BUFSIZE];
188 :     char sourcedir[CF_BUFSIZE];
189 :     char destdir[CF_BUFSIZE];
190 :     char destfile[CF_BUFSIZE];
191 :     struct stat sourcestatbuf, deststatbuf;
192 :     struct cfdirent *dirp;
193 :     int save_uid, save_gid, found;
194 :    
195 :     Debug("VerifyCopy (source=%s destination=%s)\n",source,destination);
196 :    
197 :     if (attr.copy.link_type == cfa_notlinked)
198 :     {
199 :     Debug("Treating links as files for %s\n",source);
200 :     found = cf_stat(source,&sourcestatbuf,attr,pp);
201 :     }
202 :     else
203 :     {
204 :     found = cf_lstat(source,&sourcestatbuf,attr,pp);
205 :     }
206 :    
207 :     if (found == -1)
208 :     {
209 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",source);
210 :     CfLog(cferror,OUTPUT,"");
211 :     DeleteClientCache(attr,pp);
212 :     SummarizeTransaction(pp,attr,CF_FAIL);
213 :     return;
214 :     }
215 :    
216 :     if (sourcestatbuf.st_nlink > 1) /* Preserve hard link structure when copying */
217 :     {
218 :     RegisterAHardLink(sourcestatbuf.st_ino,destination,attr,pp);
219 :     }
220 :    
221 :     if (S_ISDIR(sourcestatbuf.st_mode))
222 :     {
223 :     strcpy(sourcedir,source);
224 :     AddSlash(sourcedir);
225 :     strcpy(destdir,destination);
226 :     AddSlash(destdir);
227 :    
228 :     if ((dirh = cf_opendir(sourcedir,attr,pp)) == NULL)
229 :     {
230 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",sourcedir);
231 :     CfLog(cfverbose,OUTPUT,"opendir");
232 :     DeleteClientCache(attr,pp);
233 :     return;
234 :     }
235 :    
236 :     /* Now check any overrides */
237 :    
238 :     if (stat(destdir,&deststatbuf) == -1)
239 :     {
240 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat directory %s\n",destdir);
241 :     CfLog(cferror,OUTPUT,"stat");
242 :     }
243 :     else
244 :     {
245 :     VerifyCopiedFileAttributes(destdir,&deststatbuf,&sourcestatbuf,attr,pp);
246 :     }
247 :    
248 :     for (dirp = cf_readdir(dirh,attr,pp); dirp != NULL; dirp = cf_readdir(dirh,attr,pp))
249 :     {
250 :     if (!ConsiderFile(dirp->d_name,sourcedir,attr,pp))
251 :     {
252 :     continue;
253 :     }
254 :    
255 :     strcpy(sourcefile, sourcedir);
256 :    
257 :     if (!JoinPath(sourcefile,dirp->d_name))
258 :     {
259 :     FatalError("VerifyCopy");
260 :     }
261 :    
262 :     strcpy(destfile, destdir);
263 :    
264 :     if (!JoinPath(destfile,dirp->d_name))
265 :     {
266 :     FatalError("VerifyCopy");
267 :     }
268 :    
269 :     if (attr.copy.link_type == cfa_notlinked)
270 :     {
271 :     if (cf_stat(sourcefile,&sourcestatbuf,attr,pp) == -1)
272 :     {
273 :     snprintf(OUTPUT,CF_BUFSIZE,"Can't stat %s\n",sourcefile);
274 :     CfLog(cfinform,OUTPUT,"stat");
275 :     DeleteClientCache(attr,pp);
276 :     return;
277 :     }
278 :     }
279 :     else
280 :     {
281 :     if (cf_lstat(sourcefile,&sourcestatbuf,attr,pp) == -1)
282 :     {
283 :     snprintf(OUTPUT,CF_BUFSIZE,"Can't stat %s\n",sourcefile);
284 :     CfLog(cfinform,OUTPUT,"lstat");
285 :     DeleteClientCache(attr,pp);
286 :     return;
287 :     }
288 :     }
289 :    
290 :     CopyFile(sourcefile,destfile,sourcestatbuf,attr,pp);
291 :     }
292 :    
293 :     cfclosedir(dirh);
294 :     DeleteClientCache(attr,pp);
295 :     return;
296 :     }
297 :    
298 :     strcpy(sourcefile,source);
299 :     strcpy(destfile,destination);
300 :    
301 :     CopyFile(sourcefile,destfile,sourcestatbuf,attr,pp);
302 :     DeleteClientCache(attr,pp);
303 :     }
304 :    
305 :     /*********************************************************************/
306 :    
307 :     void PurgeLocalFiles(struct Item *filelist,char *directory,struct FileAttr attr,struct Promise *pp)
308 :    
309 :     { DIR *dirh;
310 :     struct stat statbuf;
311 :     struct dirent *dirp;
312 :     char filename[CF_BUFSIZE];
313 :    
314 :     Debug("PurgeFiles(%s)\n",directory);
315 :    
316 :     /* If we purge with no authentication we wipe out EVERYTHING */
317 :    
318 :     if (strlen(directory) < 2)
319 :     {
320 :     snprintf(OUTPUT,CF_BUFSIZE,"Purge of %s denied -- too dangerous!",directory);
321 :     CfLog(cferror,OUTPUT,"");
322 :     return;
323 :     }
324 :    
325 :     if (!AUTHENTICATED)
326 :     {
327 :     Verbose("Not purging %s - no verified contact with server\n",directory);
328 :     return;
329 :     }
330 :    
331 :     if ((dirh = opendir(directory)) == NULL)
332 :     {
333 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",directory);
334 :     CfLog(cfverbose,OUTPUT,"cfopendir");
335 :     return;
336 :     }
337 :    
338 :     for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
339 :     {
340 :     if (!ConsiderFile(dirp->d_name,directory,attr,pp))
341 :     {
342 :     continue;
343 :     }
344 :    
345 :     if (!IsItemIn(filelist,dirp->d_name))
346 :     {
347 :     strncpy(filename,directory,CF_BUFSIZE-2);
348 :     AddSlash(filename);
349 :     strncat(filename,dirp->d_name,CF_BUFSIZE-2);
350 :    
351 :     Debug("Checking purge %s..\n",filename);
352 :    
353 :     if (DONTDO)
354 :     {
355 :     printf("Need to purge %s from copy dest directory\n",filename);
356 :     }
357 :     else
358 :     {
359 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Purging %s in copy dest directory\n",filename);
360 :     CfLog(cfinform,OUTPUT,"");
361 :    
362 :     if (lstat(filename,&statbuf) == -1)
363 :     {
364 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't stat %s while purging\n",filename);
365 :     CfLog(cfverbose,OUTPUT,"stat");
366 :     }
367 :     else if (S_ISDIR(statbuf.st_mode))
368 :     {
369 :     struct Tidy tp;
370 :     struct TidyPattern tpat;
371 :     /*
372 :     tp.maxrecurse = 2;
373 :     tp.done = 'n';
374 :     tp.tidylist = &tpat;
375 :     tp.next = NULL;
376 :     tp.path = filename;
377 :     tp.exclusions = inclusions; // exclude means don't purge, i.e. include here
378 :     tp.ignores = NULL;
379 :    
380 :     tpat.filters = NULL;
381 :     tpat.recurse = CF_INF_RECURSE;
382 :     tpat.age = 0;
383 :     tpat.size = 0;
384 :     tpat.pattern = strdup("*");
385 :     tpat.classes = strdup("any");
386 :     tpat.defines = NULL;
387 :     tpat.elsedef = NULL;
388 :     tpat.dirlinks = 'y';
389 :     tpat.travlinks = 'n';
390 :     tpat.rmdirs = 'y';
391 :     tpat.searchtype = 'a';
392 :     tpat.compress = 'n';
393 :     tpat.log = 'd';
394 :     tpat.inform = 'd';
395 :     tpat.next = NULL;
396 :     RecursiveTidySpecialArea(filename,&tp,CF_INF_RECURSE,&statbuf);
397 :     free(tpat.pattern);
398 :     free(tpat.classes);
399 :    
400 :     chdir("..");
401 :    
402 :     if (rmdir(filename) == -1)
403 :     {
404 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't remove directory %s while purging\n",filename);
405 :     CfLog(cfverbose,OUTPUT,"rmdir");
406 :     }
407 :     */
408 :     continue;
409 :     }
410 :     else if (unlink(filename) == -1)
411 :     {
412 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't unlink %s while purging\n",filename);
413 :     CfLog(cfverbose,OUTPUT,"");
414 :     }
415 :     }
416 :     }
417 :     }
418 :    
419 :     closedir(dirh);
420 :     }
421 :    
422 :    
423 :     /*********************************************************************/
424 :     /* Level 3 */
425 :     /*********************************************************************/
426 :    
427 :     void CopyFile(char *sourcefile,char *destfile,struct stat ssb,struct FileAttr attr, struct Promise *pp)
428 :    
429 :     { char *lastnode,*server;
430 :     struct stat dsb;
431 :     struct Link empty;
432 :     struct Item *ptr, *ptr1;
433 :     int found,succeed = false;
434 :     mode_t srcmode = ssb.st_mode;
435 :    
436 :     Debug2("CopyFile(%s,%s)\n",sourcefile,destfile);
437 :    
438 :     if (attr.copy.servers)
439 :     {
440 :     server = (char *)attr.copy.servers->item;
441 :     }
442 :     else
443 :     {
444 :     server = NULL;
445 :     }
446 :    
447 :     if ((strcmp(sourcefile,destfile) == 0) && (strcmp(server,"localhost") == 0))
448 :     {
449 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Image loop: file/dir %s copies to itself",sourcefile);
450 :     CfLog(cfinform,OUTPUT,"");
451 :     return;
452 :     }
453 :    
454 :     memset(&empty,0,sizeof(struct Link));
455 :     empty.nofile = true;
456 :    
457 :     if (!SelectLeaf(sourcefile,&ssb,attr,pp))
458 :     {
459 :     Debug("Skipping non-selected file %s\n",sourcefile);
460 :     return;
461 :     }
462 :    
463 :     /*
464 :     if (IsItemIn(VEXCLUDECACHE,destfile))
465 :     {
466 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Skipping single-copied file %s class %s\n",destfile,ip->classes);
467 :     CfLog(cfverbose,OUTPUT,"");
468 :     return;
469 :     }
470 :     */
471 :    
472 :     if (attr.copy.link_type != cfa_notlinked)
473 :     {
474 :     lastnode=ReadLastNode(sourcefile);
475 :    
476 :     if (MatchRlistItem(attr.copy.link_instead,lastnode))
477 :     {
478 :     Verbose("cfengine: copy item %s marked for linking instead\n",sourcefile);
479 :     LinkCopy(sourcefile,destfile,&ssb,attr,pp);
480 :     return;
481 :     }
482 :     }
483 :    
484 :     found = lstat(destfile,&dsb);
485 :    
486 :     if (found != -1)
487 :     {
488 :     if ((S_ISLNK(dsb.st_mode) && (attr.copy.link_type == cfa_notlinked)) || (S_ISLNK(dsb.st_mode) && ! S_ISLNK(ssb.st_mode)))
489 :     {
490 :     if (!S_ISLNK(ssb.st_mode) && (attr.copy.type_check && (attr.copy.link_type != cfa_notlinked)))
491 :     {
492 :     snprintf(OUTPUT,CF_BUFSIZE,"file image exists but destination type is silly (file/dir/link doesn't match)\n");
493 :     CfLog(cferror,OUTPUT,"");
494 :     PromiseRef(cferror,pp);
495 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
496 :     return;
497 :     }
498 :    
499 :     if (DONTDO)
500 :     {
501 :     Verbose("Need to remove old symbolic link %s to make way for copy\n",destfile);
502 :     }
503 :     else
504 :     {
505 :     if (unlink(destfile) == -1)
506 :     {
507 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't remove link %s",destfile);
508 :     CfLog(cferror,OUTPUT,"unlink");
509 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
510 :     return;
511 :     }
512 :    
513 :     Verbose("Removing old symbolic link %s to make way for copy\n",destfile);
514 :     found = -1;
515 :     }
516 :     }
517 :     }
518 :    
519 :     if (attr.copy.min_size == 0 && attr.copy.max_size == 0)
520 :     {
521 :     if (ssb.st_size < attr.copy.min_size || ssb.st_size > attr.copy.max_size)
522 :     {
523 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Source file %s size is not in the permitted range\n",sourcefile);
524 :     CfLog(cfinform,OUTPUT,"");
525 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
526 :     return;
527 :     }
528 :     }
529 :    
530 :     if (found == -1)
531 :     {
532 :     if (attr.transaction.action == cfa_warn)
533 :     {
534 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Image file %s is non-existent\n",destfile);
535 :     CfLog(cferror,OUTPUT,"");
536 :     snprintf(OUTPUT,CF_BUFSIZE*2,"(should be copy of %s)\n",sourcefile);
537 :     CfLog(cferror,OUTPUT,"");
538 :     return;
539 :     }
540 :    
541 :     if (S_ISREG(srcmode) || (S_ISLNK(srcmode) && attr.copy.link_type == cfa_notlinked))
542 :     {
543 :     if (DONTDO)
544 :     {
545 :     snprintf(OUTPUT,CF_BUFSIZE*2,"%s wasn't at destination (needs copying)",destfile);
546 :     CfLog(cfverbose,OUTPUT,"");
547 :     return;
548 :     }
549 :     else
550 :     {
551 :     snprintf(OUTPUT,CF_BUFSIZE*2,"%s wasn't at destination (copying)",destfile);
552 :     CfLog(cfverbose,OUTPUT,"");
553 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Copying from %s:%s\n",server,sourcefile);
554 :     CfLog(cfinform,OUTPUT,"");
555 :     }
556 :    
557 :     if (CopyRegularFile(sourcefile,destfile,ssb,dsb,attr,pp))
558 :     {
559 :     if (stat(destfile,&dsb) == -1)
560 :     {
561 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",destfile);
562 :     CfLog(cferror,OUTPUT,"stat");
563 :     }
564 :     else
565 :     {
566 :     VerifyCopiedFileAttributes(destfile,&dsb,&ssb,attr,pp);
567 :     }
568 :    
569 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Copied from %s:%s\n",server,sourcefile);
570 :     SummarizeTransaction(pp,attr,CF_CHG);
571 :    
572 :     /*
573 :     if (controlVAL SINGLECOPY LIST)
574 :     {
575 :     if (!IsItemIn(VEXCLUDECACHE,destfile))
576 :     {
577 :     Debug("Appending image %s class %s to singlecopy list\n",destfile,ip->classes);
578 :     PrependItem(&VEXCLUDECACHE,destfile,NULL);
579 :     }
580 :     }
581 :    
582 :     for (ptr = VAUTODEFINE; ptr != NULL; ptr=ptr->next)
583 :     {
584 :     if (WildMatch(ptr->name,destfile))
585 :     {
586 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Image %s was set to autodefine class %s\n",ptr->name,ptr->classes);
587 :     CfLog(cfinform,OUTPUT,"");
588 :     AddMultipleClasses(ptr->classes);
589 :     }
590 :     }
591 :    
592 :     */
593 :     }
594 :     else
595 :     {
596 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Copy from %s:%s failed\n",server,sourcefile);
597 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
598 :     }
599 :    
600 :     Debug2("Leaving CopyFile\n");
601 :     return;
602 :     }
603 :    
604 :     if (S_ISFIFO (srcmode))
605 :     {
606 :     #ifdef HAVE_MKFIFO
607 :     if (DONTDO)
608 :     {
609 :     Silent("%s: Make FIFO %s\n",VPREFIX,destfile);
610 :     }
611 :     else if (mkfifo (destfile,srcmode))
612 :     {
613 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot create fifo `%s'", destfile);
614 :     CfLog(cferror,OUTPUT,"mkfifo");
615 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
616 :     return;
617 :     }
618 :    
619 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Created fifo %s", destfile);
620 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
621 :     #endif
622 :     }
623 :     else
624 :     {
625 :     if (S_ISBLK (srcmode) || S_ISCHR (srcmode) || S_ISSOCK (srcmode))
626 :     {
627 :     if (DONTDO)
628 :     {
629 :     Silent("%s: Make BLK/CHR/SOCK %s\n",VPREFIX,destfile);
630 :     }
631 :     else if (mknod (destfile, srcmode, ssb.st_rdev))
632 :     {
633 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot create special file `%s'",destfile);
634 :     CfLog(cferror,OUTPUT,"mknod");
635 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
636 :     return;
637 :     }
638 :    
639 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Created socket/device %s", destfile);
640 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
641 :     }
642 :     }
643 :    
644 :     if (S_ISLNK(srcmode) && attr.copy.link_type != cfa_notlinked)
645 :     {
646 :     LinkCopy(sourcefile,destfile,&ssb,attr,pp);
647 :     }
648 :     }
649 :     else
650 :     {
651 :     int ok_to_copy = false;
652 :    
653 :     Debug("Destination file %s already exists\n",destfile);
654 :    
655 :     if (!attr.copy.force_update)
656 :     {
657 :     ok_to_copy = CompareForFileCopy(sourcefile,destfile,&ssb,&dsb,attr,pp);
658 :     }
659 :    
660 :     if (attr.copy.type_check && attr.copy.link_type != cfa_notlinked)
661 :     {
662 :     if ((S_ISDIR(dsb.st_mode) && ! S_ISDIR(ssb.st_mode)) ||
663 :     (S_ISREG(dsb.st_mode) && ! S_ISREG(ssb.st_mode)) ||
664 :     (S_ISBLK(dsb.st_mode) && ! S_ISBLK(ssb.st_mode)) ||
665 :     (S_ISCHR(dsb.st_mode) && ! S_ISCHR(ssb.st_mode)) ||
666 :     (S_ISSOCK(dsb.st_mode) && ! S_ISSOCK(ssb.st_mode)) ||
667 :     (S_ISFIFO(dsb.st_mode) && ! S_ISFIFO(ssb.st_mode)) ||
668 :     (S_ISLNK(dsb.st_mode) && ! S_ISLNK(ssb.st_mode)))
669 :    
670 :     {
671 :     snprintf(OUTPUT,CF_BUFSIZE,"Image %s exists but type mismatch with source=%s\n",destfile,sourcefile);
672 :     CfLog(cfinform,OUTPUT,"");
673 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
674 :     return;
675 :     }
676 :     }
677 :    
678 :     if (attr.copy.force_update || ok_to_copy || S_ISLNK(ssb.st_mode)) /* Always check links */
679 :     {
680 :     if (S_ISREG(srcmode) || attr.copy.link_type == cfa_notlinked)
681 :     {
682 :     if (DONTDO)
683 :     {
684 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Should update image %s from master %s on %s",destfile,sourcefile,server);
685 :     CfLog(cferror,OUTPUT,"");
686 :     return;
687 :     }
688 :     else
689 :     {
690 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Updated image %s from master %s on %s",destfile,sourcefile,server);
691 :     CfLog(cfinform,OUTPUT,"");
692 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
693 :     }
694 :    
695 :     /*
696 :     for (ptr = VAUTODEFINE; ptr != NULL; ptr=ptr->next)
697 :     {
698 :     if (WildMatch(ptr->name,destfile))
699 :     {
700 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Image %s was set to autodefine class %s\n",ptr->name,ptr->classes);
701 :     CfLog(cfinform,OUTPUT,"");
702 :     AddMultipleClasses(ptr->classes);
703 :     }
704 :     }
705 :     */
706 :    
707 :     if (CopyRegularFile(sourcefile,destfile,ssb,dsb,attr,pp))
708 :     {
709 :     if (stat(destfile,&dsb) == -1)
710 :     {
711 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",destfile);
712 :     CfLog(cferror,OUTPUT,"stat");
713 :     ClassAuditLog(pp,attr,OUTPUT,CF_INTERPT);
714 :     }
715 :     else
716 :     {
717 :     VerifyCopiedFileAttributes(destfile,&dsb,&ssb,attr,pp);
718 :     }
719 :    
720 :     /* if (ALL_SINGLECOPY || IsWildItemIn(VSINGLECOPY,destfile))
721 :     {
722 :     if (!IsItemIn(VEXCLUDECACHE,destfile))
723 :     {
724 :     Debug("Appending image %s class %s to singlecopy list\n",destfile,ip->classes);
725 :     PrependItem(&VEXCLUDECACHE,destfile,NULL);
726 :     }
727 :     }
728 :     */
729 :     }
730 :     else
731 :     {
732 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",destfile);
733 :     CfLog(cferror,OUTPUT,"stat");
734 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
735 :     }
736 :    
737 :     return;
738 :     }
739 :    
740 :     if (S_ISLNK(ssb.st_mode))
741 :     {
742 :     LinkCopy(sourcefile,destfile,&ssb,attr,pp);
743 :     }
744 :     }
745 :     else
746 :     {
747 :     VerifyCopiedFileAttributes(destfile,&dsb,&ssb,attr,pp);
748 :    
749 :     /* Now we have to check for single copy, even though nothing was copied
750 :     otherwise we can get oscillations between multipe versions if type is based on a checksum */
751 :     /*
752 :     if (ALL_SINGLECOPY || IsWildItemIn(VSINGLECOPY,destfile))
753 :     {
754 :     if (!IsItemIn(VEXCLUDECACHE,destfile))
755 :     {
756 :     Debug("Appending image %s class %s to singlecopy list\n",destfile,ip->classes);
757 :     PrependItem(&VEXCLUDECACHE,destfile,NULL);
758 :     }
759 :     }
760 :     */
761 :     snprintf(OUTPUT,CF_BUFSIZE,"Image file is up to date: %s\n",destfile);
762 :     CfLog(cfinform,OUTPUT,"");
763 :     ClassAuditLog(pp,attr,OUTPUT,CF_NOP);
764 :     }
765 :     }
766 :     }
767 :    
768 :     /*********************************************************************/
769 :    
770 :     int cf_stat(char *file,struct stat *buf,struct FileAttr attr,struct Promise *pp)
771 :    
772 :     { int res;
773 :    
774 :     if (attr.copy.servers == NULL || strcmp(attr.copy.servers->item,"localhost") == 0)
775 :     {
776 :     res = stat(file,buf);
777 :     CheckForFileHoles(buf,attr,pp);
778 :     return res;
779 :     }
780 :     else
781 :     {
782 :     return cf_remote_stat(file,buf,"file",attr,pp);
783 :     }
784 :     }
785 :    
786 :     /*********************************************************************/
787 :    
788 :     int cf_lstat(char *file,struct stat *buf,struct FileAttr attr,struct Promise *pp)
789 :    
790 :     { int res;
791 :    
792 :     if (attr.copy.servers == NULL || strcmp(attr.copy.servers->item,"localhost") == 0)
793 :     {
794 :     res = lstat(file,buf);
795 :     CheckForFileHoles(buf,attr,pp);
796 :     return res;
797 :     }
798 :     else
799 :     {
800 :     return cf_remote_stat(file,buf,"link",attr,pp);
801 :     }
802 :     }
803 :    
804 :     /*********************************************************************/
805 :    
806 :     int cf_readlink(char *sourcefile,char *linkbuf,int buffsize,struct FileAttr attr,struct Promise *pp)
807 :    
808 :     /* wrapper for network access */
809 :    
810 :     { struct cfstat *sp;
811 :    
812 :     memset(linkbuf,0,buffsize);
813 :    
814 :     if (attr.copy.servers == NULL || strcmp(attr.copy.servers->item,"localhost") == 0)
815 :     {
816 :     return readlink(sourcefile,linkbuf,buffsize-1);
817 :     }
818 :    
819 :     for (sp = pp->cache; sp != NULL; sp=sp->next)
820 :     {
821 :     if ((strcmp(attr.copy.servers->item,sp->cf_server) == 0) && (strcmp(sourcefile,sp->cf_filename) == 0))
822 :     {
823 :     if (sp->cf_readlink != NULL)
824 :     {
825 :     if (strlen(sp->cf_readlink)+1 > buffsize)
826 :     {
827 :     snprintf(OUTPUT,CF_BUFSIZE,"readlink value is too large in cfreadlink\n");
828 :     CfLog(cferror,OUTPUT,"");
829 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
830 :     snprintf(OUTPUT,CF_BUFSIZE,"%s: [%s]]n",VPREFIX,sp->cf_readlink);
831 :     CfLog(cferror,OUTPUT,"");
832 :     return -1;
833 :     }
834 :     else
835 :     {
836 :     memset(linkbuf,0,buffsize);
837 :     strcpy(linkbuf,sp->cf_readlink);
838 :     return 0;
839 :     }
840 :     }
841 :     }
842 :     }
843 :    
844 :     return -1;
845 :     }
846 :    
847 :     /*********************************************************************/
848 :    
849 :     CFDIR *cf_opendir(char *name,struct FileAttr attr,struct Promise *pp)
850 :    
851 :     { CFDIR *returnval;
852 :    
853 :     if (attr.copy.servers == NULL || strcmp(attr.copy.servers->item,"localhost") == 0)
854 :     {
855 :     if ((returnval = (CFDIR *)malloc(sizeof(CFDIR))) == NULL)
856 :     {
857 :     FatalError("Can't allocate memory in cfopendir()\n");
858 :     }
859 :    
860 :     returnval->cf_list = NULL;
861 :     returnval->cf_listpos = NULL;
862 :     returnval->cf_dirh = opendir(name);
863 :    
864 :     if (returnval->cf_dirh != NULL)
865 :     {
866 :     return returnval;
867 :     }
868 :     else
869 :     {
870 :     free ((char *)returnval);
871 :     return NULL;
872 :     }
873 :     }
874 :     else
875 :     {
876 :     return cf_remote_opendir(name,attr,pp);
877 :     }
878 :     }
879 :    
880 :     /*********************************************************************/
881 :    
882 :     struct cfdirent *cf_readdir(CFDIR *cfdirh,struct FileAttr attr,struct Promise *pp)
883 :    
884 :     /* We need this cfdirent type to handle the weird hack */
885 :     /* used in SVR4/solaris dirent structures */
886 :    
887 :     { static struct cfdirent dir;
888 :     struct dirent *dirp;
889 :    
890 :     memset(dir.d_name,0,CF_BUFSIZE);
891 :    
892 :     if (attr.copy.servers == NULL || strcmp(attr.copy.servers->item,"localhost") == 0)
893 :     {
894 :     dirp = readdir(cfdirh->cf_dirh);
895 :    
896 :     if (dirp == NULL)
897 :     {
898 :     return NULL;
899 :     }
900 :    
901 :     strncpy(dir.d_name,dirp->d_name,CF_BUFSIZE-1);
902 :     return &dir;
903 :     }
904 :     else
905 :     {
906 :     if (cfdirh->cf_listpos != NULL)
907 :     {
908 :     strncpy(dir.d_name,(cfdirh->cf_listpos)->name,CF_BUFSIZE);
909 :     cfdirh->cf_listpos = cfdirh->cf_listpos->next;
910 :     return &dir;
911 :     }
912 :     else
913 :     {
914 :     return NULL;
915 :     }
916 :     }
917 :     }
918 :    
919 :     /*********************************************************************/
920 :    
921 :     void cf_closedir(CFDIR *dirh)
922 :    
923 :     {
924 :     if ((dirh != NULL) && (dirh->cf_dirh != NULL))
925 :     {
926 :     closedir(dirh->cf_dirh);
927 :     }
928 :    
929 :     Debug("cfclosedir()\n");
930 :     DeleteItemList(dirh->cf_list);
931 :     free((char *)dirh);
932 :     }
933 :    
934 :     /*********************************************************************/
935 :     /* Level 4 */
936 :     /*********************************************************************/
937 :    
938 :     int CompareForFileCopy(char *sourcefile,char *destfile,struct stat *ssb, struct stat *dsb,struct FileAttr attr,struct Promise *pp)
939 :    
940 :     { int ok_to_copy;
941 :    
942 :     switch (attr.copy.compare)
943 :     {
944 :     case cfa_checksum:
945 :    
946 :     if (S_ISREG(dsb->st_mode) && S_ISREG(ssb->st_mode))
947 :     {
948 :     ok_to_copy = CompareFileHashes(sourcefile,destfile,ssb,dsb,attr,pp);
949 :     }
950 :     else
951 :     {
952 :     CfLog(cfinform,"Checksum comparison replaced by ctime: files not regular\n","");
953 :     snprintf(OUTPUT,CF_BUFSIZE*2,"%s -> %s\n",sourcefile,destfile);
954 :     CfLog(cfinform,OUTPUT,"");
955 :     ok_to_copy = (dsb->st_ctime < ssb->st_ctime)||(dsb->st_mtime < ssb->st_mtime);
956 :     }
957 :    
958 :     if (ok_to_copy && (attr.transaction.action == cfa_warn))
959 :     {
960 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Image file %s has a wrong MD5 checksum (should be copy of %s)\n",destfile,sourcefile);
961 :     CfLog(cfinform,OUTPUT,"");
962 :     return ok_to_copy;
963 :     }
964 :     break;
965 :    
966 :     case cfa_binary:
967 :    
968 :     if (S_ISREG(dsb->st_mode) && S_ISREG(ssb->st_mode))
969 :     {
970 :     ok_to_copy = CompareBinaryFiles(sourcefile,destfile,ssb,dsb,attr,pp);
971 :     }
972 :     else
973 :     {
974 :     CfLog(cfinform,"Byte comparison replaced by ctime: files not regular\n","");
975 :     snprintf(OUTPUT,CF_BUFSIZE*2,"%s -> %s\n",sourcefile,destfile);
976 :     CfLog(cfinform,OUTPUT,"");
977 :     ok_to_copy = (dsb->st_ctime < ssb->st_ctime)||(dsb->st_mtime < ssb->st_mtime);
978 :     }
979 :    
980 :     if (ok_to_copy && (attr.transaction.action == cfa_warn))
981 :     {
982 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Image file %s has a wrong binary checksum (should be copy of %s)\n",destfile,sourcefile);
983 :     CfLog(cferror,OUTPUT,"");
984 :     return ok_to_copy;
985 :     }
986 :     break;
987 :    
988 :     case cfa_mtime:
989 :    
990 :     ok_to_copy = (dsb->st_mtime < ssb->st_mtime);
991 :    
992 :     if (ok_to_copy && (attr.transaction.action == cfa_warn))
993 :     {
994 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Image file %s out of date (should be copy of %s)\n",destfile,sourcefile);
995 :     CfLog(cferror,OUTPUT,"");
996 :     return ok_to_copy;
997 :     }
998 :     break;
999 :    
1000 :     case cfa_atime:
1001 :    
1002 :     ok_to_copy = (dsb->st_ctime < ssb->st_ctime)||
1003 :     (dsb->st_mtime < ssb->st_mtime)||
1004 :     CompareBinaryFiles(sourcefile,destfile,ssb,dsb,attr,pp);
1005 :    
1006 :     if (ok_to_copy && (attr.transaction.action == cfa_warn))
1007 :     {
1008 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Image file %s is updated somehow (should be copy of %s)\n",destfile,sourcefile);
1009 :     CfLog(cferror,OUTPUT,"");
1010 :     return ok_to_copy;
1011 :     }
1012 :     break;
1013 :    
1014 :     default:
1015 :     ok_to_copy = (dsb->st_ctime < ssb->st_ctime)||(dsb->st_mtime < ssb->st_mtime);
1016 :    
1017 :     if (ok_to_copy && (attr.transaction.action == cfa_warn))
1018 :     {
1019 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Image file %s out of date (should be copy of %s)\n",destfile,sourcefile);
1020 :     CfLog(cferror,OUTPUT,"");
1021 :     return ok_to_copy;
1022 :     }
1023 :     break;
1024 :     }
1025 :    
1026 :     return false;
1027 :     }
1028 :    
1029 :     /*************************************************************************************/
1030 :    
1031 :     void LinkCopy(char *sourcefile,char *destfile,struct stat *sb,struct FileAttr attr, struct Promise *pp)
1032 :    
1033 :     { char linkbuf[CF_BUFSIZE];
1034 :     int succeed = false;
1035 :     struct stat dsb;
1036 :    
1037 :     if (cf_readlink(sourcefile,linkbuf,CF_BUFSIZE,attr,pp) == -1)
1038 :     {
1039 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Can't readlink %s\n",sourcefile);
1040 :     CfLog(cferror,OUTPUT,"");
1041 :     ClassAuditLog(pp,attr,OUTPUT,CF_FAIL);
1042 :     return;
1043 :     }
1044 :    
1045 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Checking link from %s to %s\n",destfile,linkbuf);
1046 :     CfLog(cfverbose,OUTPUT,"");
1047 :    
1048 :     if (attr.copy.link_type == cfa_absolute && linkbuf[0] != '/') /* Not absolute path - must fix */
1049 :     {
1050 :     char vbuff[CF_BUFSIZE];
1051 :     strcpy(vbuff,sourcefile);
1052 :     ChopLastNode(vbuff);
1053 :     AddSlash(vbuff);
1054 :     strncat(vbuff,linkbuf,CF_BUFSIZE-1);
1055 :     strncpy(linkbuf,vbuff,CF_BUFSIZE-1);
1056 :     }
1057 :    
1058 :     switch (attr.copy.link_type)
1059 :     {
1060 :     case cfa_symlink:
1061 :    
1062 :     if (*linkbuf == '.')
1063 :     {
1064 :     succeed = VerifyRelativeLink(destfile,linkbuf,attr,pp);
1065 :     }
1066 :     else
1067 :     {
1068 :     succeed = VerifyLink(destfile,linkbuf,attr,pp);
1069 :     }
1070 :     break;
1071 :    
1072 :     case cfa_relative:
1073 :     succeed = VerifyRelativeLink(destfile,linkbuf,attr,pp);
1074 :     break;
1075 :    
1076 :     case cfa_absolute:
1077 :     succeed = VerifyAbsoluteLink(destfile,linkbuf,attr,pp);
1078 :     break;
1079 :    
1080 :     default:
1081 :     FatalError("LinkCopy software error");
1082 :     return;
1083 :     }
1084 :    
1085 :     if (succeed)
1086 :     {
1087 :     if (lstat(destfile,&dsb) == -1)
1088 :     {
1089 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Can't lstat %s\n",destfile);
1090 :     CfLog(cferror,OUTPUT,"lstat");
1091 :     }
1092 :     else
1093 :     {
1094 :     VerifyCopiedFileAttributes(destfile,&dsb,sb,attr,pp);
1095 :     }
1096 :    
1097 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Created link %s", destfile);
1098 :     ClassAuditLog(pp,attr,OUTPUT,CF_CHG);
1099 :     }
1100 :     }
1101 :    
1102 :     /*************************************************************************************/
1103 :    
1104 :     int CopyRegularFile(char *source,char *dest,struct stat sstat,struct stat dstat,struct FileAttr attr,struct Promise *pp)
1105 :    
1106 :     { char backup[CF_BUFSIZE];
1107 :     char new[CF_BUFSIZE], *linkable;
1108 :     struct cfagent_connection *conn = pp->conn;
1109 :     int remote = false, silent, backupisdir=false, backupok=false,discardbackup;
1110 :     struct stat s;
1111 :     #ifdef HAVE_UTIME_H
1112 :     struct utimbuf timebuf;
1113 :     #endif
1114 :    
1115 :     #ifdef DARWIN
1116 :     /* For later copy from new to dest */
1117 :     char *rsrcbuf;
1118 :     int rsrcbytesr; /* read */
1119 :     int rsrcbytesw; /* written */
1120 :     int rsrcbytesl; /* to read */
1121 :     int rsrcrd;
1122 :     int rsrcwd;
1123 :    
1124 :     /* Keep track of if a resrouce fork */
1125 :     char * tmpstr;
1126 :     char * forkpointer;
1127 :     int rsrcfork = 0;
1128 :     #endif
1129 :    
1130 :     #ifdef WITH_SELINUX
1131 :     int selinux_enabled=0;
1132 :     /* need to keep track of security context of destination file (if any) */
1133 :     security_context_t scontext=NULL;
1134 :     struct stat cur_dest;
1135 :     int dest_exists;
1136 :     selinux_enabled = (is_selinux_enabled()>0);
1137 :     #endif
1138 :    
1139 :     Debug2("CopyRegularFile(%s,%s)\n",source,dest);
1140 :    
1141 :     discardbackup = (attr.copy.backup == cfa_nobackup || attr.copy.backup == cfa_repos_store);
1142 :    
1143 :     if (DONTDO)
1144 :     {
1145 :     snprintf(OUTPUT,CF_BUFSIZE,"Promise requires copy from %s to %s\n",source,dest);
1146 :     CfLog(cferror,OUTPUT,"");
1147 :     return false;
1148 :     }
1149 :    
1150 :     #ifdef WITH_SELINUX
1151 :     if (selinux_enabled)
1152 :     {
1153 :     dest_exists = stat(dest,&cur_dest);
1154 :    
1155 :     if(dest_exists == 0)
1156 :     {
1157 :     /* get current security context of destination file */
1158 :     getfilecon(dest,&scontext);
1159 :     }
1160 :     else
1161 :     {
1162 :     /* use default security context when creating destination file */
1163 :     matchpathcon(dest,0,&scontext);
1164 :     setfscreatecon(scontext);
1165 :     }
1166 :     }
1167 :     #endif
1168 :    
1169 :     /* Make an assoc array of inodes used to preserve hard links */
1170 :    
1171 :     linkable = CompressedArrayValue(pp->inode_cache,sstat.st_ino);
1172 :    
1173 :     if (sstat.st_nlink > 1) /* Preserve hard links, if possible */
1174 :     {
1175 :     if (CompressedArrayElementExists(pp->inode_cache,sstat.st_ino) && (strcmp(dest,linkable) != 0))
1176 :     {
1177 :     unlink(dest);
1178 :     DoHardLink(dest,linkable,NULL);
1179 :     return true;
1180 :     }
1181 :     }
1182 :    
1183 :     if (attr.copy.servers != NULL && strcmp(attr.copy.servers->item,"localhost") != 0)
1184 :     {
1185 :     Debug("This is a remote copy from server: %s\n",attr.copy.servers->item);
1186 :     remote = true;
1187 :     }
1188 :    
1189 :     #ifdef DARWIN
1190 :     if (strstr(dest, _PATH_RSRCFORKSPEC))
1191 :     { /* Need to munge the "new" name */
1192 :     rsrcfork = 1;
1193 :    
1194 :     tmpstr = malloc(CF_BUFSIZE);
1195 :    
1196 :     /* Drop _PATH_RSRCFORKSPEC */
1197 :     strncpy(tmpstr, dest, CF_BUFSIZE);
1198 :     forkpointer = strstr(tmpstr, _PATH_RSRCFORKSPEC);
1199 :     *forkpointer = '\0';
1200 :    
1201 :     strncpy(new, tmpstr, CF_BUFSIZE);
1202 :    
1203 :     free(tmpstr);
1204 :     }
1205 :     else
1206 :     {
1207 :     #endif
1208 :    
1209 :     if (BufferOverflow(dest,CF_NEW))
1210 :     {
1211 :     printf(" culprit: CopyReg\n");
1212 :     return false;
1213 :     }
1214 :     strcpy(new,dest);
1215 :    
1216 :     #ifdef DARWIN
1217 :     }
1218 :     #endif
1219 :    
1220 :     strcat(new,CF_NEW);
1221 :    
1222 :     if (remote)
1223 :     {
1224 :     if (conn->error)
1225 :     {
1226 :     return false;
1227 :     }
1228 :    
1229 :     if (!CopyRegularFileNet(source,new,sstat.st_size,attr,pp))
1230 :     {
1231 :     return false;
1232 :     }
1233 :     }
1234 :     else
1235 :     {
1236 :     if (!CopyRegularFileDisk(source,new,attr,pp))
1237 :     {
1238 :     return false;
1239 :     }
1240 :    
1241 :     if (attr.copy.stealth)
1242 :     {
1243 :     #ifdef HAVE_UTIME_H
1244 :     timebuf.actime = sstat.st_atime;
1245 :     timebuf.modtime = sstat.st_mtime;
1246 :     utime(source,&timebuf);
1247 :     #endif
1248 :     }
1249 :     }
1250 :    
1251 :     Debug("CopyRegular succeeded in copying to %s to %s\n",source,new);
1252 :    
1253 :     if (!discardbackup)
1254 :     {
1255 :     char stamp[CF_BUFSIZE];
1256 :     time_t stampnow;
1257 :    
1258 :     Debug("Backup file %s\n",source);
1259 :    
1260 :     stampnow = time((time_t *)NULL);
1261 :    
1262 :     sprintf(stamp, "_%d_%s", CFSTARTTIME, CanonifyName(ctime(&stampnow)));
1263 :    
1264 :     if (BufferOverflow(dest,stamp))
1265 :     {
1266 :     printf(" culprit: CopyReg\n");
1267 :     return false;
1268 :     }
1269 :    
1270 :     strcpy(backup,dest);
1271 :    
1272 :     if (attr.copy.backup == cfa_timestamp)
1273 :     {
1274 :     strcat(backup,stamp);
1275 :     }
1276 :    
1277 :     /* rely on prior BufferOverflow() and on strlen(CF_SAVED) < CF_BUFFERMARGIN */
1278 :    
1279 :     strcat(backup,CF_SAVED);
1280 :    
1281 :     /* Now in case of multiple copies of same object, try to avoid overwriting original backup */
1282 :    
1283 :     if (lstat(backup,&s) != -1)
1284 :     {
1285 :     if (S_ISDIR(s.st_mode)) /* if there is a dir in the way */
1286 :     {
1287 :     backupisdir = true;
1288 :     PurgeFiles(NULL,backup,NULL);
1289 :     rmdir(backup);
1290 :     }
1291 :    
1292 :     unlink(backup);
1293 :     }
1294 :    
1295 :     if (rename(dest,backup) == -1)
1296 :     {
1297 :     /* ignore */
1298 :     }
1299 :    
1300 :     backupok = (lstat(backup,&s) != -1); /* Did the rename() succeed? NFS-safe */
1301 :     }
1302 :     else
1303 :     {
1304 :     /* Mainly important if there is a dir in the way */
1305 :    
1306 :     if (stat(dest,&s) != -1)
1307 :     {
1308 :     if (S_ISDIR(s.st_mode))
1309 :     {
1310 :     PurgeFiles(NULL,dest,NULL);
1311 :     rmdir(dest);
1312 :     }
1313 :     }
1314 :     }
1315 :    
1316 :     if (stat(new,&dstat) == -1)
1317 :     {
1318 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat new file %s\n",new);
1319 :     CfLog(cferror,OUTPUT,"stat");
1320 :     return false;
1321 :     }
1322 :    
1323 :     if (dstat.st_size != sstat.st_size)
1324 :     {
1325 :     snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING: new file %s seems to have been corrupted in transit (sizes %d and %d), aborting!\n",new, (int) dstat.st_size, (int) sstat.st_size);
1326 :     CfLog(cfverbose,OUTPUT,"");
1327 :     if (backupok)
1328 :     {
1329 :     rename(backup,dest); /* ignore failure */
1330 :     }
1331 :     return false;
1332 :     }
1333 :    
1334 :     if (attr.copy.verify)
1335 :     {
1336 :     Verbose("Final verification of transmission: %s -> %s\n",source,new);
1337 :    
1338 :     if (CompareFileHashes(source,new,&sstat,&dstat,attr,pp))
1339 :     {
1340 :     snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING: new file %s seems to have been corrupted in transit, aborting!\n",new);
1341 :     CfLog(cfverbose,OUTPUT,"");
1342 :     if (backupok)
1343 :     {
1344 :     rename(backup,dest); /* ignore failure */
1345 :     }
1346 :     return false;
1347 :     }
1348 :     }
1349 :    
1350 :     #ifdef DARWIN
1351 :     if (rsrcfork)
1352 :     { /* Can't just "mv" the resource fork, unfortunately */
1353 :     rsrcrd = open(new, O_RDONLY|O_BINARY);
1354 :     rsrcwd = open(dest, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0600);
1355 :    
1356 :     if (rsrcrd == -1 || rsrcwd == -1)
1357 :     {
1358 :     snprintf(OUTPUT, CF_BUFSIZE, "Open of rsrcrd/rsrcwd failed\n");
1359 :     CfLog(cfinform,OUTPUT,"open");
1360 :     close(rsrcrd);
1361 :     close(rsrcwd);
1362 :     return(false);
1363 :     }
1364 :    
1365 :     rsrcbuf = malloc(CF_BUFSIZE);
1366 :    
1367 :     rsrcbytesr = 0;
1368 :    
1369 :     while(1)
1370 :     {
1371 :     rsrcbytesr = read(rsrcrd, rsrcbuf, CF_BUFSIZE);
1372 :    
1373 :     if (rsrcbytesr == -1)
1374 :     { /* Ck error */
1375 :     if (errno == EINTR)
1376 :     {
1377 :     continue;
1378 :     }
1379 :     else
1380 :     {
1381 :     snprintf(OUTPUT, CF_BUFSIZE, "Read of rsrcrd failed\n");
1382 :     CfLog(cfinform,OUTPUT,"read");
1383 :     close(rsrcrd);
1384 :     close(rsrcwd);
1385 :     free(rsrcbuf);
1386 :     return(false);
1387 :     }
1388 :     }
1389 :    
1390 :     else if (rsrcbytesr == 0)
1391 :     { /* Reached EOF */
1392 :     close(rsrcrd);
1393 :     close(rsrcwd);
1394 :     free(rsrcbuf);
1395 :    
1396 :     unlink(new); /* Go ahead and unlink .cfnew */
1397 :    
1398 :     break;
1399 :     }
1400 :    
1401 :     rsrcbytesl = rsrcbytesr;
1402 :     rsrcbytesw = 0;
1403 :    
1404 :     while (rsrcbytesl > 0)
1405 :     {
1406 :    
1407 :     rsrcbytesw += write(rsrcwd, rsrcbuf, rsrcbytesl);
1408 :    
1409 :     if (rsrcbytesw == -1)
1410 :     { /* Ck error */
1411 :     if (errno == EINTR)
1412 :     {
1413 :     continue;
1414 :     }
1415 :     else
1416 :     {
1417 :     snprintf(OUTPUT, CF_BUFSIZE, "Write of rsrcwd failed\n");
1418 :     CfLog(cfinform,OUTPUT,"write");
1419 :    
1420 :     close(rsrcrd);
1421 :     close(rsrcwd);
1422 :     free(rsrcbuf);
1423 :     return(false);
1424 :     }
1425 :     }
1426 :     rsrcbytesl = rsrcbytesr - rsrcbytesw;
1427 :     }
1428 :     }
1429 :    
1430 :     }
1431 :     else
1432 :     {
1433 :     #endif
1434 :    
1435 :     if (rename(new,dest) == -1)
1436 :     {
1437 :     snprintf(OUTPUT,CF_BUFSIZE*2,"Problem: could not install copy file as %s, directory in the way?\n",dest);
1438 :     CfLog(cferror,OUTPUT,"rename");
1439 :     if (backupok)
1440 :     {
1441 :     rename(backup,dest); /* ignore failure */
1442 :     }
1443 :     return false;
1444 :     }
1445 :    
1446 :     #ifdef DARWIN
1447 :     }
1448 :     #endif
1449 :    
1450 :     if (!discardbackup && backupisdir)
1451 :     {
1452 :     snprintf(OUTPUT,CF_BUFSIZE,"Cannot move a directory to repository, leaving at %s",backup);
1453 :     CfLog(cfinform,OUTPUT,"");
1454 :     }
1455 :     else if (!discardbackup && ArchiveToRepository(backup,attr,pp))
1456 :     {
1457 :     unlink(backup);
1458 :     }
1459 :    
1460 :     if (attr.copy.preserve)
1461 :     {
1462 :     #ifdef HAVE_UTIME_H
1463 :     timebuf.actime = sstat.st_atime;
1464 :     timebuf.modtime = sstat.st_mtime;
1465 :     utime(dest,&timebuf);
1466 :     #endif
1467 :     }
1468 :    
1469 :     #ifdef WITH_SELINUX
1470 :     if (selinux_enabled)
1471 :     {
1472 :     if (dest_exists == 0)
1473 :     {
1474 :     /* set dest context to whatever it was before copy */
1475 :     setfilecon(dest,scontext);
1476 :     }
1477 :     else
1478 :     {
1479 :     /* set create context back to default */
1480 :     setfscreatecon(NULL);
1481 :     }
1482 :     freecon(scontext);
1483 :     }
1484 :     #endif
1485 :    
1486 :     return true;
1487 :     }
1488 :    
1489 :     /*********************************************************************/
1490 :     /* Level 3 */
1491 :     /*********************************************************************/
1492 :    
1493 :     void RegisterAHardLink(int i,char *value,struct FileAttr attr,struct Promise *pp)
1494 :    
1495 :     {
1496 :     if (!FixCompressedArrayValue(i,value,&(pp->inode_cache)))
1497 :     {
1498 :     /* Not root hard link, remove to preserve consistency */
1499 :     if (DONTDO)
1500 :     {
1501 :     Verbose("Need to remove old hard link %s to preserve structure..\n",value);
1502 :     }
1503 :     else
1504 :     {
1505 :     if (attr.transaction.action = cfa_warn)
1506 :     {
1507 :     Verbose("Need to remove old hard link %s to preserve structure..\n",value);
1508 :     }
1509 :     else
1510 :     {
1511 :     Verbose("Removing old hard link %s to preserve structure..\n",value);
1512 :     unlink(value);
1513 :     }
1514 :     }
1515 :     }
1516 :     }

Administrator
ViewVC Help
Powered by ViewVC 1.0.3