|
11 | 11 | #include <sys/stat.h> // NOLINT
|
12 | 12 |
|
13 | 13 | #include "bin/dartutils.h"
|
| 14 | +#include "bin/crypto.h" |
14 | 15 | #include "bin/file.h"
|
15 | 16 | #include "bin/namespace.h"
|
16 | 17 | #include "bin/utils.h"
|
17 | 18 | #include "bin/utils_win.h"
|
18 | 19 | #include "platform/syslog.h"
|
| 20 | +#include "platform/utils.h" |
19 | 21 |
|
20 | 22 | #undef DeleteFile
|
21 | 23 |
|
@@ -384,12 +386,8 @@ const char* Directory::SystemTemp(Namespace* namespc) {
|
384 | 386 | return path.AsScopedString();
|
385 | 387 | }
|
386 | 388 |
|
387 |
| -const char* Directory::CreateTemp(Namespace* namespc, const char* prefix) { |
388 |
| - // Returns a new, unused directory name, adding characters to the |
389 |
| - // end of prefix. |
390 |
| - // Creates this directory, with a default security |
391 |
| - // descriptor inherited from its parent directory. |
392 |
| - // The return value is Dart_ScopeAllocated. |
| 389 | +// Creates a new temporary directory with a UUID as suffix. |
| 390 | +static const char* CreateTempFromUUID(const char* prefix) { |
393 | 391 | PathBuffer path;
|
394 | 392 | Utf8ToWideScope system_prefix(prefix);
|
395 | 393 | if (!path.AddW(system_prefix.wide())) {
|
@@ -423,6 +421,57 @@ const char* Directory::CreateTemp(Namespace* namespc, const char* prefix) {
|
423 | 421 | return path.AsScopedString();
|
424 | 422 | }
|
425 | 423 |
|
| 424 | +// Creates a new, unused directory, adding characters to the end of prefix, and |
| 425 | +// returns the directory's name. |
| 426 | +// |
| 427 | +// Creates this directory, with a default security descriptor inherited from its |
| 428 | +// parent directory. The return value is Dart_ScopeAllocated. |
| 429 | +// |
| 430 | +// First, attempts appending a suffix created from a random uint32_t. If that |
| 431 | +// name is already taken, falls back on using a UUID for the suffix. |
| 432 | +// |
| 433 | +// Note: More attempts at finding an available short suffix would more reliably |
| 434 | +// avoid a uuid suffix. We choose one attempt here because it is simpler, and |
| 435 | +// to have a small bound on the number of calls to CreateDirectoryW(). |
| 436 | +const char* Directory::CreateTemp(Namespace* namespc, const char* prefix) { |
| 437 | + PathBuffer path; |
| 438 | + Utf8ToWideScope system_prefix(prefix); |
| 439 | + if (!path.AddW(system_prefix.wide())) { |
| 440 | + return NULL; |
| 441 | + } |
| 442 | + |
| 443 | + // Adding 8 hex digits. |
| 444 | + if (path.length() > MAX_LONG_PATH - 8) { |
| 445 | + // No fallback, there won't be enough room for the UUID, either. |
| 446 | + return NULL; |
| 447 | + } |
| 448 | + |
| 449 | + // First try a short suffix using the rng, then if that fails fall back on |
| 450 | + // a uuid. |
| 451 | + uint32_t suffix_bytes = 0; |
| 452 | + const int kSuffixSize = sizeof(suffix_bytes); |
| 453 | + if (!Crypto::GetRandomBytes( |
| 454 | + kSuffixSize, reinterpret_cast<uint8_t*>(&suffix_bytes))) { |
| 455 | + // Getting random bytes failed, maybe the UUID will work? |
| 456 | + return CreateTempFromUUID(prefix); |
| 457 | + } |
| 458 | + |
| 459 | + // Two digits per byte plus null. |
| 460 | + char suffix[kSuffixSize * 2 + 1]; |
| 461 | + Utils::SNPrint(suffix, sizeof(suffix), "%x", suffix_bytes); |
| 462 | + if (!path.Add(suffix)) { |
| 463 | + // Adding to the path failed, maybe because of low-memory. Don't fall back. |
| 464 | + return NULL; |
| 465 | + } |
| 466 | + |
| 467 | + if (!CreateDirectoryW(path.AsStringW(), NULL)) { |
| 468 | + // Creation failed, possibly because an entry with the name already exists. |
| 469 | + // Fall back to using the UUID suffix. |
| 470 | + return CreateTempFromUUID(prefix); |
| 471 | + } |
| 472 | + return path.AsScopedString(); |
| 473 | +} |
| 474 | + |
426 | 475 | bool Directory::Delete(Namespace* namespc,
|
427 | 476 | const char* dir_name,
|
428 | 477 | bool recursive) {
|
|
0 commit comments