dom/system/OSFileConstants.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "mozilla/DebugOnly.h"
     7 #include "fcntl.h"
     8 #include "errno.h"
    10 #include "prsystem.h"
    12 #if defined(XP_UNIX)
    13 #include "unistd.h"
    14 #include "dirent.h"
    15 #include "sys/stat.h"
    16 #if defined(ANDROID)
    17 #include <sys/vfs.h>
    18 #define statvfs statfs
    19 #else
    20 #include "sys/statvfs.h"
    21 #include <spawn.h>
    22 #endif // defined(ANDROID)
    23 #endif // defined(XP_UNIX)
    25 #if defined(XP_LINUX)
    26 #include <linux/fadvise.h>
    27 #endif // defined(XP_LINUX)
    29 #if defined(XP_MACOSX)
    30 #include "copyfile.h"
    31 #endif // defined(XP_MACOSX)
    33 #if defined(XP_WIN)
    34 #include <windows.h>
    35 #include <accctrl.h>
    36 #endif // defined(XP_WIN)
    38 #include "jsapi.h"
    39 #include "jsfriendapi.h"
    40 #include "BindingUtils.h"
    42 // Used to provide information on the OS
    44 #include "nsThreadUtils.h"
    45 #include "nsIObserverService.h"
    46 #include "nsIObserver.h"
    47 #include "nsDirectoryServiceUtils.h"
    48 #include "nsIXULRuntime.h"
    49 #include "nsIPropertyBag2.h"
    50 #include "nsXPCOMCIDInternal.h"
    51 #include "nsServiceManagerUtils.h"
    52 #include "nsString.h"
    53 #include "nsAutoPtr.h"
    54 #include "nsDirectoryServiceDefs.h"
    55 #include "nsXULAppAPI.h"
    56 #include "nsAppDirectoryServiceDefs.h"
    57 #include "mozJSComponentLoader.h"
    59 #include "OSFileConstants.h"
    60 #include "nsIOSFileConstantsService.h"
    61 #include "nsZipArchive.h"
    63 #if defined(__DragonFly__) || defined(__FreeBSD__) \
    64   || defined(__NetBSD__) || defined(__OpenBSD__)
    65 #define __dd_fd dd_fd
    66 #endif
    68 /**
    69  * This module defines the basic libc constants (error numbers, open modes,
    70  * etc.) used by OS.File and possibly other OS-bound JavaScript libraries.
    71  */
    74 namespace mozilla {
    76 // Use an anonymous namespace to hide the symbols and avoid any collision
    77 // with, for instance, |extern bool gInitialized;|
    78 namespace {
    79 /**
    80  * |true| if this module has been initialized, |false| otherwise
    81  */
    82 bool gInitialized = false;
    84 struct Paths {
    85   /**
    86    * The name of the directory holding all the libraries (libxpcom, libnss, etc.)
    87    */
    88   nsString libDir;
    89   nsString tmpDir;
    90   nsString profileDir;
    91   nsString localProfileDir;
    92   /**
    93    * The user's home directory
    94    */
    95   nsString homeDir;
    96   /**
    97    * The user's desktop directory, if there is one. Otherwise this is
    98    * the same as homeDir.
    99    */
   100   nsString desktopDir;
   101   /**
   102    * The user's 'application data' directory.
   103    * Windows:
   104    *   HOME = Documents and Settings\$USER\Application Data
   105    *   UAppData = $HOME[\$vendor]\$name
   106    *
   107    * Unix:
   108    *   HOME = ~
   109    *   UAppData = $HOME/.[$vendor/]$name
   110    *
   111    * Mac:
   112    *   HOME = ~
   113    *   UAppData = $HOME/Library/Application Support/$name
   114    */
   115   nsString userApplicationDataDir;
   117 #if defined(XP_WIN)
   118   /**
   119    * The user's application data directory.
   120    */
   121   nsString winAppDataDir;
   122   /**
   123    * The programs subdirectory in the user's start menu directory.
   124    */
   125   nsString winStartMenuProgsDir;
   126 #endif // defined(XP_WIN)
   128 #if defined(XP_MACOSX)
   129   /**
   130    * The user's Library directory.
   131    */
   132   nsString macUserLibDir;
   133   /**
   134    * The Application directory, that stores applications installed in the
   135    * system.
   136    */
   137   nsString macLocalApplicationsDir;
   138 #endif // defined(XP_MACOSX)
   140   Paths()
   141   {
   142     libDir.SetIsVoid(true);
   143     tmpDir.SetIsVoid(true);
   144     profileDir.SetIsVoid(true);
   145     localProfileDir.SetIsVoid(true);
   146     homeDir.SetIsVoid(true);
   147     desktopDir.SetIsVoid(true);
   148     userApplicationDataDir.SetIsVoid(true);
   150 #if defined(XP_WIN)
   151     winAppDataDir.SetIsVoid(true);
   152     winStartMenuProgsDir.SetIsVoid(true);
   153 #endif // defined(XP_WIN)
   155 #if defined(XP_MACOSX)
   156     macUserLibDir.SetIsVoid(true);
   157     macLocalApplicationsDir.SetIsVoid(true);
   158 #endif // defined(XP_MACOSX)
   159   }
   160 };
   162 /**
   163  * System directories.
   164  */
   165 Paths* gPaths = nullptr;
   167 /**
   168  * (Unix) the umask, which goes in OS.Constants.Sys but
   169  * can only be looked up (via the system-info service)
   170  * on the main thread.
   171  */
   172 uint32_t gUserUmask = 0;
   173 }
   175 /**
   176  * Return the path to one of the special directories.
   177  *
   178  * @param aKey The key to the special directory (e.g. "TmpD", "ProfD", ...)
   179  * @param aOutPath The path to the special directory. In case of error,
   180  * the string is set to void.
   181  */
   182 nsresult GetPathToSpecialDir(const char *aKey, nsString& aOutPath)
   183 {
   184   nsCOMPtr<nsIFile> file;
   185   nsresult rv = NS_GetSpecialDirectory(aKey, getter_AddRefs(file));
   186   if (NS_FAILED(rv) || !file) {
   187     return rv;
   188   }
   190   return file->GetPath(aOutPath);
   191 }
   193 /**
   194  * In some cases, OSFileConstants may be instantiated before the
   195  * profile is setup. In such cases, |OS.Constants.Path.profileDir| and
   196  * |OS.Constants.Path.localProfileDir| are undefined. However, we want
   197  * to ensure that this does not break existing code, so that future
   198  * workers spawned after the profile is setup have these constants.
   199  *
   200  * For this purpose, we register an observer to set |gPaths->profileDir|
   201  * and |gPaths->localProfileDir| once the profile is setup.
   202  */
   203 class DelayedPathSetter MOZ_FINAL: public nsIObserver
   204 {
   205   NS_DECL_ISUPPORTS
   206   NS_DECL_NSIOBSERVER
   208   DelayedPathSetter() {}
   209 };
   211 NS_IMPL_ISUPPORTS(DelayedPathSetter, nsIObserver)
   213 NS_IMETHODIMP
   214 DelayedPathSetter::Observe(nsISupports*, const char * aTopic, const char16_t*)
   215 {
   216   if (gPaths == nullptr) {
   217     // Initialization of gPaths has not taken place, something is wrong,
   218     // don't make things worse.
   219     return NS_OK;
   220   }
   221   nsresult rv = GetPathToSpecialDir(NS_APP_USER_PROFILE_50_DIR, gPaths->profileDir);
   222   if (NS_FAILED(rv)) {
   223     return rv;
   224   }
   225   rv = GetPathToSpecialDir(NS_APP_USER_PROFILE_LOCAL_50_DIR, gPaths->localProfileDir);
   226   if (NS_FAILED(rv)) {
   227     return rv;
   228   }
   230   return NS_OK;
   231 }
   233 /**
   234  * Perform the part of initialization that can only be
   235  * executed on the main thread.
   236  */
   237 nsresult InitOSFileConstants()
   238 {
   239   MOZ_ASSERT(NS_IsMainThread());
   240   if (gInitialized) {
   241     return NS_OK;
   242   }
   244   gInitialized = true;
   246   nsAutoPtr<Paths> paths(new Paths);
   248   // Initialize paths->libDir
   249   nsCOMPtr<nsIFile> file;
   250   nsresult rv = NS_GetSpecialDirectory(NS_XPCOM_LIBRARY_FILE, getter_AddRefs(file));
   251   if (NS_FAILED(rv)) {
   252     return rv;
   253   }
   255   nsCOMPtr<nsIFile> libDir;
   256   rv = file->GetParent(getter_AddRefs(libDir));
   257   if (NS_FAILED(rv)) {
   258     return rv;
   259   }
   261   rv = libDir->GetPath(paths->libDir);
   262   if (NS_FAILED(rv)) {
   263     return rv;
   264   }
   266   // Setup profileDir and localProfileDir immediately if possible (we
   267   // assume that NS_APP_USER_PROFILE_50_DIR and
   268   // NS_APP_USER_PROFILE_LOCAL_50_DIR are set simultaneously)
   269   rv = GetPathToSpecialDir(NS_APP_USER_PROFILE_50_DIR, paths->profileDir);
   270   if (NS_SUCCEEDED(rv)) {
   271     rv = GetPathToSpecialDir(NS_APP_USER_PROFILE_LOCAL_50_DIR, paths->localProfileDir);
   272   }
   274   // Otherwise, delay setup of profileDir/localProfileDir until they
   275   // become available.
   276   if (NS_FAILED(rv)) {
   277     nsCOMPtr<nsIObserverService> obsService = do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
   278     if (NS_FAILED(rv)) {
   279       return rv;
   280     }
   281     nsRefPtr<DelayedPathSetter> pathSetter = new DelayedPathSetter();
   282     rv = obsService->AddObserver(pathSetter, "profile-do-change", false);
   283     if (NS_FAILED(rv)) {
   284       return rv;
   285     }
   286   }
   288   // For other directories, ignore errors (they may be undefined on
   289   // some platforms or in non-Firefox embeddings of Gecko).
   291   GetPathToSpecialDir(NS_OS_TEMP_DIR, paths->tmpDir);
   292   GetPathToSpecialDir(NS_OS_HOME_DIR, paths->homeDir);
   293   GetPathToSpecialDir(NS_OS_DESKTOP_DIR, paths->desktopDir);
   294   GetPathToSpecialDir(XRE_USER_APP_DATA_DIR, paths->userApplicationDataDir);
   296 #if defined(XP_WIN)
   297   GetPathToSpecialDir(NS_WIN_APPDATA_DIR, paths->winAppDataDir);
   298   GetPathToSpecialDir(NS_WIN_PROGRAMS_DIR, paths->winStartMenuProgsDir);
   299 #endif // defined(XP_WIN)
   301 #if defined(XP_MACOSX)
   302   GetPathToSpecialDir(NS_MAC_USER_LIB_DIR, paths->macUserLibDir);
   303   GetPathToSpecialDir(NS_OSX_LOCAL_APPLICATIONS_DIR, paths->macLocalApplicationsDir);
   304 #endif // defined(XP_MACOSX)
   306   gPaths = paths.forget();
   308   // Get the umask from the system-info service.
   309   // The property will always be present, but it will be zero on
   310   // non-Unix systems.
   311   nsCOMPtr<nsIPropertyBag2> infoService =
   312     do_GetService("@mozilla.org/system-info;1");
   313   MOZ_ASSERT(infoService, "Could not access the system information service");
   314   rv = infoService->GetPropertyAsUint32(NS_LITERAL_STRING("umask"),
   315                                         &gUserUmask);
   316   if (NS_FAILED(rv)) {
   317     return rv;
   318   }
   320   return NS_OK;
   321 }
   323 /**
   324  * Perform the cleaning up that can only be executed on the main thread.
   325  */
   326 void CleanupOSFileConstants()
   327 {
   328   MOZ_ASSERT(NS_IsMainThread());
   329   if (!gInitialized) {
   330     return;
   331   }
   333   gInitialized = false;
   334   delete gPaths;
   335 }
   338 /**
   339  * Define a simple read-only property holding an integer.
   340  *
   341  * @param name The name of the constant. Used both as the JS name for the
   342  * constant and to access its value. Must be defined.
   343  *
   344  * Produces a |ConstantSpec|.
   345  */
   346 #define INT_CONSTANT(name)      \
   347   { #name, INT_TO_JSVAL(name) }
   349 /**
   350  * Define a simple read-only property holding an unsigned integer.
   351  *
   352  * @param name The name of the constant. Used both as the JS name for the
   353  * constant and to access its value. Must be defined.
   354  *
   355  * Produces a |ConstantSpec|.
   356  */
   357 #define UINT_CONSTANT(name)      \
   358   { #name, UINT_TO_JSVAL((name)) }
   360 /**
   361  * End marker for ConstantSpec
   362  */
   363 #define PROP_END { nullptr, JS::UndefinedValue() }
   366 // Define missing constants for Android
   367 #if !defined(S_IRGRP)
   368 #define S_IXOTH 0001
   369 #define S_IWOTH 0002
   370 #define S_IROTH 0004
   371 #define S_IRWXO 0007
   372 #define S_IXGRP 0010
   373 #define S_IWGRP 0020
   374 #define S_IRGRP 0040
   375 #define S_IRWXG 0070
   376 #define S_IXUSR 0100
   377 #define S_IWUSR 0200
   378 #define S_IRUSR 0400
   379 #define S_IRWXU 0700
   380 #endif // !defined(S_IRGRP)
   382 /**
   383  * The properties defined in libc.
   384  *
   385  * If you extend this list of properties, please
   386  * separate categories ("errors", "open", etc.),
   387  * keep properties organized by alphabetical order
   388  * and #ifdef-away properties that are not portable.
   389  */
   390 static const dom::ConstantSpec gLibcProperties[] =
   391 {
   392   // Arguments for open
   393   INT_CONSTANT(O_APPEND),
   394   INT_CONSTANT(O_CREAT),
   395 #if defined(O_DIRECTORY)
   396   INT_CONSTANT(O_DIRECTORY),
   397 #endif // defined(O_DIRECTORY)
   398 #if defined(O_EVTONLY)
   399   INT_CONSTANT(O_EVTONLY),
   400 #endif // defined(O_EVTONLY)
   401   INT_CONSTANT(O_EXCL),
   402 #if defined(O_EXLOCK)
   403   INT_CONSTANT(O_EXLOCK),
   404 #endif // defined(O_EXLOCK)
   405 #if defined(O_LARGEFILE)
   406   INT_CONSTANT(O_LARGEFILE),
   407 #endif // defined(O_LARGEFILE)
   408 #if defined(O_NOFOLLOW)
   409   INT_CONSTANT(O_NOFOLLOW),
   410 #endif // defined(O_NOFOLLOW)
   411 #if defined(O_NONBLOCK)
   412   INT_CONSTANT(O_NONBLOCK),
   413 #endif // defined(O_NONBLOCK)
   414   INT_CONSTANT(O_RDONLY),
   415   INT_CONSTANT(O_RDWR),
   416 #if defined(O_RSYNC)
   417   INT_CONSTANT(O_RSYNC),
   418 #endif // defined(O_RSYNC)
   419 #if defined(O_SHLOCK)
   420   INT_CONSTANT(O_SHLOCK),
   421 #endif // defined(O_SHLOCK)
   422 #if defined(O_SYMLINK)
   423   INT_CONSTANT(O_SYMLINK),
   424 #endif // defined(O_SYMLINK)
   425 #if defined(O_SYNC)
   426   INT_CONSTANT(O_SYNC),
   427 #endif // defined(O_SYNC)
   428   INT_CONSTANT(O_TRUNC),
   429   INT_CONSTANT(O_WRONLY),
   431 #if defined(AT_EACCESS)
   432   INT_CONSTANT(AT_EACCESS),
   433 #endif //defined(AT_EACCESS)
   434 #if defined(AT_FDCWD)
   435   INT_CONSTANT(AT_FDCWD),
   436 #endif //defined(AT_FDCWD)
   437 #if defined(AT_SYMLINK_NOFOLLOW)
   438   INT_CONSTANT(AT_SYMLINK_NOFOLLOW),
   439 #endif //defined(AT_SYMLINK_NOFOLLOW)
   441 #if defined(POSIX_FADV_SEQUENTIAL)
   442   INT_CONSTANT(POSIX_FADV_SEQUENTIAL),
   443 #endif //defined(POSIX_FADV_SEQUENTIAL)
   445   // access
   446 #if defined(F_OK)
   447   INT_CONSTANT(F_OK),
   448   INT_CONSTANT(R_OK),
   449   INT_CONSTANT(W_OK),
   450   INT_CONSTANT(X_OK),
   451 #endif // defined(F_OK)
   453   // modes
   454   INT_CONSTANT(S_IRGRP),
   455   INT_CONSTANT(S_IROTH),
   456   INT_CONSTANT(S_IRUSR),
   457   INT_CONSTANT(S_IRWXG),
   458   INT_CONSTANT(S_IRWXO),
   459   INT_CONSTANT(S_IRWXU),
   460   INT_CONSTANT(S_IWGRP),
   461   INT_CONSTANT(S_IWOTH),
   462   INT_CONSTANT(S_IWUSR),
   463   INT_CONSTANT(S_IXOTH),
   464   INT_CONSTANT(S_IXGRP),
   465   INT_CONSTANT(S_IXUSR),
   467   // seek
   468   INT_CONSTANT(SEEK_CUR),
   469   INT_CONSTANT(SEEK_END),
   470   INT_CONSTANT(SEEK_SET),
   472   // copyfile
   473 #if defined(COPYFILE_DATA)
   474   INT_CONSTANT(COPYFILE_DATA),
   475   INT_CONSTANT(COPYFILE_EXCL),
   476   INT_CONSTANT(COPYFILE_XATTR),
   477   INT_CONSTANT(COPYFILE_STAT),
   478   INT_CONSTANT(COPYFILE_ACL),
   479   INT_CONSTANT(COPYFILE_MOVE),
   480 #endif // defined(COPYFILE_DATA)
   482   // error values
   483   INT_CONSTANT(EACCES),
   484   INT_CONSTANT(EAGAIN),
   485   INT_CONSTANT(EBADF),
   486   INT_CONSTANT(EEXIST),
   487   INT_CONSTANT(EFAULT),
   488   INT_CONSTANT(EFBIG),
   489   INT_CONSTANT(EINVAL),
   490   INT_CONSTANT(EIO),
   491   INT_CONSTANT(EISDIR),
   492 #if defined(ELOOP) // not defined with VC9
   493   INT_CONSTANT(ELOOP),
   494 #endif // defined(ELOOP)
   495   INT_CONSTANT(EMFILE),
   496   INT_CONSTANT(ENAMETOOLONG),
   497   INT_CONSTANT(ENFILE),
   498   INT_CONSTANT(ENOENT),
   499   INT_CONSTANT(ENOMEM),
   500   INT_CONSTANT(ENOSPC),
   501   INT_CONSTANT(ENOTDIR),
   502   INT_CONSTANT(ENXIO),
   503 #if defined(EOPNOTSUPP) // not defined with VC 9
   504   INT_CONSTANT(EOPNOTSUPP),
   505 #endif // defined(EOPNOTSUPP)
   506 #if defined(EOVERFLOW) // not defined with VC 9
   507   INT_CONSTANT(EOVERFLOW),
   508 #endif // defined(EOVERFLOW)
   509   INT_CONSTANT(EPERM),
   510   INT_CONSTANT(ERANGE),
   511 #if defined(ETIMEDOUT) // not defined with VC 9
   512   INT_CONSTANT(ETIMEDOUT),
   513 #endif // defined(ETIMEDOUT)
   514 #if defined(EWOULDBLOCK) // not defined with VC 9
   515   INT_CONSTANT(EWOULDBLOCK),
   516 #endif // defined(EWOULDBLOCK)
   517   INT_CONSTANT(EXDEV),
   519 #if defined(DT_UNKNOWN)
   520   // Constants for |readdir|
   521   INT_CONSTANT(DT_UNKNOWN),
   522   INT_CONSTANT(DT_FIFO),
   523   INT_CONSTANT(DT_CHR),
   524   INT_CONSTANT(DT_DIR),
   525   INT_CONSTANT(DT_BLK),
   526   INT_CONSTANT(DT_REG),
   527   INT_CONSTANT(DT_LNK),
   528   INT_CONSTANT(DT_SOCK),
   529 #endif // defined(DT_UNKNOWN)
   531 #if defined(S_IFIFO)
   532   // Constants for |stat|
   533   INT_CONSTANT(S_IFMT),
   534   INT_CONSTANT(S_IFIFO),
   535   INT_CONSTANT(S_IFCHR),
   536   INT_CONSTANT(S_IFDIR),
   537   INT_CONSTANT(S_IFBLK),
   538   INT_CONSTANT(S_IFREG),
   539   INT_CONSTANT(S_IFLNK),
   540   INT_CONSTANT(S_IFSOCK),
   541 #endif // defined(S_IFIFO)
   543   // Constants used to define data structures
   544   //
   545   // Many data structures have different fields/sizes/etc. on
   546   // various OSes / versions of the same OS / platforms. For these
   547   // data structures, we need to compute and export from C the size
   548   // and, if necessary, the offset of fields, so as to be able to
   549   // define the structure in JS.
   551 #if defined(XP_UNIX)
   552   // The size of |mode_t|.
   553   { "OSFILE_SIZEOF_MODE_T", INT_TO_JSVAL(sizeof (mode_t)) },
   555   // The size of |gid_t|.
   556   { "OSFILE_SIZEOF_GID_T", INT_TO_JSVAL(sizeof (gid_t)) },
   558   // The size of |uid_t|.
   559   { "OSFILE_SIZEOF_UID_T", INT_TO_JSVAL(sizeof (uid_t)) },
   561   // The size of |time_t|.
   562   { "OSFILE_SIZEOF_TIME_T", INT_TO_JSVAL(sizeof (time_t)) },
   564   // The size of |fsblkcnt_t|.
   565   { "OSFILE_SIZEOF_FSBLKCNT_T", INT_TO_JSVAL(sizeof (fsblkcnt_t)) },
   567 #if !defined(ANDROID)
   568   // The size of |posix_spawn_file_actions_t|.
   569   { "OSFILE_SIZEOF_POSIX_SPAWN_FILE_ACTIONS_T", INT_TO_JSVAL(sizeof (posix_spawn_file_actions_t)) },
   570 #endif // !defined(ANDROID)
   572   // Defining |dirent|.
   573   // Size
   574   { "OSFILE_SIZEOF_DIRENT", INT_TO_JSVAL(sizeof (dirent)) },
   576   // Offset of field |d_name|.
   577   { "OSFILE_OFFSETOF_DIRENT_D_NAME", INT_TO_JSVAL(offsetof (struct dirent, d_name)) },
   578   // An upper bound to the length of field |d_name| of struct |dirent|.
   579   // (may not be exact, depending on padding).
   580   { "OSFILE_SIZEOF_DIRENT_D_NAME", INT_TO_JSVAL(sizeof (struct dirent) - offsetof (struct dirent, d_name)) },
   582   // Defining |timeval|.
   583   { "OSFILE_SIZEOF_TIMEVAL", INT_TO_JSVAL(sizeof (struct timeval)) },
   584   { "OSFILE_OFFSETOF_TIMEVAL_TV_SEC", INT_TO_JSVAL(offsetof (struct timeval, tv_sec)) },
   585   { "OSFILE_OFFSETOF_TIMEVAL_TV_USEC", INT_TO_JSVAL(offsetof (struct timeval, tv_usec)) },
   587 #if defined(DT_UNKNOWN)
   588   // Position of field |d_type| in |dirent|
   589   // Not strictly posix, but seems defined on all platforms
   590   // except mingw32.
   591   { "OSFILE_OFFSETOF_DIRENT_D_TYPE", INT_TO_JSVAL(offsetof (struct dirent, d_type)) },
   592 #endif // defined(DT_UNKNOWN)
   594   // Under MacOS X and BSDs, |dirfd| is a macro rather than a
   595   // function, so we need a little help to get it to work
   596 #if defined(dirfd)
   597   { "OSFILE_SIZEOF_DIR", INT_TO_JSVAL(sizeof (DIR)) },
   599   { "OSFILE_OFFSETOF_DIR_DD_FD", INT_TO_JSVAL(offsetof (DIR, __dd_fd)) },
   600 #endif
   602   // Defining |stat|
   604   { "OSFILE_SIZEOF_STAT", INT_TO_JSVAL(sizeof (struct stat)) },
   606   { "OSFILE_OFFSETOF_STAT_ST_MODE", INT_TO_JSVAL(offsetof (struct stat, st_mode)) },
   607   { "OSFILE_OFFSETOF_STAT_ST_UID", INT_TO_JSVAL(offsetof (struct stat, st_uid)) },
   608   { "OSFILE_OFFSETOF_STAT_ST_GID", INT_TO_JSVAL(offsetof (struct stat, st_gid)) },
   609   { "OSFILE_OFFSETOF_STAT_ST_SIZE", INT_TO_JSVAL(offsetof (struct stat, st_size)) },
   611 #if defined(HAVE_ST_ATIMESPEC)
   612   { "OSFILE_OFFSETOF_STAT_ST_ATIME", INT_TO_JSVAL(offsetof (struct stat, st_atimespec)) },
   613   { "OSFILE_OFFSETOF_STAT_ST_MTIME", INT_TO_JSVAL(offsetof (struct stat, st_mtimespec)) },
   614   { "OSFILE_OFFSETOF_STAT_ST_CTIME", INT_TO_JSVAL(offsetof (struct stat, st_ctimespec)) },
   615 #else
   616   { "OSFILE_OFFSETOF_STAT_ST_ATIME", INT_TO_JSVAL(offsetof (struct stat, st_atime)) },
   617   { "OSFILE_OFFSETOF_STAT_ST_MTIME", INT_TO_JSVAL(offsetof (struct stat, st_mtime)) },
   618   { "OSFILE_OFFSETOF_STAT_ST_CTIME", INT_TO_JSVAL(offsetof (struct stat, st_ctime)) },
   619 #endif // defined(HAVE_ST_ATIME)
   621   // Several OSes have a birthtime field. For the moment, supporting only Darwin.
   622 #if defined(_DARWIN_FEATURE_64_BIT_INODE)
   623   { "OSFILE_OFFSETOF_STAT_ST_BIRTHTIME", INT_TO_JSVAL(offsetof (struct stat, st_birthtime)) },
   624 #endif // defined(_DARWIN_FEATURE_64_BIT_INODE)
   626   // Defining |statvfs|
   628   { "OSFILE_SIZEOF_STATVFS", INT_TO_JSVAL(sizeof (struct statvfs)) },
   630   { "OSFILE_OFFSETOF_STATVFS_F_BSIZE", INT_TO_JSVAL(offsetof (struct statvfs, f_bsize)) },
   631   { "OSFILE_OFFSETOF_STATVFS_F_BAVAIL", INT_TO_JSVAL(offsetof (struct statvfs, f_bavail)) },
   633 #endif // defined(XP_UNIX)
   637   // System configuration
   639   // Under MacOSX, to avoid using deprecated functions that do not
   640   // match the constants we define in this object (including
   641   // |sizeof|/|offsetof| stuff, but not only), for a number of
   642   // functions, we need to adapt the name of the symbols we are using,
   643   // whenever macro _DARWIN_FEATURE_64_BIT_INODE is set. We export
   644   // this value to be able to do so from JavaScript.
   645 #if defined(_DARWIN_FEATURE_64_BIT_INODE)
   646    { "_DARWIN_FEATURE_64_BIT_INODE", INT_TO_JSVAL(1) },
   647 #endif // defined(_DARWIN_FEATURE_64_BIT_INODE)
   649   // Similar feature for Linux
   650 #if defined(_STAT_VER)
   651   INT_CONSTANT(_STAT_VER),
   652 #endif // defined(_STAT_VER)
   654   PROP_END
   655 };
   658 #if defined(XP_WIN)
   659 /**
   660  * The properties defined in windows.h.
   661  *
   662  * If you extend this list of properties, please
   663  * separate categories ("errors", "open", etc.),
   664  * keep properties organized by alphabetical order
   665  * and #ifdef-away properties that are not portable.
   666  */
   667 static const dom::ConstantSpec gWinProperties[] =
   668 {
   669   // FormatMessage flags
   670   INT_CONSTANT(FORMAT_MESSAGE_FROM_SYSTEM),
   671   INT_CONSTANT(FORMAT_MESSAGE_IGNORE_INSERTS),
   673   // The max length of paths
   674   INT_CONSTANT(MAX_PATH),
   676   // CreateFile desired access
   677   INT_CONSTANT(GENERIC_ALL),
   678   INT_CONSTANT(GENERIC_EXECUTE),
   679   INT_CONSTANT(GENERIC_READ),
   680   INT_CONSTANT(GENERIC_WRITE),
   682   // CreateFile share mode
   683   INT_CONSTANT(FILE_SHARE_DELETE),
   684   INT_CONSTANT(FILE_SHARE_READ),
   685   INT_CONSTANT(FILE_SHARE_WRITE),
   687   // CreateFile creation disposition
   688   INT_CONSTANT(CREATE_ALWAYS),
   689   INT_CONSTANT(CREATE_NEW),
   690   INT_CONSTANT(OPEN_ALWAYS),
   691   INT_CONSTANT(OPEN_EXISTING),
   692   INT_CONSTANT(TRUNCATE_EXISTING),
   694   // CreateFile attributes
   695   INT_CONSTANT(FILE_ATTRIBUTE_ARCHIVE),
   696   INT_CONSTANT(FILE_ATTRIBUTE_DIRECTORY),
   697   INT_CONSTANT(FILE_ATTRIBUTE_NORMAL),
   698   INT_CONSTANT(FILE_ATTRIBUTE_READONLY),
   699   INT_CONSTANT(FILE_ATTRIBUTE_REPARSE_POINT),
   700   INT_CONSTANT(FILE_ATTRIBUTE_TEMPORARY),
   701   INT_CONSTANT(FILE_FLAG_BACKUP_SEMANTICS),
   703   // CreateFile error constant
   704   { "INVALID_HANDLE_VALUE", INT_TO_JSVAL(INT_PTR(INVALID_HANDLE_VALUE)) },
   707   // CreateFile flags
   708   INT_CONSTANT(FILE_FLAG_DELETE_ON_CLOSE),
   710   // SetFilePointer methods
   711   INT_CONSTANT(FILE_BEGIN),
   712   INT_CONSTANT(FILE_CURRENT),
   713   INT_CONSTANT(FILE_END),
   715   // SetFilePointer error constant
   716   UINT_CONSTANT(INVALID_SET_FILE_POINTER),
   718   // File attributes
   719   INT_CONSTANT(FILE_ATTRIBUTE_DIRECTORY),
   722   // MoveFile flags
   723   INT_CONSTANT(MOVEFILE_COPY_ALLOWED),
   724   INT_CONSTANT(MOVEFILE_REPLACE_EXISTING),
   726   // GetFileAttributes error constant
   727   INT_CONSTANT(INVALID_FILE_ATTRIBUTES),
   729   // GetNamedSecurityInfo and SetNamedSecurityInfo constants
   730   INT_CONSTANT(UNPROTECTED_DACL_SECURITY_INFORMATION),
   731   INT_CONSTANT(SE_FILE_OBJECT),
   732   INT_CONSTANT(DACL_SECURITY_INFORMATION),
   734   // Errors
   735   INT_CONSTANT(ERROR_INVALID_HANDLE),
   736   INT_CONSTANT(ERROR_ACCESS_DENIED),
   737   INT_CONSTANT(ERROR_DIR_NOT_EMPTY),
   738   INT_CONSTANT(ERROR_FILE_EXISTS),
   739   INT_CONSTANT(ERROR_ALREADY_EXISTS),
   740   INT_CONSTANT(ERROR_FILE_NOT_FOUND),
   741   INT_CONSTANT(ERROR_NO_MORE_FILES),
   742   INT_CONSTANT(ERROR_PATH_NOT_FOUND),
   743   INT_CONSTANT(ERROR_BAD_ARGUMENTS),
   744   INT_CONSTANT(ERROR_NOT_SUPPORTED),
   746   PROP_END
   747 };
   748 #endif // defined(XP_WIN)
   751 /**
   752  * Get a field of an object as an object.
   753  *
   754  * If the field does not exist, create it. If it exists but is not an
   755  * object, throw a JS error.
   756  */
   757 JSObject *GetOrCreateObjectProperty(JSContext *cx, JS::Handle<JSObject*> aObject,
   758                                     const char *aProperty)
   759 {
   760   JS::Rooted<JS::Value> val(cx);
   761   if (!JS_GetProperty(cx, aObject, aProperty, &val)) {
   762     return nullptr;
   763   }
   764   if (!val.isUndefined()) {
   765     if (val.isObject()) {
   766       return &val.toObject();
   767     }
   769     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
   770       JSMSG_UNEXPECTED_TYPE, aProperty, "not an object");
   771     return nullptr;
   772   }
   773   return JS_DefineObject(cx, aObject, aProperty, nullptr, nullptr,
   774                          JSPROP_ENUMERATE);
   775 }
   777 /**
   778  * Set a property of an object from a nsString.
   779  *
   780  * If the nsString is void (i.e. IsVoid is true), do nothing.
   781  */
   782 bool SetStringProperty(JSContext *cx, JS::Handle<JSObject*> aObject, const char *aProperty,
   783                        const nsString aValue)
   784 {
   785   if (aValue.IsVoid()) {
   786     return true;
   787   }
   788   JSString* strValue = JS_NewUCStringCopyZ(cx, aValue.get());
   789   NS_ENSURE_TRUE(strValue, false);
   790   JS::Rooted<JS::Value> valValue(cx, STRING_TO_JSVAL(strValue));
   791   return JS_SetProperty(cx, aObject, aProperty, valValue);
   792 }
   794 /**
   795  * Define OS-specific constants.
   796  *
   797  * This function creates or uses JS object |OS.Constants| to store
   798  * all its constants.
   799  */
   800 bool DefineOSFileConstants(JSContext *cx, JS::Handle<JSObject*> global)
   801 {
   802   MOZ_ASSERT(gInitialized);
   804   if (gPaths == nullptr) {
   805     // If an initialization error was ignored, we may end up with
   806     // |gInitialized == true| but |gPaths == nullptr|. We cannot
   807     // |MOZ_ASSERT| this, as this would kill precompile_cache.js,
   808     // so we simply return an error.
   809     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
   810       JSMSG_CANT_OPEN, "OSFileConstants", "initialization has failed");
   811     return false;
   812   }
   814   JS::Rooted<JSObject*> objOS(cx);
   815   if (!(objOS = GetOrCreateObjectProperty(cx, global, "OS"))) {
   816     return false;
   817   }
   818   JS::Rooted<JSObject*> objConstants(cx);
   819   if (!(objConstants = GetOrCreateObjectProperty(cx, objOS, "Constants"))) {
   820     return false;
   821   }
   823   // Build OS.Constants.libc
   825   JS::Rooted<JSObject*> objLibc(cx);
   826   if (!(objLibc = GetOrCreateObjectProperty(cx, objConstants, "libc"))) {
   827     return false;
   828   }
   829   if (!dom::DefineConstants(cx, objLibc, gLibcProperties)) {
   830     return false;
   831   }
   833 #if defined(XP_WIN)
   834   // Build OS.Constants.Win
   836   JS::Rooted<JSObject*> objWin(cx);
   837   if (!(objWin = GetOrCreateObjectProperty(cx, objConstants, "Win"))) {
   838     return false;
   839   }
   840   if (!dom::DefineConstants(cx, objWin, gWinProperties)) {
   841     return false;
   842   }
   843 #endif // defined(XP_WIN)
   845   // Build OS.Constants.Sys
   847   JS::Rooted<JSObject*> objSys(cx);
   848   if (!(objSys = GetOrCreateObjectProperty(cx, objConstants, "Sys"))) {
   849     return false;
   850   }
   852   nsCOMPtr<nsIXULRuntime> runtime = do_GetService(XULRUNTIME_SERVICE_CONTRACTID);
   853   if (runtime) {
   854     nsAutoCString os;
   855     DebugOnly<nsresult> rv = runtime->GetOS(os);
   856     MOZ_ASSERT(NS_SUCCEEDED(rv));
   858     JSString* strVersion = JS_NewStringCopyZ(cx, os.get());
   859     if (!strVersion) {
   860       return false;
   861     }
   863     JS::Rooted<JS::Value> valVersion(cx, STRING_TO_JSVAL(strVersion));
   864     if (!JS_SetProperty(cx, objSys, "Name", valVersion)) {
   865       return false;
   866     }
   867   }
   869 #if defined(DEBUG)
   870   JS::Rooted<JS::Value> valDebug(cx, JSVAL_TRUE);
   871   if (!JS_SetProperty(cx, objSys, "DEBUG", valDebug)) {
   872     return false;
   873   }
   874 #endif
   876   dom::ConstantSpec umask_cs[] = {
   877     { "umask", UINT_TO_JSVAL(gUserUmask) },
   878     PROP_END
   879   };
   880   if (!dom::DefineConstants(cx, objSys, umask_cs)) {
   881       return false;
   882   }
   884   // Build OS.Constants.Path
   886   JS::Rooted<JSObject*> objPath(cx);
   887   if (!(objPath = GetOrCreateObjectProperty(cx, objConstants, "Path"))) {
   888     return false;
   889   }
   891   // Locate libxul
   892   // Note that we don't actually provide the full path, only the name of the
   893   // library, which is sufficient to link to the library using js-ctypes.
   895 #if defined(XP_MACOSX)
   896   // Under MacOS X, for some reason, libxul is called simply "XUL",
   897   // and we need to provide the full path.
   898   nsAutoString libxul;
   899   libxul.Append(gPaths->libDir);
   900   libxul.Append(NS_LITERAL_STRING("/XUL"));
   901 #else
   902   // On other platforms, libxul is a library "xul" with regular
   903   // library prefix/suffix.
   904   nsAutoString libxul;
   905   libxul.Append(NS_LITERAL_STRING(DLL_PREFIX));
   906   libxul.Append(NS_LITERAL_STRING("xul"));
   907   libxul.Append(NS_LITERAL_STRING(DLL_SUFFIX));
   908 #endif // defined(XP_MACOSX)
   910   if (!SetStringProperty(cx, objPath, "libxul", libxul)) {
   911     return false;
   912   }
   914   if (!SetStringProperty(cx, objPath, "libDir", gPaths->libDir)) {
   915     return false;
   916   }
   918   if (!SetStringProperty(cx, objPath, "tmpDir", gPaths->tmpDir)) {
   919     return false;
   920   }
   922   // Configure profileDir only if it is available at this stage
   923   if (!gPaths->profileDir.IsVoid()
   924     && !SetStringProperty(cx, objPath, "profileDir", gPaths->profileDir)) {
   925     return false;
   926   }
   928   // Configure localProfileDir only if it is available at this stage
   929   if (!gPaths->localProfileDir.IsVoid()
   930     && !SetStringProperty(cx, objPath, "localProfileDir", gPaths->localProfileDir)) {
   931     return false;
   932   }
   934   if (!SetStringProperty(cx, objPath, "homeDir", gPaths->homeDir)) {
   935     return false;
   936   }
   938   if (!SetStringProperty(cx, objPath, "desktopDir", gPaths->desktopDir)) {
   939     return false;
   940   }
   942   if (!SetStringProperty(cx, objPath, "userApplicationDataDir", gPaths->userApplicationDataDir)) {
   943     return false;
   944   }
   946 #if defined(XP_WIN)
   947   if (!SetStringProperty(cx, objPath, "winAppDataDir", gPaths->winAppDataDir)) {
   948     return false;
   949   }
   951   if (!SetStringProperty(cx, objPath, "winStartMenuProgsDir", gPaths->winStartMenuProgsDir)) {
   952     return false;
   953   }
   954 #endif // defined(XP_WIN)
   956 #if defined(XP_MACOSX)
   957   if (!SetStringProperty(cx, objPath, "macUserLibDir", gPaths->macUserLibDir)) {
   958     return false;
   959   }
   961   if (!SetStringProperty(cx, objPath, "macLocalApplicationsDir", gPaths->macLocalApplicationsDir)) {
   962     return false;
   963   }
   964 #endif // defined(XP_MACOSX)
   966   // sqlite3 is linked from different places depending on the platform
   967   nsAutoString libsqlite3;
   968 #if defined(ANDROID)
   969   // On Android, we use the system's libsqlite3
   970   libsqlite3.Append(NS_LITERAL_STRING(DLL_PREFIX));
   971   libsqlite3.Append(NS_LITERAL_STRING("sqlite3"));
   972   libsqlite3.Append(NS_LITERAL_STRING(DLL_SUFFIX));
   973 #elif defined(XP_WIN)
   974   // On Windows, for some reason, this is part of nss3.dll
   975   libsqlite3.Append(NS_LITERAL_STRING(DLL_PREFIX));
   976   libsqlite3.Append(NS_LITERAL_STRING("nss3"));
   977   libsqlite3.Append(NS_LITERAL_STRING(DLL_SUFFIX));
   978 #else
   979     // On other platforms, we link sqlite3 into libxul
   980   libsqlite3 = libxul;
   981 #endif // defined(ANDROID) || defined(XP_WIN)
   983   if (!SetStringProperty(cx, objPath, "libsqlite3", libsqlite3)) {
   984     return false;
   985   }
   987   return true;
   988 }
   990 NS_IMPL_ISUPPORTS(OSFileConstantsService, nsIOSFileConstantsService)
   992 OSFileConstantsService::OSFileConstantsService()
   993 {
   994   MOZ_ASSERT(NS_IsMainThread());
   995 }
   997 OSFileConstantsService::~OSFileConstantsService()
   998 {
   999   mozilla::CleanupOSFileConstants();
  1003 NS_IMETHODIMP
  1004 OSFileConstantsService::Init(JSContext *aCx)
  1006   nsresult rv = mozilla::InitOSFileConstants();
  1007   if (NS_FAILED(rv)) {
  1008     return rv;
  1011   mozJSComponentLoader* loader = mozJSComponentLoader::Get();
  1012   JS::Rooted<JSObject*> targetObj(aCx);
  1013   rv = loader->FindTargetObject(aCx, &targetObj);
  1014   NS_ENSURE_SUCCESS(rv, rv);
  1016   if (!mozilla::DefineOSFileConstants(aCx, targetObj)) {
  1017     return NS_ERROR_FAILURE;
  1020   return NS_OK;
  1023 } // namespace mozilla

mercurial