]> git.proxmox.com Git - ceph.git/blame - ceph/src/include/filepath.h
update sources to 12.2.10
[ceph.git] / ceph / src / include / filepath.h
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7 *
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.
12 *
13 */
14
15
16#ifndef CEPH_FILEPATH_H
17#define CEPH_FILEPATH_H
18
19/*
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?
22 *
23 */
24
25
26#include <iosfwd>
27#include <string>
94b18763 28#include <boost/utility/string_view.hpp>
7c673cae
FG
29#include <vector>
30using namespace std;
31
32#include "buffer.h"
33#include "encoding.h"
34#include "include/types.h"
35#include "include/fs_types.h"
36
37#include "common/Formatter.h"
38
39
40class filepath {
41 inodeno_t ino; // base inode. ino=0 implies pure relative path.
42 string path; // relative path.
43
44 /** bits - path segments
45 * this is ['a', 'b', 'c'] for both the aboslute and relative case.
46 *
47 * NOTE: this value is LAZILY maintained... i.e. it's a cache
48 */
49 mutable vector<string> bits;
50 bool encoded;
51
52 void rebuild_path() {
53 path.clear();
54 for (unsigned i=0; i<bits.size(); i++) {
55 if (i) path += "/";
56 path += bits[i];
57 }
58 }
59 void parse_bits() const {
60 bits.clear();
61 int off = 0;
62 while (off < (int)path.length()) {
63 int nextslash = path.find('/', off);
64 if (nextslash < 0)
65 nextslash = path.length(); // no more slashes
66 if (((nextslash - off) > 0) || encoded) {
67 // skip empty components unless they were introduced deliberately
68 // see commit message for more detail
69 bits.push_back( path.substr(off,nextslash-off) );
70 }
71 off = nextslash+1;
72 }
73 }
74
75 public:
76 filepath() : ino(0), encoded(false) { }
94b18763 77 filepath(boost::string_view s, inodeno_t i) : ino(i), path(s), encoded(false) { }
7c673cae
FG
78 filepath(const string& s, inodeno_t i) : ino(i), path(s), encoded(false) { }
79 filepath(const char* s, inodeno_t i) : ino(i), path(s), encoded(false) { }
80 filepath(const filepath& o) {
81 ino = o.ino;
82 path = o.path;
83 bits = o.bits;
84 encoded = o.encoded;
85 }
86 filepath(inodeno_t i) : ino(i), encoded(false) { }
87
7c673cae
FG
88 /*
89 * if we are fed a relative path as a string, either set ino=0 (strictly
90 * relative) or 1 (absolute). throw out any leading '/'.
91 */
94b18763 92 filepath(boost::string_view s) : encoded(false) {
7c673cae
FG
93 set_path(s);
94 }
94b18763
FG
95 filepath(const char *s) : encoded(false) {
96 set_path(boost::string_view(s));
97 }
98
99 void set_path(boost::string_view s, inodeno_t b) {
100 path = std::string(s);
101 ino = b;
102 }
103 void set_path(boost::string_view s) {
7c673cae 104 if (s[0] == '/') {
94b18763 105 path = std::string(s.substr(1));
7c673cae
FG
106 ino = 1;
107 } else {
108 ino = 0;
94b18763 109 path = std::string(s);
7c673cae
FG
110 }
111 bits.clear();
112 }
113
114
115 // accessors
116 inodeno_t get_ino() const { return ino; }
117 const string& get_path() const { return path; }
118 const char *c_str() const { return path.c_str(); }
119
120 int length() const { return path.length(); }
121 unsigned depth() const {
122 if (bits.empty() && path.length() > 0) parse_bits();
123 return bits.size();
124 }
125 bool empty() const { return path.length() == 0 && ino == 0; }
126
127 bool absolute() const { return ino == 1; }
128 bool pure_relative() const { return ino == 0; }
129 bool ino_relative() const { return ino > 0; }
130
131 const string& operator[](int i) const {
132 if (bits.empty() && path.length() > 0) parse_bits();
133 return bits[i];
134 }
135
136 const string& last_dentry() const {
137 if (bits.empty() && path.length() > 0) parse_bits();
138 assert(!bits.empty());
139 return bits[ bits.size()-1 ];
140 }
141
142 filepath prefixpath(int s) const {
143 filepath t(ino);
144 for (int i=0; i<s; i++)
145 t.push_dentry(bits[i]);
146 return t;
147 }
148 filepath postfixpath(int s) const {
149 filepath t;
150 for (unsigned i=s; i<bits.size(); i++)
151 t.push_dentry(bits[i]);
152 return t;
153 }
154
155
156 // modifiers
157 // string can be relative "a/b/c" (ino=0) or absolute "/a/b/c" (ino=1)
158 void _set_ino(inodeno_t i) { ino = i; }
159 void clear() {
160 ino = 0;
161 path = "";
162 bits.clear();
163 }
164
165 void pop_dentry() {
166 if (bits.empty() && path.length() > 0)
167 parse_bits();
168 bits.pop_back();
169 rebuild_path();
170 }
94b18763 171 void push_dentry(boost::string_view s) {
7c673cae
FG
172 if (bits.empty() && path.length() > 0)
173 parse_bits();
174 if (!bits.empty())
175 path += "/";
94b18763
FG
176 path += std::string(s);
177 bits.emplace_back(std::string(s));
178 }
179 void push_dentry(const string& s) {
180 push_dentry(boost::string_view(s));
7c673cae
FG
181 }
182 void push_dentry(const char *cs) {
94b18763 183 push_dentry(boost::string_view(cs, strlen(cs)));
7c673cae
FG
184 }
185 void push_front_dentry(const string& s) {
186 bits.insert(bits.begin(), s);
187 rebuild_path();
188 }
189 void append(const filepath& a) {
190 assert(a.pure_relative());
191 for (unsigned i=0; i<a.depth(); i++)
192 push_dentry(a[i]);
193 }
194
195 // encoding
196 void encode(bufferlist& bl) const {
197 __u8 struct_v = 1;
198 ::encode(struct_v, bl);
199 ::encode(ino, bl);
200 ::encode(path, bl);
201 }
202 void decode(bufferlist::iterator& blp) {
203 bits.clear();
204 __u8 struct_v;
205 ::decode(struct_v, blp);
206 ::decode(ino, blp);
207 ::decode(path, blp);
208 encoded = true;
209 }
210 void dump(Formatter *f) const {
211 f->dump_unsigned("base_ino", ino);
212 f->dump_string("relative_path", path);
213 }
214 static void generate_test_instances(list<filepath*>& o) {
215 o.push_back(new filepath);
216 o.push_back(new filepath("/usr/bin", 0));
217 o.push_back(new filepath("/usr/sbin", 1));
218 o.push_back(new filepath("var/log", 1));
219 o.push_back(new filepath("foo/bar", 101));
220 }
91327a77
AA
221
222 bool is_last_dot_or_dotdot() const {
223 if (depth() > 0) {
224 std::string dname = last_dentry();
225 if (dname == "." || dname == "..") {
226 return true;
227 }
228 }
229
230 return false;
231 }
7c673cae
FG
232};
233
234WRITE_CLASS_ENCODER(filepath)
235
236inline ostream& operator<<(ostream& out, const filepath& path)
237{
238 if (path.get_ino()) {
239 out << '#' << path.get_ino();
91327a77 240 if (path.length())
7c673cae
FG
241 out << '/';
242 }
243 return out << path.get_path();
244}
245
246#endif