From: len@gibbon.cornell.edu ()
Subject: installation images directory table of contents
Nntp-Posting-User: @cornell.edu
Organization: Cornell University CIT
Date: Wed, 6 Jan 1993 18:25:57 GMT


This problem occurs in the smit menu "install software with updates",
preliminary to executing the command

        installp -qa -d/usr/sys/inst.images -X ...

From this menu, my AIX 3.2 install server presents over 2200 lines of
program product and update information, sorted in essentially random order.
The order is roughly derived from the order in the table of contents
file .toc, built by the inutoc command.  Apparently, inutoc reads
the directory /usr/sys/inst.images in its actual random order and build its
.toc file in the reverse of the order it finds.

My install server now has 579 program products and updates -- apparently
this is more than the developers of installp planned for.

I called IBM defect support, apparently inutoc is "broken as designed" --
I submitted a design change request through my IBM representative, but we
don't expect any quick action.

Not expecting any help from IBM, I wrote this little C program to sort the
.toc file.  If you can use this, please feel free.  After running this
program and replacing the .toc file with the sorted version, the list
produced by smit is still not perfectly sorted, but I can live with it:

------------------------------------------------------------------

/* program to sort a .toc file -- crude, but works
 *
 * default input /inst.images/.toc, output /tmp/.toc.new,
 * follow by mv /tmp/.toc.new .toc if satisfied
 *
 * program takes 2 parameters for input file and output file if desired
 *
 * apparently the format for a .toc record is head{body}tail
 * except for the first record, some kind of header
 *
 */

#include <stdio.h>
#include <string.h>

/* these are guesses */
#define MAX_RECORDS 2048
#define RECORD_SIZE 20480

char *malloc();

/* defaults for input parameters */
char *ifile="/usr/sys/inst.images/.toc";
char *ofile="/tmp/.toc.new";

/* globals for the table of contents records and sizes */
char *records[MAX_RECORDS];
int sizes[MAX_RECORDS];

main(argc,argv) int argc; char **argv; {
    int i;
    int got_eof;
    FILE *ifp, *ofp;
    int head, body, tail;
    int n;
    char *pbuf;

    /* process input arguments */
    if (argc>1) ifile=argv[1];
    if (argc>2) ofile=argv[2];
    if ((ifp=fopen(ifile,"r")) == NULL) {
	fprintf(stderr,"can't open %s\n",ifile);
	exit(1);
	}
    if ((ofp=fopen(ofile,"w")) == NULL) {
	fprintf(stderr,"can't open %s\n",ofile);
	exit(1);
	}

    /* read record 0: special case */
    if ((pbuf=malloc(RECORD_SIZE)) == NULL) {
	fprintf(stderr, "can't malloc %d bytes\n",RECORD_SIZE);
	exit(1);
	}
    records[0]=pbuf;
    got_eof = read_until('\n',ifp, pbuf, &head);
    sizes[0]=head;

    /* all other records are of form head{body}tail --
     * the body, enclosed in curly brackets, may contain other sets of
     * curly brackets
     */
    n = 1;
    while(!feof(ifp)) {
	head=0;
	body=0;
	if ((pbuf=malloc(RECORD_SIZE)) == NULL) {
	    fprintf(stderr, "can't malloc %d bytes\n",RECORD_SIZE);
	    fprintf(stderr, "program abortina\n");
	    exit(1);
	    }
	records[n]=pbuf;
	got_eof = read_until('{',ifp, pbuf, &head);
	if (got_eof < 0) {
	    sizes[n++]=head;
	    break;
	    }

	got_eof = read_and_stack('}', '{', ifp, &pbuf[head], &body);
	got_eof = read_until('\n',ifp, &pbuf[head+body], &tail);
	sizes[n++]=head+body+tail;

	if (n > MAX_RECORDS) {
	    fprintf(stderr, "%d records > MAX_RECORDS=%d\n", n,MAX_RECORDS);
	    fprintf(stderr, "recompile with larger MAX_RECORDS\n");
	    fprintf(stderr, "program abortina\n");
	    exit(1);
	    }
	}

    /* sort here
     *
     * leave first record alone, sort the others
     */
    sort(1, n-1);

    /* all done, write the sorted file */
    for (i=0; i<n; i++)
	fwrite(records[i], 1, sizes[i], ofp);
    fclose(ifp);
    fclose(ofp);
    printf("%s sorted, result in %s\n\n", ifile,ofile);
}


/* read_and_stack is called to look for the closing '}', stacking '{' chars
 * along the way
 */
int
read_and_stack(stopc, stackc, ifp, buf, pcount)
int stopc, stackc; FILE *ifp; char *buf; int *pcount;
{
   int i, c, stacked;

   for (i=0, stacked=0; ; i++) {
	c = getc(ifp);
	buf[i] = c;
	if (c==stackc)
	    stacked++;
	if (c==stopc) {
	    if (stacked==0) {
		i++;
		break;
		}
	    stacked--;
	    }
	if (feof(ifp)) {
	    *pcount = i;
	    return -1;
	    }
	}

   *pcount = i;
   return 0;
}

/* read_until is called to read up to the next '{', or the next '\n'
 */
int
read_until(stopc, ifp, buf, pcount)
int stopc; FILE *ifp; char *buf; int *pcount;
{
   int i;
   int c;
   i = 0;
   do {
	c = getc(ifp);
	buf[i] = c;
	if (feof(ifp)) {
	    *pcount = i;
	    return -1;
	    }
	i++;
	}
   while (c != stopc);
   *pcount = i;
   return 0;
}

/* a standard swap */
swap(start,a,b) int a,b; {
    char *swap_ptr;
    int swap_int;
    swap_ptr=records[start+a];
    records[start+a]=records[start+b];
    records[start+b]=swap_ptr;
    swap_int=sizes[start+a];
    sizes[start+a]=sizes[start+b];
    sizes[start+b]=swap_int;
}

/* standard sort straight from K&R */
sort(start, how_many) int start, how_many; {
    char **p;
    int gap, i, j;
    p=&records[start];
    for (gap=how_many/2; gap>0; gap /=2)
	for (i=gap; i<how_many; i++)
	    for (j=i-gap; j>=0; j-=gap) {
		if(strcmp(p[j],p[j+gap]) <= 0)
		    break;
		swap(start,j,j+gap);
		}
}
Newsgroups: comp.unix.aix