diff --git a/common/writeThoughFile.go b/common/writeThoughFile.go index 76cb824e2..2fe184762 100644 --- a/common/writeThoughFile.go +++ b/common/writeThoughFile.go @@ -42,15 +42,28 @@ const PreserveOwnerDefault = true var RootDriveRegex = regexp.MustCompile(`(?i)(^[A-Z]:\/?$)`) var RootShareRegex = regexp.MustCompile(`(^\/\/[^\/]*\/?$)`) +func isRootPath(s string) bool { + shortParentDir := strings.ReplaceAll(ToShortPath(s), OS_PATH_SEPARATOR, AZCOPY_PATH_SEPARATOR_STRING) + return RootDriveRegex.MatchString(shortParentDir) || + RootShareRegex.MatchString(shortParentDir) || + strings.EqualFold(shortParentDir, "/") +} + + func CreateParentDirectoryIfNotExist(destinationPath string, tracker FolderCreationTracker) error { - // find the parent directory - directory := destinationPath[:strings.LastIndex(destinationPath, DeterminePathSeparator(destinationPath))] + // If we're pointing at the root of a drive, don't try because it won't work. + if isRootPath(destinationPath) { + return nil + } + + lastIndex := strings.LastIndex(destinationPath, DeterminePathSeparator(destinationPath)) + directory := destinationPath[:lastIndex] return CreateDirectoryIfNotExist(directory, tracker) } func CreateDirectoryIfNotExist(directory string, tracker FolderCreationTracker) error { // If we're pointing at the root of a drive, don't try because it won't work. - if shortParentDir := strings.ReplaceAll(ToShortPath(directory), OS_PATH_SEPARATOR, AZCOPY_PATH_SEPARATOR_STRING); RootDriveRegex.MatchString(shortParentDir) || RootShareRegex.MatchString(shortParentDir) || strings.EqualFold(shortParentDir, "/") { + if isRootPath(directory) { return nil } diff --git a/testSuite/scripts/test_blob_download.py b/testSuite/scripts/test_blob_download.py index 0e0fa9f3c..24642c1af 100644 --- a/testSuite/scripts/test_blob_download.py +++ b/testSuite/scripts/test_blob_download.py @@ -41,6 +41,29 @@ def test_download_1kb_blob_to_null(self): dst = os.devnull result = util.Command("copy").add_arguments(src).add_arguments(dst).add_flags("log-level", "info") + def test_download_1kb_blob_to_root(self): + # create file of size 1kb + filename = "test_1kb_blob_upload_download_null.txt" + file_path = util.create_test_file(filename, 1024) + + # upload 1kb using azcopy + src = file_path + dst = util.test_container_url + result = util.Command("copy").add_arguments(src).add_arguments(dst). \ + add_flags("log-level", "info").execute_azcopy_copy_command() + self.assertTrue(result) + + # verify the uploaded blob + resource_url = util.get_resource_sas(filename) + result = util.Command("testBlob").add_arguments(file_path).add_arguments(resource_url).execute_azcopy_verify() + self.assertTrue(result) + + # downloading the uploaded blob to devnull + # note we have no tests to verify the success of check-md5. TODO: remove this when fault induction is introduced + src = util.get_resource_sas(filename) + dst = "/" + result = util.Command("copy").add_arguments(src).add_arguments(dst).add_flags("log-level", "info") + # test_download_1kb_blob verifies the download of 1Kb blob using azcopy. def test_download_1kb_blob(self): # create file of size 1KB.