Parent Directory
|
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 |