1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
16 #ifndef CEPH_FILEPATH_H
17 #define CEPH_FILEPATH_H
20 * BUG: /a/b/c is equivalent to a/b/c in dentry-breakdown, but not string.
21 * -> should it be different? how? should this[0] be "", with depth 4?
33 #include "include/types.h"
34 #include "include/fs_types.h"
36 #include "common/Formatter.h"
40 inodeno_t ino; // base inode. ino=0 implies pure relative path.
41 string path; // relative path.
43 /** bits - path segments
44 * this is ['a', 'b', 'c'] for both the aboslute and relative case.
46 * NOTE: this value is LAZILY maintained... i.e. it's a cache
48 mutable vector<string> bits;
53 for (unsigned i=0; i<bits.size(); i++) {
58 void parse_bits() const {
61 while (off < (int)path.length()) {
62 int nextslash = path.find('/', off);
64 nextslash = path.length(); // no more slashes
65 if (((nextslash - off) > 0) || encoded) {
66 // skip empty components unless they were introduced deliberately
67 // see commit message for more detail
68 bits.push_back( path.substr(off,nextslash-off) );
75 filepath() : ino(0), encoded(false) { }
76 filepath(const string& s, inodeno_t i) : ino(i), path(s), encoded(false) { }
77 filepath(const char* s, inodeno_t i) : ino(i), path(s), encoded(false) { }
78 filepath(const filepath& o) {
84 filepath(inodeno_t i) : ino(i), encoded(false) { }
86 void set_path(const char *s, inodeno_t b) {
92 * if we are fed a relative path as a string, either set ino=0 (strictly
93 * relative) or 1 (absolute). throw out any leading '/'.
95 filepath(const char *s) : encoded(false) {
98 void set_path(const char *s) {
111 inodeno_t get_ino() const { return ino; }
112 const string& get_path() const { return path; }
113 const char *c_str() const { return path.c_str(); }
115 int length() const { return path.length(); }
116 unsigned depth() const {
117 if (bits.empty() && path.length() > 0) parse_bits();
120 bool empty() const { return path.length() == 0 && ino == 0; }
122 bool absolute() const { return ino == 1; }
123 bool pure_relative() const { return ino == 0; }
124 bool ino_relative() const { return ino > 0; }
126 const string& operator[](int i) const {
127 if (bits.empty() && path.length() > 0) parse_bits();
131 const string& last_dentry() const {
132 if (bits.empty() && path.length() > 0) parse_bits();
133 assert(!bits.empty());
134 return bits[ bits.size()-1 ];
137 filepath prefixpath(int s) const {
139 for (int i=0; i<s; i++)
140 t.push_dentry(bits[i]);
143 filepath postfixpath(int s) const {
145 for (unsigned i=s; i<bits.size(); i++)
146 t.push_dentry(bits[i]);
152 // string can be relative "a/b/c" (ino=0) or absolute "/a/b/c" (ino=1)
153 void _set_ino(inodeno_t i) { ino = i; }
161 if (bits.empty() && path.length() > 0)
166 void push_dentry(const string& s) {
167 if (bits.empty() && path.length() > 0)
174 void push_dentry(const char *cs) {
178 void push_front_dentry(const string& s) {
179 bits.insert(bits.begin(), s);
182 void append(const filepath& a) {
183 assert(a.pure_relative());
184 for (unsigned i=0; i<a.depth(); i++)
189 void encode(bufferlist& bl) const {
191 ::encode(struct_v, bl);
195 void decode(bufferlist::iterator& blp) {
198 ::decode(struct_v, blp);
203 void dump(Formatter *f) const {
204 f->dump_unsigned("base_ino", ino);
205 f->dump_string("relative_path", path);
207 static void generate_test_instances(list<filepath*>& o) {
208 o.push_back(new filepath);
209 o.push_back(new filepath("/usr/bin", 0));
210 o.push_back(new filepath("/usr/sbin", 1));
211 o.push_back(new filepath("var/log", 1));
212 o.push_back(new filepath("foo/bar", 101));
216 WRITE_CLASS_ENCODER(filepath)
218 inline ostream& operator<<(ostream& out, const filepath& path)
220 if (path.get_ino()) {
221 out << '#' << path.get_ino();
225 return out << path.get_path();