int IgnoredOrExcluded(enum actions action,char *file,struct Item *inclusions,struct Item *exclusions) { char *lastnode; Debug("IgnoredOrExcluded(%s)\n",file); if (strstr(file,"/")) { for (lastnode = file+strlen(file); *lastnode != '/'; lastnode--) { } lastnode++; } else { lastnode = file; } if ((inclusions != NULL) && !IsWildItemIn(inclusions,lastnode)) { Debug("cfengine: skipping non-included pattern %s\n",file); return true; } switch(action) { case image: if (IsWildItemIn(VEXCLUDECOPY,lastnode) || IsWildItemIn(exclusions,lastnode)) { Debug("Skipping excluded pattern %s\n",file); return true; } break; case links: if (IsWildItemIn(VEXCLUDELINK,lastnode) || IsWildItemIn(exclusions,lastnode)) { Debug("Skipping excluded pattern %s\n",file); return true; } break; default: if (IsWildItemIn(exclusions,lastnode)) { Debug("Skipping excluded pattern %s\n",file); return true; } } return false; }
/* should return true if 'to' found */ int HardLinkFiles(char *from, char *to, struct Item *inclusions, struct Item *exclusions, struct Item *copy, short nofile, struct Link *ptr) { struct stat frombuf,tobuf; char saved[CF_BUFSIZE], *lastnode; struct UidList fakeuid; struct Image ip; char stamp[CF_BUFSIZE]; time_t STAMPNOW; STAMPNOW = time((time_t *)NULL); for (lastnode = from+strlen(from); *lastnode != '/'; lastnode--) { } lastnode++; if (inclusions != NULL && !IsWildItemIn(inclusions,lastnode)) { Verbose("%s: Skipping non-included pattern %s\n",g_vprefix,from); return true; } if (IsWildItemIn(g_vexcludelink,lastnode) || IsWildItemIn(exclusions,lastnode)) { Verbose("%s: Skipping excluded pattern %s\n",g_vprefix,from); return true; } if (IsWildItemIn(g_vcopylinks,lastnode) || IsWildItemIn(copy,lastnode)) { fakeuid.uid = CF_SAME_OWNER; fakeuid.next = NULL; ip.plus = CF_SAMEMODE; ip.minus = CF_SAMEMODE; ip.uid = &fakeuid; ip.gid = (struct GidList *) &fakeuid; ip.action = "do"; ip.recurse = 0; ip.type = 't'; ip.backup = true; ip.plus_flags = 0; ip.minus_flags = 0; ip.exclusions = NULL; ip.symlink = NULL; Verbose("%s: Link item %s marked for copying instead\n", g_vprefix, from); CheckImage(to,from,&ip); return true; } if (stat(to,&tobuf) == -1) { /* no error warning, since the higher level routine uses this */ return(false); } if (! S_ISREG(tobuf.st_mode)) { snprintf(g_output, CF_BUFSIZE*2, "%s: will only hard link regular files " "and %s is not regular\n", g_vprefix, to); CfLog(cfsilent,g_output,""); return true; } Debug2("Trying to (hard) link %s -> %s\n",from,to); if (stat(from,&frombuf) == -1) { DoHardLink(from,to,ptr->defines); return true; } /* * Both files exist, but are they the same file? POSIX says the * files could be on different devices, but unix doesn't allow this * behaviour so the tests below are theoretical... */ if (frombuf.st_ino != tobuf.st_ino && frombuf.st_dev != frombuf.st_dev) { Verbose("If this is POSIX, unable to determine if %s is " "hard link is correct\n", from); Verbose("since it points to a different filesystem!\n"); if (frombuf.st_mode == tobuf.st_mode && frombuf.st_size == tobuf.st_size) { snprintf(g_output,CF_BUFSIZE*2, "Hard link (%s->%s) on different device APPEARS okay\n", from,to); CfLog(cfverbose,g_output,""); AddMultipleClasses(ptr->elsedef); return true; } } if (frombuf.st_ino == tobuf.st_ino && frombuf.st_dev == frombuf.st_dev) { snprintf(g_output,CF_BUFSIZE*2, "Hard link (%s->%s) exists and is okay.\n",from,to); CfLog(cfverbose,g_output,""); AddMultipleClasses(ptr->elsedef); return true; } snprintf(g_output,CF_BUFSIZE*2, "%s does not appear to be a hard link to %s\n",from,to); CfLog(cfinform,g_output,""); if (g_enforcelinks) { snprintf(g_output, CF_BUFSIZE*2, "Moving %s to %s.%s\n", from, from, CF_SAVED); CfLog(cfinform,g_output,""); if (g_dontdo) { return true; } saved[0] = '\0'; strcpy(saved,from); sprintf(stamp, "_%d_%s", g_cfstarttime, CanonifyName(ctime(&STAMPNOW))); strcat(saved,stamp); strcat(saved,CF_SAVED); if (rename(from,saved) == -1) { perror("rename"); return(true); } DoHardLink(from,to,ptr->defines); } return(true); }
/* should return true if 'to' found */ int LinkFiles(char *from,char *to_tmp, struct Item *inclusions,struct Item *exclusions,struct Item *copy, short nofile,struct Link *ptr) { struct stat buf,savebuf; char to[CF_BUFSIZE], linkbuf[CF_BUFSIZE]; char saved[CF_BUFSIZE],absto[CF_BUFSIZE],*lastnode; struct UidList fakeuid; struct Image ip; char stamp[CF_BUFSIZE]; time_t STAMPNOW; STAMPNOW = time((time_t *)NULL); memset(to,0,CF_BUFSIZE); memset(&ip,0, sizeof(ip)); /* links without a directory reference */ if ((*to_tmp != '/') && (*to_tmp != '.')) { strcpy(to,"./"); } if (strlen(to_tmp)+3 > CF_BUFSIZE) { printf("%s: CF_BUFSIZE boundaries exceeded in LinkFiles(%s->%s)\n", g_vprefix,from,to_tmp); return false; } strcat(to,to_tmp); Debug2("Linkfiles(%s,%s)\n",from,to); for (lastnode = from+strlen(from); *lastnode != '/'; lastnode--) { } lastnode++; if (IgnoredOrExcluded(links,lastnode,inclusions,exclusions)) { Verbose("%s: Skipping non-included pattern %s\n",g_vprefix,from); return true; } if (IsWildItemIn(g_vcopylinks,lastnode) || IsWildItemIn(copy,lastnode)) { fakeuid.uid = CF_SAME_OWNER; fakeuid.next = NULL; ip.plus = CF_SAMEMODE; ip.minus = CF_SAMEMODE; ip.uid = &fakeuid; ip.gid = (struct GidList *) &fakeuid; ip.action = "do"; ip.recurse = 0; ip.type = 't'; ip.defines = ptr->defines; ip.elsedef = ptr->elsedef; ip.backup = true; ip.exclusions = NULL; ip.inclusions = NULL; ip.symlink = NULL; ip.classes = NULL; ip.plus_flags = 0; ip.size = CF_NOSIZE; ip.linktype = 's'; ip.minus_flags = 0; ip.server = strdup("localhost"); Verbose("%s: Link item %s marked for copying instead\n", g_vprefix, from); MakeDirectoriesFor(to,'n'); CheckImage(to,from,&ip); free(ip.server); return true; } /* relative path, must still check if exists */ if (*to != '/') { Debug("Relative link destination detected: %s\n",to); strcpy(absto,AbsLinkPath(from,to)); Debug("Absolute path to relative link = %s, from %s\n",absto,from); } else { strcpy(absto,to); } if (!nofile) { if (stat(absto,&buf) == -1) { /* no error warning, since the higher level routine uses this */ return(false); } } Debug2("Trying to link %s -> %s (%s)\n",from,to,absto); if (lstat(from,&buf) == 0) { if (! S_ISLNK(buf.st_mode) && ! g_enforcelinks) { snprintf(g_output,CF_BUFSIZE*2,"Error linking %s -> %s\n",from,to); CfLog(cfsilent,g_output,""); snprintf(g_output, CF_BUFSIZE*2, "Cannot make link: %s exists and is not a link! " "(uid %d)\n", from, buf.st_uid); CfLog(cfsilent,g_output,""); return(true); } if (S_ISREG(buf.st_mode) && g_enforcelinks) { snprintf(g_output, CF_BUFSIZE*2, "Moving %s to %s%s\n", from, from, CF_SAVED); CfLog(cfsilent,g_output,""); if (g_dontdo) { return true; } saved[0] = '\0'; strcpy(saved,from); sprintf(stamp, "_%d_%s", g_cfstarttime, CanonifyName(ctime(&STAMPNOW))); strcat(saved,stamp); strcat(saved,CF_SAVED); if (rename(from,saved) == -1) { snprintf(g_output, CF_BUFSIZE*2, "Can't rename %s to %s\n", from,saved); CfLog(cferror,g_output,"rename"); return(true); } if (Repository(saved,g_vrepository)) { unlink(saved); } } if (S_ISDIR(buf.st_mode) && g_enforcelinks) { snprintf(g_output,CF_BUFSIZE*2,"Moving directory %s to %s%s.dir\n", from,from,CF_SAVED); CfLog(cfsilent,g_output,""); if (g_dontdo) { return true; } saved[0] = '\0'; strcpy(saved,from); sprintf(stamp, "_%d_%s", g_cfstarttime, CanonifyName(ctime(&STAMPNOW))); strcat(saved,stamp); strcat(saved,CF_SAVED); strcat(saved,".dir"); if (stat(saved,&savebuf) != -1) { snprintf(g_output,CF_BUFSIZE*2, "Couldn't save directory %s, " "since %s exists already\n", from,saved); CfLog(cferror,g_output,""); snprintf(g_output,CF_BUFSIZE*2, "Unable to force link to " "existing directory %s\n",from); CfLog(cferror,g_output,""); return true; } if (rename(from,saved) == -1) { snprintf(g_output, CF_BUFSIZE*2, "Can't rename %s to %s\n", from,saved); CfLog(cferror,g_output,"rename"); return(true); } } } memset(linkbuf,0,CF_BUFSIZE); if (readlink(from,linkbuf,CF_BUFSIZE-1) == -1) { /* link doesn't exist */ if (! MakeDirectoriesFor(from,'n')) { snprintf(g_output,CF_BUFSIZE*2, "Couldn't build directory tree up to %s!\n",from); CfLog(cfsilent,g_output,""); snprintf(g_output,CF_BUFSIZE*2, "One element was a plain file, not a directory!\n"); CfLog(cfsilent,g_output,""); return(true); } } else { int off1 = 0, off2 = 0; DeleteSlash(linkbuf); /* Ignore ./ at beginning */ if (strncmp(linkbuf,"./",2) == 0) { off1 = 2; } if (strncmp(to,"./",2) == 0) { off2 = 2; } if (strcmp(linkbuf+off1,to+off2) != 0) { if (g_enforcelinks) { snprintf(g_output,CF_BUFSIZE*2,"Removing link %s\n",from); CfLog(cfinform,g_output,""); if (!g_dontdo) { if (unlink(from) == -1) { perror("unlink"); return true; } return DoLink(from,to,ptr->defines); } } else { snprintf(g_output,CF_BUFSIZE*2, "Old link %s points somewhere else. Doing nothing!\n", from); CfLog(cfsilent,g_output,""); snprintf(g_output, CF_BUFSIZE*2, "(Link points to %s not %s)\n\n", linkbuf,to); CfLog(cfsilent,g_output,""); return(true); } } else { snprintf(g_output, CF_BUFSIZE*2, "Link (%s->%s) exists.\n", from, to_tmp); CfLog(cfverbose,g_output,""); if (!nofile) { /* Check whether link points somewhere */ KillOldLink(from,ptr->defines); return true; } AddMultipleClasses(ptr->elsedef); return(true); } } return DoLink(from,to,ptr->defines); }