|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T s ┃
Length: 6414 (0x190e) Types: TextFile Names: »shrink.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/shrink/shrink.c«
/* * Rename a file so's it will be unique under systems without * extended filename size. * The new name is written on the stardard output. * * Example: * To copy lots of files from a 4.?BSD system to a * SystemV, SystemIII, 2.?BSD or V7 system, without * having to worry about overlapping filenames * (eg, so "what_a_long_filename.c" and "what_a_long_filename.h" * don't get squished), just do * for i in * * do * j=`shrink -m $i` * uucp $j othersys!/stuff/$j (or rcp, hhcp, ...) * done * * Bug: It gets overenthusiastic and deletes characters * unnecessarily if the filename begins with a "." * * Author: * Simon Brown * Department of Computer Science, University of Edinburgh. */ #include <stdio.h> /* * maximum no. of "segments" allowed in a file */ #define MAXSEGS 10 /* * silly names for strchr/strrchr under non-usg unices */ #ifndef sysV #define strchr index #define strrchr rindex #endif sysV char *getsegment(); char *strchr(), *strrchr(); struct segment { char seg_string[63]; char seg_sep; } seg[MAXSEGS]; char defaults[] = "._+-,@~="; char usagemsg[] = "Usage: %s [-<maxlength>] [-mnSv] [-s<separators>] filename ...\n"; int max = 14; /* target length */ int nocheck = 0; /* don't check for existance (-n flag) */ int chatty = 0; /* talk a lot (-v flag) */ int silent = 0; /* don't say anything (-s flag) */ int move = 0; /* rename file (-m flag) */ char *file, *prefix; int modified = 0; char realname[512]; char *separators = defaults; main(argc,argv) char **argv; { register int i, j; int nsegs, suflen, remainder, delete; int total; int zap = 0; register char *op; char *progname = argv[0]; if (argv[1] == (char *)0){ fprintf(stderr, usagemsg, progname); exit(1); } while (*++argv) /* process command-line options... */ if (**argv=='-') while (*++*argv) switch(**argv){ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* change target length */ max = atoi(*argv); if (max<=0){ fprintf(stderr,"%s: illegal length %s\n", argv[0], argv[1]); exit(1); } while (*++*argv); --*argv; break; case 's': /* change separator definition */ separators = ++*argv; while (*++*argv); --*argv; break; case 'n': /* don't create a uniquely named file */ nocheck=1; break; case 'v': /* talk a lot */ chatty=1; break; case 'm': /* move files */ move=1; break; case'S': /* silent */ silent=1; break; default: fprintf(stderr,usagemsg,progname); exit(1); } else break; while (*argv){ strcpy(realname, *argv); if (prefix=strrchr(*argv,'/')){ /* dir/.../file */ file=prefix+1; *prefix = '\0'; prefix = *argv; } else file = *argv; argv++; op=file; modified=0; /* split into logical parts */ for (i=0; i<MAXSEGS && (op=getsegment(op,i)); i++); if (i==MAXSEGS){ fprintf(stderr,"%s: too many segments\n", file); continue; } nsegs = i-1; if ((nsegs*2) >= max){ fprintf(stderr,"%s: too many segments\n", file); continue; } suflen = strlen(seg[nsegs].seg_string); if (suflen>max-nsegs-1){ if (chatty) fprintf(stderr,"warning: %s: suffix truncated\n", file); suflen = max-(2*nsegs)-1; seg[nsegs].seg_string[suflen-1] = '\0'; modified=1; } else if (suflen+nsegs > max-nsegs-1){ zap = nsegs - (max-suflen)/2; if (chatty && zap) fprintf(stderr,"warning: %s: %d segments removed\n", file, zap); } if (nsegs>=1){ /* complicated filename */ for (i=zap+1; i<=nsegs; i++) if (seg[i].seg_sep) suflen++; if (seg[0].seg_sep) suflen++; remainder = max - suflen; delete = remainder/nsegs; total = suflen; for (i=zap+1; i<nsegs; i++){ if (strlen(seg[i].seg_string) > delete) modified=1; seg[i].seg_string[delete] = '\0'; total += delete; } if (strlen(seg[0].seg_string) > max-total) modified=1; seg[0].seg_string[max-total] = '\0'; } unique(zap,nsegs,modified); } } /* * get a segment from a filename. * returns pointer to remainder of filename, or 0 at end of filename */ char * getsegment(cp,i) char *cp; { register char *xp = seg[i].seg_string; while (*cp && strchr(separators,*cp)==0) *xp++ = *cp++; *xp = '\0'; seg[i].seg_sep = *cp; if (*cp) cp++; if (seg[i].seg_string[0] || seg[i].seg_sep) return(cp); else return((char *)0); } /* * print out the current filename in a unique form */ unique(zap,n,mod) { register int i, j; int jmax[MAXSEGS]; int xstart, xstop; if (ok(zap,zap||mod)) return; xstart = (n==0)? 0 : 1; xstop = (n==0)? 1 : n; more: if (xstop <= xstart){ xstart=0; xstop = n+1; } for (i=xstart; i<xstop; i++) jmax[i] = strlen(seg[i].seg_string); for (j=0; j<5; j++){ for (i=xstart; i<xstop; i++){ if (j >= jmax[i]) continue; increment(seg[i].seg_string,j); if (ok(zap,1)) return; } } if (xstart>0 || xstop<n+1){ /* Desparation time: try _any_ segment! */ xstop = -1; goto more; } fprintf(stderr,"Can't generate unique name for %s\n", file); } /* * modify a character in a string (stupid algorithm) */ increment(str,ind) char *str; { char ch = str[ind]; if (ch>='a' && ch<='z') ch += ('A'-'a'); else if (ch>='A' && ch<='Z') ch += ('a'-'A'); str[ind] = ch; } /* * see if a filename is reasonable, and if so print it out * and return 1. * otherwise return 0. */ ok(zap,changed) { char buffer[512]; register char *cp = buffer; register char *xp; register int i; if (prefix){ for (xp=prefix; *xp; ) *cp++ = *xp++; *cp++ = '/'; } for (xp=seg[0].seg_string; *xp; ) /* copy initial segment */ *cp++ = *xp++; if (seg[0].seg_sep){ *cp++ = seg[0].seg_sep; for (i=zap+1; ; i++){ /* copy rest of segments */ for (xp=seg[i].seg_string; *xp; ) *cp++ = *xp++; if (seg[i].seg_sep) *cp++ = seg[i].seg_sep; else if (seg[i].seg_string[0] == '\0') break; } } *cp = '\0'; if (changed && nocheck==0 && access(buffer,0)==0){ if (chatty) fprintf(stderr,"warning: %s already exists - trying again\n",buffer); return(0); } else { if (silent==0) printf("%s\n", buffer); if (move && strcmp(realname,buffer)){ if (link(realname,buffer)==-1 || unlink(realname)==-1) fprintf(stderr,"%s: link/unlink failure\n", realname); } return(1); } }