+/**********************************************************************/
+
+struct file_node {
+ struct file_node *next;
+ char *name;
+ size_t size;
+ ino_t inode;
+ int group_id; /* one per identical file content */
+ int dir_id; /* 1 for DIR1, and 2 for DIR2 */
+#ifdef WITH_MD5
+ int md5_computed;
+ unsigned char md5[MD5_DIGEST_LENGTH];
+#endif
+};
+
+void file_list_delete(struct file_node *head) {
+ struct file_node *next;
+ while(head) {
+ next = head->next;
+ free(head->name);
+ free(head);
+ head = next;
+ }
+}
+
+int file_list_length(struct file_node *head) {
+ int l = 0;
+ while(head) {
+ l++;
+ head = head->next;
+ }
+ return l;
+}
+
+/**********************************************************************/
+
+int same_content(struct file_node *f1, struct file_node *f2,
+ char *buffer1, char *buffer2) {
+ int fd1, fd2, s1, s2;
+
+#ifdef WITH_MD5
+ MD5_CTX c1, c2;
+
+ if(use_md5) {
+ if(f1->md5_computed && f2->md5_computed) {
+ if(!memcmp(f1->md5, f2->md5, MD5_DIGEST_LENGTH)) {
+ return 0;
+ }
+ } else {
+ if(!f1->md5_computed) {
+ MD5_Init(&c1);
+ }
+ if(!f2->md5_computed) {
+ MD5_Init(&c2);
+ }
+ }
+ }
+#endif
+
+ fd1 = open(f1->name, O_RDONLY);
+ fd2 = open(f2->name, O_RDONLY);
+
+ if(fd1 >= 0 && fd2 >= 0) {
+ while(1) {
+ s1 = read(fd1, buffer1, READ_BUFFER_SIZE);
+ s2 = read(fd2, buffer2, READ_BUFFER_SIZE);
+
+ if(s1 < 0 || s2 < 0) {
+ close(fd1);
+ close(fd2);
+ return 0;
+ }
+
+ if(s1 == s2) {
+ if(s1 == 0) {
+ close(fd1);
+ close(fd2);
+#ifdef WITH_MD5
+ if(use_md5) {
+ if(!f1->md5_computed) {
+ MD5_Final(f1->md5, &c1);
+ f1->md5_computed = 1;
+ }
+ if(!f2->md5_computed) {
+ MD5_Final(f2->md5, &c2);
+ f2->md5_computed = 1;
+ }
+ }
+#endif
+ return 1;
+ } else {
+ if(memcmp(buffer1, buffer2, s1)) {
+ close(fd1);
+ close(fd2);
+ return 0;
+ }
+#ifdef WITH_MD5
+ if(use_md5) {
+ if(!f1->md5_computed) {
+ MD5_Update(&c1, buffer1, s1);
+ }
+ if(!f2->md5_computed) {
+ MD5_Update(&c2, buffer2, s2);
+ }
+ }
+#endif
+ }
+ } else {
+ fprintf(stderr,
+ "Different read size without error on files of same size.\n");
+ exit(EXIT_FAILURE);
+ }