blob: 18fa83bc31fd9cf9bf25b60dca0c44edc6567e26 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/file_utils/file_util.h"
#include <stdint.h>
#include "mojo/services/files/interfaces/types.mojom.h"
namespace file_utils {
mojo::InterfaceHandle<mojo::files::File> CreateTemporaryFileInDir(
mojo::SynchronousInterfacePtr<mojo::files::Directory>* directory,
std::string* path_name) {
std::string internal_path_name;
const std::string charset("abcdefghijklmnopqrstuvwxyz1234567890");
const unsigned kSuffixLength = 6;
const unsigned kMaxNumAttempts = 10;
mojo::InterfaceHandle<mojo::files::File> temp_file;
mojo::files::Error error = mojo::files::Error::INTERNAL;
uint64_t random_value = 0;
for (unsigned attempt = 0; attempt < kMaxNumAttempts; attempt++) {
internal_path_name = ".org.chromium.Mojo.";
uint64_t microseconds = static_cast<uint64_t>(MojoGetTimeTicksNow());
for (unsigned i = 0; i < kSuffixLength; i++) {
// This roughly matches glibc's mapping from time to "random_time_bits",
// it seems to be good enough for creating temporary files.
random_value += (microseconds << 16) ^ (microseconds / 1000000);
internal_path_name.push_back(charset[random_value % charset.length()]);
}
if (!(*directory)
->OpenFile(internal_path_name, GetProxy(&temp_file),
mojo::files::kOpenFlagWrite |
mojo::files::kOpenFlagRead |
mojo::files::kOpenFlagCreate |
mojo::files::kOpenFlagExclusive,
&error))
return nullptr;
// TODO(smklein): React to error code when ErrnoToError can return something
// other than Error::UNKNOWN. We only want to retry when "EEXIST" is thrown.
if (error == mojo::files::Error::OK) {
*path_name = internal_path_name;
return temp_file;
}
}
return nullptr;
}
} // namespace file_utils