ftp.nice.ch/pub/next/unix/graphics/tiff-utils.s.tar.gz#/tiff-utils/tifflink.c

This is tifflink.c in view mode; [Download] [Up]

/*
 * tifflink.c - A utility to take all .tiff files in a directory (and sub-
 * directories) and replace duplicate .tiff files with hard links.
 *
 * Version 1.0, Michael.Glenn@Dartmouth.edu, March 3 1993.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/stat.h>

#define PRIME 101

struct node {
	char *file;
	int inode, size;
	struct node *next;
};

struct node *table[PRIME];

char *
string_copy (char *str) {
	char *p;
	p = (char *)malloc (strlen(str)+1);
	strcpy(p,str);
	return p;
}

struct node *
make_node (char *file, int size, int inode) {
   struct node *p;
   p = (struct node *) malloc (sizeof(struct node));
   p->file = string_copy(file);
   p->size = size;
   p->inode = inode;
   p->next = 0;
   return p;
}

init_table() {
	int i;
	for (i=0; i<sizeof(table); i++)
		table[i] = 0;
}

free_node (struct node *p) {
	if (!p) return;
	free (p->file);
	free (p);
}

free_table() {
	struct node *p, *q;
	int i;
    for (i=0; i<sizeof(table); i++) {
	   p = table[i];
	   while (p) {
		  q = p;
		  p = p->next;
		  free_node(q);
	   }
       table[i] = 0;
    }
}

is_tiff_file(char *fname) {
	int l;
	return (l=strlen(fname)) > 4 && !strcmp(&(fname[l-5]), ".tiff");
}

link_files (char *file1, char *file2) {
	unlink (file2);
	link (file1, file2);
	printf("Files %s and %s hard linked.\n", file1, file2);
}

do_diff(char *file1, char *file2) {
	FILE *fp;
	int i;
	char buff[256];
	sprintf(buff,"diff \"%s\" \"%s\"",file1,file2);
    fp = popen(buff,"r");
    i = (int)fgets(buff, sizeof(buff), fp);
	pclose(fp);
	return (i == 0) ? 1 : 0;
}

do_file (char *fname) {
	char buff[256];
	struct stat s;
	DIR *dp;
	struct direct *p;

	if (lstat(fname,&s) == -1) {
		fprintf(stderr, "File %s not found.\n", fname);
		return;
	}

	if ((s.st_mode & S_IFMT) == S_IFLNK) {
		if (is_tiff_file(fname))
			printf("Ignoring symbolic link at %s\n", fname);
		else if (stat(fname,&s) == -1)
			fprintf(stderr, "Could not follow link at %s\n", fname);
		else if ((s.st_mode & S_IFMT) == S_IFDIR)
			printf("Ignoring symbolic link at %s\n", fname);
		return;
	}

	if ((s.st_mode & S_IFMT) == S_IFDIR) {
		if (!(dp=opendir(fname))) {
			fprintf (stderr, "Failed to open directory %s\n", fname);
			return;
		}
		while (p=readdir(dp))
			if (strcmp(p->d_name,".") && strcmp(p->d_name,"..")) {
				sprintf(buff,"%s/%s", fname, p->d_name);
				do_file(buff);
			}
		closedir(dp);
		return;
	}

	if (is_tiff_file(fname)) {
		struct node **q, *r;
		q = &(table[s.st_size % PRIME]);
		while (*q && s.st_size < (*q)->size && s.st_ino < (*q)->inode)
			q = &((*q)->next);
		r = (*q);
		while (*q && s.st_size == (*q)->size && s.st_ino < (*q)->inode)
			q = &((*q)->next);
		if (*q && s.st_ino == (*q)->inode) {
			printf("%s and %s already hard linked.\n", (*q)->file, fname);
			return;
		}
		while (r && s.st_size == r->size) {
			if (do_diff(r->file, fname)) {
				link_files(r->file, fname);
				return;
			}
			r = r->next;
		}
		r = make_node(fname,s.st_size,s.st_ino);
		r->next = *q;
		*q = r;
	}
}

main(int argc, char **argv) {
	if (argc == 1) {
		fprintf(stderr, "usage: %s file1 [file2 file3 ...]\n", argv[0]);
		fprintf(stderr, "       %s all\n", argv[0]);
		exit(1);
	}
	init_table();
	if (argc == 2 && !strcmp(argv[1], "all"))
		do_file(".");
	else
		for (; argc > 1; argc--, argv++)
			do_file (argv[1]);
	free_table();
	printf("Done.\n");
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.