1 /*****************************************************************************
2  * Author:   Valient Gough <vgough@pobox.com>
3  *
4  *****************************************************************************
5  * Copyright (c) 2004, Valient Gough
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "Interface.h"
22 
23 #include <utility>
24 
25 #include "ConfigVar.h"
26 #include "Error.h"
27 
28 namespace encfs {
29 
Interface(const char * name_,int Current,int Revision,int Age)30 Interface::Interface(const char *name_, int Current, int Revision, int Age)
31     : _name(name_), _current(Current), _revision(Revision), _age(Age) {}
32 
Interface(std::string name_,int Current,int Revision,int Age)33 Interface::Interface(std::string name_, int Current, int Revision, int Age)
34     : _name(std::move(name_)),
35       _current(Current),
36       _revision(Revision),
37       _age(Age) {}
38 
Interface()39 Interface::Interface() : _current(0), _revision(0), _age(0) {}
40 
41 Interface &Interface::operator=(const Interface &src) = default;
42 
name() const43 const std::string &Interface::name() const { return _name; }
44 
name()45 std::string &Interface::name() { return _name; }
46 
current() const47 int Interface::current() const { return _current; }
48 
current()49 int &Interface::current() { return _current; }
50 
revision() const51 int Interface::revision() const { return _revision; }
52 
revision()53 int &Interface::revision() { return _revision; }
54 
age() const55 int Interface::age() const { return _age; }
56 
age()57 int &Interface::age() { return _age; }
58 
operator ==(const Interface & A,const Interface & B)59 bool operator==(const Interface &A, const Interface &B) {
60   return (A.name() == B.name() && A.current() == B.current() &&
61           A.revision() == B.revision() && A.age() == B.age());
62 }
63 
operator !=(const Interface & A,const Interface & B)64 bool operator!=(const Interface &A, const Interface &B) {
65   return (A.name() != B.name() || A.current() != B.current() ||
66           A.revision() != B.revision() || A.age() != B.age());
67 }
68 
69 // zero branch method of getting comparison sign..
70 // tricky.. makes assumptions
71 #if 0
72 static int sign( int a, int b )
73 {
74     unsigned int ab = ((unsigned int)(a - b)) >> 31;
75     unsigned int ba = ((unsigned int)(b - a)) >> 31;
76 
77     return 1 + ba - ab;
78 }
79 #else
80 // simple, easy to check, unlikely to break due to unforseen events..
sign(int a,int b)81 static int sign(int a, int b) {
82   if (a < b) {
83     return 0;
84   }
85   if (a == b) {
86     return 1;
87   }
88   return 2;
89 }
90 #endif
91 
diffSum(const Interface & A,const Interface & B)92 static int diffSum(const Interface &A, const Interface &B) {
93   int cS = sign(A.current(), B.current());
94   int aS = sign(A.age(), B.age());
95   int rS = sign(A.revision(), B.revision());
96 
97   return (cS * 3 + aS) * 3 + rS;
98 }
99 
100 const int EqualVersion = (1 * 3 + 1) * 3 + 1;
101 
implements(const Interface & B) const102 bool Interface::implements(const Interface &B) const {
103   VLOG(1) << "checking if " << name() << "(" << current() << ":" << revision()
104           << ":" << age() << ") implements " << B.name() << "(" << B.current()
105           << ":" << B.revision() << ")";
106 
107   if (name() != B.name()) {
108     return false;
109   }
110 
111   int currentDiff = current() - B.current();
112   return (currentDiff >= 0 && currentDiff <= age());
113 }
114 
operator <(const Interface & A,const Interface & B)115 bool operator<(const Interface &A, const Interface &B) {
116   if (A.name() == B.name()) {
117     return (diffSum(A, B) < EqualVersion);
118   }
119   return A.name() < B.name();
120 }
121 
operator >(const Interface & A,const Interface & B)122 bool operator>(const Interface &A, const Interface &B) {
123   if (A.name() == B.name()) {
124     return (diffSum(A, B) > EqualVersion);
125   }
126   return A.name() < B.name();
127 }
128 
operator <=(const Interface & A,const Interface & B)129 bool operator<=(const Interface &A, const Interface &B) {
130   if (A.name() == B.name()) {
131     return (diffSum(A, B) <= EqualVersion);
132   }
133   return A.name() < B.name();
134 }
135 
operator >=(const Interface & A,const Interface & B)136 bool operator>=(const Interface &A, const Interface &B) {
137   if (A.name() == B.name()) {
138     return (diffSum(A, B) >= EqualVersion);
139   }
140   return A.name() < B.name();
141 }
142 
operator <<(ConfigVar & dst,const Interface & iface)143 ConfigVar &operator<<(ConfigVar &dst, const Interface &iface) {
144   dst << iface.name() << iface.current() << iface.revision() << iface.age();
145   return dst;
146 }
147 
operator >>(const ConfigVar & src,Interface & iface)148 const ConfigVar &operator>>(const ConfigVar &src, Interface &iface) {
149   src >> iface.name();
150   src >> iface.current();
151   src >> iface.revision();
152   src >> iface.age();
153   return src;
154 }
155 
156 }  // namespace encfs
157