rajkosto

backupUser.js

Mar 25th, 2018
887
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // backups all the files from the USER NAND partition to a folder on the sdcard
  2. // - by rajkosto 25.03.2018.
  3.  
  4. if (IFileSystem.prototype.CreateDir === undefined || IFileSystem.prototype.DeleteDir === undefined)
  5. {
  6.     throw new Error("Missing IFileSystem functions, update your PegaSwitch from git!")
  7. }
  8.  
  9. if (IFile.prototype.SetSize === undefined)
  10. {
  11.     throw new Error("Missing IFile functions, update your PegaSwitch from git!")
  12. }
  13.  
  14. IFile.prototype.ReadPart = function (offset, size, buf) {
  15.     if(size instanceof ArrayBuffer || ArrayBuffer.isView(size)) {
  16.         buf = size;
  17.         size = buf.byteLength;
  18.     }
  19.     var ipcRes = this.sc.ipcMsg(0).datau64(0, offset, size).bDescriptor(buf, size, 1).sendTo(this.handle);
  20.     var bytes_read = [ipcRes.data[0], ipcRes.data[1]];
  21.     return ipcRes.asResult().replaceValue(bytes_read);
  22. };
  23.  
  24. sc.getFSPPR = function () {
  25.     if (sc.closed_pr !== undefined) {
  26.         return;
  27.     }
  28.     sc.enableTurbo();
  29.     var i = 0;
  30.     var srv = null;
  31.     while (true) {
  32.         sc.ipcMsg(2).setType(5).sendTo('pm:shell');
  33.         var srvResult = sc.getService("fsp-pr");
  34.         if(srvResult.isOk) {
  35.             srv = srvResult.getValue();
  36.             break;
  37.         }
  38.         i++;
  39.     }
  40.     utils.log('Got fsp-pr handle after ' + i + ' iterations: ');
  41.     utils.log('fsp-pr handle: 0x' + srv.toString(16));
  42.     sc.svcCloseHandle(srv).assertOk();
  43.     sc.closed_pr = true;
  44. };
  45.  
  46. sc.getFSPPR();
  47. sc.enableTurbo();
  48.  
  49. if(sc.pr_handle) {
  50.     sc.svcCloseHandle(sc.pr_handle);
  51.     sc.pr_handle = undefined;
  52. }
  53.  
  54. sc.getService("fsp-pr", (fsppr) => {
  55.     var pid = sc.getService('fsp-srv', (tmp_hnd) => {
  56.         utils.log("got fspsrv handle: 0x" + tmp_hnd.toString(16));
  57.         sc.ipcMsg(1).sendPid().data(0).sendTo(tmp_hnd).assertOk();
  58.         return sc.read4(sc.ipcBufAddr, 0xC >> 2);
  59.     });
  60.     utils.log('Got process PID: '+pid.toString(16));
  61.    
  62.     var buf1_sz = 0x1C;
  63.     var buf2_sz = 0x2C;
  64.     var buf = sc.malloc(buf1_sz + buf2_sz);
  65.     var buf2 = utils.add2(buf, buf1_sz);
  66.    
  67.     // buffer init
  68.     sc.write4(1, buf, 0x0>>2);
  69.     sc.write8([0xFFFFFFFF, 0xFFFFFFFF], buf, 0x4 >> 2); // This is the permissions value.
  70.     sc.write4(buf1_sz, buf, 0xC >> 2);
  71.     sc.write4(buf1_sz, buf, 0x14 >> 2);
  72.    
  73.     sc.write4(1, buf2, 0x0 >> 2);
  74.     sc.write8([0xFFFFFFFF, 0xFFFFFFFF], buf2, 0x4 >> 2); // This is the permissions value -- actual perms = buf2_val & buf1_val
  75.     sc.write4(0xFFFFFFFF, buf2, 0x14 >> 2);
  76.     sc.write4(0xFFFFFFFF, buf2, 0x18 >> 2);
  77.     sc.write4(0xFFFFFFFF, buf2, 0x24 >> 2);
  78.     sc.write4(0xFFFFFFFF, buf2, 0x28 >> 2);
  79.    
  80.     /* Change to mount a particular title's romfs */
  81.     var tid = '0000000000000000';
  82.    
  83.     sc.ipcMsg(256).data(0).sendTo(fsppr).assertOk().show();
  84.     sc.ipcMsg(1).data(pid).sendTo(fsppr).assertOk().show();
  85.     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();
  86.     sc.free(buf);
  87.     sc.free(buf2);
  88. });
  89.  
  90. foreachDirEntry = function(dir_obj, callback)
  91. {
  92.     var entryCount = utils.trunc32(dir_obj.GetEntryCount().assertOk());
  93.     if (entryCount > 0 && callback !== undefined)
  94.     {
  95.         var entryBuf = new Uint32Array(0x310 * entryCount);
  96.         dir_obj.GetEntries(entryBuf, entryCount).assertOk();
  97.         for (var entryIdx = 0; entryIdx < entryCount; entryIdx++)
  98.         {
  99.             var fn = utils.u8a2str(new Uint8Array(entryBuf.buffer, 0x310 * entryIdx, 0x300));
  100.             for (var strIdx=0; strIdx<fn.length; strIdx++)
  101.             {
  102.                 if (fn.charCodeAt(strIdx) === 0)
  103.                 {
  104.                     fn = fn.substring(0, strIdx);
  105.                     break;
  106.                 }
  107.             }
  108.             var eType = entryBuf[(0x310 * entryIdx + 0x304) >> 2];         
  109.             callback(fn, eType);
  110.         }
  111.     }
  112.    
  113.     return entryCount;
  114. };
  115.  
  116. copyFiles = function(src_dir, dst_dir)
  117. {
  118.     var thefiles = [];
  119.     foreachDirEntry(src_dir, function(fn, eType)
  120.     {
  121.         if (eType === 1) { thefiles.push(fn); }
  122.     });
  123.     //dont need handle to dst_dir anymore (and it will interfere with Commit ops)
  124.     var dst_dir_fs = dst_dir.fs;
  125.     var dst_dir_path = dst_dir.path;
  126.     dst_dir.Close(); dst_dir = null;
  127.  
  128.     var CHUNK_SIZE = 1024*1024;
  129.     var buf = new ArrayBuffer(CHUNK_SIZE);
  130.     for (var fileIdx=0; fileIdx<thefiles.length; fileIdx++)
  131.     {
  132.         var fn = thefiles[fileIdx];
  133.         utils.log('[Opening existing file] ' + src_dir.path + fn);
  134.         var f_src = src_dir.fs.OpenFile(src_dir.path + fn).assertOk();
  135.         var size = f_src.GetSize().assertOk();
  136.         utils.log('[Source file size] ' + src_dir.path + fn + ' = ' + size + ' bytes');
  137.  
  138.         var f_dst = null;
  139.         try
  140.         {
  141.             //try open existing destination file
  142.             f_dst = dst_dir_fs.OpenFile(dst_dir_path + fn);
  143.             if (f_dst.isOk) //file exists, so lets just resize it to target size
  144.             {
  145.                 f_dst = f_dst.assertOk();
  146.                 var dst_size = f_dst.GetSize().assertOk();
  147.                 if (!utils.eq(dst_size, size))
  148.                 {
  149.                     utils.log('[Resizing existing file] ' + dst_dir_path + fn + ' ' + dst_size + ' -> ' + size);
  150.                     f_dst.SetSize(dst_size).assertOk();
  151.                     var new_size = f_dst.GetSize().assertOk();
  152.                     utils.log('[Resize complete] ' + dst_dir_path + fn + ' now ' + new_size);
  153.                 }                
  154.             }
  155.             else
  156.             {
  157.                 utils.log('[Creating new file] ' + dst_dir_path + fn + ' with size ' + size + ' bytes');
  158.                 dst_dir_fs.CreateFile(dst_dir_path + fn, size).assertOk();
  159.                 utils.log('[Opening new file] ' + dst_dir_path + fn);          
  160.                 f_dst = dst_dir_fs.OpenFile(dst_dir_path + fn).assertOk();
  161.             }            
  162.             utils.log('[Open dst file OK] ' + dst_dir_path + fn);
  163.             var doneBytes = [0, 0];
  164.             for (var totalSize = size; !utils.eq(doneBytes, totalSize); )
  165.             {
  166.                 var currBlockSize = totalSize;
  167.                 if (!utils.nullptr(doneBytes)) { currBlockSize = utils.sub2(totalSize, doneBytes); }
  168.                 if ((currBlockSize[1] != 0) || (currBlockSize[0] > CHUNK_SIZE)) { currBlockSize = CHUNK_SIZE; }
  169.                 else { currBlockSize = utils.trunc32(currBlockSize); }
  170.                
  171.                 var read_bytes = f_src.ReadPart(doneBytes, currBlockSize, buf).assertOk();
  172.                 utils.log('[Read bytes] ' + '@' + doneBytes + ' (' + currBlockSize + ') returned ' + read_bytes );
  173.                 /*if ((read_bytes[1] != 0) || (read_bytes[0] != currBlockSize))
  174.                 {
  175.                     throw new Error("Read mismatch, wanted " + currBlockSize + " bytes, got " + read_bytes + " bytes");
  176.                 }*/
  177.  
  178.                 var sizeAfterWrite = utils.add2(doneBytes, read_bytes);
  179.                 f_dst.Write(doneBytes, buf, read_bytes).assertOk();
  180.                 utils.log('[Wrote bytes] ' + '@' + doneBytes + ' + ' + read_bytes);
  181.                 doneBytes = sizeAfterWrite;
  182.             }
  183.             utils.log('[Write file Complete] ' + dst_dir_path + fn + ' -> ' + doneBytes + ' bytes');
  184.             f_dst.Close(); f_dst = null;
  185.             utils.log('[Close file OK] ' + dst_dir_path + fn);
  186.         }
  187.         finally
  188.         {
  189.             if (f_dst !== null && f_dst instanceof IFile) { f_dst.Close(); f_dst = null; }
  190.             if (f_src !== null) { f_src.Close(); f_src = null; }
  191.         }
  192.     }
  193.  
  194.     return dst_dir;
  195. };
  196.  
  197. evaluateDirs = function(fs_obj, root_dir)
  198. {
  199.     var folders = [];
  200.    
  201.     var dir_obj = fs_obj.OpenDir(root_dir, 1); //directories only
  202.     if (!dir_obj.isOk) { return folders; } //no dirs
  203.     else { dir_obj = dir_obj.assertOk(); }
  204.    
  205.     folders.push(dir_obj.path); //this dir
  206.     for (var evalIdx=0; evalIdx<folders.length; evalIdx++)
  207.     {
  208.         if (evalIdx !== 0)
  209.         {
  210.             dir_obj = fs_obj.OpenDir(folders[evalIdx], 1);
  211.             if (!dir_obj.isOk) { throw new Error('Unable to open dir ' + folders[evalIdx] + ' for listing'); }         
  212.             else { dir_obj = dir_obj.assertOk(); }
  213.         }
  214.  
  215.         foreachDirEntry(dir_obj, function(fn) { folders.push(dir_obj.path + fn + '/'); });
  216.         dir_obj.Close(); dir_obj = null;
  217.     }
  218.  
  219.     return folders;
  220. };
  221.  
  222. clearOutFolder = function(fs_obj, start_dir_path)
  223. {
  224.     utils.log('[Opening existing dir for listing] ' + start_dir_path + ' on ' + fs_obj.partition);
  225.     var start_dir = fs_obj.OpenDir(start_dir_path, 1).assertOk(); //directories only
  226.     var listEntries = [];
  227.     foreachDirEntry(start_dir, function(fn) { listEntries.push(start_dir.path + fn + '/'); });
  228.     start_dir.Close(); start_dir = null;
  229.     for (var saveDirIdx=0; saveDirIdx<listEntries.length; saveDirIdx++)
  230.     {
  231.         var currDirPath = listEntries[saveDirIdx];
  232.         utils.log('[Deleting existing dir] ' + currDirPath + ' on ' + fs_obj.partition);
  233.         fs_obj.DeleteDir(currDirPath, true).assertOk();
  234.         utils.log('[Existing dir deleted] ' + currDirPath  + ' on ' + fs_obj.partition);
  235.     }
  236.     start_dir = fs_obj.OpenDir(start_dir_path, 2).assertOk(); //files only
  237.     listEntries = [];
  238.     foreachDirEntry(start_dir, function(fn) { listEntries.push(start_dir.path + fn); });
  239.     start_dir.Close(); start_dir = null;
  240.     for (var saveFnIdx=0; saveFnIdx<listEntries.length; saveFnIdx++)
  241.     {
  242.         var currFilePath = listEntries[saveFnIdx];
  243.         utils.log('[Deleting existing file] ' + currFilePath + ' on ' + fs_obj.partition);
  244.         fs_obj.DeleteFile(currFilePath).assertOk();
  245.         utils.log('[Existing file deleted] ' + currFilePath + ' on ' + fs_obj.partition);
  246.     }
  247.     listEntries = [];
  248. };
  249.  
  250. makeOrClearFolder = function(fs_obj, start_dir_path)
  251. {
  252.     var res = fs_obj.CreateDir(start_dir_path);
  253.     if (res.isOk)
  254.     {
  255.         utils.log('[Created new dir] ' + start_dir_path + ' on ' + fs_obj.partition);
  256.     }
  257.     else
  258.     {
  259.         clearOutFolder(fs_obj, start_dir_path);
  260.         utils.log('[Using existing dir] ' + start_dir_path + ' on ' + fs_obj.partition);
  261.     }
  262. };
  263.  
  264. sc.getService('fsp-srv', (fsp_handle) => {
  265.     utils.log('initialized fsp-srv handle: 0x' + fsp_handle.toString(16));
  266.     sc.ipcMsg(1).sendPid().datau64(0).sendTo(fsp_handle).assertOk();
  267.  
  268.     mountSDCard = function () {
  269.         var self = this;
  270.         return sc.ipcMsg(18).sendTo(fsp_handle).asResult()
  271.             .map((r) => new self.sc.IFileSystem(self.sc, r.movedHandles[0]));
  272.     };
  273.    
  274.     mountBisFatPart = function (partId) {
  275.         var pbuf = new ArrayBuffer(1); //just a null terminator
  276.         var self = this;
  277.         return sc.ipcMsg(11).datau32(partId).xDescriptor(pbuf, pbuf.byteLength, 0).sendTo(fsp_handle).asResult()
  278.             .map((r) => new self.sc.IFileSystem(self.sc, r.movedHandles[0]));
  279.     };
  280.  
  281.     var fs_sd = null;
  282.     var fs_user = null;
  283.  
  284.     try {
  285.         utils.log("Mounting SD card");
  286.         try { fs_sd = mountSDCard().assertOk(); }
  287.         catch(e) { throw new Error("Failed to open SD card. Is it inserted?"); }
  288.         fs_sd.partition = "SDCARD";
  289.         utils.log('SDCARD handle = 0x' + fs_sd.handle.toString(16));
  290.        
  291.         utils.log("Mounting USER partition");
  292.         try { fs_user = mountBisFatPart(30).assertOk(); }
  293.         catch(e) { throw new Error("Failed to mount USER partition"); }
  294.         fs_user.partition = "USER";
  295.         utils.log('USER handle = 0x' + fs_user.handle.toString());
  296.  
  297.         utils.log('[Listing folders in USER part]');
  298.         var dirList = evaluateDirs(fs_user, '/');
  299.         if (dirList.length < 1)
  300.         {
  301.             throw new Error("Unable to list USER partition dirs");
  302.         }
  303.         utils.log(dirList.length + ' folders found on USER part');
  304.  
  305.         var date = new Date();
  306.         var sdFolderName = "/user-" + date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
  307.                             + "-" + date.getHours() + "-" + date.getMinutes() +'/';
  308.         makeOrClearFolder(fs_sd, sdFolderName);
  309.         sdFolderName = sdFolderName.substr(0, sdFolderName.length-1);
  310.  
  311.         for (var dirIndex = 0; dirIndex < dirList.length; dirIndex++)
  312.         {
  313.             var left_side = dirList[dirIndex];
  314.             var right_side = sdFolderName + dirList[dirIndex];
  315.            
  316.             utils.log('[Opening folder on USER] '+ left_side);
  317.             var dir_user = fs_user.OpenDir(left_side, 2).assertOk();
  318.             utils.log('[Opening folder on SD] '+ right_side);
  319.             var dir_sd = fs_sd.OpenDir(right_side, 2);
  320.             if (!dir_sd.isOk)
  321.             {
  322.                 utils.log('[Making folder on SD] '+ right_side);
  323.                 fs_sd.CreateDir(right_side).assertOk();
  324.                 utils.log('[Opening newly made folder] ' + right_side);            
  325.                 dir_sd = fs_sd.OpenDir(right_side, 2).assertOk();
  326.                 utils.log('[New folder opened OK] '+ right_side);
  327.             }
  328.             else
  329.             {
  330.                 dir_sd = dir_sd.assertOk();
  331.                 utils.log('[Existing folder opened OK] '+ right_side);
  332.             }
  333.    
  334.             try
  335.             {
  336.                 dir_sd = copyFiles(dir_user, dir_sd); //because we might change dst_dir inside
  337.             }
  338.             finally
  339.             {
  340.                 if (dir_user !== null) { dir_user.Close(); dir_user = null; }
  341.                 if (dir_sd !== null) { dir_sd.Close(); dir_sd = null; }
  342.             }
  343.         }
  344.        
  345.         utils.log('[Closing file systems]');
  346.     }
  347.     finally
  348.     {
  349.         if (fs_user !== null) { fs_user.Close(); fs_user = null; }
  350.         if (fs_sd !== null) { fs_sd.Close(); fs_sd = null; }
  351.     }
  352. });
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×