blob: 8eae5f369dc4354b4fa875f4f7dc25b57b41c840 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart=2.12
import 'dart:convert';
import 'dart:io' show File;
import 'package:logging/logging.dart';
import 'dump.dart';
import 'sl4f_client.dart';
final _log = Logger('storage');
/// Interact with files in the DUT storage using [Sl4f].
class Storage {
final Sl4f _sl4f;
final Dump _dump;
/// Constructs a [Storage] object.
Storage(this._sl4f, [Dump? dump]) : _dump = dump ?? Dump();
/// Closes the underlying HTTP client. This need not be called if the
/// Sl4f client was provided.
void close() {
_sl4f.close();
}
/// Puts the contents of [file] in [filename] in the DUT.
///
/// Throws a [JsonRpcException] if the SL4F server replied with a non-null
/// error string.
Future<void> putFile(String filename, File file) async {
final bytes = await file.readAsBytes();
return putBytes(filename, bytes);
}
/// Puts [bytes] in [filename] in the DUT.
///
/// Throws a [JsonRpcException] if the SL4F server replied with a non-null
/// error string.
Future<void> putBytes(String filename, List<int> bytes) {
_log.fine('Creating $filename (${bytes.length} bytes).');
return _sl4f.request('file_facade.WriteFile', {
'dst': filename,
'data': base64Encode(bytes),
});
}
/// Reads the contents of file.
///
/// Throws a [JsonRpcException] if the SL4F server replied with a non-null
/// error string, like when the file doesn't exist or can't be read.
Future<List<int>> readFile(String filename) async {
_log.fine('Reading $filename.');
final result =
await _sl4f.request('file_facade.ReadFile', {'path': filename});
return base64.decode(result);
}
/// Dumps the contents of a file to a local file.
///
/// Throws a [JsonRpcException] if the SL4F server replied with a non-null
/// error string, like when the file doesn't exist or can't be read.
Future<File?> dumpFile(
String filename, String dumpName, String extension) async =>
_dump.writeAsBytes(dumpName, extension, await readFile(filename));
/// Deletes a file in the device under test.
///
/// Throws a [JsonRpcException] if the SL4F server replied with a non-null
/// error string. It returns "NotFound" when the file didn't exist to begin
/// with.
Future<String> deleteFile(String filename) async {
_log.fine('Deleting $filename.');
String result =
await _sl4f.request('file_facade.DeleteFile', {'path': filename});
return result;
}
/// Creates a new directory.
///
/// If [recurse] is true, then all parent directories are also created.
/// Throws a [JsonRpcException] if the SL4F server replied with a non-null
/// error string. It returns "AlreadyExists" when the directory already
/// exists.
Future<String> makeDirectory(String path, {bool recurse = false}) async {
_log.fine('Creating directory $path.');
String result = await _sl4f
.request('file_facade.MakeDir', {'path': path, 'recurse': recurse});
return result;
}
Future<Map<String, dynamic>?> stat(String path) async {
_log.fine('Stat\'ing $path.');
final result = await _sl4f.request('file_facade.Stat', {'path': path});
if (result == 'NotFound') {
return null;
}
return result;
}
}