Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added backup functions, device status (recovery,device,fastboot), fol… #28

Closed
wants to merge 4 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 166 additions & 0 deletions src/adb.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,23 @@ const DEFAULT_EXEC = (args, callback) => {
callback
);
};

// AW : Allow execution of custom command, not only adb
Alain94W marked this conversation as resolved.
Show resolved Hide resolved
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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -487,6 +525,134 @@ class Adb {
);
});
}

// AW : return the file size of a complete folder
Alain94W marked this conversation as resolved.
Show resolved Hide resolved
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 ...)
Alain94W marked this conversation as resolved.
Show resolved Hide resolved
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 => {
Alain94W marked this conversation as resolved.
Show resolved Hide resolved
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 => {
Alain94W marked this conversation as resolved.
Show resolved Hide resolved
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;