Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // backups all the files from the USER NAND partition to a folder on the sdcard
- // - by rajkosto 25.03.2018.
- if (IFileSystem.prototype.CreateDir === undefined || IFileSystem.prototype.DeleteDir === undefined)
- {
- throw new Error("Missing IFileSystem functions, update your PegaSwitch from git!")
- }
- if (IFile.prototype.SetSize === undefined)
- {
- throw new Error("Missing IFile functions, update your PegaSwitch from git!")
- }
- IFile.prototype.ReadPart = function (offset, size, buf) {
- if(size instanceof ArrayBuffer || ArrayBuffer.isView(size)) {
- buf = size;
- size = buf.byteLength;
- }
- var ipcRes = this.sc.ipcMsg(0).datau64(0, offset, size).bDescriptor(buf, size, 1).sendTo(this.handle);
- var bytes_read = [ipcRes.data[0], ipcRes.data[1]];
- return ipcRes.asResult().replaceValue(bytes_read);
- };
- sc.getFSPPR = function () {
- if (sc.closed_pr !== undefined) {
- return;
- }
- sc.enableTurbo();
- var i = 0;
- var srv = null;
- while (true) {
- sc.ipcMsg(2).setType(5).sendTo('pm:shell');
- var srvResult = sc.getService("fsp-pr");
- if(srvResult.isOk) {
- srv = srvResult.getValue();
- break;
- }
- i++;
- }
- utils.log('Got fsp-pr handle after ' + i + ' iterations: ');
- utils.log('fsp-pr handle: 0x' + srv.toString(16));
- sc.svcCloseHandle(srv).assertOk();
- sc.closed_pr = true;
- };
- sc.getFSPPR();
- sc.enableTurbo();
- if(sc.pr_handle) {
- sc.svcCloseHandle(sc.pr_handle);
- sc.pr_handle = undefined;
- }
- sc.getService("fsp-pr", (fsppr) => {
- var pid = sc.getService('fsp-srv', (tmp_hnd) => {
- utils.log("got fspsrv handle: 0x" + tmp_hnd.toString(16));
- sc.ipcMsg(1).sendPid().data(0).sendTo(tmp_hnd).assertOk();
- return sc.read4(sc.ipcBufAddr, 0xC >> 2);
- });
- utils.log('Got process PID: '+pid.toString(16));
- var buf1_sz = 0x1C;
- var buf2_sz = 0x2C;
- var buf = sc.malloc(buf1_sz + buf2_sz);
- var buf2 = utils.add2(buf, buf1_sz);
- // buffer init
- sc.write4(1, buf, 0x0>>2);
- sc.write8([0xFFFFFFFF, 0xFFFFFFFF], buf, 0x4 >> 2); // This is the permissions value.
- sc.write4(buf1_sz, buf, 0xC >> 2);
- sc.write4(buf1_sz, buf, 0x14 >> 2);
- sc.write4(1, buf2, 0x0 >> 2);
- sc.write8([0xFFFFFFFF, 0xFFFFFFFF], buf2, 0x4 >> 2); // This is the permissions value -- actual perms = buf2_val & buf1_val
- sc.write4(0xFFFFFFFF, buf2, 0x14 >> 2);
- sc.write4(0xFFFFFFFF, buf2, 0x18 >> 2);
- sc.write4(0xFFFFFFFF, buf2, 0x24 >> 2);
- sc.write4(0xFFFFFFFF, buf2, 0x28 >> 2);
- /* Change to mount a particular title's romfs */
- var tid = '0000000000000000';
- sc.ipcMsg(256).data(0).sendTo(fsppr).assertOk().show();
- sc.ipcMsg(1).data(pid).sendTo(fsppr).assertOk().show();
- sc.ipcMsg(0).data(2, [pid,0], utils.parseAddr(tid), buf1_sz, buf2_sz, pid, pid, 0, 0, 0, 0, 0).aDescriptor(buf, buf1_sz).aDescriptor(buf2, buf2_sz).sendTo(fsppr).assertOk().show();
- sc.free(buf);
- sc.free(buf2);
- });
- foreachDirEntry = function(dir_obj, callback)
- {
- var entryCount = utils.trunc32(dir_obj.GetEntryCount().assertOk());
- if (entryCount > 0 && callback !== undefined)
- {
- var entryBuf = new Uint32Array(0x310 * entryCount);
- dir_obj.GetEntries(entryBuf, entryCount).assertOk();
- for (var entryIdx = 0; entryIdx < entryCount; entryIdx++)
- {
- var fn = utils.u8a2str(new Uint8Array(entryBuf.buffer, 0x310 * entryIdx, 0x300));
- for (var strIdx=0; strIdx<fn.length; strIdx++)
- {
- if (fn.charCodeAt(strIdx) === 0)
- {
- fn = fn.substring(0, strIdx);
- break;
- }
- }
- var eType = entryBuf[(0x310 * entryIdx + 0x304) >> 2];
- callback(fn, eType);
- }
- }
- return entryCount;
- };
- copyFiles = function(src_dir, dst_dir)
- {
- var thefiles = [];
- foreachDirEntry(src_dir, function(fn, eType)
- {
- if (eType === 1) { thefiles.push(fn); }
- });
- //dont need handle to dst_dir anymore (and it will interfere with Commit ops)
- var dst_dir_fs = dst_dir.fs;
- var dst_dir_path = dst_dir.path;
- dst_dir.Close(); dst_dir = null;
- var CHUNK_SIZE = 1024*1024;
- var buf = new ArrayBuffer(CHUNK_SIZE);
- for (var fileIdx=0; fileIdx<thefiles.length; fileIdx++)
- {
- var fn = thefiles[fileIdx];
- utils.log('[Opening existing file] ' + src_dir.path + fn);
- var f_src = src_dir.fs.OpenFile(src_dir.path + fn).assertOk();
- var size = f_src.GetSize().assertOk();
- utils.log('[Source file size] ' + src_dir.path + fn + ' = ' + size + ' bytes');
- var f_dst = null;
- try
- {
- //try open existing destination file
- f_dst = dst_dir_fs.OpenFile(dst_dir_path + fn);
- if (f_dst.isOk) //file exists, so lets just resize it to target size
- {
- f_dst = f_dst.assertOk();
- var dst_size = f_dst.GetSize().assertOk();
- if (!utils.eq(dst_size, size))
- {
- utils.log('[Resizing existing file] ' + dst_dir_path + fn + ' ' + dst_size + ' -> ' + size);
- f_dst.SetSize(dst_size).assertOk();
- var new_size = f_dst.GetSize().assertOk();
- utils.log('[Resize complete] ' + dst_dir_path + fn + ' now ' + new_size);
- }
- }
- else
- {
- utils.log('[Creating new file] ' + dst_dir_path + fn + ' with size ' + size + ' bytes');
- dst_dir_fs.CreateFile(dst_dir_path + fn, size).assertOk();
- utils.log('[Opening new file] ' + dst_dir_path + fn);
- f_dst = dst_dir_fs.OpenFile(dst_dir_path + fn).assertOk();
- }
- utils.log('[Open dst file OK] ' + dst_dir_path + fn);
- var doneBytes = [0, 0];
- for (var totalSize = size; !utils.eq(doneBytes, totalSize); )
- {
- var currBlockSize = totalSize;
- if (!utils.nullptr(doneBytes)) { currBlockSize = utils.sub2(totalSize, doneBytes); }
- if ((currBlockSize[1] != 0) || (currBlockSize[0] > CHUNK_SIZE)) { currBlockSize = CHUNK_SIZE; }
- else { currBlockSize = utils.trunc32(currBlockSize); }
- var read_bytes = f_src.ReadPart(doneBytes, currBlockSize, buf).assertOk();
- utils.log('[Read bytes] ' + '@' + doneBytes + ' (' + currBlockSize + ') returned ' + read_bytes );
- /*if ((read_bytes[1] != 0) || (read_bytes[0] != currBlockSize))
- {
- throw new Error("Read mismatch, wanted " + currBlockSize + " bytes, got " + read_bytes + " bytes");
- }*/
- var sizeAfterWrite = utils.add2(doneBytes, read_bytes);
- f_dst.Write(doneBytes, buf, read_bytes).assertOk();
- utils.log('[Wrote bytes] ' + '@' + doneBytes + ' + ' + read_bytes);
- doneBytes = sizeAfterWrite;
- }
- utils.log('[Write file Complete] ' + dst_dir_path + fn + ' -> ' + doneBytes + ' bytes');
- f_dst.Close(); f_dst = null;
- utils.log('[Close file OK] ' + dst_dir_path + fn);
- }
- finally
- {
- if (f_dst !== null && f_dst instanceof IFile) { f_dst.Close(); f_dst = null; }
- if (f_src !== null) { f_src.Close(); f_src = null; }
- }
- }
- return dst_dir;
- };
- evaluateDirs = function(fs_obj, root_dir)
- {
- var folders = [];
- var dir_obj = fs_obj.OpenDir(root_dir, 1); //directories only
- if (!dir_obj.isOk) { return folders; } //no dirs
- else { dir_obj = dir_obj.assertOk(); }
- folders.push(dir_obj.path); //this dir
- for (var evalIdx=0; evalIdx<folders.length; evalIdx++)
- {
- if (evalIdx !== 0)
- {
- dir_obj = fs_obj.OpenDir(folders[evalIdx], 1);
- if (!dir_obj.isOk) { throw new Error('Unable to open dir ' + folders[evalIdx] + ' for listing'); }
- else { dir_obj = dir_obj.assertOk(); }
- }
- foreachDirEntry(dir_obj, function(fn) { folders.push(dir_obj.path + fn + '/'); });
- dir_obj.Close(); dir_obj = null;
- }
- return folders;
- };
- clearOutFolder = function(fs_obj, start_dir_path)
- {
- utils.log('[Opening existing dir for listing] ' + start_dir_path + ' on ' + fs_obj.partition);
- var start_dir = fs_obj.OpenDir(start_dir_path, 1).assertOk(); //directories only
- var listEntries = [];
- foreachDirEntry(start_dir, function(fn) { listEntries.push(start_dir.path + fn + '/'); });
- start_dir.Close(); start_dir = null;
- for (var saveDirIdx=0; saveDirIdx<listEntries.length; saveDirIdx++)
- {
- var currDirPath = listEntries[saveDirIdx];
- utils.log('[Deleting existing dir] ' + currDirPath + ' on ' + fs_obj.partition);
- fs_obj.DeleteDir(currDirPath, true).assertOk();
- utils.log('[Existing dir deleted] ' + currDirPath + ' on ' + fs_obj.partition);
- }
- start_dir = fs_obj.OpenDir(start_dir_path, 2).assertOk(); //files only
- listEntries = [];
- foreachDirEntry(start_dir, function(fn) { listEntries.push(start_dir.path + fn); });
- start_dir.Close(); start_dir = null;
- for (var saveFnIdx=0; saveFnIdx<listEntries.length; saveFnIdx++)
- {
- var currFilePath = listEntries[saveFnIdx];
- utils.log('[Deleting existing file] ' + currFilePath + ' on ' + fs_obj.partition);
- fs_obj.DeleteFile(currFilePath).assertOk();
- utils.log('[Existing file deleted] ' + currFilePath + ' on ' + fs_obj.partition);
- }
- listEntries = [];
- };
- makeOrClearFolder = function(fs_obj, start_dir_path)
- {
- var res = fs_obj.CreateDir(start_dir_path);
- if (res.isOk)
- {
- utils.log('[Created new dir] ' + start_dir_path + ' on ' + fs_obj.partition);
- }
- else
- {
- clearOutFolder(fs_obj, start_dir_path);
- utils.log('[Using existing dir] ' + start_dir_path + ' on ' + fs_obj.partition);
- }
- };
- sc.getService('fsp-srv', (fsp_handle) => {
- utils.log('initialized fsp-srv handle: 0x' + fsp_handle.toString(16));
- sc.ipcMsg(1).sendPid().datau64(0).sendTo(fsp_handle).assertOk();
- mountSDCard = function () {
- var self = this;
- return sc.ipcMsg(18).sendTo(fsp_handle).asResult()
- .map((r) => new self.sc.IFileSystem(self.sc, r.movedHandles[0]));
- };
- mountBisFatPart = function (partId) {
- var pbuf = new ArrayBuffer(1); //just a null terminator
- var self = this;
- return sc.ipcMsg(11).datau32(partId).xDescriptor(pbuf, pbuf.byteLength, 0).sendTo(fsp_handle).asResult()
- .map((r) => new self.sc.IFileSystem(self.sc, r.movedHandles[0]));
- };
- var fs_sd = null;
- var fs_user = null;
- try {
- utils.log("Mounting SD card");
- try { fs_sd = mountSDCard().assertOk(); }
- catch(e) { throw new Error("Failed to open SD card. Is it inserted?"); }
- fs_sd.partition = "SDCARD";
- utils.log('SDCARD handle = 0x' + fs_sd.handle.toString(16));
- utils.log("Mounting USER partition");
- try { fs_user = mountBisFatPart(30).assertOk(); }
- catch(e) { throw new Error("Failed to mount USER partition"); }
- fs_user.partition = "USER";
- utils.log('USER handle = 0x' + fs_user.handle.toString());
- utils.log('[Listing folders in USER part]');
- var dirList = evaluateDirs(fs_user, '/');
- if (dirList.length < 1)
- {
- throw new Error("Unable to list USER partition dirs");
- }
- utils.log(dirList.length + ' folders found on USER part');
- var date = new Date();
- var sdFolderName = "/user-" + date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
- + "-" + date.getHours() + "-" + date.getMinutes() +'/';
- makeOrClearFolder(fs_sd, sdFolderName);
- sdFolderName = sdFolderName.substr(0, sdFolderName.length-1);
- for (var dirIndex = 0; dirIndex < dirList.length; dirIndex++)
- {
- var left_side = dirList[dirIndex];
- var right_side = sdFolderName + dirList[dirIndex];
- utils.log('[Opening folder on USER] '+ left_side);
- var dir_user = fs_user.OpenDir(left_side, 2).assertOk();
- utils.log('[Opening folder on SD] '+ right_side);
- var dir_sd = fs_sd.OpenDir(right_side, 2);
- if (!dir_sd.isOk)
- {
- utils.log('[Making folder on SD] '+ right_side);
- fs_sd.CreateDir(right_side).assertOk();
- utils.log('[Opening newly made folder] ' + right_side);
- dir_sd = fs_sd.OpenDir(right_side, 2).assertOk();
- utils.log('[New folder opened OK] '+ right_side);
- }
- else
- {
- dir_sd = dir_sd.assertOk();
- utils.log('[Existing folder opened OK] '+ right_side);
- }
- try
- {
- dir_sd = copyFiles(dir_user, dir_sd); //because we might change dst_dir inside
- }
- finally
- {
- if (dir_user !== null) { dir_user.Close(); dir_user = null; }
- if (dir_sd !== null) { dir_sd.Close(); dir_sd = null; }
- }
- }
- utils.log('[Closing file systems]');
- }
- finally
- {
- if (fs_user !== null) { fs_user.Close(); fs_user = null; }
- if (fs_sd !== null) { fs_sd.Close(); fs_sd = null; }
- }
- });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement