where one cannot tell that the path given to separate was rooted if one just gets a list of
components. that's why we used to treat the top-level dir as its own component, but that also
isn't very helpful or sensible. so now separate and join both have a rooted parameter; separate
reports if the path was rooted, and join needs to know that so it can recreate the original
path.
FUNCDEF("recursive_create");
filename dir(directory_name);
string_array pieces;
- dir.separate(pieces);
+ bool rooted;
+ dir.separate(rooted, pieces);
for (int i = 0; i < pieces.length(); i++) {
// check each location along the way.
string_array partial = pieces.subarray(0, i);
filename curr;
- curr.join(partial); // this is our current location.
+ curr.join(rooted, partial); // this is our current location.
// make sure, if we see a drive letter component, that we call it
// a proper directory name.
if (curr.raw()[curr.raw().end()] == ':')
{
FUNCDEF("jump_to");
string_array pieces;
- filename(sub_path).separate(pieces);
+ bool rooted;
+ filename(sub_path).separate(rooted, pieces);
for (int i = 0; i < pieces.length(); i++) {
filename_tree *curr = dynamic_cast<filename_tree *>(scanning.current());
#ifdef DEBUG_DIRECTORY_TREE
#endif
string_array sub_pieces = pieces.subarray(i, i);
filename curr_path;
- curr_path.join(sub_pieces);
+ curr_path.join(rooted, sub_pieces);
curr_path = filename(curr->_dirname.raw() + filename::default_separator()
+ curr_path.raw());
#ifdef DEBUG_DIRECTORY_TREE
int source_pieces = 0;
{
string_array temp;
- filename(real_source_start).separate(temp);
+ bool rooted_source;
+ filename(real_source_start).separate(rooted_source, temp);
source_pieces = temp.length();
}
#endif
string_array pieces;
- curr.separate(pieces); // get the components of the current location.
+ bool curr_rooted;
+ curr.separate(curr_rooted, pieces); // get the components of the current location.
#ifdef DEBUG_DIRECTORY_TREE
LOG(astring("name in pieces:") + pieces.text_form());
#endif
// snap the root components out of there.
filename corresponding_name;
- corresponding_name.join(pieces);
+//hmmm: is that right decision?
+ corresponding_name.join(false, pieces);
#ifdef DEBUG_DIRECTORY_TREE
LOG(astring("computed target name as: ") + corresponding_name);
#endif
// break up the path into pieces.
pieces.reset();
- adding.separate(pieces);
+ bool rooted;
+ adding.separate(rooted, pieces);
// break up our root into pieces; we must take off components that are
// already in the root.
string_array root_pieces;
+ bool root_rooted;
filename temp_file(path());
- temp_file.separate(root_pieces);
+ temp_file.separate(root_rooted, root_pieces);
// locate the last place where the path we were given touches our tree.
// it could be totally new, partially new, or already contained.
#endif
// handle the case for files now that we have our proper node.
string_array partial_pieces;
- filename(reassembled).separate(partial_pieces);
+ bool partial_rooted;
+ filename(reassembled).separate(partial_rooted, partial_pieces);
int levels_missing = pieces.length() - partial_pieces.length();
// we loop over all the pieces that were missing in between the last
return true;
}
-void filename::separate(string_array &pieces) const
+void filename::separate(bool &rooted, string_array &pieces) const
{
pieces.reset();
const astring &raw_form = raw();
astring accumulator; // holds the names we find.
+ rooted = raw_form.length() && separator(raw_form[0]);
for (int i = 0; i < raw_form.length(); i++) {
if (separator(raw_form[i])) {
// this is a separator character, so eat it and add the accumulated
if (accumulator.length()) pieces += accumulator;
}
-void filename::join(const string_array &pieces)
+void filename::join(bool rooted, const string_array &pieces)
{
astring constructed_name; // we'll make a filename here.
+ if (rooted) constructed_name += DEFAULT_SEPARATOR;
for (int i = 0; i < pieces.length(); i++) {
constructed_name += pieces[i];
if (!i || (i != pieces.length() - 1))
bool filename::base_compare_prefix(const filename &to_compare,
string_array &first, string_array &second)
{
- separate(first);
- to_compare.separate(second);
+ bool first_rooted;
+ separate(first_rooted, first);
+ bool second_rooted;
+ to_compare.separate(second_rooted, second);
+ if (first_rooted != second_rooted) {
+ return false;
+ }
// that case should never be allowed, since there are some bits missing
// in the name to be compared.
if (first.length() > second.length())
bool filename::base_compare_suffix(const filename &to_compare,
string_array &first, string_array &second)
{
- separate(first);
- to_compare.separate(second);
+ bool first_rooted;
+ separate(first_rooted, first);
+ bool second_rooted;
+ to_compare.separate(second_rooted, second);
// that case should never be allowed, since there are some bits missing
// in the name to be compared.
if (first.length() > second.length())
the file to be created or accessed). the "replacement" is used as the
character that is substituted instead of illegal characters. */
- void separate(structures::string_array &pieces) const;
+ void separate(bool &rooted, structures::string_array &pieces) const;
//!< breaks the filename into its component parts.
- /*!< this returns an array containing the component names. the last
- component, unless the filename held is actually a directory, should be the
- name of the file.
-//hmmm: what does this mean, below?
- if the first character is a directory, then the first
- component will be empty. */
-
- void join(const structures::string_array &pieces);
+ /*!< this returns an array containing the component names for the path in
+ this filename object. if the "rooted" flag is set to true, then the path
+ was absolute (i.e. started at '/' in unix. this notion is not needed for
+ dos/windoze, as the first component will be something like 'a:'). */
+
+ void join(bool rooted, const structures::string_array &pieces);
//!< undoes a separate() operation to get the filename back.
/*!< "this" is set to a filename made from each of the "pieces". if there
- are any directory separators inside the pieces, then they will be removed
- by canonicalize(). */
+ are any directory separators inside the pieces themselves, then they will
+ be removed by canonicalize(). if separate() said the path was rooted,
+ then join needs to be told that. */
// these implement the packing functionality.
virtual void pack(basis::byte_array &packed_form) const;
if (byte_start < 0) return BAD_INPUT;
filename targ_name(target);
- if (!directory::recursive_create(targ_name.dirname().raw())) {
+ astring targ_dir = targ_name.dirname().raw();
+#ifdef DEBUG_HEAVY_FILE_OPS
+ LOG(astring("creating target's directory: ") + targ_name.dirname().raw());
+#endif
+ if (!directory::recursive_create(targ_dir)) {
LOG(astring("failed to create directory: ") + targ_name.dirname().raw());
return TARGET_DIR_ERROR;
}
astring GROUP = "separate-- ";
filename turkey("/omega/ralph/turkey/buzzard.txt");
string_array pieces;
- turkey.separate(pieces);
+ bool rooted;
+ turkey.separate(rooted, pieces);
+ ASSERT_TRUE(rooted, GROUP + "the rooted value is erreonous.");
ASSERT_TRUE(pieces[0].equal_to("omega"), GROUP + "the first piece didn't match.");
ASSERT_TRUE(pieces[1].equal_to("ralph"), GROUP + "the second piece didn't match.");
ASSERT_TRUE(pieces[2].equal_to("turkey"), GROUP + "the third piece didn't match.");
astring translate(const astring &source_path) const {
FUNCDEF("translate");
string_array pieces;
- filename(source_path).separate(pieces);
+ bool rooted;
+ filename(source_path).separate(rooted, pieces);
astring source_mapping = pieces[0];
pieces.zap(0, 0); // remove source part.
// get the mapping from the specified location on this side.
filename splitting(req._src_root);
string_array pieces;
- splitting.separate(pieces);
+ bool rooted;
+ splitting.separate(rooted, pieces);
astring source_mapping = pieces[0];
// patch the name up to find the sub_path for the source.
filename source_start;
pieces.zap(0, 0);
- source_start.join(pieces);
+ source_start.join(rooted, pieces);
// locate the allowed transfer depot for the mapping they provided.
file_transfer_record *mapping_record
astring full_file = resp._dest_root + filename::default_separator()
+ recorded_info->secondary();
+LOG(astring("telling it to write to fullfile: ") + full_file);
outcome ret = heavy_file_operations::write_file_chunk(full_file,
found._byte_start, to_write);