From b34fd35e624ac7caebb9ca490ce7cf28cfecc8e9 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Mon, 18 May 2009 15:33:36 +0200 Subject: [PATCH] Fixed bugs in iso_node_cmp_flag() introduced with revision 559 and clarified constraints for stream comparison functions in libisofs.h --- libisofs/libisofs.h | 16 +++++++++++++--- libisofs/node.c | 34 ++++++++++++++++++++++++---------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index b3907ce..b68136d 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -898,9 +898,19 @@ struct IsoStream_Iface * Compare two streams whether they are based on the same input and will * produce the same output. If in any doubt, then this comparison should * indicate no match. A match might allow hardlinking of IsoFile objects. + * * This function has to establish an equivalence and order relation: - * A = A, if A = B then B = A, if A = B and B = C then A = C, - * if A < B then not B < A, if A < B and B < C then A < C + * cmp_ino(A,A) == 0 + * cmp_ino(A,B) == -cmp_ino(B,A) + * if cmp_ino(A,B) == 0 && cmp_ino(B,C) == 0 then cmp_ino(A,C) == 0 + * if cmp_ino(A,B) < 0 && cmp_ino(B,C) < 0 then cmp_ino(A,C) < 0 + * + * A big hazard to the last constraint are tests which do not apply to some + * types of streams. In this case for any A that is applicable and any B + * that is not applicable, cmp_ino(A,B) must have the same non-zero + * result. I.e. a pair of applicable and non-applicable streams must + * return that non-zero result before the test for a pair of applicable + * streams would happen. * * A function s1.(*cmp_ino)() must only accept stream s2 if function * s2.(*cmp_ino)() would accept s1. Best is to accept only the own stream @@ -2494,7 +2504,7 @@ time_t iso_node_get_ctime(const IsoNode *node); /** * Set if the node will be hidden in RR/ISO tree, Joliet tree or both. * - * If the file is setted as hidden in one tree, it won't be included there, so + * If the file is set as hidden in one tree, it won't be included there, so * it won't be visible in a OS accessing CD using that tree. For example, * GNU/Linux systems access to Rock Ridge / ISO9960 tree in order to see * what is recorded on CD, while MS Windows make use of the Joliet tree. If a diff --git a/libisofs/node.c b/libisofs/node.c index 2444740..487d4af 100644 --- a/libisofs/node.c +++ b/libisofs/node.c @@ -2423,6 +2423,16 @@ int iso_node_set_unique_id(IsoNode *node, IsoImage *image, int flag) /* ts A90508 */ /* + * Note to programmers: It is crucial not to break the following constraints. + * Anti-symmetry: cmp(X,Y) == - cmp(Y,X) + * Transitivity : if cmp(A,B) < 0 && cmp(B,C) < 0 then cmp(A,C) < 0 + * if cmp(A,B) == 0 && cmp(B,C) == 0 then cmp(A,C) == 0 + * A big transitivity hazard are tests which do not apply to some nodes. + * In this case for any A that is applicable and any B that is not applicable + * the comparison must have the same non-zero result. I.e. a pair of applicable + * and non-applicable node must return that non-zero result before the test + * for a pair of applicable nodes would happen. + * * @param flag * bit0= compare stat properties and attributes * bit1= treat all nodes with image ino == 0 as unique @@ -2440,8 +2450,10 @@ int iso_node_cmp_flag(IsoNode *n1, IsoNode *n2, int flag) if (n1 == n2) return 0; + if (n1->type != n2->type) + return (n1->type < n2->type ? -1 : 1); - /* Imported or explicite ISO image node id has absolute priority */ + /* Imported or explicite ISO image node id has priority */ ret1 = (iso_node_get_id(n1, &fs_id1, &dev_id1, &ino_id1, 1) > 0); ret2 = (iso_node_get_id(n2, &fs_id2, &dev_id2, &ino_id2, 1) > 0); if (ret1 != ret2) @@ -2452,11 +2464,10 @@ int iso_node_cmp_flag(IsoNode *n1, IsoNode *n2, int flag) */ if (ino_id1 != ino_id2) return (ino_id1 < ino_id2 ? -1 : 1); - goto inode_match; + if (ino_id1 == 0) /* Image ino 0 is always unique */ + return (n1 < n2 ? -1 : 1); + goto image_inode_match; } - - if (n1->type != n2->type) - return (n1->type < n2->type ? -1 : 1); if (n1->type == LIBISO_FILE) { @@ -2506,13 +2517,16 @@ int iso_node_cmp_flag(IsoNode *n1, IsoNode *n2, int flag) return (n1 < n2 ? -1 : 1); inode_match:; + if (flag & 2) { - iso_node_get_id(n1, &fs_id1, &dev_id1, &ino_id1, 1); - iso_node_get_id(n2, &fs_id2, &dev_id2, &ino_id2, 1); - if (ino_id1 == 0 || ino_id2 == 0) - return (n1 < n2 ? -1 : 1); + /* What comes here has no predefined image ino resp. image_ino == 0 . + Regard this as not equal. + */ + return (n1 < n2 ? -1 : 1); } +image_inode_match:; + if (!(flag & 1)) return 0; if (n1->type == LIBISO_SYMLINK) { @@ -2566,5 +2580,5 @@ inode_match:; /* API */ int iso_node_cmp_ino(IsoNode *n1, IsoNode *n2, int flag) { - return iso_node_cmp_flag(n1, n2, 1 | 2); + return iso_node_cmp_flag(n1, n2, 1); }