[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Ubuntu dpkg 1.13.22ubuntu4



This e-mail has been sent due to an upload to Ubuntu that contains Ubuntu
changes.  It contains the difference between the new version and the
previous version of the same source package in Ubuntu.
Format: 1.7
Date: Fri, 21 Jul 2006 17:22:24 +0100
Source: dpkg
Binary: dpkg dselect dpkg-dev
Architecture: source
Version: 1.13.22ubuntu4
Distribution: edgy
Urgency: low
Maintainer: Dpkg Developers <team@dpkg.org>
Changed-By: Ian Jackson <iwj@ubuntu.com>
Description: 
 dpkg       - package maintenance system for Debian
 dpkg-dev   - package building tools for Debian
 dselect    - user tool to manage Debian packages
Changes: 
 dpkg (1.13.22ubuntu4) edgy; urgency=low
 .
   * Implement Breaks.  References:
      http://lists.debian.org/debian-devel/1997/10/msg00643.html
      https://wiki.ubuntu.com/PackageDependencyFieldBreaks
 .
   Decisions made:
   * Specifying Breaks: <virtual package> is fairly meaningless
     without versioned Provides but to make versioned Provides easier
     in the future we support it fully.
   * We do not transitively deconfigure things when we deconfigure
     due to Breaks, just as we don't do so when we deconfigure due
     to removal due to Conflicts (see also #378009).
   * Just as for deconfigure due to Conflicts, we don't deconfigure
     Essential packages without --force-remove-essential.
   * We aren't willing to deconfigure more than one package as a result
     of a single element of a Breaks, just as we aren't willing to
     remove more than one package as a result of a single element of
     a Conflicts.  (Note that this can only occur due to virtual
     packages so it can be worked around by specifying the individual
     real packages instead.)
   * We're happy to deconfigure a package that's on hold even if
     afterwards, due to Breaks, there might not be a way to reconfigure it.
     (This is analogous to the situation where we install a package
     which no longer satisfies the dependencies of an on-hold
     package; it's not clear what the right answer is.)
   * We invent a new --force-breaks which does much the
     same as --force-conflicts.
   * --ignore-depends works for Breaks even though it doesn't work
     for Conflicts.
   * <deconfigured's prerm> deconfigure in-favour <installing> <ver>
       as well as
     <deconfigured's prerm> deconfigure in-favour <installing> <ver> \
                                        removing <conflictor> <ver>
       and of course the corresponding
     <deconfigured's postinst> abort-deconfigure in-favour <installing> <ver>
 .
   Two other changes bundled:
   * mlib contains m_strdup (part of the fix for #379028).
   * Fix for #378003 (multiple deconfigurations).
 .
 dpkg (1.13.22ubuntu3) edgy; urgency=low
 .
   * Fix formatting of these files:
        lib/showpkg.c
        lib/tarfn.c
        src/configure.c
        src/archives.c (function quote_filename only)
     to conform to the rest of dpkg by running them through
     expand -t2 (and in the last case using M-x indent-rigidly once).
     As discussed on debian-dpkg.  Debian #375711.
Files: 
 15c2f49ea0ed9ab4d99bc657a545432d 867 admin required dpkg_1.13.22ubuntu4.dsc
 171c7d72f616e18707a1852a3cec4e74 3108507 admin required dpkg_1.13.22ubuntu4.tar.gz
diff -pruN 1.13.22ubuntu2/debian/changelog 1.13.22ubuntu4/debian/changelog
--- 1.13.22ubuntu2/debian/changelog	2006-07-11 19:02:07.000000000 +0100
+++ 1.13.22ubuntu4/debian/changelog	2006-07-21 17:33:57.000000000 +0100
@@ -1,3 +1,59 @@
+dpkg (1.13.22ubuntu4) edgy; urgency=low
+
+  * Implement Breaks.  References:
+     http://lists.debian.org/debian-devel/1997/10/msg00643.html
+     https://wiki.ubuntu.com/PackageDependencyFieldBreaks
+
+  Decisions made:
+  * Specifying Breaks: <virtual package> is fairly meaningless
+    without versioned Provides but to make versioned Provides easier
+    in the future we support it fully.
+  * We do not transitively deconfigure things when we deconfigure
+    due to Breaks, just as we don't do so when we deconfigure due
+    to removal due to Conflicts (see also #378009).
+  * Just as for deconfigure due to Conflicts, we don't deconfigure
+    Essential packages without --force-remove-essential.
+  * We aren't willing to deconfigure more than one package as a result
+    of a single element of a Breaks, just as we aren't willing to
+    remove more than one package as a result of a single element of
+    a Conflicts.  (Note that this can only occur due to virtual
+    packages so it can be worked around by specifying the individual
+    real packages instead.)
+  * We're happy to deconfigure a package that's on hold even if
+    afterwards, due to Breaks, there might not be a way to reconfigure it.
+    (This is analogous to the situation where we install a package
+    which no longer satisfies the dependencies of an on-hold
+    package; it's not clear what the right answer is.)
+  * We invent a new --force-breaks which does much the
+    same as --force-conflicts.
+  * --ignore-depends works for Breaks even though it doesn't work
+    for Conflicts.
+  * <deconfigured's prerm> deconfigure in-favour <installing> <ver>
+      as well as
+    <deconfigured's prerm> deconfigure in-favour <installing> <ver> \
+                                       removing <conflictor> <ver>
+      and of course the corresponding
+    <deconfigured's postinst> abort-deconfigure in-favour <installing> <ver>
+
+  Two other changes bundled:
+  * mlib contains m_strdup (part of the fix for #379028).
+  * Fix for #378003 (multiple deconfigurations).
+
+ -- Ian Jackson <iwj@ubuntu.com>  Fri, 21 Jul 2006 17:22:24 +0100
+
+dpkg (1.13.22ubuntu3) edgy; urgency=low
+
+  * Fix formatting of these files:
+       lib/showpkg.c
+       lib/tarfn.c
+       src/configure.c
+       src/archives.c (function quote_filename only)
+    to conform to the rest of dpkg by running them through
+    expand -t2 (and in the last case using M-x indent-rigidly once).
+    As discussed on debian-dpkg.  Debian #375711.
+
+ -- Ian Jackson <iwj@ubuntu.com>  Fri, 21 Jul 2006 17:17:49 +0100
+
 dpkg (1.13.22ubuntu2) edgy; urgency=low
 
   * `Breaks': Implement step 1 of PackageDependencyFieldBreaks:
diff -pruN 1.13.22ubuntu2/lib/dpkg.h 1.13.22ubuntu4/lib/dpkg.h
--- 1.13.22ubuntu2/lib/dpkg.h	2006-01-18 08:30:03.000000000 +0000
+++ 1.13.22ubuntu4/lib/dpkg.h	2006-07-21 17:20:25.000000000 +0100
@@ -223,6 +223,7 @@ void warningf(const char *fmt, ...);
 void setcloexec(int fd, const char* fn);
 void *m_malloc(size_t);
 void *m_realloc(void*, size_t);
+char *m_strdup(const char *s);
 int m_fork(void);
 void m_dup2(int oldfd, int newfd);
 void m_pipe(int fds[2]);
diff -pruN 1.13.22ubuntu2/lib/mlib.c 1.13.22ubuntu4/lib/mlib.c
--- 1.13.22ubuntu2/lib/mlib.c	2006-02-06 21:49:20.000000000 +0000
+++ 1.13.22ubuntu4/lib/mlib.c	2006-07-21 17:20:25.000000000 +0100
@@ -79,6 +79,15 @@ static void cu_m_fork(int argc, void **a
    */
 }
 
+char *m_strdup(const char *s) {
+  size_t l;
+  char *r;
+  l= strlen(s);
+  r= m_malloc(l+1);
+  strcpy(r,s);
+  return r;
+}
+
 int m_fork(void) {
   pid_t r;
   r= fork();
diff -pruN 1.13.22ubuntu2/lib/showpkg.c 1.13.22ubuntu4/lib/showpkg.c
--- 1.13.22ubuntu2/lib/showpkg.c	2006-05-18 09:10:38.000000000 +0100
+++ 1.13.22ubuntu4/lib/showpkg.c	2006-07-21 17:15:29.000000000 +0100
@@ -32,242 +32,242 @@
 typedef enum { invalid, string, field } itemtype_t;
 
 struct lstitem {
-	itemtype_t type;
-	size_t width;
-	int pad;
-	char* data;
-	struct lstitem* next;
+  itemtype_t type;
+  size_t width;
+  int pad;
+  char* data;
+  struct lstitem* next;
 };
 
 
 static struct lstitem* alloclstitem(void) {
-	struct lstitem*	buf;
+  struct lstitem* buf;
 
-	buf=(struct lstitem*)malloc(sizeof(struct lstitem));
-	buf->type=invalid;
-	buf->next=NULL;
-	buf->data=NULL;
-	buf->width=0;
-	buf->pad=0;
+  buf=(struct lstitem*)malloc(sizeof(struct lstitem));
+  buf->type=invalid;
+  buf->next=NULL;
+  buf->data=NULL;
+  buf->width=0;
+  buf->pad=0;
 
-	return buf;
+  return buf;
 }
 
 
 static int parsefield(struct lstitem* cur, const char* fmt, const char* fmtend) {
-	int len;
-	const char* ws;
+  int len;
+  const char* ws;
 
-	len=fmtend-fmt+1;
+  len=fmtend-fmt+1;
 
-	ws=(const char*)memchr(fmt, ';', len);
-	if (ws) {
-		char* endptr;
-		long w;
-
-		w=strtol(ws+1,&endptr,0);
-		if (endptr[0]!='}') {
-			fprintf(stderr, _("invalid character `%c' in field width\n"), *endptr);
-			return 0;
-		}
-
-		if (w<0) {
-			cur->pad=1;
-			cur->width=(size_t)-w;
-		} else
-			cur->width=(size_t)w;
-
-		len=ws-fmt;
-	}
-
-	cur->type=field;
-	cur->data=(char*)malloc(len+1);
-	memcpy(cur->data, fmt, len);
-	cur->data[len]='\0';
+  ws=(const char*)memchr(fmt, ';', len);
+  if (ws) {
+    char* endptr;
+    long w;
+
+    w=strtol(ws+1,&endptr,0);
+    if (endptr[0]!='}') {
+      fprintf(stderr, _("invalid character `%c' in field width\n"), *endptr);
+      return 0;
+    }
+
+    if (w<0) {
+      cur->pad=1;
+      cur->width=(size_t)-w;
+    } else
+      cur->width=(size_t)w;
+
+    len=ws-fmt;
+  }
+
+  cur->type=field;
+  cur->data=(char*)malloc(len+1);
+  memcpy(cur->data, fmt, len);
+  cur->data[len]='\0';
 
-	return 1;
+  return 1;
 }
 
 
 static int parsestring(struct lstitem* cur, const char* fmt, const char* fmtend) {
-	int len;
-	char* write;
+  int len;
+  char* write;
 
-	len=fmtend-fmt+1;
+  len=fmtend-fmt+1;
 
-	cur->type=string;
-	write=cur->data=(char*)malloc(len+1);
-	while (fmt<=fmtend) {
-		if (*fmt=='\\') {
-			fmt++;
-			switch (*fmt) {
-				case 'n':
-					*write='\n';
-					break;
-				case 't':
-					*write='\t';
-					break;
-				case 'r':
-					*write='\r';
-					break;
-				case '\\':
-				default:
-					*write=*fmt;
-					break;
-			}
-		} else
-			*write=*fmt;
-		write++;
-		fmt++;
-	}
-	*write='\0';
+  cur->type=string;
+  write=cur->data=(char*)malloc(len+1);
+  while (fmt<=fmtend) {
+    if (*fmt=='\\') {
+      fmt++;
+      switch (*fmt) {
+        case 'n':
+          *write='\n';
+          break;
+        case 't':
+          *write='\t';
+          break;
+        case 'r':
+          *write='\r';
+          break;
+        case '\\':
+        default:
+          *write=*fmt;
+          break;
+      }
+    } else
+      *write=*fmt;
+    write++;
+    fmt++;
+  }
+  *write='\0';
 
-	return 1;
+  return 1;
 }
 
 
 void freeformat(struct lstitem* head) {
-	struct lstitem* next;
+  struct lstitem* next;
 
-	while (head) {
-		next=head->next;
-		free(head->data);
-		free(head);
-		head=next;
-	}
+  while (head) {
+    next=head->next;
+    free(head->data);
+    free(head);
+    head=next;
+  }
 }
 
 
 struct lstitem* parseformat(const char* fmt) {
-	struct lstitem* head;
-	struct lstitem* cur;
-	const char* fmtend;
-
-	head=cur=NULL;
-	
-	while (*fmt) {
-		if (cur)
-			cur=cur->next=alloclstitem();
-		else
-			head=cur=alloclstitem();
-
-		if (fmt[0]=='$' && fmt[1]=='{') {
-			fmtend=strchr(fmt, '}');
-			if (!fmtend) {
-				fprintf(stderr, _("Closing brace missing in format\n"));
-				freeformat(head);
-				return NULL;
-			}
-			cur->type=field;
-			if (!parsefield(cur, fmt+2, fmtend-1)) {
-				freeformat(head);
-				return NULL;
-			}
-			fmt=fmtend+1;
-		} else {
-			fmtend=fmt;
-			do {
-				fmtend+=1;
-				fmtend=strchr(fmtend, '$');
-			} while (fmtend && fmtend[1]!='{');
-
-			if (!fmtend)
-				fmtend=fmt+strlen(fmt);
-
-			if (!parsestring(cur, fmt, fmtend-1)) {
-				freeformat(head);
-				return NULL;
-			}
-			fmt=fmtend;
-		}
-	}
+  struct lstitem* head;
+  struct lstitem* cur;
+  const char* fmtend;
+
+  head=cur=NULL;
+  
+  while (*fmt) {
+    if (cur)
+      cur=cur->next=alloclstitem();
+    else
+      head=cur=alloclstitem();
+
+    if (fmt[0]=='$' && fmt[1]=='{') {
+      fmtend=strchr(fmt, '}');
+      if (!fmtend) {
+        fprintf(stderr, _("Closing brace missing in format\n"));
+        freeformat(head);
+        return NULL;
+      }
+      cur->type=field;
+      if (!parsefield(cur, fmt+2, fmtend-1)) {
+        freeformat(head);
+        return NULL;
+      }
+      fmt=fmtend+1;
+    } else {
+      fmtend=fmt;
+      do {
+        fmtend+=1;
+        fmtend=strchr(fmtend, '$');
+      } while (fmtend && fmtend[1]!='{');
+
+      if (!fmtend)
+        fmtend=fmt+strlen(fmt);
+
+      if (!parsestring(cur, fmt, fmtend-1)) {
+        freeformat(head);
+        return NULL;
+      }
+      fmt=fmtend;
+    }
+  }
 
-	return head;
+  return head;
 }
 
 
 #define dumpchain(head) {\
-	const struct lstitem* ptr = head;\
-	while (ptr) {\
-		printf("Type: %s\n", (ptr->type==string) ? "string" : "field");\
-		printf("Width: %d\n", ptr->width);\
-		printf("Data: %s\n", ptr->data);\
-		printf("\n");\
-		ptr=ptr->next;\
-	}\
+  const struct lstitem* ptr = head;\
+  while (ptr) {\
+    printf("Type: %s\n", (ptr->type==string) ? "string" : "field");\
+    printf("Width: %d\n", ptr->width);\
+    printf("Data: %s\n", ptr->data);\
+    printf("\n");\
+    ptr=ptr->next;\
+  }\
 }\
 
 
 void show1package(const struct lstitem* head, struct pkginfo *pkg) {
-	struct varbuf vb, fb, wb;
+  struct varbuf vb, fb, wb;
 
-	/* Make sure we have package info available, even if it's all empty. */
-	if (!pkg->installed.valid)
-		blankpackageperfile(&pkg->installed);
-
-	varbufinit(&vb);
-	varbufinit(&fb);
-	varbufinit(&wb);
-
-	while (head) {
-		int ok;
-		char fmt[16];
-
-		ok=0;
-
-		if (head->width>0)
-			snprintf(fmt,16,"%%%s%ds",
-				((head->pad) ? "-" : ""), head->width);
-		else
-			strcpy(fmt, "%s");
-
-		if (head->type==string) {
-			varbufprintf(&fb, fmt, head->data);
-			ok=1;
-		} else if (head->type==field) {
-			const struct fieldinfo* fip;
-
-			for (fip=fieldinfos; fip->name; fip++) 
-				if (strcasecmp(head->data, fip->name)==0)  {
-					fip->wcall(&wb,pkg,&pkg->installed,0,fip);
-
-					varbufaddc(&wb, '\0');
-					varbufprintf(&fb, fmt, wb.buf);
-					varbufreset(&wb);
-					ok=1;
-					break;
-				}
-
-			if (!fip->name && pkg->installed.valid) {
-				const struct arbitraryfield* afp;
-
-				for (afp=pkg->installed.arbs; afp; afp=afp->next)
-					if (strcasecmp(head->data, afp->name)==0) {
-						varbufprintf(&fb, fmt, afp->value);
-						ok=1;
-						break;
-					}
-			}
-		}
-
-		if (ok) {
-			size_t len=strlen(fb.buf);
-			if ((head->width>0) && (len>head->width))
-				len=head->width;
-			varbufaddbuf(&vb, fb.buf, len);
-		}
-
-		varbufreset(&fb);
-		head=head->next;
-	}
-
-	if (vb.buf) {
-		varbufaddc(&vb, '\0');
-		fputs(vb.buf,stdout);
-	}
-
-	varbuffree(&wb);
-	varbuffree(&fb);
-	varbuffree(&vb);
+  /* Make sure we have package info available, even if it's all empty. */
+  if (!pkg->installed.valid)
+    blankpackageperfile(&pkg->installed);
+
+  varbufinit(&vb);
+  varbufinit(&fb);
+  varbufinit(&wb);
+
+  while (head) {
+    int ok;
+    char fmt[16];
+
+    ok=0;
+
+    if (head->width>0)
+      snprintf(fmt,16,"%%%s%ds",
+        ((head->pad) ? "-" : ""), head->width);
+    else
+      strcpy(fmt, "%s");
+
+    if (head->type==string) {
+      varbufprintf(&fb, fmt, head->data);
+      ok=1;
+    } else if (head->type==field) {
+      const struct fieldinfo* fip;
+
+      for (fip=fieldinfos; fip->name; fip++) 
+        if (strcasecmp(head->data, fip->name)==0)  {
+          fip->wcall(&wb,pkg,&pkg->installed,0,fip);
+
+          varbufaddc(&wb, '\0');
+          varbufprintf(&fb, fmt, wb.buf);
+          varbufreset(&wb);
+          ok=1;
+          break;
+        }
+
+      if (!fip->name && pkg->installed.valid) {
+        const struct arbitraryfield* afp;
+
+        for (afp=pkg->installed.arbs; afp; afp=afp->next)
+          if (strcasecmp(head->data, afp->name)==0) {
+            varbufprintf(&fb, fmt, afp->value);
+            ok=1;
+            break;
+          }
+      }
+    }
+
+    if (ok) {
+      size_t len=strlen(fb.buf);
+      if ((head->width>0) && (len>head->width))
+        len=head->width;
+      varbufaddbuf(&vb, fb.buf, len);
+    }
+
+    varbufreset(&fb);
+    head=head->next;
+  }
+
+  if (vb.buf) {
+    varbufaddc(&vb, '\0');
+    fputs(vb.buf,stdout);
+  }
+
+  varbuffree(&wb);
+  varbuffree(&fb);
+  varbuffree(&vb);
 }
 
diff -pruN 1.13.22ubuntu2/lib/tarfn.c 1.13.22ubuntu4/lib/tarfn.c
--- 1.13.22ubuntu2/lib/tarfn.c	2006-01-18 08:30:03.000000000 +0000
+++ 1.13.22ubuntu4/lib/tarfn.c	2006-07-21 17:15:29.000000000 +0100
@@ -16,144 +16,144 @@
 #include <tarfn.h>
 
 struct TarHeader {
-	char Name[100];
-	char Mode[8];
-	char UserID[8];
-	char GroupID[8];
-	char Size[12];
-	char ModificationTime[12];
-	char Checksum[8];
-	char LinkFlag;
-	char LinkName[100];
-	char MagicNumber[8];
-	char UserName[32];
-	char GroupName[32];
-	char MajorDevice[8];
-	char MinorDevice[8];
+  char Name[100];
+  char Mode[8];
+  char UserID[8];
+  char GroupID[8];
+  char Size[12];
+  char ModificationTime[12];
+  char Checksum[8];
+  char LinkFlag;
+  char LinkName[100];
+  char MagicNumber[8];
+  char UserName[32];
+  char GroupName[32];
+  char MajorDevice[8];
+  char MinorDevice[8];
 };
-typedef struct TarHeader	TarHeader;
+typedef struct TarHeader  TarHeader;
 
-static const unsigned int	TarChecksumOffset
-	= (unsigned int)&(((TarHeader *)NULL)->Checksum);
+static const unsigned int TarChecksumOffset
+  = (unsigned int)&(((TarHeader *)NULL)->Checksum);
 
 /* Octal-ASCII-to-long */
 static long
 OtoL(const char * s, int size)
 {
-	int	n = 0;
+  int n = 0;
 
-	while ( *s == ' ' ) {
-		s++;
-		size--;
-	}
+  while ( *s == ' ' ) {
+    s++;
+    size--;
+  }
 
-	while ( --size >= 0 && *s >= '0' && *s <= '7' )
-		n = (n * 010) + (*s++ - '0');
+  while ( --size >= 0 && *s >= '0' && *s <= '7' )
+    n = (n * 010) + (*s++ - '0');
 
-	return n;
+  return n;
 }
 
 /* String block to C null-terminated string */
 char *
 StoC(const char *s, int size)
 {
-	int	len;
-	char *	str;
+  int len;
+  char *  str;
 
-	len = strnlen(s, size);
-	str = malloc(len + 1);
-	memcpy(str, s, len);
-	str[len] = 0;
+  len = strnlen(s, size);
+  str = malloc(len + 1);
+  memcpy(str, s, len);
+  str[len] = 0;
 
-	return str;
+  return str;
 }
 
 static int
 DecodeTarHeader(char * block, TarInfo * d)
 {
-	TarHeader *		h = (TarHeader *)block;
-	unsigned char *		s = (unsigned char *)block;
-	struct passwd *		passwd = NULL;
-	struct group *		group = NULL;
-	unsigned int		i;
-	long			sum;
-	long			checksum;
-
-	if ( *h->UserName )
-		passwd = getpwnam(h->UserName);
-	if ( *h->GroupName )
-		group = getgrnam(h->GroupName);
-
-	d->Name = StoC(h->Name, sizeof(h->Name));
-	d->LinkName = StoC(h->LinkName, sizeof(h->LinkName));
-	d->Mode = (mode_t)OtoL(h->Mode, sizeof(h->Mode));
-	d->Size = (size_t)OtoL(h->Size, sizeof(h->Size));
-	d->ModTime = (time_t)OtoL(h->ModificationTime
-	 ,sizeof(h->ModificationTime));
-	d->Device = ((OtoL(h->MajorDevice, sizeof(h->MajorDevice)) & 0xff) << 8)
-	 | (OtoL(h->MinorDevice, sizeof(h->MinorDevice)) & 0xff);
-	checksum = OtoL(h->Checksum, sizeof(h->Checksum));
-	d->UserID = (uid_t)OtoL(h->UserID, sizeof(h->UserID));
-	d->GroupID = (gid_t)OtoL(h->GroupID, sizeof(h->GroupID));
-	d->Type = (TarFileType)h->LinkFlag;
-
-	if ( passwd )
-		d->UserID = passwd->pw_uid;
-
-	if ( group )
-		d->GroupID = group->gr_gid;
-
-	
-	sum = ' ' * sizeof(h->Checksum);/* Treat checksum field as all blank */
-	for ( i = TarChecksumOffset; i > 0; i-- )
-		sum += *s++;
-	s += sizeof(h->Checksum);	/* Skip the real checksum field */
-	for ( i = (512 - TarChecksumOffset - sizeof(h->Checksum)); i > 0; i-- )
-		sum += *s++;
+  TarHeader *   h = (TarHeader *)block;
+  unsigned char *   s = (unsigned char *)block;
+  struct passwd *   passwd = NULL;
+  struct group *    group = NULL;
+  unsigned int    i;
+  long      sum;
+  long      checksum;
+
+  if ( *h->UserName )
+    passwd = getpwnam(h->UserName);
+  if ( *h->GroupName )
+    group = getgrnam(h->GroupName);
+
+  d->Name = StoC(h->Name, sizeof(h->Name));
+  d->LinkName = StoC(h->LinkName, sizeof(h->LinkName));
+  d->Mode = (mode_t)OtoL(h->Mode, sizeof(h->Mode));
+  d->Size = (size_t)OtoL(h->Size, sizeof(h->Size));
+  d->ModTime = (time_t)OtoL(h->ModificationTime
+   ,sizeof(h->ModificationTime));
+  d->Device = ((OtoL(h->MajorDevice, sizeof(h->MajorDevice)) & 0xff) << 8)
+   | (OtoL(h->MinorDevice, sizeof(h->MinorDevice)) & 0xff);
+  checksum = OtoL(h->Checksum, sizeof(h->Checksum));
+  d->UserID = (uid_t)OtoL(h->UserID, sizeof(h->UserID));
+  d->GroupID = (gid_t)OtoL(h->GroupID, sizeof(h->GroupID));
+  d->Type = (TarFileType)h->LinkFlag;
+
+  if ( passwd )
+    d->UserID = passwd->pw_uid;
+
+  if ( group )
+    d->GroupID = group->gr_gid;
+
+  
+  sum = ' ' * sizeof(h->Checksum);/* Treat checksum field as all blank */
+  for ( i = TarChecksumOffset; i > 0; i-- )
+    sum += *s++;
+  s += sizeof(h->Checksum); /* Skip the real checksum field */
+  for ( i = (512 - TarChecksumOffset - sizeof(h->Checksum)); i > 0; i-- )
+    sum += *s++;
 
-	return ( sum == checksum );
+  return ( sum == checksum );
 }
 
 typedef struct symlinkList {
-	TarInfo h;
-	struct symlinkList *next;
+  TarInfo h;
+  struct symlinkList *next;
 } symlinkList;
 
 extern int
 TarExtractor(
- void *			userData
-,const TarFunctions *	functions)
+ void *     userData
+,const TarFunctions * functions)
 {
-	int	status;
-	char	buffer[512];
-	TarInfo	h;
+  int status;
+  char  buffer[512];
+  TarInfo h;
 
        char    *next_long_name, *next_long_link;
        char    *bp;
        char    **longp;
        int     long_read;
-	symlinkList *symListTop, *symListBottom, *symListPointer;
+  symlinkList *symListTop, *symListBottom, *symListPointer;
 
        next_long_name = NULL;
        next_long_link = NULL;
        long_read = 0;
-	symListBottom = symListPointer = symListTop = malloc(sizeof(symlinkList));
-	symListTop->next = NULL;
+  symListBottom = symListPointer = symListTop = malloc(sizeof(symlinkList));
+  symListTop->next = NULL;
 
-	h.UserData = userData;
+  h.UserData = userData;
 
-	while ( (status = functions->Read(userData, buffer, 512)) == 512 ) {
-		int	nameLength;
+  while ( (status = functions->Read(userData, buffer, 512)) == 512 ) {
+    int nameLength;
 
-		if ( !DecodeTarHeader(buffer, &h) ) {
-			if ( h.Name[0] == '\0' ) {
-				status = 0;	/* End of tape */
-			} else {
-				errno = 0;	/* Indicates broken tarfile */
-				status = -1;	/* Header checksum error */
-			}
-			break;
-		}
+    if ( !DecodeTarHeader(buffer, &h) ) {
+      if ( h.Name[0] == '\0' ) {
+        status = 0; /* End of tape */
+      } else {
+        errno = 0;  /* Indicates broken tarfile */
+        status = -1;  /* Header checksum error */
+      }
+      break;
+    }
                if ( h.Type != GNU_LONGLINK && h.Type != GNU_LONGNAME ) {
                  if (next_long_name) {
                    h.Name = next_long_name;
@@ -167,61 +167,61 @@ TarExtractor(
                  next_long_name = NULL;
                }
 
-		if ( h.Name[0] == '\0' ) {
-			errno = 0;	/* Indicates broken tarfile */
-			status = -1;	/* Bad header data */
-			break;
-		}
-
-		nameLength = strlen(h.Name);
-
-		switch ( h.Type ) {
-		case NormalFile0:
-		case NormalFile1:
-			/* Compatibility with pre-ANSI ustar */
-			if ( h.Name[nameLength - 1] != '/' ) {
-				status = (*functions->ExtractFile)(&h);
-				break;
-			}
-			/* Else, Fall Through */
-		case Directory:
-			if ( h.Name[nameLength - 1] == '/' ) {
-				h.Name[nameLength - 1] = '\0';
-			}
-			status = (*functions->MakeDirectory)(&h);
-			break;
-		case HardLink:
-			status = (*functions->MakeHardLink)(&h);
-			break;
-		case SymbolicLink:
-			memcpy(&symListBottom->h, &h, sizeof(TarInfo));
-			if ((symListBottom->h.Name = strdup(h.Name)) == NULL) {
-				status = -1;
-				errno = 0;
-				break;
-			}
-			if ((symListBottom->h.LinkName = strdup(h.LinkName)) == NULL) {
-				free(symListBottom->h.Name);
-				status = -1;
-				errno = 0;
-				break;
-			}
-			if ((symListBottom->next = malloc(sizeof(symlinkList))) == NULL) {
-				free(symListBottom->h.LinkName);
-				free(symListBottom->h.Name);
-				status = -1;
-				errno = 0;
-				break;
-			}
-			symListBottom = symListBottom->next;
-			symListBottom->next = NULL;
-			status = 0;
-			break;
-		case CharacterDevice:
-		case BlockDevice:
-		case FIFO:
-			status = (*functions->MakeSpecialFile)(&h);
-			break;
+    if ( h.Name[0] == '\0' ) {
+      errno = 0;  /* Indicates broken tarfile */
+      status = -1;  /* Bad header data */
+      break;
+    }
+
+    nameLength = strlen(h.Name);
+
+    switch ( h.Type ) {
+    case NormalFile0:
+    case NormalFile1:
+      /* Compatibility with pre-ANSI ustar */
+      if ( h.Name[nameLength - 1] != '/' ) {
+        status = (*functions->ExtractFile)(&h);
+        break;
+      }
+      /* Else, Fall Through */
+    case Directory:
+      if ( h.Name[nameLength - 1] == '/' ) {
+        h.Name[nameLength - 1] = '\0';
+      }
+      status = (*functions->MakeDirectory)(&h);
+      break;
+    case HardLink:
+      status = (*functions->MakeHardLink)(&h);
+      break;
+    case SymbolicLink:
+      memcpy(&symListBottom->h, &h, sizeof(TarInfo));
+      if ((symListBottom->h.Name = strdup(h.Name)) == NULL) {
+        status = -1;
+        errno = 0;
+        break;
+      }
+      if ((symListBottom->h.LinkName = strdup(h.LinkName)) == NULL) {
+        free(symListBottom->h.Name);
+        status = -1;
+        errno = 0;
+        break;
+      }
+      if ((symListBottom->next = malloc(sizeof(symlinkList))) == NULL) {
+        free(symListBottom->h.LinkName);
+        free(symListBottom->h.Name);
+        status = -1;
+        errno = 0;
+        break;
+      }
+      symListBottom = symListBottom->next;
+      symListBottom->next = NULL;
+      status = 0;
+      break;
+    case CharacterDevice:
+    case BlockDevice:
+    case FIFO:
+      status = (*functions->MakeSpecialFile)(&h);
+      break;
                case GNU_LONGLINK:
                case GNU_LONGNAME:
                  // set longp to the location of the long filename or link
@@ -236,16 +236,16 @@ TarExtractor(
                  if (NULL == (*longp = (char *)malloc(h.Size))) {
                    /* malloc failed, so bail */
                    errno = 0;
-		   status = -1;
-		   break;
+       status = -1;
+       break;
                  }
                  bp = *longp;
 
                  // the way the GNU long{link,name} stuff works is like this:  
-		 // The first header is a "dummy" header that contains the size
-		 // of the filename.  The next N headers contain the filename.
-		 // After the headers with the filename comes the "real" header
-		 // with a bogus name or link.
+     // The first header is a "dummy" header that contains the size
+     // of the filename.  The next N headers contain the filename.
+     // After the headers with the filename comes the "real" header
+     // with a bogus name or link.
                  for (long_read = h.Size; long_read > 0;
                       long_read -= 512) {
 
@@ -254,12 +254,12 @@ TarExtractor(
                    status = functions->Read(userData, buffer, 512);
                    // if we didn't get 512 bytes read, punt
                    if (512 != status) {
-		     if ( status > 0 ) { /* Read partial header record */
-		       errno = 0;
-		       status = -1;
+         if ( status > 0 ) { /* Read partial header record */
+           errno = 0;
+           status = -1;
                      }
                      break;
-		   }
+       }
 
                    copysize = long_read > 512 ? 512 : long_read;
                    memcpy (bp, buffer, copysize);
@@ -271,30 +271,30 @@ TarExtractor(
                  // guess what we just did was successful.
                  status = 0;
                  break;
-		default:
-			errno = 0;	/* Indicates broken tarfile */
-			status = -1;	/* Bad header field */
-		}
-		if ( status != 0 )
-			break;	/* Pass on status from coroutine */
-	}
-	while(symListPointer->next) {
-		if ( status == 0 )
-			status = (*functions->MakeSymbolicLink)(&symListPointer->h);
-		symListBottom = symListPointer->next;
-		free(symListPointer->h.Name);
-		free(symListPointer->h.LinkName);
-		free(symListPointer);
-		symListPointer = symListBottom;
-	}
-	free(symListPointer);
-	free(h.Name);
-	free(h.LinkName);
-	if ( status > 0 ) {	/* Read partial header record */
-		errno = 0;	/* Indicates broken tarfile */
-		return -1;
-	} else {
-		return status;	/* Whatever I/O function returned */
-	}
+    default:
+      errno = 0;  /* Indicates broken tarfile */
+      status = -1;  /* Bad header field */
+    }
+    if ( status != 0 )
+      break;  /* Pass on status from coroutine */
+  }
+  while(symListPointer->next) {
+    if ( status == 0 )
+      status = (*functions->MakeSymbolicLink)(&symListPointer->h);
+    symListBottom = symListPointer->next;
+    free(symListPointer->h.Name);
+    free(symListPointer->h.LinkName);
+    free(symListPointer);
+    symListPointer = symListBottom;
+  }
+  free(symListPointer);
+  free(h.Name);
+  free(h.LinkName);
+  if ( status > 0 ) { /* Read partial header record */
+    errno = 0;  /* Indicates broken tarfile */
+    return -1;
+  } else {
+    return status;  /* Whatever I/O function returned */
+  }
 }
 
diff -pruN 1.13.22ubuntu2/man/C/dpkg.1 1.13.22ubuntu4/man/C/dpkg.1
--- 1.13.22ubuntu2/man/C/dpkg.1	2006-05-17 06:38:11.000000000 +0100
+++ 1.13.22ubuntu4/man/C/dpkg.1	2006-07-21 17:31:07.000000000 +0100
@@ -371,6 +371,9 @@ Turn all dependency problems into warnin
 \fBdepends\-version\fP:
 Don't care about versions when checking dependencies.
 
+\fBbreaks\fP:
+Install, even if this would break another package.
+
 \fBconflicts\fP:
 Install, even if it conflicts with another package. This is dangerous,
 for it will usually cause overwriting of some files.
diff -pruN 1.13.22ubuntu2/src/archives.c 1.13.22ubuntu4/src/archives.c
--- 1.13.22ubuntu2/src/archives.c	2006-07-10 16:41:59.000000000 +0100
+++ 1.13.22ubuntu4/src/archives.c	2006-07-21 17:20:25.000000000 +0100
@@ -80,39 +80,38 @@ int cflict_index = 0;
 static char *
 quote_filename(char *buf, int size, char *s)
 {
-       char *r = buf;
-       while (size > 0) {
-               switch (*s) {
-               case '\0':
-                       *buf = '\0';
-                       return r;
-               case '\\':
-                       *buf++ = '\\';
-                       *buf++ = '\\';
-                       size -= 2;
-                       break;
-               default:
-                       if (((*s)&0x80) == 0) {
-                               *buf++ = *s++;
-                               --size;
-                       } else {
-                               if (size > 4) {
-                                       sprintf(buf, "\\%03o",
-                                               *(unsigned char *)s);
-                                       size -= 4;
-                                       buf += 4;
-                                       s++;
-                               } else {
-                                       /* buffer full */
-                                       *buf = '\0'; /* XXX */
-                                       return r;
-                               }
-                       }
-               }
-       }
-       *buf = '\0'; /* XXX */
-       return r;
-
+  char *r = buf;
+  while (size > 0) {
+    switch (*s) {
+    case '\0':
+      *buf = '\0';
+      return r;
+    case '\\':
+      *buf++ = '\\';
+      *buf++ = '\\';
+      size -= 2;
+      break;
+    default:
+      if (((*s)&0x80) == 0) {
+	*buf++ = *s++;
+	--size;
+      } else {
+	if (size > 4) {
+	  sprintf(buf, "\\%03o",
+	    *(unsigned char *)s);
+	  size -= 4;
+	  buf += 4;
+	  s++;
+	} else {
+	  /* buffer full */
+	  *buf = '\0'; /* XXX */
+	  return r;
+	}
+      }
+    }
+  }
+  *buf = '\0'; /* XXX */
+  return r;
 }
 
 /* special routine to handle partial reads from the tarfile */
@@ -822,42 +821,124 @@ int tarobject(struct TarInfo *ti) {
   return 0;
 }
 
-static int try_remove_can(struct deppossi *pdep,
-                          struct pkginfo *fixbyrm,
-                          const char *why) {
+static int try_deconfigure_can(int (*force_p)(struct deppossi*),
+			       struct pkginfo *pkg,
+			       struct deppossi *pdep,
+			       const char *action,
+			       struct pkginfo *removal,
+			       const char *why) {
+  /* Also checks whether the pdep is forced, first, according to force_p.
+   * force_p may be 0 in which case nothing is considered forced.
+   *
+   * Action is a string describing the action which causes the
+   * deconfiguration:
+   *     removal of <package>         (due to Conflicts+Depends   removal!=0)
+   *     installation of <package>    (due to Breaks              removal==0)
+   *
+   * Return values:  2: forced (no deconfiguration needed, why is printed)
+   *                 1: deconfiguration queued ok (no message printed)
+   *                 0: not possible (why is printed)
+   */
   struct packageinlist *newdeconf;
   
-  if (force_depends(pdep)) {
+  if (force_p && force_p(pdep)) {
     fprintf(stderr, _("dpkg: warning - "
-            "ignoring dependency problem with removal of %s:\n%s"),
-            fixbyrm->name, why);
-    return 1;
+            "ignoring dependency problem with %s:\n%s"),
+            action, why);
+    return 2;
   } else if (f_autodeconf) {
-    if (pdep->up->up->installed.essential) {
+    if (pkg->installed.essential) {
       if (fc_removeessential) {
         fprintf(stderr, _("dpkg: warning - considering deconfiguration of essential\n"
-                " package %s, to enable removal of %s.\n"),
-                pdep->up->up->name,fixbyrm->name);
+                " package %s, to enable %s.\n"),
+                pkg->name, action);
       } else {
         fprintf(stderr, _("dpkg: no, %s is essential, will not deconfigure\n"
-                " it in order to enable removal of %s.\n"),
-                pdep->up->up->name,fixbyrm->name);
+                " it in order to enable %s.\n"),
+                pkg->name, action);
         return 0;
       }
     }
-    pdep->up->up->clientdata->istobe= itb_deconfigure;
+    pkg->clientdata->istobe= itb_deconfigure;
     newdeconf= malloc(sizeof(struct packageinlist));
     newdeconf->next= deconfigure;
-    newdeconf->pkg= pdep->up->up;
+    newdeconf->pkg= pkg;
+    newdeconf->xinfo= removal;
     deconfigure= newdeconf;
     return 1;
   } else {
-    fprintf(stderr, _("dpkg: no, cannot remove %s (--auto-deconfigure will help):\n%s"),
-            fixbyrm->name, why);
+    fprintf(stderr, _("dpkg: no, cannot proceed with %s (--auto-deconfigure will help):\n%s"),
+            action, why);
     return 0;
   }
 }
 
+static int try_remove_can(struct deppossi *pdep,
+                          struct pkginfo *fixbyrm,
+                          const char *why) {
+  char action[512];
+  sprintf(action,_("removal of %.250s"),fixbyrm->name);
+  return try_deconfigure_can(force_depends, pdep->up->up, pdep,
+			     action, fixbyrm, why);
+}
+
+void check_breaks(struct dependency *dep, struct pkginfo *pkg,
+		  const char *pfilename) {
+  struct pkginfo *fixbydeconf;
+  struct varbuf why;
+  int ok;
+
+  varbufinit(&why);
+
+  fixbydeconf= 0;
+  if (depisok(dep, &why, &fixbydeconf, 0)) {
+    varbuffree(&why);
+    return;
+  }
+
+  varbufaddc(&why,0);
+  
+  if (fixbydeconf && f_autodeconf) {
+    char action[512];
+
+    ensure_package_clientdata(fixbydeconf);
+    assert(fixbydeconf->clientdata->istobe == itb_normal);
+
+    sprintf(action,_("installation of %.250s"),pkg->name);
+    fprintf(stderr, _("dpkg: considering deconfiguration of %s,"
+		      " which would be broken by %s ...\n"),
+	    fixbydeconf->name, action);
+
+    ok= try_deconfigure_can(force_breaks, fixbydeconf, dep->list,
+			    action, 0, why.buf);
+    if (ok==1) {
+      fprintf(stderr, _("dpkg: yes, will deconfigure %s (broken by %s).\n"),
+	      fixbydeconf->name, pkg->name);
+    }
+  } else {
+    fprintf(stderr, _("dpkg: regarding %s containing %s:\n%s"),
+	    pfilename, pkg->name, why.buf);
+    ok= 0;
+  }
+  varbuffree(&why);
+  if (ok>0) return;
+  
+  if (force_breaks(dep->list)) {
+    fprintf(stderr, _("dpkg: warning - ignoring breakage,"
+		      " may proceed anyway !\n"));
+    return;
+  }
+
+  if (fixbydeconf && !f_autodeconf) {
+    ohshit(_("installing %.250s would break %.250s, and\n"
+ " deconfiguration is not permitted (--auto-deconfigure might help)"),
+	   pkg->name, fixbydeconf->name);
+  } else {
+    ohshit(_("installing %.250s would break existing software"),
+	   pkg->name);
+  }
+}
+
 void check_conflict(struct dependency *dep, struct pkginfo *pkg,
                     const char *pfilename) {
   struct pkginfo *fixbyrm;
diff -pruN 1.13.22ubuntu2/src/archives.h 1.13.22ubuntu4/src/archives.h
--- 1.13.22ubuntu2/src/archives.h	2006-02-10 16:22:50.000000000 +0000
+++ 1.13.22ubuntu4/src/archives.h	2006-07-21 17:20:25.000000000 +0100
@@ -65,6 +65,8 @@ int filesavespackage(struct fileinlist*,
 
 void check_conflict(struct dependency *dep, struct pkginfo *pkg,
                     const char *pfilename);
+void check_breaks(struct dependency *dep, struct pkginfo *pkg,
+		  const char *pfilename);
 
 struct fileinlist *addfiletolist(struct tarcontext *tc,
 				 struct filenamenode *namenode);
diff -pruN 1.13.22ubuntu2/src/cleanup.c 1.13.22ubuntu4/src/cleanup.c
--- 1.13.22ubuntu2/src/cleanup.c	2006-01-18 08:30:03.000000000 +0000
+++ 1.13.22ubuntu4/src/cleanup.c	2006-07-21 17:20:25.000000000 +0100
@@ -120,7 +120,8 @@ void cu_prermupgrade(int argc, void **ar
 
 void ok_prermdeconfigure(int argc, void **argv) {
   struct pkginfo *deconf= (struct pkginfo*)argv[0];
-  /* also has conflictor in argv[1] and infavour in argv[2] */
+  /* also has conflictor in argv[1] and infavour in argv[2].
+   * conflictor may be 0 if deconfigure was due to Breaks */
   
   if (cipaction->arg == act_install)
     add_to_queue(deconf);
@@ -128,16 +129,17 @@ void ok_prermdeconfigure(int argc, void 
 
 void cu_prermdeconfigure(int argc, void **argv) {
   struct pkginfo *deconf= (struct pkginfo*)argv[0];
-  struct pkginfo *conflictor= (struct pkginfo*)argv[1];
+  struct pkginfo *conflictor= (struct pkginfo*)argv[1]; /* may be 0 */
   struct pkginfo *infavour= (struct pkginfo*)argv[2];
 
   maintainer_script_installed(deconf,POSTINSTFILE,"post-installation",
                               "abort-deconfigure", "in-favour", infavour->name,
                               versiondescribe(&infavour->available.version,
                                               vdew_nonambig),
-                              "removing", conflictor->name,
-                              versiondescribe(&conflictor->installed.version,
-                                              vdew_nonambig),
+                              conflictor ? "removing" : (char*)0,
+			      conflictor ? conflictor->name : (char*)0,
+                              conflictor ? versiondescribe(&conflictor->installed.version,
+                                              vdew_nonambig) : (char*)0,
                               (char*)0);
   deconf->status= stat_installed;
   modstatdb_note(deconf);
diff -pruN 1.13.22ubuntu2/src/configure.c 1.13.22ubuntu4/src/configure.c
--- 1.13.22ubuntu2/src/configure.c	2006-05-16 05:37:20.000000000 +0100
+++ 1.13.22ubuntu4/src/configure.c	2006-07-21 17:20:25.000000000 +0100
@@ -52,261 +52,263 @@ static void copyfileperm(const char* sou
 static void showdiff(const char* old, const char* new);
 static void suspend(void);
 static enum conffopt promptconfaction(const char* cfgfile, const char* realold,
-		const char* realnew, int useredited, int distedited,
-		enum conffopt what);
+    const char* realnew, int useredited, int distedited,
+    enum conffopt what);
 
 extern struct pipef *status_pipes;
 
 
 void deferred_configure(struct pkginfo *pkg) {
-	/* The algorithm for deciding what to configure first is as follows:
-	 * Loop through all packages doing a `try 1' until we've been round
-	 * and nothing has been done, then do `try 2' and `try 3' likewise.
-	 * The incrementing of `dependtry' is done by process_queue().
-	 * Try 1:
-	 *  Are all dependencies of this package done ?  If so, do it.
-	 *  Are any of the dependencies missing or the wrong version ?
-	 *   If so, abort (unless --force-depends, in which case defer)
-	 *  Will we need to configure a package we weren't given as an
-	 *   argument ?  If so, abort - except if --force-configure-any,
-	 *   in which case we add the package to the argument list.
-	 *  If none of the above, defer the package.
-	 * Try 2:
-	 *  Find a cycle and break it (see above).
-	 *  Do as for try 1.
-	 * Try 3 (only if --force-depends-version).
-	 *  Same as for try 2, but don't mind version number in dependencies.
-	 * Try 4 (only if --force-depends).
-	 *  Do anyway.
-	 */
-	struct varbuf aemsgs, cdr, cdr2;
-	char *cdr2rest;
-	int ok, r, useredited, distedited;
-	struct conffile *conff;
-	char *currenthash= 0, *newdisthash= 0;
-	struct stat stab;
-	enum conffopt what;
-	static const char *EMPTY_HASH = "-";
-
-	if (pkg->status == stat_notinstalled)
-		ohshit(_("no package named `%s' is installed, cannot configure"),pkg->name);
-	if (pkg->status == stat_installed)
-		ohshit(_("package %.250s is already installed and configured"), pkg->name);
-	if (pkg->status != stat_unpacked && pkg->status != stat_halfconfigured)
-		ohshit(_("package %.250s is not ready for configuration\n"
-					" cannot configure (current status `%.250s')"),
-				pkg->name, statusinfos[pkg->status].name);
-
-	if (dependtry > 1)
-		if (findbreakcycle(pkg))
-			sincenothing= 0; 
-
-	varbufinit(&aemsgs);
-	ok= dependencies_ok(pkg,0,&aemsgs);
-	if (ok == 1) {
-		varbuffree(&aemsgs);
-		pkg->clientdata->istobe= itb_installnew;
-		add_to_queue(pkg);
-		return;
-	} else if (ok == 0) {
-		sincenothing= 0;
-		varbufaddc(&aemsgs,0);
-		fprintf(stderr,
-				_("dpkg: dependency problems prevent configuration of %s:\n%s"),
-				pkg->name, aemsgs.buf);
-		varbuffree(&aemsgs);
-		ohshit(_("dependency problems - leaving unconfigured"));
-	} else if (aemsgs.used) {
-		varbufaddc(&aemsgs,0);
-		fprintf(stderr,
-				_("dpkg: %s: dependency problems, but configuring anyway as you request:\n%s"),
-				pkg->name, aemsgs.buf);
-	}
-	varbuffree(&aemsgs);
-	sincenothing= 0;
-
-	if (pkg->eflag & eflagf_reinstreq)
-		forcibleerr(fc_removereinstreq,
-				_("Package is in a very bad inconsistent state - you should\n"
-					" reinstall it before attempting configuration."));
-
-	printf(_("Setting up %s (%s) ...\n"),pkg->name,
-			versiondescribe(&pkg->installed.version,vdew_never));
-
-	if (f_noact) {
-		pkg->status= stat_installed;
-		pkg->clientdata->istobe= itb_normal;
-		return;
-	}
-
-	if (pkg->status == stat_unpacked) {
-		debug(dbg_general,"deferred_configure updating conffiles");
-		/* This will not do at all the right thing with overridden conffiles
-		 * or conffiles that are the `target' of an override; all the references
-		 * here would be to the `contested' filename, and in any case there'd
-		 * only be one hash for both `versions' of the conffile.
-		 *
-		 * Overriding conffiles is a silly thing to do anyway :-).
-		 */
-
-		modstatdb_note(pkg);
-
-		/* On entry, the `new' version of each conffile has been
-		 * unpacked as *.dpkg-new, and the `installed' version is
-		 * as-yet untouched in `*'.  The hash of the `old distributed'
-		 * version is in the conffiles data for the package.
-		 * If `*.dpkg-new' no longer exists we assume that we've already
-		 * processed this one.
-		 */
-		varbufinit(&cdr);
-		varbufinit(&cdr2);
-		for (conff= pkg->installed.conffiles; conff; conff= conff->next) {
-			r= conffderef(pkg, &cdr, conff->name);
-			if (r == -1) {
-				conff->hash= EMPTY_HASH;
-				continue;
-			}
-			md5hash(pkg,&currenthash,cdr.buf);
-
-			varbufreset(&cdr2);
-			varbufaddstr(&cdr2,cdr.buf);
-			cdr2.used+=50; varbufaddc(&cdr2,0); cdr2rest= cdr2.buf+strlen(cdr.buf);
-			/* From now on we can just strcpy(cdr2rest,extension); */
-
-			strcpy(cdr2rest,DPKGNEWEXT);
-			/* If the .dpkg-new file is no longer there, ignore this one. */
-			if (lstat(cdr2.buf,&stab)) {
-				if (errno == ENOENT) continue;
-				ohshite(_("unable to stat new dist conffile `%.250s'"),cdr2.buf);
-			}
-			md5hash(pkg,&newdisthash,cdr2.buf);
-
-			/* Copy the permissions from the installed version to the new
-			 * distributed version.
-			 */
-			if (!stat(cdr.buf,&stab))
-				copyfileperm(cdr.buf, cdr2.buf);
-			else if (errno != ENOENT)
-				ohshite(_("unable to stat current installed conffile `%.250s'"),cdr.buf);
-
-			/* Select what the do */
-			if (!strcmp(currenthash,newdisthash)) {
-				/* They're both the same so there's no point asking silly questions. */
-				useredited= -1;
-				distedited= -1;
-				what= cfo_identical;
-			} else if (!strcmp(currenthash,NONEXISTENTFLAG) && fc_conff_miss) {
-				fprintf(stderr, _("\nConfiguration file `%s', does not exist on system.\n"
-							"Installing new config file as you request.\n"), conff->name);
-				what= cfo_newconff;
-				useredited= -1;
-				distedited= -1;
-			} else if (!strcmp(conff->hash,NEWCONFFILEFLAG)) {
-				if (!strcmp(currenthash,NONEXISTENTFLAG)) {
-					what= cfo_newconff;
-					useredited= -1;
-					distedited= -1;
-				} else {
-					useredited= 1;
-					distedited= 1;
-					what= conffoptcells[useredited][distedited] | cfof_isnew;
-				}
-			} else {
-				useredited= strcmp(conff->hash,currenthash) != 0;
-				distedited= strcmp(conff->hash,newdisthash) != 0;
-				what= conffoptcells[useredited][distedited];
-				if (!strcmp(currenthash,NONEXISTENTFLAG))
-					what |= cfof_userrmd;
-			}
-
-			debug(dbg_conff,
-					"deferred_configure `%s' (= `%s') useredited=%d distedited=%d what=%o",
-					conff->name, cdr.buf, useredited, distedited, what);
-
-			what=promptconfaction(conff->name, cdr.buf, cdr2.buf, useredited, distedited, what);
-
-			switch (what & ~(cfof_isnew|cfof_userrmd)) {
-				case cfo_keep | cfof_backup:
-					strcpy(cdr2rest,DPKGOLDEXT);
-					if (unlink(cdr2.buf) && errno != ENOENT)
-						fprintf(stderr,
-								_("dpkg: %s: warning - failed to remove old backup `%.250s': %s\n"),
-								pkg->name, cdr2.buf, strerror(errno));
-					cdr.used--;
-					varbufaddstr(&cdr,DPKGDISTEXT);
-					varbufaddc(&cdr,0);
-					strcpy(cdr2rest,DPKGNEWEXT);
-					if (rename(cdr2.buf,cdr.buf))
-						fprintf(stderr,
-								_("dpkg: %s: warning - failed to rename `%.250s' to `%.250s': %s\n"),
-								pkg->name, cdr2.buf, cdr.buf, strerror(errno));
-					break;
-
-				case cfo_keep:
-					strcpy(cdr2rest,DPKGNEWEXT);
-					if (unlink(cdr2.buf))
-						fprintf(stderr,
-								_("dpkg: %s: warning - failed to remove `%.250s': %s\n"),
-								pkg->name, cdr2.buf, strerror(errno));
-					break;
-
-				case cfo_install | cfof_backup:
-					strcpy(cdr2rest,DPKGDISTEXT);
-					if (unlink(cdr2.buf) && errno != ENOENT)
-						fprintf(stderr,
-								_("dpkg: %s: warning - failed to remove old distrib version `%.250s': %s\n"),
-								pkg->name, cdr2.buf, strerror(errno));
-					strcpy(cdr2rest,DPKGOLDEXT);
-					if (unlink(cdr2.buf) && errno != ENOENT)
-						fprintf(stderr,
-								_("dpkg: %s: warning - failed to remove `%.250s' (before overwrite): %s\n"),
-								pkg->name, cdr2.buf, strerror(errno));
-					if (!(what & cfof_userrmd))
-						if (link(cdr.buf,cdr2.buf))
-							fprintf(stderr,
-								_("dpkg: %s: warning - failed to link `%.250s' to `%.250s': %s\n"),
-								pkg->name, cdr.buf, cdr2.buf, strerror(errno));
-					/* fall through */
-				case cfo_install:
-					printf(_("Installing new version of config file %s ...\n"),conff->name);
-				case cfo_newconff:
-					strcpy(cdr2rest,DPKGNEWEXT);
-					if (rename(cdr2.buf,cdr.buf))
-						ohshite(_("unable to install `%.250s' as `%.250s'"),cdr2.buf,cdr.buf);
-					break;
-
-				default:
-					internerr("unknown what");
-			}
-
-			conff->hash= nfstrsave(newdisthash);
-			modstatdb_note(pkg);
-			free(newdisthash);
-			free(currenthash);
-
-		} /* for (conff= ... */
-		varbuffree(&cdr);
-		varbuffree(&cdr2);
-
-		pkg->status= stat_halfconfigured;
-	}
-
-	assert(pkg->status == stat_halfconfigured);
-
-	modstatdb_note(pkg);
-
-	if (maintainer_script_installed(pkg, POSTINSTFILE, "post-installation",
-				"configure",
-				informativeversion(&pkg->configversion)
-				? versiondescribe(&pkg->configversion,
-					vdew_nonambig)
-				: "",
-				(char*)0))
-		putchar('\n');
-
-	pkg->status= stat_installed;
-	pkg->eflag= eflagv_ok;
-	modstatdb_note(pkg);
+  /* The algorithm for deciding what to configure first is as follows:
+   * Loop through all packages doing a `try 1' until we've been round
+   * and nothing has been done, then do `try 2' and `try 3' likewise.
+   * The incrementing of `dependtry' is done by process_queue().
+   * Try 1:
+   *  Are all dependencies of this package done ?  If so, do it.
+   *  Are any of the dependencies missing or the wrong version ?
+   *   If so, abort (unless --force-depends, in which case defer)
+   *  Will we need to configure a package we weren't given as an
+   *   argument ?  If so, abort - except if --force-configure-any,
+   *   in which case we add the package to the argument list.
+   *  If none of the above, defer the package.
+   * Try 2:
+   *  Find a cycle and break it (see above).
+   *  Do as for try 1.
+   * Try 3 (only if --force-depends-version).
+   *  Same as for try 2, but don't mind version number in dependencies.
+   * Try 4 (only if --force-depends).
+   *  Do anyway.
+   */
+  struct varbuf aemsgs, cdr, cdr2;
+  char *cdr2rest;
+  int ok, r, useredited, distedited;
+  struct conffile *conff;
+  char *currenthash= 0, *newdisthash= 0;
+  struct stat stab;
+  enum conffopt what;
+  static const char *EMPTY_HASH = "-";
+
+  if (pkg->status == stat_notinstalled)
+    ohshit(_("no package named `%s' is installed, cannot configure"),pkg->name);
+  if (pkg->status == stat_installed)
+    ohshit(_("package %.250s is already installed and configured"), pkg->name);
+  if (pkg->status != stat_unpacked && pkg->status != stat_halfconfigured)
+    ohshit(_("package %.250s is not ready for configuration\n"
+          " cannot configure (current status `%.250s')"),
+        pkg->name, statusinfos[pkg->status].name);
+
+  if (dependtry > 1)
+    if (findbreakcycle(pkg))
+      sincenothing= 0; 
+
+  varbufinit(&aemsgs);
+  ok= dependencies_ok(pkg,0,&aemsgs);
+  if (ok == 1) {
+    varbuffree(&aemsgs);
+    pkg->clientdata->istobe= itb_installnew;
+    add_to_queue(pkg);
+    return;
+  }
+  ok= breakses_ok(pkg,&aemsgs) ? ok : 0;
+  if (ok == 0) {
+    sincenothing= 0;
+    varbufaddc(&aemsgs,0);
+    fprintf(stderr,
+        _("dpkg: dependency problems prevent configuration of %s:\n%s"),
+        pkg->name, aemsgs.buf);
+    varbuffree(&aemsgs);
+    ohshit(_("dependency problems - leaving unconfigured"));
+  } else if (aemsgs.used) {
+    varbufaddc(&aemsgs,0);
+    fprintf(stderr,
+        _("dpkg: %s: dependency problems, but configuring anyway as you request:\n%s"),
+        pkg->name, aemsgs.buf);
+  }
+  varbuffree(&aemsgs);
+  sincenothing= 0;
+
+  if (pkg->eflag & eflagf_reinstreq)
+    forcibleerr(fc_removereinstreq,
+        _("Package is in a very bad inconsistent state - you should\n"
+          " reinstall it before attempting configuration."));
+
+  printf(_("Setting up %s (%s) ...\n"),pkg->name,
+      versiondescribe(&pkg->installed.version,vdew_never));
+
+  if (f_noact) {
+    pkg->status= stat_installed;
+    pkg->clientdata->istobe= itb_normal;
+    return;
+  }
+
+  if (pkg->status == stat_unpacked) {
+    debug(dbg_general,"deferred_configure updating conffiles");
+    /* This will not do at all the right thing with overridden conffiles
+     * or conffiles that are the `target' of an override; all the references
+     * here would be to the `contested' filename, and in any case there'd
+     * only be one hash for both `versions' of the conffile.
+     *
+     * Overriding conffiles is a silly thing to do anyway :-).
+     */
+
+    modstatdb_note(pkg);
+
+    /* On entry, the `new' version of each conffile has been
+     * unpacked as *.dpkg-new, and the `installed' version is
+     * as-yet untouched in `*'.  The hash of the `old distributed'
+     * version is in the conffiles data for the package.
+     * If `*.dpkg-new' no longer exists we assume that we've already
+     * processed this one.
+     */
+    varbufinit(&cdr);
+    varbufinit(&cdr2);
+    for (conff= pkg->installed.conffiles; conff; conff= conff->next) {
+      r= conffderef(pkg, &cdr, conff->name);
+      if (r == -1) {
+        conff->hash= EMPTY_HASH;
+        continue;
+      }
+      md5hash(pkg,&currenthash,cdr.buf);
+
+      varbufreset(&cdr2);
+      varbufaddstr(&cdr2,cdr.buf);
+      cdr2.used+=50; varbufaddc(&cdr2,0); cdr2rest= cdr2.buf+strlen(cdr.buf);
+      /* From now on we can just strcpy(cdr2rest,extension); */
+
+      strcpy(cdr2rest,DPKGNEWEXT);
+      /* If the .dpkg-new file is no longer there, ignore this one. */
+      if (lstat(cdr2.buf,&stab)) {
+        if (errno == ENOENT) continue;
+        ohshite(_("unable to stat new dist conffile `%.250s'"),cdr2.buf);
+      }
+      md5hash(pkg,&newdisthash,cdr2.buf);
+
+      /* Copy the permissions from the installed version to the new
+       * distributed version.
+       */
+      if (!stat(cdr.buf,&stab))
+        copyfileperm(cdr.buf, cdr2.buf);
+      else if (errno != ENOENT)
+        ohshite(_("unable to stat current installed conffile `%.250s'"),cdr.buf);
+
+      /* Select what the do */
+      if (!strcmp(currenthash,newdisthash)) {
+        /* They're both the same so there's no point asking silly questions. */
+        useredited= -1;
+        distedited= -1;
+        what= cfo_identical;
+      } else if (!strcmp(currenthash,NONEXISTENTFLAG) && fc_conff_miss) {
+        fprintf(stderr, _("\nConfiguration file `%s', does not exist on system.\n"
+              "Installing new config file as you request.\n"), conff->name);
+        what= cfo_newconff;
+        useredited= -1;
+        distedited= -1;
+      } else if (!strcmp(conff->hash,NEWCONFFILEFLAG)) {
+        if (!strcmp(currenthash,NONEXISTENTFLAG)) {
+          what= cfo_newconff;
+          useredited= -1;
+          distedited= -1;
+        } else {
+          useredited= 1;
+          distedited= 1;
+          what= conffoptcells[useredited][distedited] | cfof_isnew;
+        }
+      } else {
+        useredited= strcmp(conff->hash,currenthash) != 0;
+        distedited= strcmp(conff->hash,newdisthash) != 0;
+        what= conffoptcells[useredited][distedited];
+        if (!strcmp(currenthash,NONEXISTENTFLAG))
+          what |= cfof_userrmd;
+      }
+
+      debug(dbg_conff,
+          "deferred_configure `%s' (= `%s') useredited=%d distedited=%d what=%o",
+          conff->name, cdr.buf, useredited, distedited, what);
+
+      what=promptconfaction(conff->name, cdr.buf, cdr2.buf, useredited, distedited, what);
+
+      switch (what & ~(cfof_isnew|cfof_userrmd)) {
+        case cfo_keep | cfof_backup:
+          strcpy(cdr2rest,DPKGOLDEXT);
+          if (unlink(cdr2.buf) && errno != ENOENT)
+            fprintf(stderr,
+                _("dpkg: %s: warning - failed to remove old backup `%.250s': %s\n"),
+                pkg->name, cdr2.buf, strerror(errno));
+          cdr.used--;
+          varbufaddstr(&cdr,DPKGDISTEXT);
+          varbufaddc(&cdr,0);
+          strcpy(cdr2rest,DPKGNEWEXT);
+          if (rename(cdr2.buf,cdr.buf))
+            fprintf(stderr,
+                _("dpkg: %s: warning - failed to rename `%.250s' to `%.250s': %s\n"),
+                pkg->name, cdr2.buf, cdr.buf, strerror(errno));
+          break;
+
+        case cfo_keep:
+          strcpy(cdr2rest,DPKGNEWEXT);
+          if (unlink(cdr2.buf))
+            fprintf(stderr,
+                _("dpkg: %s: warning - failed to remove `%.250s': %s\n"),
+                pkg->name, cdr2.buf, strerror(errno));
+          break;
+
+        case cfo_install | cfof_backup:
+          strcpy(cdr2rest,DPKGDISTEXT);
+          if (unlink(cdr2.buf) && errno != ENOENT)
+            fprintf(stderr,
+                _("dpkg: %s: warning - failed to remove old distrib version `%.250s': %s\n"),
+                pkg->name, cdr2.buf, strerror(errno));
+          strcpy(cdr2rest,DPKGOLDEXT);
+          if (unlink(cdr2.buf) && errno != ENOENT)
+            fprintf(stderr,
+                _("dpkg: %s: warning - failed to remove `%.250s' (before overwrite): %s\n"),
+                pkg->name, cdr2.buf, strerror(errno));
+          if (!(what & cfof_userrmd))
+            if (link(cdr.buf,cdr2.buf))
+              fprintf(stderr,
+                _("dpkg: %s: warning - failed to link `%.250s' to `%.250s': %s\n"),
+                pkg->name, cdr.buf, cdr2.buf, strerror(errno));
+          /* fall through */
+        case cfo_install:
+          printf(_("Installing new version of config file %s ...\n"),conff->name);
+        case cfo_newconff:
+          strcpy(cdr2rest,DPKGNEWEXT);
+          if (rename(cdr2.buf,cdr.buf))
+            ohshite(_("unable to install `%.250s' as `%.250s'"),cdr2.buf,cdr.buf);
+          break;
+
+        default:
+          internerr("unknown what");
+      }
+
+      conff->hash= nfstrsave(newdisthash);
+      modstatdb_note(pkg);
+      free(newdisthash);
+      free(currenthash);
+
+    } /* for (conff= ... */
+    varbuffree(&cdr);
+    varbuffree(&cdr2);
+
+    pkg->status= stat_halfconfigured;
+  }
+
+  assert(pkg->status == stat_halfconfigured);
+
+  modstatdb_note(pkg);
+
+  if (maintainer_script_installed(pkg, POSTINSTFILE, "post-installation",
+        "configure",
+        informativeversion(&pkg->configversion)
+        ? versiondescribe(&pkg->configversion,
+          vdew_nonambig)
+        : "",
+        (char*)0))
+    putchar('\n');
+
+  pkg->status= stat_installed;
+  pkg->eflag= eflagv_ok;
+  modstatdb_note(pkg);
 }
 
 
@@ -315,127 +317,127 @@ void deferred_configure(struct pkginfo *
  * Returns 0 if everything went ok, -1 otherwise.
  */
 int conffderef(struct pkginfo *pkg, struct varbuf *result, const char *in) {
-	static char*	linkreadbuf	= 0;
-	static int	linkreadbufsize	= 0;
-	struct stat	stab;
-	int		r, need;
-	int		loopprotect;
-
-	varbufreset(result);
-	varbufaddstr(result,instdir);
-	if (*in != '/') varbufaddc(result,'/');
-	varbufaddstr(result,in);
-	varbufaddc(result,0);
-
-	loopprotect= 0;
-
-	for (;;) {
-		debug(dbg_conffdetail,"conffderef in=`%s' current working=`%s'", in, result->buf);
-		if (lstat(result->buf,&stab)) {
-			if (errno != ENOENT)
-				fprintf(stderr, _("dpkg: %s: warning - unable to stat config file `%s'\n"
-							" (= `%s'): %s\n"),
-						pkg->name, in, result->buf, strerror(errno));
-			debug(dbg_conffdetail,"conffderef nonexistent");
-			return 0;
-		} else if (S_ISREG(stab.st_mode)) {
-			debug(dbg_conff,"conffderef in=`%s' result=`%s'", in, result->buf);
-			return 0;
-		} else if (S_ISLNK(stab.st_mode)) {
-			debug(dbg_conffdetail,"conffderef symlink loopprotect=%d",loopprotect);
-			if (loopprotect++ >= 25) {
-				fprintf(stderr, _("dpkg: %s: warning - config file `%s' is a circular link\n"
-							" (= `%s')\n"), pkg->name, in, result->buf);
-				return -1;
-			}
-			need= 255;
-			for (;;) {
-				if (need > linkreadbufsize) {
-					linkreadbuf= m_realloc(linkreadbuf,need);
-					linkreadbufsize= need;
-					debug(dbg_conffdetail,"conffderef readlink realloc(%d)=%p",need,linkreadbuf);
-				}
-				r= readlink(result->buf,linkreadbuf,linkreadbufsize-1);
-				if (r < 0) {
-					fprintf(stderr, _("dpkg: %s: warning - unable to readlink conffile `%s'\n"
-								" (= `%s'): %s\n"),
-							pkg->name, in, result->buf, strerror(errno));
-					return -1;
-				}
-				debug(dbg_conffdetail,"conffderef readlink gave %d, `%.*s'",
-						r, r>0 ? r : 0, linkreadbuf);
-				if (r < linkreadbufsize-1) break;
-				need= r<<2;
-			}
-			linkreadbuf[r]= 0;
-			if (linkreadbuf[0] == '/') {
-				varbufreset(result);
-				varbufaddstr(result,instdir);
-				debug(dbg_conffdetail,"conffderef readlink absolute");
-			} else {
-				for (r=result->used-2; r>0 && result->buf[r] != '/'; r--)
-					;
-				if (r < 0) {
-					fprintf(stderr,
-							_("dpkg: %s: warning - conffile `%.250s' resolves to degenerate filename\n"
-								" (`%s' is a symlink to `%s')\n"),
-							pkg->name, in, result->buf, linkreadbuf);
-					return -1;
-				}
-				if (result->buf[r] == '/') r++;
-				result->used= r;
-				debug(dbg_conffdetail,"conffderef readlink relative to `%.*s'",
-						(int)result->used, result->buf);
-			}
-			varbufaddstr(result,linkreadbuf);
-			varbufaddc(result,0);
-		} else {
-			fprintf(stderr, _("dpkg: %s: warning - conffile `%.250s' is not a plain"
-						" file or symlink (= `%s')\n"),
-					pkg->name, in, result->buf);
-			return -1;
-		}
-	}
+  static char*  linkreadbuf = 0;
+  static int  linkreadbufsize = 0;
+  struct stat stab;
+  int   r, need;
+  int   loopprotect;
+
+  varbufreset(result);
+  varbufaddstr(result,instdir);
+  if (*in != '/') varbufaddc(result,'/');
+  varbufaddstr(result,in);
+  varbufaddc(result,0);
+
+  loopprotect= 0;
+
+  for (;;) {
+    debug(dbg_conffdetail,"conffderef in=`%s' current working=`%s'", in, result->buf);
+    if (lstat(result->buf,&stab)) {
+      if (errno != ENOENT)
+        fprintf(stderr, _("dpkg: %s: warning - unable to stat config file `%s'\n"
+              " (= `%s'): %s\n"),
+            pkg->name, in, result->buf, strerror(errno));
+      debug(dbg_conffdetail,"conffderef nonexistent");
+      return 0;
+    } else if (S_ISREG(stab.st_mode)) {
+      debug(dbg_conff,"conffderef in=`%s' result=`%s'", in, result->buf);
+      return 0;
+    } else if (S_ISLNK(stab.st_mode)) {
+      debug(dbg_conffdetail,"conffderef symlink loopprotect=%d",loopprotect);
+      if (loopprotect++ >= 25) {
+        fprintf(stderr, _("dpkg: %s: warning - config file `%s' is a circular link\n"
+              " (= `%s')\n"), pkg->name, in, result->buf);
+        return -1;
+      }
+      need= 255;
+      for (;;) {
+        if (need > linkreadbufsize) {
+          linkreadbuf= m_realloc(linkreadbuf,need);
+          linkreadbufsize= need;
+          debug(dbg_conffdetail,"conffderef readlink realloc(%d)=%p",need,linkreadbuf);
+        }
+        r= readlink(result->buf,linkreadbuf,linkreadbufsize-1);
+        if (r < 0) {
+          fprintf(stderr, _("dpkg: %s: warning - unable to readlink conffile `%s'\n"
+                " (= `%s'): %s\n"),
+              pkg->name, in, result->buf, strerror(errno));
+          return -1;
+        }
+        debug(dbg_conffdetail,"conffderef readlink gave %d, `%.*s'",
+            r, r>0 ? r : 0, linkreadbuf);
+        if (r < linkreadbufsize-1) break;
+        need= r<<2;
+      }
+      linkreadbuf[r]= 0;
+      if (linkreadbuf[0] == '/') {
+        varbufreset(result);
+        varbufaddstr(result,instdir);
+        debug(dbg_conffdetail,"conffderef readlink absolute");
+      } else {
+        for (r=result->used-2; r>0 && result->buf[r] != '/'; r--)
+          ;
+        if (r < 0) {
+          fprintf(stderr,
+              _("dpkg: %s: warning - conffile `%.250s' resolves to degenerate filename\n"
+                " (`%s' is a symlink to `%s')\n"),
+              pkg->name, in, result->buf, linkreadbuf);
+          return -1;
+        }
+        if (result->buf[r] == '/') r++;
+        result->used= r;
+        debug(dbg_conffdetail,"conffderef readlink relative to `%.*s'",
+            (int)result->used, result->buf);
+      }
+      varbufaddstr(result,linkreadbuf);
+      varbufaddc(result,0);
+    } else {
+      fprintf(stderr, _("dpkg: %s: warning - conffile `%.250s' is not a plain"
+            " file or symlink (= `%s')\n"),
+          pkg->name, in, result->buf);
+      return -1;
+    }
+  }
 }
     
 /* Generate a MD5 hash for fn and store it in *hashbuf. Memory is allocated
  * by this function and should be freed manually.
  */
 static void md5hash(struct pkginfo *pkg, char **hashbuf, const char *fn) {
-	static int fd;
+  static int fd;
 
-	fd=open(fn,O_RDONLY);
+  fd=open(fn,O_RDONLY);
 
-	if (fd>=0) {
-		push_cleanup(cu_closefd,ehflag_bombout, 0,0, 1,&fd);
-		fd_md5(fd, hashbuf, -1, _("md5hash"));
-		pop_cleanup(ehflag_normaltidy); /* fd= open(cdr.buf) */
-		close(fd);
-	} else if (errno==ENOENT) {
-		*hashbuf= strdup(NONEXISTENTFLAG);
-	} else {
-		fprintf(stderr, _("dpkg: %s: warning - unable to open conffile %s for hash: %s\n"),
-				pkg->name, fn, strerror(errno));
-		*hashbuf= strdup("-");
-	}
+  if (fd>=0) {
+    push_cleanup(cu_closefd,ehflag_bombout, 0,0, 1,&fd);
+    fd_md5(fd, hashbuf, -1, _("md5hash"));
+    pop_cleanup(ehflag_normaltidy); /* fd= open(cdr.buf) */
+    close(fd);
+  } else if (errno==ENOENT) {
+    *hashbuf= strdup(NONEXISTENTFLAG);
+  } else {
+    fprintf(stderr, _("dpkg: %s: warning - unable to open conffile %s for hash: %s\n"),
+        pkg->name, fn, strerror(errno));
+    *hashbuf= strdup("-");
+  }
 }
 
 /* Copy file ownership and permissions from one file to another
  */
 static void copyfileperm(const char* source, const char* target) {
-	struct stat	stab;
+  struct stat stab;
 
-	if (stat(source, &stab)==-1) {
-		if (errno==ENOENT)
-			return;
-		ohshite(_("unable to stat current installed conffile `%.250s'"), source);
-	}
+  if (stat(source, &stab)==-1) {
+    if (errno==ENOENT)
+      return;
+    ohshite(_("unable to stat current installed conffile `%.250s'"), source);
+  }
 
-	if (chown(target, stab.st_uid, stab.st_gid)==-1)
-		ohshite(_("unable to change ownership of new dist conffile `%.250s'"), target);
+  if (chown(target, stab.st_uid, stab.st_gid)==-1)
+    ohshite(_("unable to change ownership of new dist conffile `%.250s'"), target);
 
-	if (chmod(target, (stab.st_mode & 07777))==-1)
-		ohshite(_("unable to set mode of new dist conffile `%.250s'"), target);
+  if (chmod(target, (stab.st_mode & 07777))==-1)
+    ohshite(_("unable to set mode of new dist conffile `%.250s'"), target);
 }
 
 
@@ -444,234 +446,234 @@ static void copyfileperm(const char* sou
 /* Show a diff between two files
  */
 static void showdiff(const char* old, const char* new) {
-	int	pid;
-	int	r;
-	int	status;
-
-	if (!(pid=m_fork())) {
-		/* Child process */
-		const char*	p;		/* pager */
-		const char*	s;		/* shell */
-		char		cmdbuf[1024];	/* command to run */
-
-		p=getenv(PAGERENV);
-		if (!p || !*p)
-			p=DEFAULTPAGER;
-
-		sprintf(cmdbuf, DIFF " -Nu %.250s %.250s | %.250s", old, new, p);
-
-		s=getenv(SHELLENV);
-		if (!s || !*s)
-			s=DEFAULTSHELL;
-
-		execlp(s,s,"-c", cmdbuf, NULL);
-		ohshite(_("failed to run %s (%.250s)"), DIFF, cmdbuf);
-	}
-
-	/* Parent process */
-	while (((r=waitpid(pid,&status,0))==-1) && (errno==EINTR))
-		;
-
-	if (r!=pid) {
-		onerr_abort++;
-		ohshite(_("wait for shell failed"));
-	}
+  int pid;
+  int r;
+  int status;
+
+  if (!(pid=m_fork())) {
+    /* Child process */
+    const char* p;    /* pager */
+    const char* s;    /* shell */
+    char    cmdbuf[1024]; /* command to run */
+
+    p=getenv(PAGERENV);
+    if (!p || !*p)
+      p=DEFAULTPAGER;
+
+    sprintf(cmdbuf, DIFF " -Nu %.250s %.250s | %.250s", old, new, p);
+
+    s=getenv(SHELLENV);
+    if (!s || !*s)
+      s=DEFAULTSHELL;
+
+    execlp(s,s,"-c", cmdbuf, NULL);
+    ohshite(_("failed to run %s (%.250s)"), DIFF, cmdbuf);
+  }
+
+  /* Parent process */
+  while (((r=waitpid(pid,&status,0))==-1) && (errno==EINTR))
+    ;
+
+  if (r!=pid) {
+    onerr_abort++;
+    ohshite(_("wait for shell failed"));
+  }
 }
 
 
 /* Suspend dpkg temporarily
  */
 static void suspend(void) {
-	const char*	s;
-	int		pid;
+  const char* s;
+  int   pid;
 
-	s= getenv(NOJOBCTRLSTOPENV);
-	if (s && *s) {
-		/* Do not job control to suspend but fork and start a new shell
-		 * instead.
-		 */
-
-		int	status;		/* waitpid status */
-		int	r;		/* waitpid result */
-
-		fputs(_("Type `exit' when you're done.\n"), stderr);
-
-		if (!(pid= m_fork())) {
-			/* Child process */
-			s= getenv(SHELLENV);
-			if (!s || !*s)
-				s=DEFAULTSHELL;
-
-			execlp(s,s,"-i",(char*)0);
-			ohshite(_("failed to exec shell (%.250s)"),s);
-		}
-
-		/* Parent process */
-		while (((r=waitpid(pid,&status,0))==-1) && (errno==EINTR))
-			;
-
-		if (r!=pid) {
-			onerr_abort++;
-			ohshite(_("wait for shell failed"));
-		}
-	} else {
-		fputs(_("Don't forget to foreground (`fg') this "
-					"process when you're done !\n"), stderr);
-		kill(-getpgid(0),SIGTSTP);
-	}
+  s= getenv(NOJOBCTRLSTOPENV);
+  if (s && *s) {
+    /* Do not job control to suspend but fork and start a new shell
+     * instead.
+     */
+
+    int status;   /* waitpid status */
+    int r;    /* waitpid result */
+
+    fputs(_("Type `exit' when you're done.\n"), stderr);
+
+    if (!(pid= m_fork())) {
+      /* Child process */
+      s= getenv(SHELLENV);
+      if (!s || !*s)
+        s=DEFAULTSHELL;
+
+      execlp(s,s,"-i",(char*)0);
+      ohshite(_("failed to exec shell (%.250s)"),s);
+    }
+
+    /* Parent process */
+    while (((r=waitpid(pid,&status,0))==-1) && (errno==EINTR))
+      ;
+
+    if (r!=pid) {
+      onerr_abort++;
+      ohshite(_("wait for shell failed"));
+    }
+  } else {
+    fputs(_("Don't forget to foreground (`fg') this "
+          "process when you're done !\n"), stderr);
+    kill(-getpgid(0),SIGTSTP);
+  }
 }
 
 
 /* Select what to do with a configuration file.
  */
 static enum conffopt promptconfaction(const char* cfgfile, const char* realold,
-		const char* realnew, int useredited, int distedited,
-		enum conffopt what) {
-	const char *s;
-	int c, cc;
-
-	if (!(what&cfof_prompt))
-		return what;
-
-	/* if there is a status pipe, send conffile-prompt there */
-	if (status_pipes) {
-	   static struct varbuf *status= NULL;
-	   struct pipef *pipef= status_pipes;
-	   int r;
-	   if (status == NULL) {
-	      status = nfmalloc(sizeof(struct varbuf));
-	      varbufinit(status);
-	   } else
-	      varbufreset(status);
-	   
-	   r= varbufprintf(status, "status: %s : %s : '%s' '%s' %i %i \n", 
-			   cfgfile, "conffile-prompt", 
-			   realold, realnew, useredited, distedited);
-	   while (pipef) {
-	      write(pipef->fd, status->buf, r);
-	      pipef= pipef->next;
-	   }
-	}
-
-	do {
-		/* Flush the terminal's input in case the user
-		 * involuntarily typed some characters.
-		 */
-		tcflush(STDIN_FILENO, TCIFLUSH);
-		fprintf(stderr, _("\nConfiguration file `%s'"), cfgfile);
-		if (strcmp(cfgfile, realold))
-			fprintf(stderr,_(" (actually `%s')"), realold);
-
-		if (what & cfof_isnew) {
-			fprintf(stderr,
-					_("\n"
-						" ==> File on system created by you or by a script.\n"
-						" ==> File also in package provided by package maintainer.\n"));
-		} else {
-			fprintf(stderr, !useredited ?
-					_("\n     Not modified since installation.\n") :
-							!(what & cfof_userrmd) ?
-					_("\n ==> Modified (by you or by a script) since installation.\n") :
-					_("\n ==> Deleted (by you or by a script) since installation.\n"));
-
-			fprintf(stderr, distedited ?
-					_(" ==> Package distributor has shipped an updated version.\n") :
-					_("     Version in package is the same as at last installation.\n"));
-		}
-
-		/* No --force-confdef but a forcible situtation */
-		/* TODO: check if this condition can not be simplified to just !fc_conff_def */
-		if (!(fc_conff_def && (what&(cfof_install|cfof_keep)))) {
-			if (fc_conff_new) {
-				fprintf(stderr, _(" ==> Using new file as you requested.\n"));
-				cc = 'y';
-				break;
-			} else if (fc_conff_old) {
-				fprintf(stderr, _(" ==> Using current old file as you requested.\n"));
-				cc = 'n';
-				break;
-			}
-		}
-
-
-		/* Force the default action (if there is one */
-		if (fc_conff_def) {
-			if (what&cfof_keep) {
-				fprintf(stderr, _(" ==> Keeping old config file as default.\n"));
-				cc = 'n';
-				break;
-			} else if (what&cfof_install) {
-				fprintf(stderr, _(" ==> Using new config file as default.\n"));
-				cc = 'y';
-				break;
-			}
-		}
-
-
-		fprintf(stderr,
-				_("   What would you like to do about it ?  Your options are:\n"
-					"    Y or I  : install the package maintainer's version\n"
-					"    N or O  : keep your currently-installed version\n"
-					"      D     : show the differences between the versions\n"
-					"      Z     : background this process to examine the situation\n"));
-
-		if (what & cfof_keep)
-			fprintf(stderr, _(" The default action is to keep your current version.\n"));
-		else if (what & cfof_install)
-			fprintf(stderr, _(" The default action is to install the new version.\n"));
-
-		s= strrchr(cfgfile,'/');
-		if (!s || !*++s) s= cfgfile;
-		fprintf(stderr, "*** %s (Y/I/N/O/D/Z) %s ? ",
-				s,
-				(what & cfof_keep) ? _("[default=N]") :
-				(what & cfof_install) ? _("[default=Y]") : _("[no default]"));
-
-		if (ferror(stderr))
-			ohshite(_("error writing to stderr, discovered before conffile prompt"));
-
-		cc= 0;
-		while ((c= getchar()) != EOF && c != '\n')
-			if (!isspace(c) && !cc) cc= tolower(c);
-
-		if (c == EOF) {
-			if (ferror(stdin)) ohshite(_("read error on stdin at conffile prompt"));
-			ohshit(_("EOF on stdin at conffile prompt"));
-		}
-
-		if (!cc) {
-			if (what & cfof_keep) { cc= 'n'; break; }
-			else if (what & cfof_install) { cc= 'y'; break; }
-		}
-
-		/* fixme: say something if silently not install */
-		if (cc == 'd')
-			showdiff(realold, realnew);
-
-		if (cc == 'z')
-			suspend();
-
-	} while (!strchr("yino",cc));
-
-	log_message("conffile %s %s", cfgfile,
-		    (cc == 'i' || cc == 'y') ? "install" : "keep");
-
-	what &= cfof_userrmd;
-
-	switch (cc) {
-		case 'i':
-		case 'y':
-			what |= cfof_install|cfof_backup;
-			break;
-
-		case 'n':
-		case 'o':
-			what |= cfof_keep|cfof_backup;
-			break;
-
-		default:
-			internerr("unknown response");
-	}
+    const char* realnew, int useredited, int distedited,
+    enum conffopt what) {
+  const char *s;
+  int c, cc;
+
+  if (!(what&cfof_prompt))
+    return what;
+
+  /* if there is a status pipe, send conffile-prompt there */
+  if (status_pipes) {
+     static struct varbuf *status= NULL;
+     struct pipef *pipef= status_pipes;
+     int r;
+     if (status == NULL) {
+        status = nfmalloc(sizeof(struct varbuf));
+        varbufinit(status);
+     } else
+        varbufreset(status);
+     
+     r= varbufprintf(status, "status: %s : %s : '%s' '%s' %i %i \n", 
+         cfgfile, "conffile-prompt", 
+         realold, realnew, useredited, distedited);
+     while (pipef) {
+        write(pipef->fd, status->buf, r);
+        pipef= pipef->next;
+     }
+  }
+
+  do {
+    /* Flush the terminal's input in case the user
+     * involuntarily typed some characters.
+     */
+    tcflush(STDIN_FILENO, TCIFLUSH);
+    fprintf(stderr, _("\nConfiguration file `%s'"), cfgfile);
+    if (strcmp(cfgfile, realold))
+      fprintf(stderr,_(" (actually `%s')"), realold);
+
+    if (what & cfof_isnew) {
+      fprintf(stderr,
+          _("\n"
+            " ==> File on system created by you or by a script.\n"
+            " ==> File also in package provided by package maintainer.\n"));
+    } else {
+      fprintf(stderr, !useredited ?
+          _("\n     Not modified since installation.\n") :
+              !(what & cfof_userrmd) ?
+          _("\n ==> Modified (by you or by a script) since installation.\n") :
+          _("\n ==> Deleted (by you or by a script) since installation.\n"));
+
+      fprintf(stderr, distedited ?
+          _(" ==> Package distributor has shipped an updated version.\n") :
+          _("     Version in package is the same as at last installation.\n"));
+    }
+
+    /* No --force-confdef but a forcible situtation */
+    /* TODO: check if this condition can not be simplified to just !fc_conff_def */
+    if (!(fc_conff_def && (what&(cfof_install|cfof_keep)))) {
+      if (fc_conff_new) {
+        fprintf(stderr, _(" ==> Using new file as you requested.\n"));
+        cc = 'y';
+        break;
+      } else if (fc_conff_old) {
+        fprintf(stderr, _(" ==> Using current old file as you requested.\n"));
+        cc = 'n';
+        break;
+      }
+    }
+
+
+    /* Force the default action (if there is one */
+    if (fc_conff_def) {
+      if (what&cfof_keep) {
+        fprintf(stderr, _(" ==> Keeping old config file as default.\n"));
+        cc = 'n';
+        break;
+      } else if (what&cfof_install) {
+        fprintf(stderr, _(" ==> Using new config file as default.\n"));
+        cc = 'y';
+        break;
+      }
+    }
+
+
+    fprintf(stderr,
+        _("   What would you like to do about it ?  Your options are:\n"
+          "    Y or I  : install the package maintainer's version\n"
+          "    N or O  : keep your currently-installed version\n"
+          "      D     : show the differences between the versions\n"
+          "      Z     : background this process to examine the situation\n"));
+
+    if (what & cfof_keep)
+      fprintf(stderr, _(" The default action is to keep your current version.\n"));
+    else if (what & cfof_install)
+      fprintf(stderr, _(" The default action is to install the new version.\n"));
+
+    s= strrchr(cfgfile,'/');
+    if (!s || !*++s) s= cfgfile;
+    fprintf(stderr, "*** %s (Y/I/N/O/D/Z) %s ? ",
+        s,
+        (what & cfof_keep) ? _("[default=N]") :
+        (what & cfof_install) ? _("[default=Y]") : _("[no default]"));
+
+    if (ferror(stderr))
+      ohshite(_("error writing to stderr, discovered before conffile prompt"));
+
+    cc= 0;
+    while ((c= getchar()) != EOF && c != '\n')
+      if (!isspace(c) && !cc) cc= tolower(c);
+
+    if (c == EOF) {
+      if (ferror(stdin)) ohshite(_("read error on stdin at conffile prompt"));
+      ohshit(_("EOF on stdin at conffile prompt"));
+    }
+
+    if (!cc) {
+      if (what & cfof_keep) { cc= 'n'; break; }
+      else if (what & cfof_install) { cc= 'y'; break; }
+    }
+
+    /* fixme: say something if silently not install */
+    if (cc == 'd')
+      showdiff(realold, realnew);
+
+    if (cc == 'z')
+      suspend();
+
+  } while (!strchr("yino",cc));
+
+  log_message("conffile %s %s", cfgfile,
+        (cc == 'i' || cc == 'y') ? "install" : "keep");
+
+  what &= cfof_userrmd;
+
+  switch (cc) {
+    case 'i':
+    case 'y':
+      what |= cfof_install|cfof_backup;
+      break;
+
+    case 'n':
+    case 'o':
+      what |= cfof_keep|cfof_backup;
+      break;
+
+    default:
+      internerr("unknown response");
+  }
 
-	return what;
+  return what;
 }
diff -pruN 1.13.22ubuntu2/src/depcon.c 1.13.22ubuntu4/src/depcon.c
--- 1.13.22ubuntu2/src/depcon.c	2006-07-11 19:01:38.000000000 +0100
+++ 1.13.22ubuntu4/src/depcon.c	2006-07-21 17:20:25.000000000 +0100
@@ -173,6 +173,10 @@ int depisok(struct dependency *dep, stru
    * before a package is unpacked, when it is sufficient for the package
    * to be unpacked provided that both the unpacked and previously-configured
    * versions are acceptable.
+   * On 0 return (`not OK'), *canfixbyremove refers to a package which
+   * if removed (dep_conflicts) or deconfigured (dep_breaks) will fix
+   * the problem.  Caller may pass 0 for canfixbyremove and need not
+   * initialise *canfixbyremove.
    */
   struct deppossi *possi;
   struct deppossi *provider;
@@ -188,8 +192,10 @@ int depisok(struct dependency *dep, stru
   assert(dep->type == dep_depends || dep->type == dep_predepends ||
          dep->type == dep_conflicts || dep->type == dep_recommends ||
 	 dep->type == dep_suggests || dep->type == dep_enhances ||
-	 dep->type == dep_breaks );
+	 dep->type == dep_breaks);
   
+  if (canfixbyremove) *canfixbyremove= 0;
+
   /* The dependency is always OK if we're trying to remove the depend*ing*
    * package.
    */
@@ -214,16 +220,6 @@ int depisok(struct dependency *dep, stru
     internerr("unknown istobe depending");
   }
 
-  if (dep->type == dep_breaks)
-    /* We don't implement this and we can only be in this state
-     * if either a Breaks-ignorant or a Breaks-supporting dpkg
-     * installed the package.  In both cases it's probably too
-     * late to do anything useful about it now in this version
-     * so we just ignore it and hope.
-     * fixme-implement-Breaks
-     */
-    return 1;
-
   /* Describe the dependency, in case we have to moan about it. */
   varbufreset(whynot);
   varbufaddc(whynot, ' ');
@@ -357,12 +353,11 @@ int depisok(struct dependency *dep, stru
       }
     }
 
-    if (canfixbyremove) *canfixbyremove= 0;
     return 0;
 
   } else {
     
-    /* It's a conflict.  There's only one main alternative,
+    /* It's conflicts or breaks.  There's only one main alternative,
      * but we also have to consider Providers.  We return `0' as soon
      * as we find something that matches the conflict, and only describe
      * it then.  If we get to the end without finding anything we return `1'.
@@ -372,11 +367,12 @@ int depisok(struct dependency *dep, stru
     nconflicts= 0;
 
     if (possi->ed != possi->up->up) {
-      /* If the package conflicts with itself it must mean that it conflicts
-       * with other packages which provide the same virtual name.  We therefore
-       * don't look at the real package and go on to the virtual ones.
+      /* If the package conflicts with or breaks itself it must mean
+       * other packages which provide the same virtual name.  We
+       * therefore don't look at the real package and go on to the
+       * virtual ones.
        */
-      
+
       switch (possi->ed->clientdata->istobe) {
       case itb_remove:
         break;
@@ -390,11 +386,17 @@ int depisok(struct dependency *dep, stru
         nconflicts++;
         *canfixbyremove= possi->ed;
         break;
-      case itb_normal: case itb_deconfigure: case itb_preinstall:
+      case itb_deconfigure:
+	if (dep->type == dep_breaks) break; /* already deconfiguring this */
+	/* fall through */
+      case itb_normal: case itb_preinstall:
         switch (possi->ed->status) {
         case stat_notinstalled: case stat_configfiles:
           break;
-        default:
+	case stat_halfinstalled: case stat_unpacked:
+	case stat_halfconfigured: 
+	  if (dep->type == dep_breaks) break; /* no problem */
+        case stat_installed:
           if (!versionsatisfied(&possi->ed->installed, possi)) break;
           sprintf(linebuf, _("  %.250s (version %.250s) is %s.\n"),
                   possi->ed->name,
@@ -413,7 +415,7 @@ int depisok(struct dependency *dep, stru
 
     /* If there was no version specified we try looking for Providers. */
     if (possi->verrel == dvr_none) {
-        
+
       /* See if the package we're about to install Provides it. */
       for (provider= possi->ed->available.depended;
            provider;
@@ -447,11 +449,16 @@ int depisok(struct dependency *dep, stru
           continue; 
         case itb_remove:
           continue;
-        case itb_normal: case itb_deconfigure: case itb_preinstall:
+	case itb_deconfigure:
+	  if (dep->type == dep_breaks) continue; /* already deconfiguring */
+        case itb_normal: case itb_preinstall:
           switch (provider->up->up->status) {
           case stat_notinstalled: case stat_configfiles:
             continue;
-          default:
+	  case stat_halfinstalled: case stat_unpacked:
+	  case stat_halfconfigured: 
+	    if (dep->type == dep_breaks) break; /* no problem */
+          case stat_installed:
             sprintf(linebuf, _("  %.250s provides %.250s and is %s.\n"),
                     provider->up->up->name, possi->ed->name,
                     gettext(statusstrings[provider->up->up->status]));
diff -pruN 1.13.22ubuntu2/src/help.c 1.13.22ubuntu4/src/help.c
--- 1.13.22ubuntu2/src/help.c	2006-05-19 23:46:39.000000000 +0100
+++ 1.13.22ubuntu4/src/help.c	2006-07-21 17:20:25.000000000 +0100
@@ -152,6 +152,12 @@ int force_depends(struct deppossi *possi
          ignore_depends(possi->up->up);
 }
 
+int force_breaks(struct deppossi *possi) {
+  return fc_breaks ||
+         ignore_depends(possi->ed) ||
+         ignore_depends(possi->up->up);
+}
+
 int force_conflicts(struct deppossi *possi) {
   return fc_conflicts;
 }
diff -pruN 1.13.22ubuntu2/src/main.c 1.13.22ubuntu4/src/main.c
--- 1.13.22ubuntu2/src/main.c	2006-06-02 04:45:21.000000000 +0100
+++ 1.13.22ubuntu4/src/main.c	2006-07-21 17:20:25.000000000 +0100
@@ -154,7 +154,7 @@ unsigned long f_debug=0;
 /* Change fc_overwrite to 1 to enable force-overwrite by default */
 int fc_downgrade=1, fc_configureany=0, fc_hold=0, fc_removereinstreq=0, fc_overwrite=0;
 int fc_removeessential=0, fc_conflicts=0, fc_depends=0, fc_dependsversion=0;
-int fc_badpath=0, fc_overwritediverted=0, fc_architecture=0;
+int fc_breaks=0, fc_badpath=0, fc_overwritediverted=0, fc_architecture=0;
 int fc_nonroot=0, fc_overwritedir=0, fc_conff_new=0, fc_conff_miss=0;
 int fc_conff_old=0, fc_conff_def=0;
 int fc_badverify = 0;
@@ -180,6 +180,7 @@ static const struct forceinfo {
   { "confmiss",            &fc_conff_miss               },
   { "depends",             &fc_depends                  },
   { "depends-version",     &fc_dependsversion           },
+  { "breaks",              &fc_breaks                   },
   { "bad-path",            &fc_badpath                  },
   { "not-root",            &fc_nonroot                  },
   { "overwrite",           &fc_overwrite                },
diff -pruN 1.13.22ubuntu2/src/main.h 1.13.22ubuntu4/src/main.h
--- 1.13.22ubuntu2/src/main.h	2006-05-19 23:46:39.000000000 +0100
+++ 1.13.22ubuntu4/src/main.h	2006-07-21 17:20:25.000000000 +0100
@@ -46,6 +46,7 @@ struct perpackagestate {
 struct packageinlist {
   struct packageinlist *next;
   struct pkginfo *pkg;
+  void *xinfo;
 };
 
 enum action { act_unset, act_install, act_unpack, act_avail, act_configure,
@@ -86,7 +87,7 @@ extern int f_autodeconf, f_largemem, f_n
 extern unsigned long f_debug;
 extern int fc_downgrade, fc_configureany, fc_hold, fc_removereinstreq, fc_overwrite;
 extern int fc_removeessential, fc_conflicts, fc_depends, fc_dependsversion;
-extern int fc_badpath, fc_overwritediverted, fc_architecture;
+extern int fc_breaks, fc_badpath, fc_overwritediverted, fc_architecture;
 extern int fc_nonroot, fc_overwritedir, fc_conff_new, fc_conff_miss;
 extern int fc_conff_old, fc_conff_def;
 extern int fc_badverify;
@@ -150,7 +151,8 @@ void packages(const char *const *argv);
 void removal_bulk(struct pkginfo *pkg);
 int conffderef(struct pkginfo *pkg, struct varbuf *result, const char *in);
 int dependencies_ok(struct pkginfo *pkg, struct pkginfo *removing,
-                    struct varbuf *aemsgs);
+                    struct varbuf *aemsgs); /* checks [Pre]-Depends only */
+int breakses_ok(struct pkginfo *pkg, struct varbuf *aemsgs);
 
 void deferred_remove(struct pkginfo *pkg);
 void deferred_configure(struct pkginfo *pkg);
@@ -177,6 +179,7 @@ void cu_closedir(int argc, void **argv);
 void cu_closefd(int argc, void **argv);
 
 int ignore_depends(struct pkginfo *pkg);
+int force_breaks(struct deppossi *possi);
 int force_depends(struct deppossi *possi);
 int force_conff_new(struct deppossi *possi);
 int force_conff_miss(struct deppossi *possi);
diff -pruN 1.13.22ubuntu2/src/packages.c 1.13.22ubuntu4/src/packages.c
--- 1.13.22ubuntu2/src/packages.c	2006-07-11 19:01:38.000000000 +0100
+++ 1.13.22ubuntu4/src/packages.c	2006-07-21 17:20:25.000000000 +0100
@@ -339,6 +339,82 @@ static int deppossi_ok_found(struct pkgi
   }
 }
 
+static void breaks_check_one(struct varbuf *aemsgs, int *ok,
+			     struct deppossi *breaks,
+			     struct pkginfo *broken,
+			     struct pkginfo *breaker,
+			     struct pkginfo *virtbroken) {
+  struct varbuf depmsg;
+		  
+  debug(dbg_depcondetail,"      checking breaker %s virtbroken %s",
+	breaker->name, virtbroken ? virtbroken->name : "<none>");
+
+  if (breaker->status == stat_notinstalled ||
+      breaker->status == stat_configfiles) return;
+  if (broken == breaker) return;
+  if (!versionsatisfied(&breaker->installed, breaks)) return;
+  if (ignore_depends(breaker)) return;
+  if (virtbroken && ignore_depends(virtbroken)) return;
+
+  varbufinit(&depmsg);
+  varbufdependency(&depmsg, breaks->up);
+  varbufaddc(&depmsg, 0);
+  varbufprintf(aemsgs, _(" %s (%s) breaks %s and is %s.\n"),
+	       breaker->name, 
+	       versiondescribe(&breaker->installed.version,
+			       vdew_nonambig),
+	       depmsg.buf,
+	       gettext(statusstrings[breaker->status]));
+  varbuffree(&depmsg);
+  
+  if (virtbroken) {
+    varbufprintf(aemsgs, _("  %s (%s) provides %s.\n"),
+		 broken->name,
+		 versiondescribe(&broken->installed.version,
+				 vdew_nonambig),
+		 virtbroken->name);
+  } else if (breaks->verrel != dvr_none) {
+    varbufprintf(aemsgs, _("  Version of %s to be configured is %s.\n"),
+		 broken->name,
+		 versiondescribe(&broken->installed.version,
+				 vdew_nonambig));
+    if (fc_dependsversion) return;
+  }
+  if (force_breaks(breaks)) return;
+  *ok= 0;
+}  
+
+void breaks_check_target(struct varbuf *aemsgs, int *ok,
+			 struct pkginfo *broken,
+			 struct pkginfo *target,
+			 struct pkginfo *virtbroken) {
+  struct deppossi *possi;
+  
+  for (possi= target->installed.depended; possi; possi= possi->nextrev) {
+    if (possi->up->type != dep_breaks) continue;
+    if (virtbroken && possi->verrel != dvr_none) continue;
+    breaks_check_one(aemsgs,ok, possi,broken,possi->up->up,virtbroken);
+  }
+}
+
+int breakses_ok(struct pkginfo *pkg, struct varbuf *aemsgs) {
+  struct dependency *dep;
+  struct pkginfo *virtbroken;
+  int ok= 2;
+
+  debug(dbg_depcon,"    checking Breaks");
+
+  breaks_check_target(aemsgs,&ok, pkg,pkg,0);
+
+  for (dep= pkg->installed.depends; dep; dep= dep->next) {
+    if (dep->type != dep_provides) continue;
+    virtbroken= dep->list->ed;
+    debug(dbg_depcondetail,"     checking virtbroken %s", virtbroken->name);
+    breaks_check_target(aemsgs,&ok, pkg,virtbroken,virtbroken);
+  }
+  return ok;
+}
+
 int dependencies_ok(struct pkginfo *pkg, struct pkginfo *removing,
                     struct varbuf *aemsgs) {
   int ok, matched, found, thisf, interestingwarnings;
@@ -352,9 +428,6 @@ int dependencies_ok(struct pkginfo *pkg,
   debug(dbg_depcon,"checking dependencies of %s (- %s)",
         pkg->name, removing ? removing->name : "<none>");
   assert(pkg->installed.valid);
-  /* To implement Breaks we need to add code here which prevents
-   * configuration of Broken packages.
-   * fixme-implement-Breaks */
   for (dep= pkg->installed.depends; dep; dep= dep->next) {
     if (dep->type != dep_depends && dep->type != dep_predepends) continue;
     debug(dbg_depcondetail,"  checking group ...");
diff -pruN 1.13.22ubuntu2/src/processarc.c 1.13.22ubuntu4/src/processarc.c
--- 1.13.22ubuntu2/src/processarc.c	2006-07-11 19:01:38.000000000 +0100
+++ 1.13.22ubuntu4/src/processarc.c	2006-07-21 17:20:25.000000000 +0100
@@ -241,6 +241,10 @@ void process_archive(const char *filenam
       /* Look for things we conflict with. */
       check_conflict(dsearch, pkg, pfilename);
       break;
+    case dep_breaks:
+      /* Look for things we break. */
+      check_breaks(dsearch, pkg, pfilename);
+      break;
     case dep_provides:
       /* Look for things that conflict with what we provide. */
       if (dsearch->list->ed->installed.valid) {
@@ -252,16 +256,6 @@ void process_archive(const char *filenam
         }
       }
       break;
-    case dep_breaks:
-      fprintf(stderr, _("dpkg: regarding %s containing %s:\n"
-			" package uses Breaks; not supported in this dpkg\n"),
-	      pfilename, pkg->name);
-      if (!force_depends(dsearch->list))
-	ohshit(_("unsupported dependency problem - not installing %.250s"),
-	       pkg->name);
-      fprintf(stderr, _("dpkg: warning - ignoring Breaks !\n"));
-      /* fixme-implement-Breaks */
-      break;
     case dep_suggests:
     case dep_recommends:
     case dep_depends:
@@ -404,31 +398,36 @@ void process_archive(const char *filenam
     modstatdb_note(pkg);
   }
 
+  for (deconpil= deconfigure; deconpil; deconpil= deconpil->next) {
+    struct pkginfo *removing= deconpil->xinfo;
+    
+    printf(removing ?
+	   _("De-configuring %s, to allow removal of %s ...\n") :
+	   _("De-configuring %s ...\n"),
+	   deconpil->pkg->name, removing ? removing->name : 0);
+    deconpil->pkg->status= stat_halfconfigured;
+    modstatdb_note(deconpil->pkg);
+    /* This means that we *either* go and run postinst abort-deconfigure,
+     * *or* queue the package for later configure processing, depending
+     * on which error cleanup route gets taken.
+     */
+    push_cleanup(cu_prermdeconfigure,~ehflag_normaltidy,
+		 ok_prermdeconfigure,ehflag_normaltidy,
+		 3,(void*)deconpil->pkg,(void*)removing,(void*)pkg);
+    maintainer_script_installed(deconpil->pkg, PRERMFILE, "pre-removal",
+				"deconfigure", "in-favour", pkg->name,
+				versiondescribe(&pkg->available.version,
+						vdew_nonambig),
+				removing ? "removing" : (char*)0,
+				removing ? removing->name : (char*)0,
+				removing ? versiondescribe(&removing->installed.version,
+						vdew_nonambig) : (char*)0,
+				(char*)0);
+  }
+
   for (i = 0 ; i < cflict_index ; i++) {
     if (!(conflictor[i]->status == stat_halfconfigured ||
 	  conflictor[i]->status == stat_installed)) continue;
-    for (deconpil= deconfigure; deconpil; deconpil= deconpil->next) {
-      printf(_("De-configuring %s, so that we can remove %s ...\n"),
-             deconpil->pkg->name, conflictor[i]->name);
-      deconpil->pkg->status= stat_halfconfigured;
-      modstatdb_note(deconpil->pkg);
-      /* This means that we *either* go and run postinst abort-deconfigure,
-       * *or* queue the package for later configure processing, depending
-       * on which error cleanup route gets taken.
-       */
-      push_cleanup(cu_prermdeconfigure,~ehflag_normaltidy,
-                   ok_prermdeconfigure,ehflag_normaltidy,
-                   3,(void*)deconpil->pkg,
-		   (void*)conflictor[i],(void*)pkg);
-      maintainer_script_installed(deconpil->pkg, PRERMFILE, "pre-removal",
-                                  "deconfigure", "in-favour", pkg->name,
-                                  versiondescribe(&pkg->available.version,
-                                                  vdew_nonambig),
-                                  "removing", conflictor[i]->name,
-                                  versiondescribe(&conflictor[i]->installed.version,
-                                                  vdew_nonambig),
-                                  (char*)0);
-    }
     conflictor[i]->status= stat_halfconfigured;
     modstatdb_note(conflictor[i]);
     push_cleanup(cu_prerminfavour,~ehflag_normaltidy, 0,0,

Reply to: