Browse Source

refactor: use type enum in file stats for asar archive (#39889)

Milan Burda 1 year ago
parent
commit
d75a852743

+ 18 - 26
lib/asar/fs-wrapper.ts

@@ -1,4 +1,5 @@
 import { Buffer } from 'buffer';
+import { constants } from 'fs';
 import * as path from 'path';
 import * as util from 'util';
 import type * as Crypto from 'crypto';
@@ -75,18 +76,22 @@ const gid = process.getgid?.() ?? 0;
 
 const fakeTime = new Date();
 
-const asarStatsToFsStats = function (stats: NodeJS.AsarFileStat) {
-  const { Stats, constants } = require('fs');
+enum AsarFileType {
+  kFile = (constants as any).UV_DIRENT_FILE,
+  kDirectory = (constants as any).UV_DIRENT_DIR,
+  kLink = (constants as any).UV_DIRENT_LINK,
+}
 
-  let mode = constants.S_IROTH ^ constants.S_IRGRP ^ constants.S_IRUSR ^ constants.S_IWUSR;
+const fileTypeToMode = new Map<AsarFileType, number>([
+  [AsarFileType.kFile, constants.S_IFREG],
+  [AsarFileType.kDirectory, constants.S_IFDIR],
+  [AsarFileType.kLink, constants.S_IFLNK]
+]);
 
-  if (stats.isFile) {
-    mode ^= constants.S_IFREG;
-  } else if (stats.isDirectory) {
-    mode ^= constants.S_IFDIR;
-  } else if (stats.isLink) {
-    mode ^= constants.S_IFLNK;
-  }
+const asarStatsToFsStats = function (stats: NodeJS.AsarFileStat) {
+  const { Stats } = require('fs');
+
+  const mode = constants.S_IROTH | constants.S_IRGRP | constants.S_IRUSR | constants.S_IWUSR | fileTypeToMode.get(stats.type)!;
 
   return new Stats(
     1, // dev
@@ -249,7 +254,6 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
   const logASARAccess = (asarPath: string, filePath: string, offset: number) => {
     if (!process.env.ELECTRON_LOG_ASAR_READS) return;
     if (!logFDs.has(asarPath)) {
-      const path = require('path');
       const logFilename = `${path.basename(asarPath, '.asar')}-access-log.txt`;
       const logPath = path.join(require('os').tmpdir(), logFilename);
       logFDs.set(asarPath, fs.openSync(logPath, 'a'));
@@ -676,13 +680,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
           nextTick(callback!, [error]);
           return;
         }
-        if (stats.isFile) {
-          dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_FILE));
-        } else if (stats.isDirectory) {
-          dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_DIR));
-        } else if (stats.isLink) {
-          dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_LINK));
-        }
+        dirents.push(new fs.Dirent(file, stats.type));
       }
       nextTick(callback!, [null, dirents]);
       return;
@@ -719,13 +717,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
         if (!stats) {
           throw createError(AsarError.NOT_FOUND, { asarPath, filePath: childPath });
         }
-        if (stats.isFile) {
-          dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_FILE));
-        } else if (stats.isDirectory) {
-          dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_DIR));
-        } else if (stats.isLink) {
-          dirents.push(new fs.Dirent(file, fs.constants.UV_DIRENT_LINK));
-        }
+        dirents.push(new fs.Dirent(file, stats.type));
       }
       return dirents;
     }
@@ -776,7 +768,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
     const stats = archive.stat(filePath);
     if (!stats) return -34;
 
-    return (stats.isDirectory) ? 1 : 0;
+    return (stats.type === AsarFileType.kDirectory) ? 1 : 0;
   };
 
   // Calling mkdir for directory inside asar archive should throw ENOTDIR

+ 1 - 3
shell/common/api/electron_api_asar.cc

@@ -121,9 +121,7 @@ class Archive : public node::ObjectWrap {
     gin_helper::Dictionary dict(isolate, v8::Object::New(isolate));
     dict.Set("size", stats.size);
     dict.Set("offset", stats.offset);
-    dict.Set("isFile", stats.is_file);
-    dict.Set("isDirectory", stats.is_directory);
-    dict.Set("isLink", stats.is_link);
+    dict.Set("type", static_cast<int>(stats.type));
     args.GetReturnValue().Set(dict.GetHandle());
   }
 

+ 2 - 4
shell/common/asar/archive.cc

@@ -311,14 +311,12 @@ bool Archive::Stat(const base::FilePath& path, Stats* stats) const {
     return false;
 
   if (node->Find("link")) {
-    stats->is_file = false;
-    stats->is_link = true;
+    stats->type = FileType::kLink;
     return true;
   }
 
   if (node->Find("files")) {
-    stats->is_file = false;
-    stats->is_directory = true;
+    stats->type = FileType::kDirectory;
     return true;
   }
 

+ 9 - 4
shell/common/asar/archive.h

@@ -10,6 +10,8 @@
 #include <unordered_map>
 #include <vector>
 
+#include <uv.h>
+
 #include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/synchronization/lock.h"
@@ -49,11 +51,14 @@ class Archive {
     absl::optional<IntegrityPayload> integrity;
   };
 
+  enum class FileType {
+    kFile = UV_DIRENT_FILE,
+    kDirectory = UV_DIRENT_DIR,
+    kLink = UV_DIRENT_LINK,
+  };
+
   struct Stats : public FileInfo {
-    Stats() : is_file(true), is_directory(false), is_link(false) {}
-    bool is_file;
-    bool is_directory;
-    bool is_link;
+    FileType type = FileType::kFile;
   };
 
   explicit Archive(const base::FilePath& path);

+ 1 - 3
typings/internal-ambient.d.ts

@@ -72,9 +72,7 @@ declare namespace NodeJS {
   type AsarFileStat = {
     size: number;
     offset: number;
-    isFile: boolean;
-    isDirectory: boolean;
-    isLink: boolean;
+    type: number;
   }
 
   interface AsarArchive {