From 70e3fc16addf0517ff8ef8ef1e9bcd6dee2a440f Mon Sep 17 00:00:00 2001 From: Alain94W Date: Sun, 8 Dec 2019 19:09:25 +0100 Subject: [PATCH 1/4] Added backup functions, device status (recovery,device,fastboot), folder or partition size info --- src/adb.js | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/src/adb.js b/src/adb.js index ef4d66a..23ea994 100644 --- a/src/adb.js +++ b/src/adb.js @@ -32,11 +32,23 @@ const DEFAULT_EXEC = (args, callback) => { callback ); }; + +// AW : Allow execution of custom command, not only adb +const DEFAULT_CUTOMEXEC = (args, callback) => { + exec( + [""].concat(args).join(" "), + { options: { maxBuffer: 1024 * 1024 * 2 } }, + callback + ); +}; + const DEFAULT_LOG = console.log; const DEFAULT_PORT = 5037; class Adb { constructor(options) { + // AW : custom command execution + this.execCustom = DEFAULT_CUTOMEXEC; this.exec = DEFAULT_EXEC; this.log = DEFAULT_LOG; this.port = DEFAULT_PORT; @@ -82,6 +94,32 @@ class Adb { }); } + // AW : Cutsom Command Execution + execCommandCustom(args) { + var _this = this; + return new Promise(function(resolve, reject) { + _this.execCustom([""].concat(args), (error, stdout, stderr) => { + if (error) { + reject( + common.handleError( + error, + stdout, + stderr ? stderr.trim() : undefined + ) + ); + } else if (stdout) { + if (stdout.includes("no permissions")) { + reject("no permissions"); + } else { + resolve(stdout.trim()); + } + } else { + resolve(); + } + }); + }); + } + // Kill all adb servers and start a new one to rule them all startServer() { var _this = this; @@ -487,6 +525,134 @@ class Adb { ); }); } + + // AW : return the file size of a complete folder + getFileSize(file) { + var _this = this; + return new Promise(function(resolve, reject) { + _this.getAdbState().then((stdout)=>{ + if (stdout == 1) { // Recovery + _this.shell('du -shk '+file).then( (stdout)=>{ + stdout = parseFloat(stdout); + _this.log("FileSize is "+stdout+ " Ko"); + resolve(stdout); + }).catch (reject); + } + else if (stdout == 2) { // device (type : used, size) + _this.shell('df -hBK '+file+' --output=used|tail -n1').then( (stdout)=>{ + stdout = parseFloat(stdout); + _this.log("FileSize is "+stdout+ " Ko"); + resolve(stdout); + }).catch (reject); + } + }); + }).catch (e=>{_this.log(e); reject;}); + } + + // AW : Return the status of the device (0 : bootloader, 1 : recovery, 2 : device ...) + getAdbState() { + var _this = this; + return new Promise(function(resolve, reject) { + _this.execCommand(["get-state"]).then( (stdout)=>{ + _this.log("Device state is "+stdout); + switch (stdout) { + case "device" : resolve(2); + case "bootloader" : resolve(0); + case "recovery" : resolve(1); + default : resolve(3); // Unknown + } + }).catch (e=>{ + // Try with recovery command + _this.log("Unknown error :"+e); + reject + }); + }); + } + +// AW : Backup file "srcfile" from the phone to "destfile" localy +// TO-DO : This function should be moved to devices.js + backup(srcfile,destfile, adbpath, progress) { + var _this = this; + _this.log("Backup Function Entry, will backup "+srcfile+" to "+destfile+" adbpath:"+adbpath); + return new Promise(function(resolve, reject) { + _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. + // Get file size + _this.getFileSize(srcfile).then(stdout=>{ + _this.log("Returned FileSize is "+stdout+ " Ko"); + _this.fileSize = stdout; + // Creating pipe + _this.shell("mkfifo /backup.pipe").then((stdout) => { + _this.log("Pipe created !"); + var lastSize = 0; + var progressInterval = setInterval(() => { + _this.execCommandCustom(["stat", "-t", destfile]).then(stat => { + progress ((lastSize / _this.fileSize)*100); + lastSize = eval(stat.split(" ")[1])/1024; + //_this.log("pushing: " + lastSize+"/"+_this.fileSize); + }).catch(e => { clearInterval(progressInterval);_this.log("failed to stat: " + e); + }); + }, 1000); + + // Start the backup + _this.log("Starting Backup..."); + _this.execCommand(["exec-out 'tar -cvp ",srcfile," 2>/backup.pipe' | dd of="+destfile, + " & ",(adbpath+"/adb -P"),_this.port, + " shell cat /backup.pipe", process.platform == "win32" ? ' | findstr /v "%]"' : ' | grep -v "%]"']).then( (error, stdout, stderr) => { + _this.log("Backup Ended"); + clearInterval(progressInterval); + _this.shell("rm /backup.pipe").then( ()=> { + _this.log("Pipe released."); + resolve(); // Everything's Fine ! + }).catch(e=>{utils.log.warn; reject(e+" Unable to delete the pipe "+e.length);}); // Pipe Deletion + }).catch(e=>{utils.log.warn; reject(e+" Unable to backuping the device "+e.length);}); // Backup start + }).catch(e=>{utils.log.warn; reject(e+" Pipe creation failed "+e.length);}); // Pipe Creation + }).catch(e=>{utils.log.warn; reject(e+" Unable to get the partition's filesize "+e.length);}); // Get file size + }); + } + + +// AW : Restore file "srcfile" from the computer to "destfile" on the phone +// TO-DO : This function should be moved to devices.js + restore(srcfile,destfile, adbpath, progress) { + var _this = this; + _this.log("Restore Function Entry, will restore "+srcfile+" on "+destfile+" adbpath:"+adbpath); + return new Promise(function(resolve, reject) { + _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. + // Get file size + _this.getFileSize(srcfile).then(stdout=>{ + _this.log("Returned FileSize is "+stdout+ " Ko"); + _this.fileSize = stdout; + // Creating pipe + _this.shell("mkfifo /restore.pipe").then((stdout) => { + _this.log("Pipe created !"); + var lastSize = 0; + var progressInterval = setInterval(() => { + _this.execCommandCustom(["stat", "-t", destfile]).then(stat => { + progress ((lastSize / _this.fileSize)*100); + lastSize = eval(stat.split(" ")[1])/1024; + //_this.log("pushing: " + lastSize+"/"+_this.fileSize); + }).catch(e => { clearInterval(progressInterval);_this.log("failed to stat: " + e); + }); + }, 1000); + + // Start the restoration + _this.log("Starting Restore..."); //adb push user.tar /resto.pipe & adb shell 'cd /; cat /resto.pipe | tar -xv' + _this.execCommand(["push",srcfile,"/resto.pipe &", + (adbpath+"/adb -P"),_this.port, + " shell 'cd /; cat /resto.pipe | tar -xv'"]).then( (error, stdout, stderr) => { + _this.log("Restore Ended"); + clearInterval(progressInterval); + _this.shell("rm /resotre.pipe").then( ()=> { + _this.log("Pipe released."); + resolve(); // Everything's Fine ! + }).catch(e=>{utils.log.warn; reject("Unable to delete the pipe "+e);}); // Pipe Deletion + }).catch(e=>{utils.log.warn; reject("Unable to restore the backup "+e);}); // Backup start + }).catch(e=>{utils.log.warn; reject("Pipe creation failed "+e);}); // Pipe Creation + }).catch(e=>{utils.log.warn; reject("Unable to get the partition's filesize "+e);}); // Get file size + }); + } + + } module.exports = Adb; From 15bc51b01d286b2f6023a726572ee6c92466251f Mon Sep 17 00:00:00 2001 From: Alain94W Date: Mon, 9 Dec 2019 17:53:04 +0100 Subject: [PATCH 2/4] modifying backup and restore functions according to the remarks of NeoTheThird, removed customcommandexec --- src/adb.js | 333 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 191 insertions(+), 142 deletions(-) diff --git a/src/adb.js b/src/adb.js index 23ea994..6733ceb 100644 --- a/src/adb.js +++ b/src/adb.js @@ -33,22 +33,11 @@ const DEFAULT_EXEC = (args, callback) => { ); }; -// AW : Allow execution of custom command, not only adb -const DEFAULT_CUTOMEXEC = (args, callback) => { - exec( - [""].concat(args).join(" "), - { options: { maxBuffer: 1024 * 1024 * 2 } }, - callback - ); -}; - const DEFAULT_LOG = console.log; const DEFAULT_PORT = 5037; class Adb { constructor(options) { - // AW : custom command execution - this.execCustom = DEFAULT_CUTOMEXEC; this.exec = DEFAULT_EXEC; this.log = DEFAULT_LOG; this.port = DEFAULT_PORT; @@ -94,32 +83,6 @@ class Adb { }); } - // AW : Cutsom Command Execution - execCommandCustom(args) { - var _this = this; - return new Promise(function(resolve, reject) { - _this.execCustom([""].concat(args), (error, stdout, stderr) => { - if (error) { - reject( - common.handleError( - error, - stdout, - stderr ? stderr.trim() : undefined - ) - ); - } else if (stdout) { - if (stdout.includes("no permissions")) { - reject("no permissions"); - } else { - resolve(stdout.trim()); - } - } else { - resolve(); - } - }); - }); - } - // Kill all adb servers and start a new one to rule them all startServer() { var _this = this; @@ -527,132 +490,218 @@ class Adb { } // AW : return the file size of a complete folder - getFileSize(file) { - var _this = this; - return new Promise(function(resolve, reject) { - _this.getAdbState().then((stdout)=>{ - if (stdout == 1) { // Recovery - _this.shell('du -shk '+file).then( (stdout)=>{ - stdout = parseFloat(stdout); - _this.log("FileSize is "+stdout+ " Ko"); - resolve(stdout); - }).catch (reject); - } - else if (stdout == 2) { // device (type : used, size) - _this.shell('df -hBK '+file+' --output=used|tail -n1').then( (stdout)=>{ - stdout = parseFloat(stdout); - _this.log("FileSize is "+stdout+ " Ko"); - resolve(stdout); - }).catch (reject); - } - }); - }).catch (e=>{_this.log(e); reject;}); - } + getFileSize(file) { + var _this = this; + return new Promise(function(resolve, reject) { + _this.getAdbState().then(stdout => { + if (stdout == 1) { + // Recovery + _this + .shell("du -shk " + file) + .then(stdout => { + stdout = parseFloat(stdout); + _this.log("FileSize is " + stdout + " Ko"); + resolve(stdout); + }) + .catch(reject); + } else if (stdout == 2) { + // device (type : used, size) + _this + .shell("df -hBK " + file + " --output=used|tail -n1") + .then(stdout => { + stdout = parseFloat(stdout); + _this.log("FileSize is " + stdout + " Ko"); + resolve(stdout); + }) + .catch(reject); + } + }); + }).catch(e => { + _this.log(e); + reject; + }); + } // AW : Return the status of the device (0 : bootloader, 1 : recovery, 2 : device ...) - getAdbState() { - var _this = this; - return new Promise(function(resolve, reject) { - _this.execCommand(["get-state"]).then( (stdout)=>{ - _this.log("Device state is "+stdout); - switch (stdout) { - case "device" : resolve(2); - case "bootloader" : resolve(0); - case "recovery" : resolve(1); - default : resolve(3); // Unknown - } - }).catch (e=>{ + getAdbState() { + var _this = this; + return new Promise(function(resolve, reject) { + _this + .execCommand(["get-state"]) + .then(stdout => { + _this.log("Device state is " + stdout); + switch (stdout) { + case "device": + resolve(2); + case "bootloader": + resolve(0); + case "recovery": + resolve(1); + default: + resolve(3); // Unknown + } + }) + .catch(e => { // Try with recovery command - _this.log("Unknown error :"+e); - reject - }); - }); - } - -// AW : Backup file "srcfile" from the phone to "destfile" localy -// TO-DO : This function should be moved to devices.js - backup(srcfile,destfile, adbpath, progress) { + _this.log("Unknown error :" + e); + reject; + }); + }); + } + + // AW : Backup file "srcfile" from the phone to "destfile" localy + // TO-DO : This function should be moved to devices.js + backupremote(srcfile, destfile, adbpath, progress) { var _this = this; - _this.log("Backup Function Entry, will backup "+srcfile+" to "+destfile+" adbpath:"+adbpath); + _this.log( + "Backup Function Entry, will backup " + + srcfile + + " to " + + destfile + + " adbpath:" + + adbpath + ); return new Promise(function(resolve, reject) { - _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. - // Get file size - _this.getFileSize(srcfile).then(stdout=>{ - _this.log("Returned FileSize is "+stdout+ " Ko"); - _this.fileSize = stdout; - // Creating pipe - _this.shell("mkfifo /backup.pipe").then((stdout) => { + _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. + // Get file size + _this + .getFileSize(srcfile) + .then(stdout => { + _this.log("Returned FileSize is " + stdout + " Ko"); + _this.fileSize = stdout; + // Creating pipe + _this + .shell("mkfifo /backup.pipe") + .then(stdout => { _this.log("Pipe created !"); var lastSize = 0; var progressInterval = setInterval(() => { - _this.execCommandCustom(["stat", "-t", destfile]).then(stat => { - progress ((lastSize / _this.fileSize)*100); - lastSize = eval(stat.split(" ")[1])/1024; - //_this.log("pushing: " + lastSize+"/"+_this.fileSize); - }).catch(e => { clearInterval(progressInterval);_this.log("failed to stat: " + e); - }); + const stats = fs.statSync(destfile); + const fileSizeInBytes = stats.size; + progress((lastSize / _this.fileSize) * 100); + lastSize = fileSizeInBytes / 1024; }, 1000); // Start the backup _this.log("Starting Backup..."); - _this.execCommand(["exec-out 'tar -cvp ",srcfile," 2>/backup.pipe' | dd of="+destfile, - " & ",(adbpath+"/adb -P"),_this.port, - " shell cat /backup.pipe", process.platform == "win32" ? ' | findstr /v "%]"' : ' | grep -v "%]"']).then( (error, stdout, stderr) => { - _this.log("Backup Ended"); - clearInterval(progressInterval); - _this.shell("rm /backup.pipe").then( ()=> { - _this.log("Pipe released."); - resolve(); // Everything's Fine ! - }).catch(e=>{utils.log.warn; reject(e+" Unable to delete the pipe "+e.length);}); // Pipe Deletion - }).catch(e=>{utils.log.warn; reject(e+" Unable to backuping the device "+e.length);}); // Backup start - }).catch(e=>{utils.log.warn; reject(e+" Pipe creation failed "+e.length);}); // Pipe Creation - }).catch(e=>{utils.log.warn; reject(e+" Unable to get the partition's filesize "+e.length);}); // Get file size - }); - } - - -// AW : Restore file "srcfile" from the computer to "destfile" on the phone -// TO-DO : This function should be moved to devices.js - restore(srcfile,destfile, adbpath, progress) { + _this + .execCommand([ + "exec-out 'tar -cvp ", + srcfile, + " 2>/backup.pipe' | dd of=" + destfile, + " & ", + adbpath + "/adb -P", + _this.port, + " shell cat /backup.pipe", + process.platform == "win32" + ? ' | findstr /v "%]"' + : ' | grep -v "%]"' + ]) + .then((error, stdout, stderr) => { + _this.log("Backup Ended"); + clearInterval(progressInterval); + _this + .shell("rm /backup.pipe") + .then(() => { + _this.log("Pipe released."); + resolve(); // Everything's Fine ! + }) + .catch(e => { + utils.log.warn; + reject(e + " Unable to delete the pipe " + e.length); + }); // Pipe Deletion + }) + .catch(e => { + utils.log.warn; + reject(e + " Unable to backuping the device " + e.length); + }); // Backup start + }) + .catch(e => { + utils.log.warn; + reject(e + " Pipe creation failed " + e.length); + }); // Pipe Creation + }) + .catch(e => { + utils.log.warn; + reject(e + " Unable to get the partition's filesize " + e.length); + }); // Get file size + }); + } + + // AW : Restore file "srcfile" from the computer to "destfile" on the phone + // TO-DO : This function should be moved to devices.js + restoreremote(srcfile, destfile, adbpath, progress) { var _this = this; - _this.log("Restore Function Entry, will restore "+srcfile+" on "+destfile+" adbpath:"+adbpath); + _this.log( + "Restore Function Entry, will restore " + + srcfile + + " on " + + destfile + + " adbpath:" + + adbpath + ); return new Promise(function(resolve, reject) { - _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. - // Get file size - _this.getFileSize(srcfile).then(stdout=>{ - _this.log("Returned FileSize is "+stdout+ " Ko"); - _this.fileSize = stdout; - // Creating pipe - _this.shell("mkfifo /restore.pipe").then((stdout) => { + _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. + // Get file size + _this + .getFileSize(srcfile) + .then(stdout => { + _this.log("Returned FileSize is " + stdout + " Ko"); + _this.fileSize = stdout; + // Creating pipe + _this + .shell("mkfifo /restore.pipe") + .then(stdout => { _this.log("Pipe created !"); var lastSize = 0; var progressInterval = setInterval(() => { - _this.execCommandCustom(["stat", "-t", destfile]).then(stat => { - progress ((lastSize / _this.fileSize)*100); - lastSize = eval(stat.split(" ")[1])/1024; - //_this.log("pushing: " + lastSize+"/"+_this.fileSize); - }).catch(e => { clearInterval(progressInterval);_this.log("failed to stat: " + e); - }); + const stats = fs.statSync(destfile); + const fileSizeInBytes = stats.size; + progress((lastSize / _this.fileSize) * 100); + lastSize = fileSizeInBytes / 1024; }, 1000); // Start the restoration _this.log("Starting Restore..."); //adb push user.tar /resto.pipe & adb shell 'cd /; cat /resto.pipe | tar -xv' - _this.execCommand(["push",srcfile,"/resto.pipe &", - (adbpath+"/adb -P"),_this.port, - " shell 'cd /; cat /resto.pipe | tar -xv'"]).then( (error, stdout, stderr) => { - _this.log("Restore Ended"); - clearInterval(progressInterval); - _this.shell("rm /resotre.pipe").then( ()=> { - _this.log("Pipe released."); - resolve(); // Everything's Fine ! - }).catch(e=>{utils.log.warn; reject("Unable to delete the pipe "+e);}); // Pipe Deletion - }).catch(e=>{utils.log.warn; reject("Unable to restore the backup "+e);}); // Backup start - }).catch(e=>{utils.log.warn; reject("Pipe creation failed "+e);}); // Pipe Creation - }).catch(e=>{utils.log.warn; reject("Unable to get the partition's filesize "+e);}); // Get file size - }); - } - - + _this + .execCommand([ + "push", + srcfile, + "/resto.pipe &", + adbpath + "/adb -P", + _this.port, + " shell 'cd /; cat /resto.pipe | tar -xv'" + ]) + .then((error, stdout, stderr) => { + _this.log("Restore Ended"); + clearInterval(progressInterval); + _this + .shell("rm /restore.pipe") + .then(() => { + _this.log("Pipe released."); + resolve(); // Everything's Fine ! + }) + .catch(e => { + utils.log.warn; + reject("Unable to delete the pipe " + e); + }); // Pipe Deletion + }) + .catch(e => { + utils.log.warn; + reject("Unable to restore the backup " + e); + }); // Backup start + }) + .catch(e => { + utils.log.warn; + reject("Pipe creation failed " + e); + }); // Pipe Creation + }) + .catch(e => { + utils.log.warn; + reject("Unable to get the partition's filesize " + e); + }); // Get file size + }); + } } module.exports = Adb; From ba90fec1fd54d0d5f928fc4ab3c261b9ed7f0a52 Mon Sep 17 00:00:00 2001 From: Alain94W Date: Sun, 29 Dec 2019 19:09:54 +0100 Subject: [PATCH 3/4] Added functions(getOSName), functions renamed (backup,restore) --- src/adb.js | 349 +++++++++++++++++++++++++---------------------------- 1 file changed, 166 insertions(+), 183 deletions(-) diff --git a/src/adb.js b/src/adb.js index 6733ceb..63a0c53 100644 --- a/src/adb.js +++ b/src/adb.js @@ -333,6 +333,30 @@ class Adb { }); } + // Get OS name + getOsName() { + var _this = this; + return new Promise(function(resolve, reject) { + _this + .shell(["cat", "/etc/system-image/channel.ini","|grep tag="]) + .then(stdout => { + if (stdout) { + resolve( + stdout + .split(",") + .filter(p => p.includes("tag="))[0] + .replace("tag=", "") + .trim() + ); + } else { + reject(new Error("failed to cat default.prop: no response")); + } + + }) + .catch(e => reject(new Error("getprop error: " + e))); + }); + } + // Find out what operating system the device is running (currently android and ubuntu touch) getOs() { return this.shell(["cat", "/etc/system-image/channel.ini"]).then(stdout => { @@ -489,219 +513,178 @@ class Adb { }); } - // AW : return the file size of a complete folder + // Return the file size of a complete folder getFileSize(file) { - var _this = this; - return new Promise(function(resolve, reject) { - _this.getAdbState().then(stdout => { - if (stdout == 1) { + return this.getState().then(stdout => { + if (stdout == "recovery") { // Recovery - _this + return this .shell("du -shk " + file) .then(stdout => { stdout = parseFloat(stdout); - _this.log("FileSize is " + stdout + " Ko"); - resolve(stdout); - }) - .catch(reject); - } else if (stdout == 2) { - // device (type : used, size) - _this - .shell("df -hBK " + file + " --output=used|tail -n1") + this.log("FileSize is " + stdout + " Ko"); + return (stdout); + }).catch(e=>{throw new Error(e)}); + } else if (stdout == "device") { + // Device + return this + .shell("du -shk " + file+ " |tail -n1")// + " --output=used|tail -n1")//df -hBK .then(stdout => { stdout = parseFloat(stdout); - _this.log("FileSize is " + stdout + " Ko"); - resolve(stdout); - }) - .catch(reject); + this.log("FileSize is " + stdout + " Ko"); + return (stdout); + }).catch(e=>{throw new Error(e)}); } - }); }).catch(e => { - _this.log(e); - reject; + throw new Error("Unable to get filesize"); }); } - // AW : Return the status of the device (0 : bootloader, 1 : recovery, 2 : device ...) - getAdbState() { - var _this = this; - return new Promise(function(resolve, reject) { - _this - .execCommand(["get-state"]) - .then(stdout => { - _this.log("Device state is " + stdout); - switch (stdout) { - case "device": - resolve(2); - case "bootloader": - resolve(0); - case "recovery": - resolve(1); - default: - resolve(3); // Unknown - } - }) - .catch(e => { - // Try with recovery command - _this.log("Unknown error :" + e); - reject; - }); + // Return the available size of a partition + getAvailableSize(partition) { + return this.getState().then(stdout => { + if (stdout == "recovery") { + // Recovery + throw new Error("You must be in device mode"); + } else if (stdout == "device") { + // Device + return this + .shell("df -hBK " + partition + " --output=avail|tail -n1") + .then(stdout => { + stdout = parseFloat(stdout); + this.log("FileSize available is " + stdout + " Ko"); + return (stdout); + }).catch(e=>{throw new Error(e)}); + } + }).catch(e => { + throw new Error("Unable to get filesize"); + }); + } + + // Return the total size of a partition + getTotalSize(partition) { + return this.getState().then(stdout => { + if (stdout == "recovery") { + // Recovery + throw new Error("You must be in device mode"); + } else if (stdout == "device") { + // Device + return this + .shell("df -hBK " + partition + " --output=size|tail -n1") + .then(stdout => { + stdout = parseFloat(stdout); + this.log("FileSize total is " + stdout + " Ko"); + return (stdout); + }).catch(e=>{throw new Error(e)}); + } + }).catch(e => { + throw new Error("Unable to get filesize"); }); } - // AW : Backup file "srcfile" from the phone to "destfile" localy - // TO-DO : This function should be moved to devices.js - backupremote(srcfile, destfile, adbpath, progress) { + // Return the status of the device (bootloader, recovery, device) + getState() { + + return this.execCommand(["get-state"]).then( (stdout)=>{ + this.log("Device state is "+stdout); + return stdout; + }).catch (e=>{ + this.log("Unknown error :"+e); + throw e; + }); + } + +// Backup file "srcfile" from the phone to "destfile" localy + createRemoteUbuntuBackup(srcfile,destfile,adbpath, progress) { var _this = this; - _this.log( - "Backup Function Entry, will backup " + - srcfile + - " to " + - destfile + - " adbpath:" + - adbpath - ); + _this.log("Backup Function Entry, will backup "+srcfile+" to "+destfile+" adbpath:"+adbpath); return new Promise(function(resolve, reject) { - _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. - // Get file size - _this - .getFileSize(srcfile) - .then(stdout => { - _this.log("Returned FileSize is " + stdout + " Ko"); - _this.fileSize = stdout; - // Creating pipe - _this - .shell("mkfifo /backup.pipe") - .then(stdout => { + _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. + // Get file size + _this.getFileSize(srcfile).then(stdout=>{ + _this.log("Returned FileSize is "+stdout+ " Ko"); + _this.fileSize = stdout; + // Creating pipe + _this.shell("mkfifo /backup.pipe").then((stdout) => { _this.log("Pipe created !"); var lastSize = 0; var progressInterval = setInterval(() => { - const stats = fs.statSync(destfile); - const fileSizeInBytes = stats.size; - progress((lastSize / _this.fileSize) * 100); - lastSize = fileSizeInBytes / 1024; + const stats = fs.statSync(destfile); + const fileSizeInBytes = stats.size; + progress ((lastSize / _this.fileSize)*100); + lastSize = fileSizeInBytes/1024; }, 1000); // Start the backup _this.log("Starting Backup..."); - _this - .execCommand([ - "exec-out 'tar -cvp ", - srcfile, - " 2>/backup.pipe' | dd of=" + destfile, - " & ", - adbpath + "/adb -P", - _this.port, - " shell cat /backup.pipe", - process.platform == "win32" - ? ' | findstr /v "%]"' - : ' | grep -v "%]"' - ]) - .then((error, stdout, stderr) => { - _this.log("Backup Ended"); - clearInterval(progressInterval); - _this - .shell("rm /backup.pipe") - .then(() => { - _this.log("Pipe released."); - resolve(); // Everything's Fine ! - }) - .catch(e => { - utils.log.warn; - reject(e + " Unable to delete the pipe " + e.length); - }); // Pipe Deletion - }) - .catch(e => { - utils.log.warn; - reject(e + " Unable to backuping the device " + e.length); - }); // Backup start - }) - .catch(e => { - utils.log.warn; - reject(e + " Pipe creation failed " + e.length); - }); // Pipe Creation - }) - .catch(e => { - utils.log.warn; - reject(e + " Unable to get the partition's filesize " + e.length); - }); // Get file size - }); - } - - // AW : Restore file "srcfile" from the computer to "destfile" on the phone - // TO-DO : This function should be moved to devices.js - restoreremote(srcfile, destfile, adbpath, progress) { + _this.execCommand(["exec-out 'tar -cvp ",srcfile," 2>/backup.pipe' | dd of="+destfile]); + //_this.execCommand(["exec-out 'tar -cvp ",srcfile," 2>/backup.pipe' | dd of="+destfile, + // " & ",(adbpath+"/adb -P"),_this.port, + _this.execCommand([" shell cat /backup.pipe", + common.stdoutFilter("%]")]).then( (error, stdout, stderr) => {//process.platform == "win32" ? ' | findstr /v "%]"' : ' | grep -v "%]"'] + _this.log("Backup Ended"); + clearInterval(progressInterval); + _this.shell("rm /backup.pipe").then( ()=> { + _this.log("Pipe released."); + resolve(); // Everything's Fine ! + }).catch(e=>{reject(e+", Unable to delete the pipe ");}); // Pipe Deletion + }).catch(e=>{reject(e+", Unable to backuping the device ");}); // Backup start + }).catch(e=>{reject(e+", Pipe creation failed ");}); // Pipe Creation + }).catch(e=>{reject(e+", Unable to get the partition's filesize ");}); // Get file size + }); + } + + +// Restore file "srcfile" from the computer to "destfile" on the phone + applyRemoteUbuntuBackup(destfile,srcfile, adbpath,bckSize, progress) { var _this = this; - _this.log( - "Restore Function Entry, will restore " + - srcfile + - " on " + - destfile + - " adbpath:" + - adbpath - ); + _this.log("Restore Function Entry, will restore "+srcfile+" on "+destfile+" adbpath:"+adbpath); return new Promise(function(resolve, reject) { - _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. - // Get file size - _this - .getFileSize(srcfile) - .then(stdout => { - _this.log("Returned FileSize is " + stdout + " Ko"); - _this.fileSize = stdout; - // Creating pipe - _this - .shell("mkfifo /restore.pipe") - .then(stdout => { + _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. + + + // Creating pipe + _this.shell("mkfifo /restore.pipe").then((stdout) => { _this.log("Pipe created !"); - var lastSize = 0; - var progressInterval = setInterval(() => { - const stats = fs.statSync(destfile); - const fileSizeInBytes = stats.size; - progress((lastSize / _this.fileSize) * 100); - lastSize = fileSizeInBytes / 1024; - }, 1000); +/* + var lastSize = 0; + _this.fileSize = bckSize; + var progressInterval = setInterval(() => { + _this + .shell([ + "stat", + "-t", + common.quotepath("/restore.pipe") + ]) + .then(stat => { + + lastSize = eval(stat.split(" ")[1]); + progress ((lastSize / _this.fileSize)*100); + //lastSize = fileSizeInBytes/1024; + }) + .catch(e => { + clearInterval(progressInterval); + _this.log("failed to stat: " + e); + }); + }, 1000); + */ // Start the restoration _this.log("Starting Restore..."); //adb push user.tar /resto.pipe & adb shell 'cd /; cat /resto.pipe | tar -xv' - _this - .execCommand([ - "push", - srcfile, - "/resto.pipe &", - adbpath + "/adb -P", - _this.port, - " shell 'cd /; cat /resto.pipe | tar -xv'" - ]) - .then((error, stdout, stderr) => { - _this.log("Restore Ended"); - clearInterval(progressInterval); - _this - .shell("rm /restore.pipe") - .then(() => { - _this.log("Pipe released."); - resolve(); // Everything's Fine ! - }) - .catch(e => { - utils.log.warn; - reject("Unable to delete the pipe " + e); - }); // Pipe Deletion - }) - .catch(e => { - utils.log.warn; - reject("Unable to restore the backup " + e); - }); // Backup start - }) - .catch(e => { - utils.log.warn; - reject("Pipe creation failed " + e); - }); // Pipe Creation - }) - .catch(e => { - utils.log.warn; - reject("Unable to get the partition's filesize " + e); - }); // Get file size - }); - } + _this.execCommand(["push",srcfile,"/restore.pipe &", + (adbpath+"/adb -P"),_this.port, + " shell 'cd /; cat /restore.pipe | tar -xv'"]).then( (error, stdout, stderr) => { + _this.log("Restore Ended"); + //clearInterval(progressInterval); + _this.shell("rm /restore.pipe").then( ()=> { + _this.log("Pipe released."); + resolve(); // Everything's Fine ! + }).catch(e=>{reject(e);}); // Pipe Deletion + }).catch(e=>{reject(e);}); // Backup start + }).catch(e=>{reject(e);}); // Pipe Creation + }); + } + } module.exports = Adb; From bde3c06d2ed1638c283fee57caf75612c7ba996d Mon Sep 17 00:00:00 2001 From: Alain94W Date: Sun, 29 Dec 2019 20:17:35 +0100 Subject: [PATCH 4/4] Added functions(getOSName), functions renamed (backup,restore), corrected with lint-fix --- src/adb.js | 288 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 180 insertions(+), 108 deletions(-) diff --git a/src/adb.js b/src/adb.js index 63a0c53..80c6a76 100644 --- a/src/adb.js +++ b/src/adb.js @@ -338,20 +338,19 @@ class Adb { var _this = this; return new Promise(function(resolve, reject) { _this - .shell(["cat", "/etc/system-image/channel.ini","|grep tag="]) + .shell(["cat", "/etc/system-image/channel.ini", "|grep tag="]) .then(stdout => { - if (stdout) { - resolve( - stdout - .split(",") - .filter(p => p.includes("tag="))[0] - .replace("tag=", "") - .trim() - ); - } else { - reject(new Error("failed to cat default.prop: no response")); - } - + if (stdout) { + resolve( + stdout + .split(",") + .filter(p => p.includes("tag="))[0] + .replace("tag=", "") + .trim() + ); + } else { + reject(new Error("failed to cat default.prop: no response")); + } }) .catch(e => reject(new Error("getprop error: " + e))); }); @@ -515,138 +514,194 @@ class Adb { // Return the file size of a complete folder getFileSize(file) { - return this.getState().then(stdout => { + return this.getState() + .then(stdout => { if (stdout == "recovery") { // Recovery - return this - .shell("du -shk " + file) + return this.shell("du -shk " + file) .then(stdout => { stdout = parseFloat(stdout); this.log("FileSize is " + stdout + " Ko"); - return (stdout); - }).catch(e=>{throw new Error(e)}); + return stdout; + }) + .catch(e => { + throw new Error(e); + }); } else if (stdout == "device") { // Device - return this - .shell("du -shk " + file+ " |tail -n1")// + " --output=used|tail -n1")//df -hBK + return this.shell("du -shk " + file + " |tail -n1") // + " --output=used|tail -n1")//df -hBK .then(stdout => { stdout = parseFloat(stdout); this.log("FileSize is " + stdout + " Ko"); - return (stdout); - }).catch(e=>{throw new Error(e)}); + return stdout; + }) + .catch(e => { + throw new Error(e); + }); } - }).catch(e => { - throw new Error("Unable to get filesize"); - }); + }) + .catch(e => { + throw new Error("Unable to get filesize"); + }); } // Return the available size of a partition getAvailableSize(partition) { - return this.getState().then(stdout => { + return this.getState() + .then(stdout => { if (stdout == "recovery") { // Recovery throw new Error("You must be in device mode"); } else if (stdout == "device") { // Device - return this - .shell("df -hBK " + partition + " --output=avail|tail -n1") + return this.shell("df -hBK " + partition + " --output=avail|tail -n1") .then(stdout => { stdout = parseFloat(stdout); this.log("FileSize available is " + stdout + " Ko"); - return (stdout); - }).catch(e=>{throw new Error(e)}); + return stdout; + }) + .catch(e => { + throw new Error(e); + }); } - }).catch(e => { - throw new Error("Unable to get filesize"); - }); + }) + .catch(e => { + throw new Error("Unable to get filesize"); + }); } // Return the total size of a partition getTotalSize(partition) { - return this.getState().then(stdout => { + return this.getState() + .then(stdout => { if (stdout == "recovery") { // Recovery throw new Error("You must be in device mode"); } else if (stdout == "device") { // Device - return this - .shell("df -hBK " + partition + " --output=size|tail -n1") + return this.shell("df -hBK " + partition + " --output=size|tail -n1") .then(stdout => { stdout = parseFloat(stdout); this.log("FileSize total is " + stdout + " Ko"); - return (stdout); - }).catch(e=>{throw new Error(e)}); + return stdout; + }) + .catch(e => { + throw new Error(e); + }); } - }).catch(e => { - throw new Error("Unable to get filesize"); - }); + }) + .catch(e => { + throw new Error("Unable to get filesize"); + }); } // Return the status of the device (bootloader, recovery, device) - getState() { - - return this.execCommand(["get-state"]).then( (stdout)=>{ - this.log("Device state is "+stdout); - return stdout; - }).catch (e=>{ - this.log("Unknown error :"+e); - throw e; - }); - } - -// Backup file "srcfile" from the phone to "destfile" localy - createRemoteUbuntuBackup(srcfile,destfile,adbpath, progress) { + getState() { + return this.execCommand(["get-state"]) + .then(stdout => { + this.log("Device state is " + stdout); + return stdout; + }) + .catch(e => { + this.log("Unknown error :" + e); + throw e; + }); + } + + // Backup file "srcfile" from the phone to "destfile" localy + createRemoteUbuntuBackup(srcfile, destfile, adbpath, progress) { var _this = this; - _this.log("Backup Function Entry, will backup "+srcfile+" to "+destfile+" adbpath:"+adbpath); + _this.log( + "Backup Function Entry, will backup " + + srcfile + + " to " + + destfile + + " adbpath:" + + adbpath + ); return new Promise(function(resolve, reject) { - _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. - // Get file size - _this.getFileSize(srcfile).then(stdout=>{ - _this.log("Returned FileSize is "+stdout+ " Ko"); - _this.fileSize = stdout; - // Creating pipe - _this.shell("mkfifo /backup.pipe").then((stdout) => { + _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. + // Get file size + _this + .getFileSize(srcfile) + .then(stdout => { + _this.log("Returned FileSize is " + stdout + " Ko"); + _this.fileSize = stdout; + // Creating pipe + _this + .shell("mkfifo /backup.pipe") + .then(stdout => { _this.log("Pipe created !"); var lastSize = 0; var progressInterval = setInterval(() => { - const stats = fs.statSync(destfile); - const fileSizeInBytes = stats.size; - progress ((lastSize / _this.fileSize)*100); - lastSize = fileSizeInBytes/1024; + const stats = fs.statSync(destfile); + const fileSizeInBytes = stats.size; + progress((lastSize / _this.fileSize) * 100); + lastSize = fileSizeInBytes / 1024; }, 1000); // Start the backup _this.log("Starting Backup..."); - _this.execCommand(["exec-out 'tar -cvp ",srcfile," 2>/backup.pipe' | dd of="+destfile]); + _this.execCommand([ + "exec-out 'tar -cvp ", + srcfile, + " 2>/backup.pipe' | dd of=" + destfile + ]); //_this.execCommand(["exec-out 'tar -cvp ",srcfile," 2>/backup.pipe' | dd of="+destfile, // " & ",(adbpath+"/adb -P"),_this.port, - _this.execCommand([" shell cat /backup.pipe", - common.stdoutFilter("%]")]).then( (error, stdout, stderr) => {//process.platform == "win32" ? ' | findstr /v "%]"' : ' | grep -v "%]"'] - _this.log("Backup Ended"); - clearInterval(progressInterval); - _this.shell("rm /backup.pipe").then( ()=> { - _this.log("Pipe released."); - resolve(); // Everything's Fine ! - }).catch(e=>{reject(e+", Unable to delete the pipe ");}); // Pipe Deletion - }).catch(e=>{reject(e+", Unable to backuping the device ");}); // Backup start - }).catch(e=>{reject(e+", Pipe creation failed ");}); // Pipe Creation - }).catch(e=>{reject(e+", Unable to get the partition's filesize ");}); // Get file size - }); - } - - -// Restore file "srcfile" from the computer to "destfile" on the phone - applyRemoteUbuntuBackup(destfile,srcfile, adbpath,bckSize, progress) { + _this + .execCommand([ + " shell cat /backup.pipe", + common.stdoutFilter("%]") + ]) + .then((error, stdout, stderr) => { + //process.platform == "win32" ? ' | findstr /v "%]"' : ' | grep -v "%]"'] + _this.log("Backup Ended"); + clearInterval(progressInterval); + _this + .shell("rm /backup.pipe") + .then(() => { + _this.log("Pipe released."); + resolve(); // Everything's Fine ! + }) + .catch(e => { + reject(e + ", Unable to delete the pipe "); + }); // Pipe Deletion + }) + .catch(e => { + reject(e + ", Unable to backuping the device "); + }); // Backup start + }) + .catch(e => { + reject(e + ", Pipe creation failed "); + }); // Pipe Creation + }) + .catch(e => { + reject(e + ", Unable to get the partition's filesize "); + }); // Get file size + }); + } + + // Restore file "srcfile" from the computer to "destfile" on the phone + applyRemoteUbuntuBackup(destfile, srcfile, adbpath, bckSize, progress) { var _this = this; - _this.log("Restore Function Entry, will restore "+srcfile+" on "+destfile+" adbpath:"+adbpath); + _this.log( + "Restore Function Entry, will restore " + + srcfile + + " on " + + destfile + + " adbpath:" + + adbpath + ); return new Promise(function(resolve, reject) { - _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. - - - // Creating pipe - _this.shell("mkfifo /restore.pipe").then((stdout) => { - _this.log("Pipe created !"); -/* + _this.fileSize = 9999999999999; // Init to file size to a very high value while waiting for the real size. + + // Creating pipe + _this + .shell("mkfifo /restore.pipe") + .then(stdout => { + _this.log("Pipe created !"); + /* var lastSize = 0; _this.fileSize = bckSize; var progressInterval = setInterval(() => { @@ -669,22 +724,39 @@ class Adb { }, 1000); */ - // Start the restoration - _this.log("Starting Restore..."); //adb push user.tar /resto.pipe & adb shell 'cd /; cat /resto.pipe | tar -xv' - _this.execCommand(["push",srcfile,"/restore.pipe &", - (adbpath+"/adb -P"),_this.port, - " shell 'cd /; cat /restore.pipe | tar -xv'"]).then( (error, stdout, stderr) => { - _this.log("Restore Ended"); - //clearInterval(progressInterval); - _this.shell("rm /restore.pipe").then( ()=> { - _this.log("Pipe released."); - resolve(); // Everything's Fine ! - }).catch(e=>{reject(e);}); // Pipe Deletion - }).catch(e=>{reject(e);}); // Backup start - }).catch(e=>{reject(e);}); // Pipe Creation - }); - } - + // Start the restoration + _this.log("Starting Restore..."); //adb push user.tar /resto.pipe & adb shell 'cd /; cat /resto.pipe | tar -xv' + _this + .execCommand([ + "push", + srcfile, + "/restore.pipe &", + adbpath + "/adb -P", + _this.port, + " shell 'cd /; cat /restore.pipe | tar -xv'" + ]) + .then((error, stdout, stderr) => { + _this.log("Restore Ended"); + //clearInterval(progressInterval); + _this + .shell("rm /restore.pipe") + .then(() => { + _this.log("Pipe released."); + resolve(); // Everything's Fine ! + }) + .catch(e => { + reject(e); + }); // Pipe Deletion + }) + .catch(e => { + reject(e); + }); // Backup start + }) + .catch(e => { + reject(e); + }); // Pipe Creation + }); + } } module.exports = Adb;