hrev50884 adds 6 changesets to branch 'master'
old head: 991d9dbf6dd562590f62b82d1015fa9cd515264e
new head: 91cdfd96f8729cdfd5f80f1ab54e7d7600f5ecd5
overview:
http://cgit.haiku-os.org/haiku/log/?qt=range&q=91cdfd96f872+%5E991d9dbf6dd5
----------------------------------------------------------------------------
e5022f23b3cc: Coding style cleanup, no functional change.
a2eb6bbda477: bfs: Minor cleanup.
* Added helper methods for operator/equation characters.
f79179975d5e: bfs: Query parser needs to filter out escape char.
* When escaping operator/quote characters, the character was properly
ignored. However, the escape char was left in the string which
altered the query.
* This fixes bug #10976.
3af0b8555ecd: bfs_shell: Fixed (missing) use of the FSSH_B_PRI* macros.
* This closes ticket #12657.
9e71fa0e2117: mkfs: Added an example to the help text.
91cdfd96f872: bfs: Never publish the index root node.
* This caused the volume to be un-unmountable when you created an index
on a non-indexed volume.
[ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]
----------------------------------------------------------------------------
6 files changed, 377 insertions(+), 328 deletions(-)
src/add-ons/kernel/file_systems/bfs/Inode.cpp | 15 +-
src/add-ons/kernel/file_systems/bfs/Inode.h | 4 +
src/add-ons/kernel/file_systems/bfs/Query.cpp | 628 +++++++++++----------
src/add-ons/kernel/file_systems/bfs/Volume.cpp | 10 +-
src/bin/mkfs/main.cpp | 9 +-
src/tools/bfs_shell/command_checkfs.cpp | 39 +-
############################################################################
Commit: e5022f23b3cc87b2123206fb3fc4e5f5eec14e35
URL: http://cgit.haiku-os.org/haiku/commit/?id=e5022f23b3cc
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Thu Jan 19 19:48:07 2017 UTC
Coding style cleanup, no functional change.
----------------------------------------------------------------------------
diff --git a/src/add-ons/kernel/file_systems/bfs/Query.cpp
b/src/add-ons/kernel/file_systems/bfs/Query.cpp
index 1ec3c20..a8d127c 100644
--- a/src/add-ons/kernel/file_systems/bfs/Query.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/Query.cpp
@@ -74,31 +74,32 @@ union value {
*/
class Term {
public:
- Term(int8 op) : fOp(op),
fParent(NULL) {}
- virtual ~Term() {}
+ Term(int8 op) :
fOp(op), fParent(NULL) {}
+ virtual ~Term() {}
- int8 Op() const { return fOp; }
+ int8 Op() const { return
fOp; }
- void SetParent(Term* parent) { fParent =
parent; }
- Term* Parent() const { return fParent; }
+ void SetParent(Term* parent)
{ fParent = parent; }
+ Term* Parent() const { return
fParent; }
- virtual status_t Match(Inode* inode, const char* attribute =
NULL,
- int32 type = 0, const
uint8* key = NULL,
- size_t size = 0) = 0;
- virtual void Complement() = 0;
+ virtual status_t Match(Inode* inode,
+ const
char* attribute = NULL,
+ int32
type = 0, const uint8* key = NULL,
+ size_t
size = 0) = 0;
+ virtual void Complement() = 0;
- virtual void CalculateScore(Index& index) = 0;
- virtual int32 Score() const = 0;
+ virtual void CalculateScore(Index& index) =
0;
+ virtual int32 Score() const = 0;
- virtual status_t InitCheck() = 0;
+ virtual status_t InitCheck() = 0;
#ifdef DEBUG
- virtual void PrintToStream() = 0;
+ virtual void PrintToStream() = 0;
#endif
protected:
- int8 fOp;
- Term* fParent;
+ int8 fOp;
+ Term* fParent;
};
@@ -115,51 +116,54 @@ protected:
*/
class Equation : public Term {
public:
- Equation(char** expression);
- virtual ~Equation();
+ Equation(char**
_expression);
+ virtual ~Equation();
- virtual status_t InitCheck();
+ virtual status_t InitCheck();
- status_t ParseQuotedString(char** _start, char**
_end);
- char* CopyString(char* start, char* end);
+ virtual status_t Match(Inode* inode,
+ const
char* attribute = NULL,
+ int32
type = 0, const uint8* key = NULL,
+ size_t
size = 0);
+ virtual void Complement();
- virtual status_t Match(Inode* inode, const char* attribute =
NULL,
- int32 type = 0, const
uint8* key = NULL,
- size_t size = 0);
- virtual void Complement();
+ status_t PrepareQuery(Volume*
volume, Index& index,
+
TreeIterator** iterator,
+ bool
queryNonIndexed);
+ status_t GetNextMatching(Volume*
volume,
+
TreeIterator* iterator,
+ struct
dirent* dirent, size_t bufferSize);
- status_t PrepareQuery(Volume* volume, Index&
index,
- TreeIterator**
iterator, bool queryNonIndexed);
- status_t GetNextMatching(Volume* volume,
TreeIterator* iterator,
- struct dirent* dirent,
size_t bufferSize);
-
- virtual void CalculateScore(Index &index);
- virtual int32 Score() const { return fScore; }
+ virtual void CalculateScore(Index &index);
+ virtual int32 Score() const { return fScore; }
#ifdef DEBUG
- virtual void PrintToStream();
+ virtual void PrintToStream();
#endif
private:
- Equation(const Equation& other);
- Equation& operator=(const
Equation& other);
- // no implementation
-
- status_t ConvertValue(type_code type);
- bool CompareTo(const uint8* value, uint16
size);
- uint8* Value() const { return (uint8*)&fValue;
}
- status_t MatchEmptyString();
-
- char* fAttribute;
- char* fString;
- union value fValue;
- type_code fType;
- size_t fSize;
- bool fIsPattern;
- bool fIsSpecialTime;
-
- int32 fScore;
- bool fHasIndex;
+ Equation(const
Equation& other);
+ Equation&
operator=(const Equation& other);
+ // no
implementation
+
+ status_t
_ParseQuotedString(char** _start, char** _end);
+ char* _CopyString(char*
start, char* end);
+ status_t _ConvertValue(type_code
type);
+ bool _CompareTo(const uint8*
value, uint16 size);
+ uint8* _Value() const { return
(uint8*)&fValue; }
+ status_t _MatchEmptyString();
+
+private:
+ char* fAttribute;
+ char* fString;
+ union value fValue;
+ type_code fType;
+ size_t fSize;
+ bool fIsPattern;
+ bool fIsSpecialTime;
+
+ int32 fScore;
+ bool fHasIndex;
};
@@ -168,40 +172,42 @@ private:
*/
class Operator : public Term {
public:
- Operator(Term* left, int8 op,
Term* right);
- virtual ~Operator();
+ Operator(Term*
left, int8 op, Term* right);
+ virtual ~Operator();
- Term* Left() const { return fLeft; }
- Term* Right() const { return fRight; }
+ Term* Left() const { return
fLeft; }
+ Term* Right() const { return
fRight; }
- virtual status_t Match(Inode* inode, const char* attribute =
NULL,
- int32 type = 0, const
uint8* key = NULL,
- size_t size = 0);
- virtual void Complement();
+ virtual status_t Match(Inode* inode,
+ const
char* attribute = NULL,
+ int32
type = 0, const uint8* key = NULL,
+ size_t
size = 0);
+ virtual void Complement();
- virtual void CalculateScore(Index& index);
- virtual int32 Score() const;
+ virtual void CalculateScore(Index& index);
+ virtual int32 Score() const;
- virtual status_t InitCheck();
+ virtual status_t InitCheck();
#ifdef DEBUG
- virtual void PrintToStream();
+ virtual void PrintToStream();
#endif
private:
- Operator(const Operator& other);
- Operator& operator=(const
Operator& other);
- // no implementation
+ Operator(const
Operator& other);
+ Operator&
operator=(const Operator& other);
+ // no
implementation
- Term* fLeft;
- Term* fRight;
+private:
+ Term* fLeft;
+ Term* fRight;
};
// #pragma mark -
-Equation::Equation(char** expr)
+Equation::Equation(char** _expression)
:
Term(OP_EQUATION),
fAttribute(NULL),
@@ -209,7 +215,7 @@ Equation::Equation(char** expr)
fType(0),
fIsPattern(false)
{
- char* string = *expr;
+ char* string = *_expression;
char* start = string;
char* end = NULL;
@@ -220,7 +226,7 @@ Equation::Equation(char** expr)
if (*start == '"' || *start == '\'') {
// string is quoted (start has to be on the beginning of a
string)
- if (ParseQuotedString(&start, &end) < B_OK)
+ if (_ParseQuotedString(&start, &end) < B_OK)
return;
// set string to a valid start of the equation symbol
@@ -228,7 +234,7 @@ Equation::Equation(char** expr)
skipWhitespace(&string);
if (*string != '=' && *string != '<' && *string != '>'
&& *string != '!') {
- *expr = string;
+ *_expression = string;
return;
}
} else {
@@ -274,7 +280,7 @@ Equation::Equation(char** expr)
// any invalid characters will be rejected
default:
- *expr = string;
+ *_expression = string;
return;
}
@@ -286,14 +292,14 @@ Equation::Equation(char** expr)
// allocate & copy the attribute string
- fAttribute = CopyString(start, end);
+ fAttribute = _CopyString(start, end);
if (fAttribute == NULL)
return;
start = string;
if (*start == '"' || *start == '\'') {
// string is quoted (start has to be on the beginning of a
string)
- if (ParseQuotedString(&start, &end) < B_OK)
+ if (_ParseQuotedString(&start, &end) < B_OK)
return;
string = end + 2;
@@ -306,19 +312,19 @@ Equation::Equation(char** expr)
skipWhitespaceReverse(&end, start);
}
- // at this point, "start" will point to the first character of the
value,
+ // At this point, "start" will point to the first character of the
value,
// "end" will point to its last character, and "start" to the first non-
- // whitespace character after the value string
+ // whitespace character after the value string.
- fString = CopyString(start, end);
+ fString = _CopyString(start, end);
if (fString == NULL)
return;
- // patterns are only allowed for these operations (and strings)
+ // Patterns are only allowed for these operations (and strings)
if (fOp == OP_EQUAL || fOp == OP_UNEQUAL) {
fIsPattern = isPattern(fString);
if (fIsPattern && isValidPattern(fString) < B_OK) {
- // we only want to have valid patterns; setting fString
+ // Only valid patterns are allowed; setting fString
// to NULL will cause InitCheck() to fail
free(fString);
fString = NULL;
@@ -333,7 +339,7 @@ Equation::Equation(char** expr)
// too one day.
fIsSpecialTime = !strcmp(fAttribute, "last_modified");
- *expr = string;
+ *_expression = string;
}
@@ -354,184 +360,6 @@ Equation::InitCheck()
}
-status_t
-Equation::ParseQuotedString(char** _start, char** _end)
-{
- char* start = *_start;
- char quote = *start++;
- char* end = start;
-
- for (; *end && *end != quote; end++) {
- if (*end == '\\')
- end++;
- }
- if (*end == '\0')
- return B_BAD_VALUE;
-
- *_start = start;
- *_end = end - 1;
-
- return B_OK;
-}
-
-
-char*
-Equation::CopyString(char* start, char* end)
-{
- // end points to the last character of the string - and the length
- // also has to include the null-termination
- int32 length = end + 2 - start;
- // just to make sure; since that's the max. attribute name length and
- // the max. string in an index, it make sense to have it that way
- if (length > INODE_FILE_NAME_LENGTH || length <= 0)
- return NULL;
-
- char* copy = (char*)malloc(length);
- if (copy == NULL)
- return NULL;
-
- memcpy(copy, start, length - 1);
- copy[length - 1] = '\0';
-
- return copy;
-}
-
-
-status_t
-Equation::ConvertValue(type_code type)
-{
- // Has the type already been converted?
- if (type == fType)
- return B_OK;
-
- char* string = fString;
-
- switch (type) {
- case B_MIME_STRING_TYPE:
- type = B_STRING_TYPE;
- // supposed to fall through
- case B_STRING_TYPE:
- strncpy(fValue.String, string, INODE_FILE_NAME_LENGTH);
- fValue.String[INODE_FILE_NAME_LENGTH - 1] = '\0';
- fSize = strlen(fValue.String);
- break;
- case B_INT32_TYPE:
- fValue.Int32 = strtol(string, &string, 0);
- fSize = sizeof(int32);
- break;
- case B_UINT32_TYPE:
- fValue.Int32 = strtoul(string, &string, 0);
- fSize = sizeof(uint32);
- break;
- case B_INT64_TYPE:
- fValue.Int64 = strtoll(string, &string, 0);
- fSize = sizeof(int64);
- break;
- case B_UINT64_TYPE:
- fValue.Uint64 = strtoull(string, &string, 0);
- fSize = sizeof(uint64);
- break;
- case B_FLOAT_TYPE:
- fValue.Float = strtod(string, &string);
- fSize = sizeof(float);
- break;
- case B_DOUBLE_TYPE:
- fValue.Double = strtod(string, &string);
- fSize = sizeof(double);
- break;
- default:
- FATAL(("query value conversion to 0x%x requested!\n",
(int)type));
- // should we fail here or just do a safety int32
conversion?
- return B_ERROR;
- }
-
- fType = type;
-
- // patterns are only allowed for string types
- if (fType != B_STRING_TYPE && fIsPattern)
- fIsPattern = false;
-
- return B_OK;
-}
-
-
-/*! Returns true when the key matches the equation. You have to
- call ConvertValue() before this one.
-*/
-bool
-Equation::CompareTo(const uint8* value, uint16 size)
-{
- int32 compare;
-
- // fIsPattern is only true if it's a string type, and fOp OP_EQUAL, or
- // OP_UNEQUAL
- if (fIsPattern) {
- // we have already validated the pattern, so we don't check for
failing
- // here - if something is broken, and matchString() returns an
error,
- // we just don't match
- compare = matchString(fValue.String, (char*)value) == MATCH_OK
? 0 : 1;
- } else if (fIsSpecialTime) {
- // the index is a shifted int64 index, but we have to match
- // against an unshifted value (i.e. the last_modified index)
- int64 timeValue = *(int64*)value >> INODE_TIME_SHIFT;
- compare = compareKeys(fType, &timeValue, sizeof(int64),
&fValue.Int64,
- sizeof(int64));
- } else
- compare = compareKeys(fType, value, size, Value(), fSize);
-
- switch (fOp) {
- case OP_EQUAL:
- return compare == 0;
- case OP_UNEQUAL:
- return compare != 0;
- case OP_LESS_THAN:
- return compare < 0;
- case OP_LESS_THAN_OR_EQUAL:
- return compare <= 0;
- case OP_GREATER_THAN:
- return compare > 0;
- case OP_GREATER_THAN_OR_EQUAL:
- return compare >= 0;
- }
- FATAL(("Unknown/Unsupported operation: %d\n", fOp));
- return false;
-}
-
-
-void
-Equation::Complement()
-{
- D(if (fOp <= OP_EQUATION || fOp > OP_LESS_THAN_OR_EQUAL) {
- FATAL(("op out of range!"));
- return;
- });
-
- int8 complementOp[] = {OP_UNEQUAL, OP_EQUAL, OP_LESS_THAN_OR_EQUAL,
- OP_GREATER_THAN_OR_EQUAL, OP_LESS_THAN,
OP_GREATER_THAN};
- fOp = complementOp[fOp - OP_EQUAL];
-}
-
-
-status_t
-Equation::MatchEmptyString()
-{
- // There is no matching attribute, we will just bail out if we
- // already know that our value is not of a string type.
- // If not, it will be converted to a string - and then be compared with
"".
- // That's why we have to call ConvertValue() here - but it will be
- // a cheap call for the next time
- // TODO: Should we do this only for OP_UNEQUAL?
- if (fType != 0 && fType != B_STRING_TYPE)
- return NO_MATCH;
-
- status_t status = ConvertValue(B_STRING_TYPE);
- if (status == B_OK)
- status = CompareTo((const uint8*)"", fSize) ? MATCH_OK :
NO_MATCH;
-
- return status;
-}
-
-
/*! Matches the inode's attribute value with the equation.
Returns MATCH_OK if it matches, NO_MATCH if not, < 0 if something went
wrong.
@@ -550,7 +378,7 @@ Equation::Match(Inode* inode, const char* attributeName,
int32 type,
if (attributeName != NULL && !strcmp(fAttribute, attributeName)) {
if (key == NULL) {
if (type == B_STRING_TYPE)
- return MatchEmptyString();
+ return _MatchEmptyString();
return NO_MATCH;
}
@@ -623,13 +451,13 @@ Equation::Match(Inode* inode, const char* attributeName,
int32 type,
}
inode->ReleaseAttribute(attribute);
} else
- return MatchEmptyString();
+ return _MatchEmptyString();
}
}
// prepare own value for use, if it is possible to convert it
- status_t status = ConvertValue(type);
+ status_t status = _ConvertValue(type);
if (status == B_OK)
- status = CompareTo(buffer, size) ? MATCH_OK : NO_MATCH;
+ status = _CompareTo(buffer, size) ? MATCH_OK : NO_MATCH;
if (locked)
recursive_lock_unlock(&inode->SmallDataLock());
@@ -639,36 +467,16 @@ Equation::Match(Inode* inode, const char* attributeName,
int32 type,
void
-Equation::CalculateScore(Index &index)
+Equation::Complement()
{
- // As always, these values could be tuned and refined.
- // And the code could also need some real world testing :-)
-
- // do we have to operate on a "foreign" index?
- if (fOp == OP_UNEQUAL || index.SetTo(fAttribute) < B_OK) {
- fScore = 0;
+ D(if (fOp <= OP_EQUATION || fOp > OP_LESS_THAN_OR_EQUAL) {
+ FATAL(("op out of range!"));
return;
- }
-
- // if we have a pattern, how much does it help our search?
- if (fIsPattern)
- fScore = getFirstPatternSymbol(fString) << 3;
- else {
- // Score by operator
- if (fOp == OP_EQUAL)
- // higher than pattern="255 chars+*"
- fScore = 2048;
- else
- // the pattern search is regarded cheaper when you have
at
- // least one character to set your index to
- fScore = 5;
- }
+ });
- // take index size into account (1024 is the current node size
- // in our B+trees)
- // 2048 * 2048 == 4194304 is the maximum score (for an empty
- // tree, since the header + 1 node are already 2048 bytes)
- fScore = fScore * ((2048 * 1024LL) / index.Node()->Size());
+ int8 complementOp[] = {OP_UNEQUAL, OP_EQUAL, OP_LESS_THAN_OR_EQUAL,
+ OP_GREATER_THAN_OR_EQUAL, OP_LESS_THAN,
OP_GREATER_THAN};
+ fOp = complementOp[fOp - OP_EQUAL];
}
@@ -701,7 +509,7 @@ Equation::PrepareQuery(Volume* /*volume*/, Index& index,
type = index.Type();
}
- if (ConvertValue(type) < B_OK)
+ if (_ConvertValue(type) < B_OK)
return B_BAD_VALUE;
BPlusTree* tree = index.Node()->Tree();
@@ -753,7 +561,7 @@ Equation::PrepareQuery(Volume* /*volume*/, Index& index,
if (status == B_ENTRY_NOT_FOUND)
return B_OK;
} else {
- status = (*iterator)->Find(Value(), keySize);
+ status = (*iterator)->Find(_Value(), keySize);
if (fOp == OP_EQUAL && !fIsPattern)
return status;
else if (status == B_ENTRY_NOT_FOUND
@@ -787,7 +595,7 @@ Equation::GetNextMatching(Volume* volume, TreeIterator*
iterator,
// only compare against the index entry when this is the correct
// index for the equation
if (fHasIndex && duplicate < 2
- && !CompareTo((uint8*)&indexValue, keyLength)) {
+ && !_CompareTo((uint8*)&indexValue, keyLength)) {
// They aren't equal? Let the operation decide what to
do. Since
// we always start at the beginning of the index (or
the correct
// position), only some needs to be stopped if the
entry doesn't
@@ -876,6 +684,204 @@ Equation::GetNextMatching(Volume* volume, TreeIterator*
iterator,
}
+void
+Equation::CalculateScore(Index &index)
+{
+ // As always, these values could be tuned and refined.
+ // And the code could also need some real world testing :-)
+
+ // do we have to operate on a "foreign" index?
+ if (fOp == OP_UNEQUAL || index.SetTo(fAttribute) < B_OK) {
+ fScore = 0;
+ return;
+ }
+
+ // if we have a pattern, how much does it help our search?
+ if (fIsPattern)
+ fScore = getFirstPatternSymbol(fString) << 3;
+ else {
+ // Score by operator
+ if (fOp == OP_EQUAL)
+ // higher than pattern="255 chars+*"
+ fScore = 2048;
+ else
+ // the pattern search is regarded cheaper when you have
at
+ // least one character to set your index to
+ fScore = 5;
+ }
+
+ // take index size into account (1024 is the current node size
+ // in our B+trees)
+ // 2048 * 2048 == 4194304 is the maximum score (for an empty
+ // tree, since the header + 1 node are already 2048 bytes)
+ fScore = fScore * ((2048 * 1024LL) / index.Node()->Size());
+}
+
+
+status_t
+Equation::_ParseQuotedString(char** _start, char** _end)
+{
+ char* start = *_start;
+ char quote = *start++;
+ char* end = start;
+
+ for (; *end && *end != quote; end++) {
+ if (*end == '\\')
+ end++;
+ }
+ if (*end == '\0')
+ return B_BAD_VALUE;
+
+ *_start = start;
+ *_end = end - 1;
+
+ return B_OK;
+}
+
+
+char*
+Equation::_CopyString(char* start, char* end)
+{
+ // end points to the last character of the string - and the length
+ // also has to include the null-termination
+ int32 length = end + 2 - start;
+ // just to make sure; since that's the max. attribute name length and
+ // the max. string in an index, it make sense to have it that way
+ if (length > INODE_FILE_NAME_LENGTH || length <= 0)
+ return NULL;
+
+ char* copy = (char*)malloc(length);
+ if (copy == NULL)
+ return NULL;
+
+ memcpy(copy, start, length - 1);
+ copy[length - 1] = '\0';
+
+ return copy;
+}
+
+
+status_t
+Equation::_ConvertValue(type_code type)
+{
+ // Has the type already been converted?
+ if (type == fType)
+ return B_OK;
+
+ char* string = fString;
+
+ switch (type) {
+ case B_MIME_STRING_TYPE:
+ type = B_STRING_TYPE;
+ // supposed to fall through
+ case B_STRING_TYPE:
+ strncpy(fValue.String, string, INODE_FILE_NAME_LENGTH);
+ fValue.String[INODE_FILE_NAME_LENGTH - 1] = '\0';
+ fSize = strlen(fValue.String);
+ break;
+ case B_INT32_TYPE:
+ fValue.Int32 = strtol(string, &string, 0);
+ fSize = sizeof(int32);
+ break;
+ case B_UINT32_TYPE:
+ fValue.Int32 = strtoul(string, &string, 0);
+ fSize = sizeof(uint32);
+ break;
+ case B_INT64_TYPE:
+ fValue.Int64 = strtoll(string, &string, 0);
+ fSize = sizeof(int64);
+ break;
+ case B_UINT64_TYPE:
+ fValue.Uint64 = strtoull(string, &string, 0);
+ fSize = sizeof(uint64);
+ break;
+ case B_FLOAT_TYPE:
+ fValue.Float = strtod(string, &string);
+ fSize = sizeof(float);
+ break;
+ case B_DOUBLE_TYPE:
+ fValue.Double = strtod(string, &string);
+ fSize = sizeof(double);
+ break;
+ default:
+ FATAL(("query value conversion to 0x%x requested!\n",
(int)type));
+ // should we fail here or just do a safety int32
conversion?
+ return B_ERROR;
+ }
+
+ fType = type;
+
+ // patterns are only allowed for string types
+ if (fType != B_STRING_TYPE && fIsPattern)
+ fIsPattern = false;
+
+ return B_OK;
+}
+
+
+/*! Returns true when the key matches the equation. You have to
+ call ConvertValue() before this one.
+*/
+bool
+Equation::_CompareTo(const uint8* value, uint16 size)
+{
+ int32 compare;
+
+ // fIsPattern is only true if it's a string type, and fOp OP_EQUAL, or
+ // OP_UNEQUAL
+ if (fIsPattern) {
+ // we have already validated the pattern, so we don't check for
failing
+ // here - if something is broken, and matchString() returns an
error,
+ // we just don't match
+ compare = matchString(fValue.String, (char*)value) == MATCH_OK
? 0 : 1;
+ } else if (fIsSpecialTime) {
+ // the index is a shifted int64 index, but we have to match
+ // against an unshifted value (i.e. the last_modified index)
+ int64 timeValue = *(int64*)value >> INODE_TIME_SHIFT;
+ compare = compareKeys(fType, &timeValue, sizeof(int64),
&fValue.Int64,
+ sizeof(int64));
+ } else
+ compare = compareKeys(fType, value, size, _Value(), fSize);
+
+ switch (fOp) {
+ case OP_EQUAL:
+ return compare == 0;
+ case OP_UNEQUAL:
+ return compare != 0;
+ case OP_LESS_THAN:
+ return compare < 0;
+ case OP_LESS_THAN_OR_EQUAL:
+ return compare <= 0;
+ case OP_GREATER_THAN:
+ return compare > 0;
+ case OP_GREATER_THAN_OR_EQUAL:
+ return compare >= 0;
+ }
+ FATAL(("Unknown/Unsupported operation: %d\n", fOp));
+ return false;
+}
+
+
+status_t
+Equation::_MatchEmptyString()
+{
+ // There is no matching attribute, we will just bail out if we
+ // already know that our value is not of a string type.
+ // If not, it will be converted to a string - and then be compared with
"".
+ // That's why we have to call ConvertValue() here - but it will be
+ // a cheap call for the next time
+ // TODO: Should we do this only for OP_UNEQUAL?
+ if (fType != 0 && fType != B_STRING_TYPE)
+ return NO_MATCH;
+
+ status_t status = _ConvertValue(B_STRING_TYPE);
+ if (status == B_OK)
+ status = _CompareTo((const uint8*)"", fSize) ? MATCH_OK :
NO_MATCH;
+
+ return status;
+}
+
+
// #pragma mark -
############################################################################
Commit: a2eb6bbda477e7b89d0d6fbeaa0d05e2342e8e87
URL: http://cgit.haiku-os.org/haiku/commit/?id=a2eb6bbda477
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Thu Jan 19 19:59:13 2017 UTC
bfs: Minor cleanup.
* Added helper methods for operator/equation characters.
----------------------------------------------------------------------------
diff --git a/src/add-ons/kernel/file_systems/bfs/Query.cpp
b/src/add-ons/kernel/file_systems/bfs/Query.cpp
index a8d127c..93be7e1 100644
--- a/src/add-ons/kernel/file_systems/bfs/Query.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/Query.cpp
@@ -148,6 +148,8 @@ private:
status_t
_ParseQuotedString(char** _start, char** _end);
char* _CopyString(char*
start, char* end);
+ inline bool _IsEquationChar(char c) const;
+ inline bool _IsOperatorChar(char c) const;
status_t _ConvertValue(type_code
type);
bool _CompareTo(const uint8*
value, uint16 size);
uint8* _Value() const { return
(uint8*)&fValue; }
@@ -232,16 +234,17 @@ Equation::Equation(char** _expression)
// set string to a valid start of the equation symbol
string = end + 2;
skipWhitespace(&string);
- if (*string != '=' && *string != '<' && *string != '>'
- && *string != '!') {
+ if (!_IsEquationChar(string[0])) {
*_expression = string;
return;
}
} else {
// search the (in)equation for the actual equation symbol (and
for other operators
// in case the equation is malformed)
- while (*string && *string != '=' && *string != '<' && *string
!= '>'
- && *string != '!' && *string != '&' && *string != '|') {
+ while (string[0] != 0 && !_IsOperatorChar(string[0])
+ && !_IsEquationChar(string[0])) {
+ if (string[0] == '\\' && string[1] != 0)
+ string++;
string++;
}
@@ -305,7 +308,7 @@ Equation::Equation(char** _expression)
string = end + 2;
skipWhitespace(&string);
} else {
- while (*string && *string != '&' && *string != '|' && *string
!= ')')
+ while (string[0] && !_IsOperatorChar(string[0]) && string[0] !=
')')
string++;
end = string - 1;
@@ -761,6 +764,20 @@ Equation::_CopyString(char* start, char* end)
}
+bool
+Equation::_IsEquationChar(char c) const
+{
+ return c == '=' || c == '<' || c == '>' || c == '!';
+}
+
+
+bool
+Equation::_IsOperatorChar(char c) const
+{
+ return c == '&' || c == '|';
+}
+
+
status_t
Equation::_ConvertValue(type_code type)
{
############################################################################
Commit: f79179975d5e0a92191000708e0375b77eac051a
URL: http://cgit.haiku-os.org/haiku/commit/?id=f79179975d5e
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Thu Jan 19 20:36:13 2017 UTC
Ticket: https://dev.haiku-os.org/ticket/10976
bfs: Query parser needs to filter out escape char.
* When escaping operator/quote characters, the character was properly
ignored. However, the escape char was left in the string which
altered the query.
* This fixes bug #10976.
----------------------------------------------------------------------------
diff --git a/src/add-ons/kernel/file_systems/bfs/Query.cpp
b/src/add-ons/kernel/file_systems/bfs/Query.cpp
index 93be7e1..7cd5003 100644
--- a/src/add-ons/kernel/file_systems/bfs/Query.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/Query.cpp
@@ -757,7 +757,16 @@ Equation::_CopyString(char* start, char* end)
if (copy == NULL)
return NULL;
- memcpy(copy, start, length - 1);
+ // Filter out remaining escaping slashes
+ for (int32 i = 0; i < length; i++) {
+ char c = start++[0];
+ if (c == '\\' && i < length) {
+ length--;
+ i--;
+ continue;
+ }
+ copy[i] = c;
+ }
copy[length - 1] = '\0';
return copy;
############################################################################
Commit: 3af0b8555ecd0a887f47a52285aa818ee0cd7a81
URL: http://cgit.haiku-os.org/haiku/commit/?id=3af0b8555ecd
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Thu Jan 19 20:48:34 2017 UTC
Ticket: https://dev.haiku-os.org/ticket/12657
bfs_shell: Fixed (missing) use of the FSSH_B_PRI* macros.
* This closes ticket #12657.
----------------------------------------------------------------------------
diff --git a/src/tools/bfs_shell/command_checkfs.cpp
b/src/tools/bfs_shell/command_checkfs.cpp
index 35a6648..5dc0a7b 100644
--- a/src/tools/bfs_shell/command_checkfs.cpp
+++ b/src/tools/bfs_shell/command_checkfs.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2012, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2008-2017, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
* Distributed under the terms of the MIT License.
*/
@@ -54,12 +54,15 @@ command_checkfs(int argc, const char* const* argv)
// check all files and report errors
while (_kern_ioctl(rootDir, BFS_IOCTL_CHECK_NEXT_NODE, &result,
sizeof(result)) == B_OK) {
- if (++counter % 50 == 0)
- fssh_dprintf("%9Ld nodes processed\x1b[1A\n", counter);
+ if (++counter % 50 == 0) {
+ fssh_dprintf("%9" FSSH_B_PRIu64 " nodes
processed\x1b[1A\n",
+ counter);
+ }
if (result.pass == BFS_CHECK_PASS_BITMAP) {
if (result.errors) {
- fssh_dprintf("%s (inode = %lld)", result.name,
result.inode);
+ fssh_dprintf("%s (inode = %" FSSH_B_PRIdINO
")", result.name,
+ result.inode);
if ((result.errors & BFS_MISSING_BLOCKS) != 0)
fssh_dprintf(", some blocks weren't
allocated");
if ((result.errors & BFS_BLOCKS_ALREADY_SET) !=
0)
@@ -105,24 +108,26 @@ command_checkfs(int argc, const char* const* argv)
_kern_close(rootDir);
- fssh_dprintf(" %" B_PRIu64 " nodes checked,\n\t%" B_PRIu64 "
blocks "
- "not allocated,\n\t%" B_PRIu64 " blocks already set,\n\t%"
B_PRIu64
- " blocks could be freed\n\n", counter, result.stats.missing,
+ fssh_dprintf(" %" FSSH_B_PRIu64 " nodes checked,\n\t%"
FSSH_B_PRIu64
+ " blocks not allocated,\n\t%" FSSH_B_PRIu64 " blocks already
set,\n\t%"
+ B_PRIu64 " blocks could be freed\n\n", counter,
result.stats.missing,
result.stats.already_set, result.stats.freed);
- fssh_dprintf("\tfiles\t\t%" B_PRIu64 "\n\tdirectories\t%" B_PRIu64 "\n"
- "\tattributes\t%" B_PRIu64 "\n\tattr. dirs\t%" B_PRIu64 "\n"
- "\tindices\t\t%" B_PRIu64 "\n", files, directories, attributes,
+ fssh_dprintf("\tfiles\t\t%" FSSH_B_PRIu64 "\n\tdirectories\t%"
+ FSSH_B_PRIu64 "\n"
+ "\tattributes\t%" FSSH_B_PRIu64 "\n\tattr. dirs\t%"
FSSH_B_PRIu64 "\n"
+ "\tindices\t\t%" FSSH_B_PRIu64 "\n", files, directories,
attributes,
attributeDirectories, indices);
- fssh_dprintf("\n\tdirect block runs\t\t%" B_PRIu64 " (%lld)\n",
- result.stats.direct_block_runs,
+ fssh_dprintf("\n\tdirect block runs\t\t%" FSSH_B_PRIu64 " (%"
FSSH_B_PRIu64
+ ")\n", result.stats.direct_block_runs,
result.stats.blocks_in_direct * result.stats.block_size);
- fssh_dprintf("\tindirect block runs\t\t%" B_PRIu64 " (in %" B_PRIu64
- " array blocks, %lld)\n", result.stats.indirect_block_runs,
- result.stats.indirect_array_blocks,
+ fssh_dprintf("\tindirect block runs\t\t%" FSSH_B_PRIu64 " (in %"
+ FSSH_B_PRIu64 " array blocks, %" FSSH_B_PRIu64 ")\n",
+ result.stats.indirect_block_runs,
result.stats.indirect_array_blocks,
result.stats.blocks_in_indirect * result.stats.block_size);
- fssh_dprintf("\tdouble indirect block runs\t%" B_PRIu64 " (in %"
B_PRIu64
- " array blocks, %lld)\n",
result.stats.double_indirect_block_runs,
+ fssh_dprintf("\tdouble indirect block runs\t%" FSSH_B_PRIu64 " (in %"
+ FSSH_B_PRIu64 " array blocks, %" FSSH_B_PRIu64 ")\n",
+ result.stats.double_indirect_block_runs,
result.stats.double_indirect_array_blocks,
result.stats.blocks_in_double_indirect *
result.stats.block_size);
############################################################################
Commit: 9e71fa0e2117848fb29371ebc3fd6ce86f3e3a64
URL: http://cgit.haiku-os.org/haiku/commit/?id=9e71fa0e2117
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Thu Jan 19 20:52:01 2017 UTC
mkfs: Added an example to the help text.
----------------------------------------------------------------------------
diff --git a/src/bin/mkfs/main.cpp b/src/bin/mkfs/main.cpp
index fd4db49..26218c9 100644
--- a/src/bin/mkfs/main.cpp
+++ b/src/bin/mkfs/main.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Haiku Inc. All rights reserved.
+ * Copyright 2008-2017 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -33,7 +33,12 @@ print_help(bool out)
" -h, --help - print this help text\n"
" -o, --options <opt> - set fs specific options\n"
" -q, --dont-ask - do not ask before initializing\n"
- " -v, --verbose - set verbose output\n",
+ " -v, --verbose - set verbose output\n"
+ "\n"
+ "Example:\n"
+ " mkfs -t bfs -o 'block_size 4096; noindex' ./test.image
Data\n"
+ "\tThis will initialize \"test.image\" with BFS with a block\n"
+ "\tsize of 4096 bytes, without index, and named \"Data\".\n",
kProgramName);
}
############################################################################
Revision: hrev50884
Commit: 91cdfd96f8729cdfd5f80f1ab54e7d7600f5ecd5
URL: http://cgit.haiku-os.org/haiku/commit/?id=91cdfd96f872
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Thu Jan 19 21:13:40 2017 UTC
bfs: Never publish the index root node.
* This caused the volume to be un-unmountable when you created an index
on a non-indexed volume.
----------------------------------------------------------------------------
diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.cpp
b/src/add-ons/kernel/file_systems/bfs/Inode.cpp
index df0ceb6..fce958f 100644
--- a/src/add-ons/kernel/file_systems/bfs/Inode.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/Inode.cpp
@@ -143,7 +143,7 @@ public:
InodeAllocator(Transaction& transaction);
~InodeAllocator();
- status_t New(block_run* parentRun,
mode_t mode,
+ status_t New(block_run* parentRun,
mode_t mode, uint32 flags,
block_run& run,
fs_vnode_ops* vnodeOps,
Inode** _inode);
status_t CreateTree();
@@ -191,8 +191,8 @@ InodeAllocator::~InodeAllocator()
status_t
-InodeAllocator::New(block_run* parentRun, mode_t mode, block_run& run,
- fs_vnode_ops* vnodeOps, Inode** _inode)
+InodeAllocator::New(block_run* parentRun, mode_t mode, uint32 publishFlags,
+ block_run& run, fs_vnode_ops* vnodeOps, Inode** _inode)
{
Volume* volume = fTransaction->GetVolume();
@@ -211,7 +211,8 @@ InodeAllocator::New(block_run* parentRun, mode_t mode,
block_run& run,
if (fInode == NULL)
RETURN_ERROR(B_NO_MEMORY);
- if (!volume->IsInitializing()) {
+ if (!volume->IsInitializing()
+ && (publishFlags & BFS_DO_NOT_PUBLISH_VNODE) == 0) {
status = new_vnode(volume->FSVolume(), fInode->ID(), fInode,
vnodeOps != NULL ? vnodeOps : &gBFSVnodeOps);
if (status < B_OK) {
@@ -272,7 +273,8 @@ InodeAllocator::Keep(fs_vnode_ops* vnodeOps, uint32
publishFlags)
// Symbolic links are not published -- the caller needs to do this once
// the contents have been written.
- if (!fInode->IsSymLink() && volume->ID() >= 0) {
+ if (!fInode->IsSymLink() && !volume->IsInitializing()
+ && (publishFlags & BFS_DO_NOT_PUBLISH_VNODE) == 0) {
status = publish_vnode(volume->FSVolume(), fInode->ID(), fInode,
vnodeOps != NULL ? vnodeOps : &gBFSVnodeOps,
fInode->Mode(),
publishFlags);
@@ -2688,7 +2690,8 @@ Inode::Create(Transaction& transaction, Inode* parent,
const char* name,
InodeAllocator allocator(transaction);
block_run run;
Inode* inode;
- status = allocator.New(&parentRun, mode, run, vnodeOps, &inode);
+ status = allocator.New(&parentRun, mode, publishFlags, run, vnodeOps,
+ &inode);
if (status < B_OK)
return status;
diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.h
b/src/add-ons/kernel/file_systems/bfs/Inode.h
index 1d20f54..546f00d 100644
--- a/src/add-ons/kernel/file_systems/bfs/Inode.h
+++ b/src/add-ons/kernel/file_systems/bfs/Inode.h
@@ -23,6 +23,10 @@ class NodeGetter;
class Transaction;
+// To be used in Inode::Create() as publishFlags
+#define BFS_DO_NOT_PUBLISH_VNODE 0x80000000
+
+
class Inode : public TransactionListener {
typedef DoublyLinkedListLink<Inode> Link;
diff --git a/src/add-ons/kernel/file_systems/bfs/Volume.cpp
b/src/add-ons/kernel/file_systems/bfs/Volume.cpp
index d3f88dd..d3b5e12 100644
--- a/src/add-ons/kernel/file_systems/bfs/Volume.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/Volume.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2012, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2001-2017, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
* This file may be used under the terms of the MIT License.
*/
@@ -503,7 +503,7 @@ Volume::CreateIndicesRoot(Transaction& transaction)
off_t id;
status_t status = Inode::Create(transaction, NULL, NULL,
S_INDEX_DIR | S_STR_INDEX | S_DIRECTORY | 0700, 0, 0, NULL, &id,
- &fIndicesNode);
+ &fIndicesNode, NULL, BFS_DO_NOT_PUBLISH_VNODE);
if (status < B_OK)
RETURN_ERROR(status);
@@ -770,15 +770,15 @@ Volume::Initialize(int fd, const char* name, uint32
blockSize,
status = CreateVolumeID(transaction);
if (status < B_OK)
return status;
-
+
status = _EraseUnusedBootBlock();
if (status < B_OK)
return status;
-
+
status = WriteSuperBlock();
if (status < B_OK)
return status;
-
+
status = transaction.Done();
if (status < B_OK)
return status;