+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software
- * Foundation. See file COPYING.
- *
- */
-
-
-#ifndef CEPH_FILEPATH_H
-#define CEPH_FILEPATH_H
-
-/*
- * BUG: /a/b/c is equivalent to a/b/c in dentry-breakdown, but not string.
- * -> should it be different? how? should this[0] be "", with depth 4?
- *
- */
-
-
-#include <iosfwd>
-#include <string>
-#include <vector>
-using namespace std;
-
-#include "buffer.h"
-#include "encoding.h"
-#include "include/types.h"
-#include "include/fs_types.h"
-
-#include "common/Formatter.h"
-
-
-class filepath {
- inodeno_t ino; // base inode. ino=0 implies pure relative path.
- string path; // relative path.
-
- /** bits - path segments
- * this is ['a', 'b', 'c'] for both the aboslute and relative case.
- *
- * NOTE: this value is LAZILY maintained... i.e. it's a cache
- */
- mutable vector<string> bits;
- bool encoded;
-
- void rebuild_path() {
- path.clear();
- for (unsigned i=0; i<bits.size(); i++) {
- if (i) path += "/";
- path += bits[i];
- }
- }
- void parse_bits() const {
- bits.clear();
- int off = 0;
- while (off < (int)path.length()) {
- int nextslash = path.find('/', off);
- if (nextslash < 0)
- nextslash = path.length(); // no more slashes
- if (((nextslash - off) > 0) || encoded) {
- // skip empty components unless they were introduced deliberately
- // see commit message for more detail
- bits.push_back( path.substr(off,nextslash-off) );
- }
- off = nextslash+1;
- }
- }
-
- public:
- filepath() : ino(0), encoded(false) { }
- filepath(const string& s, inodeno_t i) : ino(i), path(s), encoded(false) { }
- filepath(const char* s, inodeno_t i) : ino(i), path(s), encoded(false) { }
- filepath(const filepath& o) {
- ino = o.ino;
- path = o.path;
- bits = o.bits;
- encoded = o.encoded;
- }
- filepath(inodeno_t i) : ino(i), encoded(false) { }
-
- void set_path(const char *s, inodeno_t b) {
- path = s;
- ino = b;
- }
-
- /*
- * if we are fed a relative path as a string, either set ino=0 (strictly
- * relative) or 1 (absolute). throw out any leading '/'.
- */
- filepath(const char *s) : encoded(false) {
- set_path(s);
- }
- void set_path(const char *s) {
- if (s[0] == '/') {
- path = s + 1;
- ino = 1;
- } else {
- ino = 0;
- path = s;
- }
- bits.clear();
- }
-
-
- // accessors
- inodeno_t get_ino() const { return ino; }
- const string& get_path() const { return path; }
- const char *c_str() const { return path.c_str(); }
-
- int length() const { return path.length(); }
- unsigned depth() const {
- if (bits.empty() && path.length() > 0) parse_bits();
- return bits.size();
- }
- bool empty() const { return path.length() == 0 && ino == 0; }
-
- bool absolute() const { return ino == 1; }
- bool pure_relative() const { return ino == 0; }
- bool ino_relative() const { return ino > 0; }
-
- const string& operator[](int i) const {
- if (bits.empty() && path.length() > 0) parse_bits();
- return bits[i];
- }
-
- const string& last_dentry() const {
- if (bits.empty() && path.length() > 0) parse_bits();
- assert(!bits.empty());
- return bits[ bits.size()-1 ];
- }
-
- filepath prefixpath(int s) const {
- filepath t(ino);
- for (int i=0; i<s; i++)
- t.push_dentry(bits[i]);
- return t;
- }
- filepath postfixpath(int s) const {
- filepath t;
- for (unsigned i=s; i<bits.size(); i++)
- t.push_dentry(bits[i]);
- return t;
- }
-
-
- // modifiers
- // string can be relative "a/b/c" (ino=0) or absolute "/a/b/c" (ino=1)
- void _set_ino(inodeno_t i) { ino = i; }
- void clear() {
- ino = 0;
- path = "";
- bits.clear();
- }
-
- void pop_dentry() {
- if (bits.empty() && path.length() > 0)
- parse_bits();
- bits.pop_back();
- rebuild_path();
- }
- void push_dentry(const string& s) {
- if (bits.empty() && path.length() > 0)
- parse_bits();
- if (!bits.empty())
- path += "/";
- path += s;
- bits.push_back(s);
- }
- void push_dentry(const char *cs) {
- string s = cs;
- push_dentry(s);
- }
- void push_front_dentry(const string& s) {
- bits.insert(bits.begin(), s);
- rebuild_path();
- }
- void append(const filepath& a) {
- assert(a.pure_relative());
- for (unsigned i=0; i<a.depth(); i++)
- push_dentry(a[i]);
- }
-
- // encoding
- void encode(bufferlist& bl) const {
- __u8 struct_v = 1;
- ::encode(struct_v, bl);
- ::encode(ino, bl);
- ::encode(path, bl);
- }
- void decode(bufferlist::iterator& blp) {
- bits.clear();
- __u8 struct_v;
- ::decode(struct_v, blp);
- ::decode(ino, blp);
- ::decode(path, blp);
- encoded = true;
- }
- void dump(Formatter *f) const {
- f->dump_unsigned("base_ino", ino);
- f->dump_string("relative_path", path);
- }
- static void generate_test_instances(list<filepath*>& o) {
- o.push_back(new filepath);
- o.push_back(new filepath("/usr/bin", 0));
- o.push_back(new filepath("/usr/sbin", 1));
- o.push_back(new filepath("var/log", 1));
- o.push_back(new filepath("foo/bar", 101));
- }
-};
-
-WRITE_CLASS_ENCODER(filepath)
-
-inline ostream& operator<<(ostream& out, const filepath& path)
-{
- if (path.get_ino()) {
- out << '#' << path.get_ino();
- if (path.depth())
- out << '/';
- }
- return out << path.get_path();
-}
-
-#endif