+/* This routine compares dev+inode info for protocols < 30. */
+static int hlink_compare_idev(int *int1, int *int2)
+{
+ struct file_struct *f1 = FPTR(*int1);
+ struct file_struct *f2 = FPTR(*int2);
+ struct idev *i1 = F_HL_IDEV(f1);
+ struct idev *i2 = F_HL_IDEV(f2);
+
+ if (i1->dev != i2->dev)
+ return i1->dev > i2->dev ? 1 : -1;
+
+ if (i1->ino != i2->ino)
+ return i1->ino > i2->ino ? 1 : -1;
+
+ return *int1 > *int2 ? 1 : -1;
+}
+
+/* This routine compares group numbers for protocols >= 30. */
+static int hlink_compare_gnum(int *int1, int *int2)
+{
+ struct file_struct *f1 = FPTR(*int1);
+ struct file_struct *f2 = FPTR(*int2);
+ int gnum1 = F_HL_GNUM(f1);
+ int gnum2 = F_HL_GNUM(f2);
+
+ if (gnum1 != gnum2)
+ return gnum1 > gnum2 ? 1 : -1;
+
+ return *int1 > *int2 ? 1 : -1;
+}
+
+/* The match routine for protocols < 30. */
+static void match_idevs(int32 *ndx_list, int ndx_count)
+{
+ int32 from, prev;
+ struct file_struct *file, *file_next;
+ struct idev *idev, *idev_next;
+
+ qsort(ndx_list, ndx_count, sizeof ndx_list[0],
+ (int (*)()) hlink_compare_idev);
+
+ for (from = 0; from < ndx_count; from++) {
+ for (file = FPTR(ndx_list[from]), idev = F_HL_IDEV(file), prev = -1;
+ from < ndx_count-1;
+ file = file_next, idev = idev_next, prev = ndx_list[from++])
+ {
+ file_next = FPTR(ndx_list[from+1]);
+ idev_next = F_HL_IDEV(file_next);
+ if (idev->dev != idev_next->dev || idev->ino != idev_next->ino)
+ break;
+ pool_free(hlink_pool, 0, idev);
+ if (prev < 0)
+ file->flags |= FLAG_HLINK_FIRST;
+ F_HL_PREV(file) = prev;
+ }
+ pool_free(hlink_pool, 0, idev);
+ if (prev < 0)
+ file->flags &= ~FLAG_HLINKED;
+ else {
+ file->flags |= FLAG_HLINK_LAST;
+ F_HL_PREV(file) = prev;
+ }
+ }
+}
+
+/* The match routine for protocols >= 30. */
+static void match_gnums(int32 *ndx_list, int ndx_count)
+{
+ int32 from, prev;
+ struct file_struct *file, *file_next;
+ int gnum, gnum_next;
+
+ qsort(ndx_list, ndx_count, sizeof ndx_list[0],
+ (int (*)()) hlink_compare_gnum);
+
+ for (from = 0; from < ndx_count; from++) {
+ for (file = FPTR(ndx_list[from]), gnum = F_HL_GNUM(file), prev = -1;
+ from < ndx_count-1;
+ file = file_next, gnum = gnum_next, prev = ndx_list[from++])
+ {
+ file_next = FPTR(ndx_list[from+1]);
+ gnum_next = F_HL_GNUM(file_next);
+ if (gnum != gnum_next)
+ break;
+ if (prev < 0)
+ file->flags |= FLAG_HLINK_FIRST;
+ F_HL_PREV(file) = prev;
+ }
+ if (prev < 0)
+ file->flags &= ~FLAG_HLINKED;
+ else {
+ file->flags |= FLAG_HLINK_LAST;
+ F_HL_PREV(file) = prev;
+ }