#!/usr/bin/perl

# $Id: linkify-pairs,v 1.1 2022/11/20 06:07:51 bscott Exp bscott $

# Turn pairs of individual files into a pair of hardlinked files.
#
# Read stdin, consisting of pairs of file names, each file assumed to be
# individual RFC-822 messages.  (The output of mbdupes is suitable as input.)
# Unlink one of the files, then create a hardlink to the other file, with the
# name of the first one.  If the two files are already a hardlinked pair,
# silently skips them.
#
# No checking to done to see if the files actually have the same content.
#
# Will fail miserably if filenames contain embedded tabs or newlines.  Spaces
# should be OK.
#
# Does not attempt to handle concurrency.  Potential race conditions abound.
# If someone else is messing with the files while this runs, bad things may
# happen.  So don't do that, then.

########################################################################
# imports

use strict;
use warnings;
use English qw( -no_match_vars );
use autodie qw( :all );
no warnings qw( experimental::signatures );
use feature qw( signatures );

########################################################################
# main program

# read pairs of filenames from stdin
while (<>) {

	chomp;
	my @names = split /\t/;

	die "wrong number of file names" if (@names != 2);

	linkify_pair (@names);

}

########################################################################
# subroutines

# ----------------------------------------------------------------------
sub linkify_pair ($nameL, $nameR) {
# Turn two different files into a pair of hardlinked files.
# No checking to see if the files are actually the same is done.

my @statL = stat $nameL or die "$nameL: stat failed";
my @statR = stat $nameR or die "$nameR: stat failed";

# we're assuming this is all one mailstore
# if that assumption is invalid, the whole concept is broken
die "$nameL: device differs: $nameR" if $statL[0] ne $statR[0];

# if the inode numbers are the same, they are already hardlinks
return if $statL[1] eq $statR[1];

unlink $nameR;

link $nameL, $nameR;

} # ckpair

# END
########################################################################
