Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Apr 1995 12:15:45 +0300
From:      Kai Vorma <vode@snakemail.hut.fi>
To:        current@FreeBSD.org
Subject:   patch for sup
Message-ID:  <199504050915.MAA10911@vinkku.hut.fi>

next in thread | raw e-mail | index | archive | help
Here is a simple patch for sup that makes it possible to have local
modifications in your source tree so that sup won't overwrite them. The
idea is simple (stolen from this mailing-list, I think :)

  If sup is updating file foo.c and there exists file foo.c#sup it
  will update the latter file an leave the former untouched.

This patch should work with regular files and perhaps with links but
you _cannot_ create shadow directory <dir>#foo. I have not tested this
too much (I did it yesterday evening) but I has worked so far just
fine :-)

Btw, why is freefall's supserver so abysmally slow? Is it because
supservers uses fork() like almost all badly designed network
servers or something else? If the problem is not fork() then I'll try
to see if I can make it faster.

..vode

PS. This patch is agains sup.tar.gz from ports-collection.

---------------------------------------------------------------------------
*** supcmeat.c.ORIG	Thu Aug 11 16:24:45 1994
--- supcmeat.c	Wed Apr  5 10:11:15 1995
***************
*** 27,32 ****
--- 27,35 ----
   **********************************************************************
   * HISTORY
   *
+  * 5-Apr-95 Kai Vorma <vode@hut.fi>
+  *      Update regular file foo.c#sup, if exists, instead of foo.c
+  *
   * 7-July-93  Nate Williams at Montana State University
   *	Modified SUP to use gzip based compression when sending files
   *	across the network to save BandWidth
***************
*** 151,156 ****
--- 154,163 ----
  #include <varargs.h>
  #endif
  
+ #define tstat(p,b)  tdostat(0,p,b)
+ #define tlstat(p,b) tdostat(1,p,b)
+ char rname[1024];
+ 
  TREE *lastT;				/* last filenames in collection */
  jmp_buf sjbuf;				/* jump location for network errors */
  int dontjump;				/* flag to void sjbuf */
***************
*** 564,572 ****
  		if ((t->Tflags&FNEW) == 0 && (thisC->Cflags&CFOLD) == 0)
  			return (SCMOK);
  		if ((t->Tmode&S_IFMT) == S_IFLNK)
! 			exists = (lstat (t->Tname,&sbuf) == 0);
  		else
! 			exists = (stat (t->Tname,&sbuf) == 0);
  		/* This is moderately complicated:
  		   If the file is the wrong type or doesn't exist, we need to
  		   fetch the whole file.  If the file is a special file, we
--- 571,579 ----
  		if ((t->Tflags&FNEW) == 0 && (thisC->Cflags&CFOLD) == 0)
  			return (SCMOK);
  		if ((t->Tmode&S_IFMT) == S_IFLNK)
! 			exists = (tlstat (t->Tname,&sbuf) == 0);
  		else
! 			exists = (tstat (t->Tname,&sbuf) == 0);
  		/* This is moderately complicated:
  		   If the file is the wrong type or doesn't exist, we need to
  		   fetch the whole file.  If the file is a special file, we
***************
*** 594,600 ****
  	/* If we get this far, we're either doing an update or a full fetch. */
  	if (!fetch && t->Tmode == sbuf.st_mode &&
  	    (t->Tmode&S_IFMT) == S_IFREG && (thisC->Cflags&CFNOUPDATE)) {
! 		vnotify ("SUP update avoided for %s\n", t->Tname);
  		return (SCMOK);
  	}
  	newt = Tinsert (&needT,t->Tname,TRUE);
--- 601,607 ----
  	/* If we get this far, we're either doing an update or a full fetch. */
  	if (!fetch && t->Tmode == sbuf.st_mode &&
  	    (t->Tmode&S_IFMT) == S_IFREG && (thisC->Cflags&CFNOUPDATE)) {
! 		vnotify ("SUP update avoided for %s\n", rname);
  		return (SCMOK);
  	}
  	newt = Tinsert (&needT,t->Tname,TRUE);
***************
*** 619,650 ****
  
  	if (t->Tflags&FUPDATE)		/* in current upgrade list */
  		return (SCMOK);
! 	if (lstat(name,&sbuf) < 0)	/* doesn't exist */
  		return (SCMOK);
  	/* is it a symbolic link ? */
  	if ((sbuf.st_mode & S_IFMT) == S_IFLNK) {
  		if (Tlookup (refuseT,name)) {
  			vnotify ("SUP Would not delete symbolic link %s\n",
! 				name);
  			return (SCMOK);
  		}
  		if (thisC->Cflags&CFLIST) {
! 			vnotify ("SUP Would delete symbolic link %s\n",name);
  			return (SCMOK);
  		}
  		if ((thisC->Cflags&CFDELETE) == 0) {
! 			notify ("SUP Please delete symbolic link %s\n",name);
  			t->Tflags |= FUPDATE;
  			return (SCMOK);
  		}
! 		x = unlink (name);
  		if (x < 0) {
  			notify ("SUP: Unable to delete symbolic link %s\n",
! 				name);
  			t->Tflags |= FUPDATE;
  			return (SCMOK);
  		}
! 		vnotify ("SUP Deleted symbolic link %s\n",name);
  		return (SCMOK);
  	}
  	/* is it a directory ? */
--- 626,657 ----
  
  	if (t->Tflags&FUPDATE)		/* in current upgrade list */
  		return (SCMOK);
! 	if (tlstat(name,&sbuf) < 0)	/* doesn't exist */
  		return (SCMOK);
  	/* is it a symbolic link ? */
  	if ((sbuf.st_mode & S_IFMT) == S_IFLNK) {
  		if (Tlookup (refuseT,name)) {
  			vnotify ("SUP Would not delete symbolic link %s\n",
! 				rname);
  			return (SCMOK);
  		}
  		if (thisC->Cflags&CFLIST) {
! 			vnotify ("SUP Would delete symbolic link %s\n",rname);
  			return (SCMOK);
  		}
  		if ((thisC->Cflags&CFDELETE) == 0) {
! 			notify ("SUP Please delete symbolic link %s\n",rname);
  			t->Tflags |= FUPDATE;
  			return (SCMOK);
  		}
! 		x = unlink (rname);
  		if (x < 0) {
  			notify ("SUP: Unable to delete symbolic link %s\n",
! 				rname);
  			t->Tflags |= FUPDATE;
  			return (SCMOK);
  		}
! 		vnotify ("SUP Deleted symbolic link %s\n",rname);
  		return (SCMOK);
  	}
  	/* is it a directory ? */
***************
*** 673,697 ****
  	}
  	/* it is a file */
  	if (Tlookup (refuseT,name)) {
! 		vnotify ("SUP Would not delete file %s\n",name);
  		return (SCMOK);
  	}
  	if (thisC->Cflags&CFLIST) {
! 		vnotify ("SUP Would delete file %s\n",name);
  		return (SCMOK);
  	}
  	if ((thisC->Cflags&CFDELETE) == 0) {
! 		notify ("SUP Please delete file %s\n",name);
  		t->Tflags |= FUPDATE;
  		return (SCMOK);
  	}
! 	x = unlink (name);
  	if (x < 0) {
! 		notify ("SUP: Unable to delete file %s\n",name);
  		t->Tflags |= FUPDATE;
  		return (SCMOK);
  	}
! 	vnotify ("SUP Deleted file %s\n",name);
  	return (SCMOK);
  }
  
--- 680,704 ----
  	}
  	/* it is a file */
  	if (Tlookup (refuseT,name)) {
! 		vnotify ("SUP Would not delete file %s\n",rname);
  		return (SCMOK);
  	}
  	if (thisC->Cflags&CFLIST) {
! 		vnotify ("SUP Would delete file %s\n",rname);
  		return (SCMOK);
  	}
  	if ((thisC->Cflags&CFDELETE) == 0) {
! 		notify ("SUP Please delete file %s\n",rname);
  		t->Tflags |= FUPDATE;
  		return (SCMOK);
  	}
! 	x = unlink (rname);
  	if (x < 0) {
! 		notify ("SUP: Unable to delete file %s\n",rname);
  		t->Tflags |= FUPDATE;
  		return (SCMOK);
  	}
! 	vnotify ("SUP Deleted file %s\n",rname);
  	return (SCMOK);
  }
  
***************
*** 746,754 ****
  	register char *type;
  
  	if (mode == S_IFLNK)
! 		*newp = (lstat (name,statp) < 0);
  	else
! 		*newp = (stat (name,statp) < 0);
  	if (*newp) {
  		if (thisC->Cflags&CFLIST)
  			return (FALSE);
--- 753,761 ----
  	register char *type;
  
  	if (mode == S_IFLNK)
! 		*newp = (tlstat (name,statp) < 0);
  	else
! 		*newp = (tstat (name,statp) < 0);
  	if (*newp) {
  		if (thisC->Cflags&CFLIST)
  			return (FALSE);
***************
*** 774,792 ****
  		break;
  	}
  	if (thisC->Cflags&CFLIST) {
! 		vnotify ("SUP Would remove %s %s\n",type,name);
  		return (FALSE);
  	}
  	if ((statp->st_mode&S_IFMT) == S_IFDIR) {
  		if (rmdir (name) < 0)
  			runp ("rm","rm","-rf",name,0);
  	} else
! 		(void) unlink (name);
! 	if (stat (name,statp) < 0) {
! 		vnotify ("SUP Removed %s %s\n",type,name);
  		return (FALSE);
  	}
! 	notify ("SUP: Couldn't remove %s %s\n",type,name);
  	return (TRUE);
  }
  
--- 781,799 ----
  		break;
  	}
  	if (thisC->Cflags&CFLIST) {
! 		vnotify ("SUP Would remove %s %s\n",type,rname);
  		return (FALSE);
  	}
  	if ((statp->st_mode&S_IFMT) == S_IFDIR) {
  		if (rmdir (name) < 0)
  			runp ("rm","rm","-rf",name,0);
  	} else
! 		(void) unlink (rname);
! 	if (stat (rname,statp) < 0) {
! 		vnotify ("SUP Removed %s %s\n",type,rname);
  		return (FALSE);
  	}
! 	notify ("SUP: Couldn't remove %s %s\n",type,rname);
  	return (TRUE);
  }
  
***************
*** 813,819 ****
  		return (SCMOK);
  	}
  	if (prepare (t->Tname,t->Tmode&S_IFMT,&new,&sbuf)) {
! 		notify ("SUP: Can't prepare path for %s\n",t->Tname);
  		if ((t->Tmode&S_IFMT) == S_IFREG) {
  			x = readskip ();	/* skip over file */
  			if (x != SCMOK)
--- 820,826 ----
  		return (SCMOK);
  	}
  	if (prepare (t->Tname,t->Tmode&S_IFMT,&new,&sbuf)) {
! 		notify ("SUP: Can't prepare path for %s\n",rname);
  		if ((t->Tmode&S_IFMT) == S_IFREG) {
  			x = readskip ();	/* skip over file */
  			if (x != SCMOK)
***************
*** 905,925 ****
  	}
  	linkname = t->Tlink->Tname;
  	if (!new && (t->Tflags&FNEW) == 0 &&
! 	    (n = readlink (t->Tname,buf,sizeof(buf))) >= 0 &&
  	    (n == strlen (linkname)) && (strncmp (linkname,buf,n) == 0))
  		return (FALSE);
  	if (thisC->Cflags&CFLIST) {
  		vnotify ("SUP Would %s symbolic link %s to %s\n",
! 			new?"create":"update",t->Tname,linkname);
  		return (FALSE);
  	}
  	if (!new)
! 		(void) unlink (t->Tname);
! 	if (symlink (linkname,t->Tname) < 0 || lstat(t->Tname,statp) < 0) {
! 		notify ("SUP: Unable to create symbolic link %s\n",t->Tname);
  		return (TRUE);
  	}
! 	vnotify ("SUP Created symbolic link %s to %s\n",t->Tname,linkname);
  	return (FALSE);
  }
  
--- 912,932 ----
  	}
  	linkname = t->Tlink->Tname;
  	if (!new && (t->Tflags&FNEW) == 0 &&
! 	    (n = readlink (rname,buf,sizeof(buf))) >= 0 &&
  	    (n == strlen (linkname)) && (strncmp (linkname,buf,n) == 0))
  		return (FALSE);
  	if (thisC->Cflags&CFLIST) {
  		vnotify ("SUP Would %s symbolic link %s to %s\n",
! 			new?"create":"update",rname,linkname);
  		return (FALSE);
  	}
  	if (!new)
! 		(void) unlink (rname);
! 	if (symlink (linkname,rname) < 0 || lstat(rname,statp) < 0) {
! 		notify ("SUP: Unable to create symbolic link %s\n",rname);
  		return (TRUE);
  	}
! 	vnotify ("SUP Created symbolic link %s to %s\n",rname,linkname);
  	return (FALSE);
  }
  
***************
*** 950,966 ****
  				return (FALSE);
  		}
  		if (thisC->Cflags&CFLIST) {
! 			vnotify ("SUP Would update file %s\n",t->Tname);
  			return (FALSE);
  		}
! 		vnotify ("SUP Updating file %s\n",t->Tname);
  		if ((t->Tflags&FNOACCT) == 0) {
! 			(void) chown (t->Tname,t->Tuid,t->Tgid);
! 			(void) chmod (t->Tname,t->Tmode&S_IMODE);
  		}
  		tbuf[0].tv_sec = time((long *)NULL);  tbuf[0].tv_usec = 0;
  		tbuf[1].tv_sec = t->Tmtime;  tbuf[1].tv_usec = 0;
! 		(void) utimes (t->Tname,tbuf);
  		return (FALSE);
  	}
  	if (thisC->Cflags&CFLIST) {
--- 957,973 ----
  				return (FALSE);
  		}
  		if (thisC->Cflags&CFLIST) {
! 			vnotify ("SUP Would update file %s\n",rname);
  			return (FALSE);
  		}
! 		vnotify ("SUP Updating file %s\n",rname);
  		if ((t->Tflags&FNOACCT) == 0) {
! 			(void) chown (rname,t->Tuid,t->Tgid);
! 			(void) chmod (rname,t->Tmode&S_IMODE);
  		}
  		tbuf[0].tv_sec = time((long *)NULL);  tbuf[0].tv_usec = 0;
  		tbuf[1].tv_sec = t->Tmtime;  tbuf[1].tv_usec = 0;
! 		(void) utimes (rname,tbuf);
  		return (FALSE);
  	}
  	if (thisC->Cflags&CFLIST) {
***************
*** 972,993 ****
  			p = "receive old";
  		else
  			p = "receive";
! 		vnotify ("SUP Would %s file %s\n",p,t->Tname);
  		return (FALSE);
  	}
! 	vnotify ("SUP Receiving file %s\n",t->Tname);
  	if (!new && (t->Tmode&S_IFMT) == S_IFREG &&
  	    (t->Tflags&FBACKUP) && (thisC->Cflags&CFBACKUP)) {
! 		fin = fopen (t->Tname,"r");	/* create backup */
  		if (fin == NULL) {
  			x = readskip ();	/* skip over file */
  			if (x != SCMOK)
  				goaway ("Can't skip file transfer");
  			notify ("SUP: Can't open %s to create backup\n",
! 				t->Tname);
  			return (TRUE);		/* mark upgrade as nogood */
  		}
! 		path (t->Tname,dirpart,filepart);
  		(void) sprintf (filename,FILEBACKUP,dirpart,filepart);
  		fout = fopen (filename,"w");
  		if (fout == NULL) {
--- 979,1000 ----
  			p = "receive old";
  		else
  			p = "receive";
! 		vnotify ("SUP Would %s file %s\n",p,rname);
  		return (FALSE);
  	}
! 	vnotify ("SUP Receiving file %s\n",rname);
  	if (!new && (t->Tmode&S_IFMT) == S_IFREG &&
  	    (t->Tflags&FBACKUP) && (thisC->Cflags&CFBACKUP)) {
! 		fin = fopen (rname,"r");	/* create backup */
  		if (fin == NULL) {
  			x = readskip ();	/* skip over file */
  			if (x != SCMOK)
  				goaway ("Can't skip file transfer");
  			notify ("SUP: Can't open %s to create backup\n",
! 				rname);
  			return (TRUE);		/* mark upgrade as nogood */
  		}
! 		path (rname,dirpart,filepart);
  		(void) sprintf (filename,FILEBACKUP,dirpart,filepart);
  		fout = fopen (filename,"w");
  		if (fout == NULL) {
***************
*** 1006,1025 ****
  		ffilecopy (fin,fout);
  		(void) fclose (fin);
  		(void) fclose (fout);
! 		vnotify ("SUP Backup of %s created\n", t->Tname);
  	}
! 	x = copyfile (t->Tname,(char *)NULL);
  	if (x)
  		return (TRUE);
  	if ((t->Tflags&FNOACCT) == 0) {
  		/* convert user and group names to local ids */
  		ugconvert (t->Tuser,t->Tgroup,&t->Tuid,&t->Tgid,&t->Tmode);
! 		(void) chown (t->Tname,t->Tuid,t->Tgid);
! 		(void) chmod (t->Tname,t->Tmode&S_IMODE);
  	}
  	tbuf[0].tv_sec = time((long *)NULL);  tbuf[0].tv_usec = 0;
  	tbuf[1].tv_sec = t->Tmtime;  tbuf[1].tv_usec = 0;
! 	(void) utimes (t->Tname,tbuf);
  	return (FALSE);
  }
  
--- 1013,1032 ----
  		ffilecopy (fin,fout);
  		(void) fclose (fin);
  		(void) fclose (fout);
! 		vnotify ("SUP Backup of %s created\n", rname);
  	}
! 	x = copyfile (rname,(char *)NULL);
  	if (x)
  		return (TRUE);
  	if ((t->Tflags&FNOACCT) == 0) {
  		/* convert user and group names to local ids */
  		ugconvert (t->Tuser,t->Tgroup,&t->Tuid,&t->Tgid,&t->Tmode);
! 		(void) chown (rname,t->Tuid,t->Tgid);
! 		(void) chmod (rname,t->Tmode&S_IMODE);
  	}
  	tbuf[0].tv_sec = time((long *)NULL);  tbuf[0].tv_usec = 0;
  	tbuf[1].tv_sec = t->Tmtime;  tbuf[1].tv_usec = 0;
! 	(void) utimes (rname,tbuf);
  	return (FALSE);
  }
  
***************
*** 1031,1038 ****
  	register char *name = t->Tname;
  	int new,x;
  	char *type;
  
! 	if (stat(*fname,&fbuf) < 0) {	/* source file */
  		if (thisC->Cflags&CFLIST) {
  			vnotify ("SUP Would link %s to %s\n",name,*fname);
  			return (SCMOK);
--- 1038,1046 ----
  	register char *name = t->Tname;
  	int new,x;
  	char *type;
+ 	char rfname[1024];	/* Kludge alert.. */
  
! 	if (tstat(*fname,&fbuf) < 0) {	/* source file */
  		if (thisC->Cflags&CFLIST) {
  			vnotify ("SUP Would link %s to %s\n",name,*fname);
  			return (SCMOK);
***************
*** 1041,1048 ****
  		thisC->Cnogood = TRUE;
  		return (SCMOK);
  	}
  	if (prepare (name,S_IFREG,&new,&sbuf)) {
! 		notify ("SUP: Can't prepare path for link %s\n",name);
  		thisC->Cnogood = TRUE;
  		return (SCMOK);
  	}
--- 1049,1057 ----
  		thisC->Cnogood = TRUE;
  		return (SCMOK);
  	}
+ 	strcpy(rfname,rname);
  	if (prepare (name,S_IFREG,&new,&sbuf)) {
! 		notify ("SUP: Can't prepare path for link %s\n",rname);
  		thisC->Cnogood = TRUE;
  		return (SCMOK);
  	}
***************
*** 1050,1069 ****
  	    fbuf.st_dev == sbuf.st_dev && fbuf.st_ino == sbuf.st_ino)
  		return (SCMOK);
  	if (thisC->Cflags&CFLIST) {
! 		vnotify ("SUP Would link %s to %s\n",name,*fname);
  		return (SCMOK);
  	}
! 	(void) unlink (name);
  	type = "";
! 	if ((x = link (*fname,name)) < 0) {
  		type = "symbolic ";
! 		x = symlink (*fname,name);
  	}
! 	if (x < 0 || lstat(name,&sbuf) < 0) {
! 		notify ("SUP: Unable to create %slink %s\n",type,name);
  		return (TRUE);
  	}
! 	vnotify ("SUP Created %slink %s to %s\n",type,name,*fname);
  	return (SCMOK);
  }
  
--- 1059,1078 ----
  	    fbuf.st_dev == sbuf.st_dev && fbuf.st_ino == sbuf.st_ino)
  		return (SCMOK);
  	if (thisC->Cflags&CFLIST) {
! 		vnotify ("SUP Would link %s to %s\n",rname,rfname);
  		return (SCMOK);
  	}
! 	(void) unlink (rname);
  	type = "";
! 	if ((x = link (rfname,rname)) < 0) {
  		type = "symbolic ";
! 		x = symlink (rfname,rname);
  	}
! 	if (x < 0 || lstat(rname,&sbuf) < 0) {
! 		notify ("SUP: Unable to create %slink %s\n",type,rname);
  		return (TRUE);
  	}
! 	vnotify ("SUP Created %slink %s to %s\n",type,rname,rfname);
  	return (SCMOK);
  }
  
***************
*** 1481,1483 ****
--- 1490,1518 ----
  	if (!dontjump)
  		longjmp (sjbuf,TRUE);
  }
+ 
+ 
+ char *SUFFIX = "#sup";
+ 
+ int tdostat(ls, path, sbuf)
+      int ls;
+      char *path;
+      struct stat *sbuf;
+ {
+   int x, l = strlen(path);
+ 
+   strcpy(rname, path);
+   if (l + strlen(SUFFIX) < sizeof(rname)) {
+     strcat(rname, SUFFIX);
+     if ((x = ls ? lstat(rname, sbuf): stat(rname, sbuf)) != -1) {
+       if (sbuf->st_mode&S_IFMT == S_IFDIR)
+ 	goaway("%s must not be a directory", rname);
+       return x;
+     }
+     if (errno != ENOENT)
+       goaway ("%sstat for %s failed (%d)", ls ? "tl" : "t", rname, errno);
+     rname[l] = '\0';
+   }
+   return (ls ? lstat(rname, sbuf) : stat(rname, sbuf));
+ }
+ 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199504050915.MAA10911>