예제 #1
0
bool
UnshareUserNamespace()
{
  // The uid and gid need to be retrieved before the unshare; see
  // below.
  uid_t uid = getuid();
  gid_t gid = getgid();
  char buf[80];
  size_t len;

  if (syscall(__NR_unshare, CLONE_NEWUSER) != 0) {
    return false;
  }

  // As mentioned in the header, this function sets up uid/gid
  // mappings that preserve the process's previous ids.  Mapping the
  // uid/gid to something is necessary in order to nest user
  // namespaces (not used yet, but we'll need this in the future for
  // pid namespace support), and leaving the ids unchanged is the
  // least confusing option.
  //
  // In recent kernels (3.19, 3.18.2, 3.17.8), for security reasons,
  // establishing gid mappings will fail unless the process first
  // revokes its ability to call setgroups() by using a /proc node
  // added in the same set of patches.
  //
  // Note that /proc/self points to the thread group leader, not the
  // current thread.  However, CLONE_NEWUSER can be unshared only in a
  // single-threaded process, so those are equivalent if we reach this
  // point.
  len = size_t(SprintfLiteral(buf, "%u %u 1\n", uid, uid));
  MOZ_ASSERT(len < sizeof(buf));
  if (!WriteStringToFile("/proc/self/uid_map", buf, len)) {
    MOZ_CRASH("Failed to write /proc/self/uid_map");
  }

  Unused << WriteStringToFile("/proc/self/setgroups", "deny", 4);

  len = size_t(SprintfLiteral(buf, "%u %u 1\n", gid, gid));
  MOZ_ASSERT(len < sizeof(buf));
  if (!WriteStringToFile("/proc/self/gid_map", buf, len)) {
    MOZ_CRASH("Failed to write /proc/self/gid_map");
  }
  return true;
}
static int do_main(int argc, char* argv[])
{
  nsCOMPtr<nsIFile> appini;
  nsresult rv;

  // Allow firefox.exe to launch XULRunner apps via -app <application.ini>
  // Note that -app must be the *first* argument.
  const char *appDataFile = getenv("XUL_APP_FILE");
  if (appDataFile && *appDataFile) {
    rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini));
    if (NS_FAILED(rv)) {
      Output("Invalid path found: '%s'", appDataFile);
      return 255;
    }
  }
  else if (argc > 1 && IsArg(argv[1], "app")) {
    if (argc == 2) {
      Output("Incorrect number of arguments passed to -app");
      return 255;
    }

    rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini));
    if (NS_FAILED(rv)) {
      Output("application.ini path not recognized: '%s'", argv[2]);
      return 255;
    }

    char appEnv[MAXPATHLEN];
    SprintfLiteral(appEnv, "XUL_APP_FILE=%s", argv[2]);
    if (putenv(strdup(appEnv))) {
      Output("Couldn't set %s.\n", appEnv);
      return 255;
    }
    argv[2] = argv[0];
    argv += 2;
    argc -= 2;
  }

#ifdef MOZ_WIDGET_GONK
  /* Start boot animation */
  mozilla::StartBootAnimation();
#endif

  if (appini) {
    nsXREAppData *appData;
    rv = XRE_CreateAppData(appini, &appData);
    if (NS_FAILED(rv)) {
      Output("Couldn't read application.ini");
      return 255;
    }
    int result = XRE_main(argc, argv, appData, 0);
    XRE_FreeAppData(appData);
    return result;
  }

  return XRE_main(argc, argv, &sAppData, 0);
}
예제 #3
0
void
FeatureState::Instance::Set(FeatureStatus aStatus, const char* aMessage /* = nullptr */)
{
  mStatus = aStatus;
  if (aMessage) {
    SprintfLiteral(mMessage, "%s", aMessage);
  } else {
    mMessage[0] = '\0';
  }
}
예제 #4
0
// Generate 'usage' and 'help' properties for the given object.
// JS_DefineFunctionsWithHelp will define individual function objects with both
// of those properties (eg getpid.usage = "getpid()" and getpid.help = "return
// the process id"). This function will generate strings for an "interface
// object", eg os.file, which contains some number of functions.
//
// .usage will be set to "<name> - interface object".
//
// .help will be set to a newline-separated list of functions that have either
// 'help' or 'usage' properties. Functions are described with their usage
// strings, if they have them, else with just their names.
//
bool
GenerateInterfaceHelp(JSContext* cx, HandleObject obj, const char* name)
{
    AutoIdVector idv(cx);
    if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN, &idv))
        return false;

    StringBuffer buf(cx);
    int numEntries = 0;
    for (size_t i = 0; i < idv.length(); i++) {
        RootedId id(cx, idv[i]);
        RootedValue v(cx);
        if (!JS_GetPropertyById(cx, obj, id, &v))
            return false;
        if (!v.isObject())
            continue;
        RootedObject prop(cx, &v.toObject());

        RootedValue usage(cx);
        RootedValue help(cx);
        if (!JS_GetProperty(cx, prop, "usage", &usage))
            return false;
        if (!JS_GetProperty(cx, prop, "help", &help))
            return false;
        if (!usage.isString() && !help.isString())
            continue;

        if (numEntries && !buf.append("\n"))
            return false;
        numEntries++;

        if (!buf.append("  ", 2))
            return false;

        if (!buf.append(usage.isString() ? usage.toString() : JSID_TO_FLAT_STRING(id)))
            return false;
    }

    RootedString s(cx, buf.finishString());
    if (!s || !JS_DefineProperty(cx, obj, "help", s, 0))
        return false;

    buf.clear();
    if (!buf.append(name, strlen(name)) || !buf.append(" - interface object with ", 25))
        return false;
    char cbuf[100];
    SprintfLiteral(cbuf, "%d %s", numEntries, numEntries == 1 ? "entry" : "entries");
    if (!buf.append(cbuf, strlen(cbuf)))
        return false;
    s = buf.finishString();
    if (!s || !JS_DefineProperty(cx, obj, "usage", s, 0))
        return false;

    return true;
}
NS_IMETHODIMP nsScriptableDateFormat::FormatDateTime(
                            const char16_t *aLocale, 
                            nsDateFormatSelector dateFormatSelector, 
                            nsTimeFormatSelector timeFormatSelector, 
                            int32_t year, 
                            int32_t month, 
                            int32_t day, 
                            int32_t hour, 
                            int32_t minute, 
                            int32_t second, 
                            char16_t **dateTimeString)
{
  // We can't have a valid date with the year, month or day
  // being lower than 1.
  if (year < 1 || month < 1 || day < 1)
    return NS_ERROR_INVALID_ARG;

  nsresult rv;
  *dateTimeString = nullptr;

  tm tmTime;
  time_t timetTime;

  memset(&tmTime, 0, sizeof(tmTime));
  tmTime.tm_year = year - 1900;
  tmTime.tm_mon = month - 1;
  tmTime.tm_mday = day;
  tmTime.tm_hour = hour;
  tmTime.tm_min = minute;
  tmTime.tm_sec = second;
  tmTime.tm_yday = tmTime.tm_wday = 0;
  tmTime.tm_isdst = -1;
  timetTime = mktime(&tmTime);

  if ((time_t)-1 != timetTime) {
    rv = mozilla::DateTimeFormat::FormatTime(dateFormatSelector, timeFormatSelector,
                                             timetTime, mStringOut);
  }
  else {
    // if mktime fails (e.g. year <= 1970), then try NSPR.
    PRTime prtime;
    char string[32];
    SprintfLiteral(string, "%.2d/%.2d/%d %.2d:%.2d:%.2d", month, day, year, hour, minute, second);
    if (PR_SUCCESS != PR_ParseTimeString(string, false, &prtime))
      return NS_ERROR_INVALID_ARG;

    rv = mozilla::DateTimeFormat::FormatPRTime(dateFormatSelector, timeFormatSelector,
                                               prtime, mStringOut);
  }
  if (NS_SUCCEEDED(rv))
    *dateTimeString = ToNewUnicode(mStringOut);

  return rv;
}
예제 #6
0
void
ResourceQueue::Dump(const char* aPath)
{
  for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
    ResourceItem* item = ResourceAt(i);

    char buf[255];
    SprintfLiteral(buf, "%s/%08u.bin", aPath, i);
    FILE* fp = fopen(buf, "wb");
    if (!fp) {
      return;
    }
    Unused << fwrite(item->mData->Elements(), item->mData->Length(), 1, fp);
    fclose(fp);
  }
}
예제 #7
0
  detail::LogFile* OpenFile(bool aShouldAppend, uint32_t aFileNum)
  {
    FILE* file;

    if (mRotate > 0) {
      char buf[2048];
      SprintfLiteral(buf, "%s.%d", mOutFilePath.get(), aFileNum);

      // rotate doesn't support append.
      file = fopen(buf, "w");
    } else {
      file = fopen(mOutFilePath.get(), aShouldAppend ? "a" : "w");
    }

    if (!file) {
      return nullptr;
    }

    return new detail::LogFile(file, aFileNum);
  }
예제 #8
0
static FILE*
OpenDumpFile(uint32_t aChannels, uint32_t aRate)
{
  /**
   * When MOZ_DUMP_AUDIO is set in the environment (to anything),
   * we'll drop a series of files in the current working directory named
   * dumped-audio-<nnn>.wav, one per AudioStream created, containing
   * the audio for the stream including any skips due to underruns.
   */
  static Atomic<int> gDumpedAudioCount(0);

  if (!getenv("MOZ_DUMP_AUDIO"))
    return nullptr;
  char buf[100];
  SprintfLiteral(buf, "dumped-audio-%d.wav", ++gDumpedAudioCount);
  FILE* f = fopen(buf, "wb");
  if (!f)
    return nullptr;

  uint8_t header[] = {
    // RIFF header
    0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45,
    // fmt chunk. We always write 16-bit samples.
    0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x00,
    // data chunk
    0x64, 0x61, 0x74, 0x61, 0xFE, 0xFF, 0xFF, 0x7F
  };
  static const int CHANNEL_OFFSET = 22;
  static const int SAMPLE_RATE_OFFSET = 24;
  static const int BLOCK_ALIGN_OFFSET = 32;
  SetUint16LE(header + CHANNEL_OFFSET, aChannels);
  SetUint32LE(header + SAMPLE_RATE_OFFSET, aRate);
  SetUint16LE(header + BLOCK_ALIGN_OFFSET, aChannels * 2);
  Unused << fwrite(header, sizeof(header), 1, f);

  return f;
}
예제 #9
0
void
GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
{
  MOZ_ASSERT(mProcess && mProcess == aHost);

  DestroyProcess();

  if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestarts())) {
    char disableMessage[64];
    SprintfLiteral(disableMessage, "GPU process disabled after %d attempts",
                   mNumProcessAttempts);
    DisableGPUProcess(disableMessage);
  } else if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestartsWithDecoder()) &&
             mDecodeVideoOnGpuProcess) {
    mDecodeVideoOnGpuProcess = false;
    Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
                                     uint32_t(FallbackType::DECODINGDISABLED));
  } else {
    Telemetry::Accumulate(Telemetry::GPU_PROCESS_CRASH_FALLBACKS,
                                     uint32_t(FallbackType::NONE));
  }

  HandleProcessLost();
}
예제 #10
0
RefPtr<DtlsIdentity> DtlsIdentity::Generate() {
    UniquePK11SlotInfo slot(PK11_GetInternalSlot());
    if (!slot) {
        return nullptr;
    }

    uint8_t random_name[16];

    SECStatus rv = PK11_GenerateRandomOnSlot(slot.get(), random_name,
                   sizeof(random_name));
    if (rv != SECSuccess)
        return nullptr;

    std::string name;
    char chunk[3];
    for (size_t i = 0; i < sizeof(random_name); ++i) {
        SprintfLiteral(chunk, "%.2x", random_name[i]);
        name += chunk;
    }

    std::string subject_name_string = "CN=" + name;
    UniqueCERTName subject_name(CERT_AsciiToName(subject_name_string.c_str()));
    if (!subject_name) {
        return nullptr;
    }

    unsigned char paramBuf[12]; // OIDs are small
    SECItem ecdsaParams = { siBuffer, paramBuf, sizeof(paramBuf) };
    SECOidData* oidData = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
    if (!oidData || (oidData->oid.len > (sizeof(paramBuf) - 2))) {
        return nullptr;
    }
    ecdsaParams.data[0] = SEC_ASN1_OBJECT_ID;
    ecdsaParams.data[1] = oidData->oid.len;
    memcpy(ecdsaParams.data + 2, oidData->oid.data, oidData->oid.len);
    ecdsaParams.len = oidData->oid.len + 2;

    SECKEYPublicKey *pubkey;
    UniqueSECKEYPrivateKey private_key(
        PK11_GenerateKeyPair(slot.get(),
                             CKM_EC_KEY_PAIR_GEN, &ecdsaParams, &pubkey,
                             PR_FALSE, PR_TRUE, nullptr));
    if (private_key == nullptr)
        return nullptr;
    UniqueSECKEYPublicKey public_key(pubkey);
    pubkey = nullptr;

    UniqueCERTSubjectPublicKeyInfo spki(
        SECKEY_CreateSubjectPublicKeyInfo(public_key.get()));
    if (!spki) {
        return nullptr;
    }

    UniqueCERTCertificateRequest certreq(
        CERT_CreateCertificateRequest(subject_name.get(), spki.get(), nullptr));
    if (!certreq) {
        return nullptr;
    }

    // From 1 day before todayto 30 days after.
    // This is a sort of arbitrary range designed to be valid
    // now with some slack in case the other side expects
    // some before expiry.
    //
    // Note: explicit casts necessary to avoid
    //       warning C4307: '*' : integral constant overflow
    static const PRTime oneDay = PRTime(PR_USEC_PER_SEC)
                                 * PRTime(60)  // sec
                                 * PRTime(60)  // min
                                 * PRTime(24); // hours
    PRTime now = PR_Now();
    PRTime notBefore = now - oneDay;
    PRTime notAfter = now + (PRTime(30) * oneDay);

    UniqueCERTValidity validity(CERT_CreateValidity(notBefore, notAfter));
    if (!validity) {
        return nullptr;
    }

    unsigned long serial;
    // Note: This serial in principle could collide, but it's unlikely
    rv = PK11_GenerateRandomOnSlot(slot.get(),
                                   reinterpret_cast<unsigned char *>(&serial),
                                   sizeof(serial));
    if (rv != SECSuccess) {
        return nullptr;
    }

    UniqueCERTCertificate certificate(
        CERT_CreateCertificate(serial, subject_name.get(), validity.get(),
                               certreq.get()));
    if (!certificate) {
        return nullptr;
    }

    PLArenaPool *arena = certificate->arena;

    rv = SECOID_SetAlgorithmID(arena, &certificate->signature,
                               SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE, 0);
    if (rv != SECSuccess)
        return nullptr;

    // Set version to X509v3.
    *(certificate->version.data) = SEC_CERTIFICATE_VERSION_3;
    certificate->version.len = 1;

    SECItem innerDER;
    innerDER.len = 0;
    innerDER.data = nullptr;

    if (!SEC_ASN1EncodeItem(arena, &innerDER, certificate.get(),
                            SEC_ASN1_GET(CERT_CertificateTemplate))) {
        return nullptr;
    }

    SECItem *signedCert = PORT_ArenaZNew(arena, SECItem);
    if (!signedCert) {
        return nullptr;
    }

    rv = SEC_DerSignData(arena, signedCert, innerDER.data, innerDER.len,
                         private_key.get(),
                         SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE);
    if (rv != SECSuccess) {
        return nullptr;
    }
    certificate->derCert = *signedCert;

    RefPtr<DtlsIdentity> identity = new DtlsIdentity(Move(private_key),
            Move(certificate),
            ssl_kea_ecdh);
    return identity.forget();
}
예제 #11
0
void
ThreadStackHelper::CollectPseudoEntry(const js::ProfileEntry& aEntry)
{
  // For non-js frames we just include the raw label.
  if (!aEntry.isJs()) {
    const char* entryLabel = aEntry.label();

    // entryLabel is a statically allocated string, so we want to store a
    // reference to it without performing any allocations. This is important, as
    // we aren't allowed to allocate within this function.
    //
    // The variant for this kind of label in our HangStack object is a
    // `nsCString`, which normally contains heap allocated string data. However,
    // `nsCString` has an optimization for literal strings which causes the
    // backing data to not be copied when being copied between nsCString
    // objects.
    //
    // We take advantage of that optimization by creating a nsCString object
    // which has the LITERAL flag set. Without this optimization, this code
    // would be incorrect.
    nsCString label;
    label.AssignLiteral(entryLabel, strlen(entryLabel));

    // Let's make sure we don't deadlock here, by asserting that `label`'s
    // backing data matches.
    MOZ_RELEASE_ASSERT(label.BeginReading() == entryLabel,
        "String copy performed during ThreadStackHelper::CollectPseudoEntry");
    TryAppendFrame(label);
    return;
  }

  if (!aEntry.script()) {
    TryAppendFrame(HangEntrySuppressed());
    return;
  }

  if (!IsChromeJSScript(aEntry.script())) {
    TryAppendFrame(HangEntryContent());
    return;
  }

  // Rather than using the profiler's dynamic string, we compute our own string.
  // This is because we want to do some size-saving strategies, and throw out
  // information which won't help us as much.
  // XXX: We currently don't collect the function name which hung.
  const char* filename = JS_GetScriptFilename(aEntry.script());
  unsigned lineno = JS_PCToLineNumber(aEntry.script(), aEntry.pc());

  // Some script names are in the form "foo -> bar -> baz".
  // Here we find the origin of these redirected scripts.
  const char* basename = GetPathAfterComponent(filename, " -> ");
  if (basename) {
    filename = basename;
  }

  // Strip chrome:// or resource:// off of the filename if present.
  basename = GetFullPathForScheme(filename, "chrome://");
  if (!basename) {
    basename = GetFullPathForScheme(filename, "resource://");
  }
  if (!basename) {
    // If we're in an add-on script, under the {profile}/extensions
    // directory, extract the path after the /extensions/ part.
    basename = GetPathAfterComponent(filename, "/extensions/");
  }
  if (!basename) {
    // Only keep the file base name for paths outside the above formats.
    basename = strrchr(filename, '/');
    basename = basename ? basename + 1 : filename;
    // Look for Windows path separator as well.
    filename = strrchr(basename, '\\');
    if (filename) {
      basename = filename + 1;
    }
  }

  char buffer[128]; // Enough to fit longest js file name from the tree
  size_t len = SprintfLiteral(buffer, "%s:%u", basename, lineno);
  if (len < sizeof(buffer)) {
    mDesiredBufferSize += len + 1;

    if (mStackToFill->stack().Capacity() > mStackToFill->stack().Length() &&
        (mStackToFill->strbuffer().Capacity() -
         mStackToFill->strbuffer().Length()) > len + 1) {
      // NOTE: We only increment this if we're going to successfully append.
      mDesiredStackSize += 1;
      uint32_t start = mStackToFill->strbuffer().Length();
      mStackToFill->strbuffer().AppendElements(buffer, len);
      mStackToFill->strbuffer().AppendElement('\0');
      mStackToFill->stack().AppendElement(HangEntryBufOffset(start));
      return;
    }
  }

  TryAppendFrame(HangEntryChromeScript());
}
NS_IMETHODIMP nsScriptableDateFormat::FormatDateTime(
                            const char16_t *aLocale, 
                            nsDateFormatSelector dateFormatSelector, 
                            nsTimeFormatSelector timeFormatSelector, 
                            int32_t year, 
                            int32_t month, 
                            int32_t day, 
                            int32_t hour, 
                            int32_t minute, 
                            int32_t second, 
                            char16_t **dateTimeString)
{
  // We can't have a valid date with the year, month or day
  // being lower than 1.
  if (year < 1 || month < 1 || day < 1)
    return NS_ERROR_INVALID_ARG;

  nsresult rv;
  nsAutoString localeName(aLocale);
  *dateTimeString = nullptr;

  nsCOMPtr<nsILocale> locale;
  // re-initialise locale pointer only if the locale was given explicitly
  if (!localeName.IsEmpty()) {
    // get locale service
    nsCOMPtr<nsILocaleService> localeService(do_GetService(kLocaleServiceCID, &rv));
    NS_ENSURE_SUCCESS(rv, rv);
    // get locale
    rv = localeService->NewLocale(localeName, getter_AddRefs(locale));
    NS_ENSURE_SUCCESS(rv, rv);
  }

  nsCOMPtr<nsIDateTimeFormat> dateTimeFormat(do_CreateInstance(kDateTimeFormatCID, &rv));
  NS_ENSURE_SUCCESS(rv, rv);

  tm tmTime;
  time_t timetTime;

  memset(&tmTime, 0, sizeof(tmTime));
  tmTime.tm_year = year - 1900;
  tmTime.tm_mon = month - 1;
  tmTime.tm_mday = day;
  tmTime.tm_hour = hour;
  tmTime.tm_min = minute;
  tmTime.tm_sec = second;
  tmTime.tm_yday = tmTime.tm_wday = 0;
  tmTime.tm_isdst = -1;
  timetTime = mktime(&tmTime);

  if ((time_t)-1 != timetTime) {
    rv = dateTimeFormat->FormatTime(locale, dateFormatSelector, timeFormatSelector, 
                                     timetTime, mStringOut);
  }
  else {
    // if mktime fails (e.g. year <= 1970), then try NSPR.
    PRTime prtime;
    char string[32];
    SprintfLiteral(string, "%.2d/%.2d/%d %.2d:%.2d:%.2d", month, day, year, hour, minute, second);
    if (PR_SUCCESS != PR_ParseTimeString(string, false, &prtime))
      return NS_ERROR_INVALID_ARG;

    rv = dateTimeFormat->FormatPRTime(locale, dateFormatSelector, timeFormatSelector, 
                                      prtime, mStringOut);
  }
  if (NS_SUCCEEDED(rv))
    *dateTimeString = ToNewUnicode(mStringOut);

  return rv;
}
예제 #13
0
int
main(int argc, char* argv[])
{
  if (test_common_init(&argc, &argv) != 0)
    return -1;

  nsresult ret;

  nsCOMPtr<nsIServiceManager> servMan;
  NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr);

  nsIInputStream* in = nullptr;

  nsCOMPtr<nsIScriptSecurityManager> secman =
    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &ret);
  if (NS_FAILED(ret)) return 1;
  nsCOMPtr<nsIPrincipal> systemPrincipal;
    ret = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
   if (NS_FAILED(ret)) return 1;

  nsCOMPtr<nsIURI> uri;
  ret = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING(TEST_URL));
  if (NS_FAILED(ret)) return 1;

  nsIChannel *channel = nullptr;
  ret = NS_NewChannel(&channel,
                      uri,
                      systemPrincipal,
                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                      nsIContentPolicy::TYPE_OTHER);
  if (NS_FAILED(ret)) return 1;

  ret = channel->Open2(&in);
  if (NS_FAILED(ret)) return 1;

  nsIPersistentProperties* props;
  ret = CallCreateInstance(kPersistentPropertiesCID, &props);
  if (NS_FAILED(ret) || (!props)) {
    printf("create nsIPersistentProperties failed\n");
    return 1;
  }
  ret = props->Load(in);
  if (NS_FAILED(ret)) {
    printf("cannot load properties\n");
    return 1;
  }
  int i = 1;
  while (1) {
    char name[16];
    name[0] = 0;
    SprintfLiteral(name, "%d", i);
    nsAutoString v;
    ret = props->GetStringProperty(nsDependentCString(name), v);
    if (NS_FAILED(ret) || (!v.Length())) {
      break;
    }
    printf("\"%d\"=\"%s\"\n", i, NS_ConvertUTF16toUTF8(v).get());
    i++;
  }

  nsCOMPtr<nsISimpleEnumerator> propEnum;
  ret = props->Enumerate(getter_AddRefs(propEnum));

  if (NS_FAILED(ret)) {
    printf("cannot enumerate properties\n");
    return 1;
  }
  

  printf("\nKey\tValue\n");
  printf(  "---\t-----\n");
  
  bool hasMore;
  while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) &&
         hasMore) {
    nsCOMPtr<nsISupports> sup;
    ret = propEnum->GetNext(getter_AddRefs(sup));
    
    nsCOMPtr<nsIPropertyElement> propElem = do_QueryInterface(sup, &ret);
	  if (NS_FAILED(ret)) {
      printf("failed to get current item\n");
      return 1;
	  }

    nsAutoCString key;
    nsAutoString value;

    ret = propElem->GetKey(key);
	  if (NS_FAILED(ret)) {
		  printf("failed to get current element's key\n");
		  return 1;
	  }
    ret = propElem->GetValue(value);
	  if (NS_FAILED(ret)) {
		  printf("failed to get current element's value\n");
		  return 1;
	  }

    printf("%s\t%s\n", key.get(), NS_ConvertUTF16toUTF8(value).get());
  }
  return 0;
}
예제 #14
0
const char*
ThreadStackHelper::AppendJSEntry(const volatile StackEntry* aEntry,
                                 intptr_t& aAvailableBufferSize,
                                 const char* aPrevLabel)
{
  // May be called from another thread or inside a signal handler.
  // We assume querying the script is safe but we must not manupulate it.
  // Also we must not allocate any memory from heap.
  MOZ_ASSERT(aEntry->isJs());
  MOZ_ASSERT(aEntry->script());

  const char* label;
  if (IsChromeJSScript(aEntry->script())) {
    const char* filename = JS_GetScriptFilename(aEntry->script());
    const unsigned lineno = JS_PCToLineNumber(aEntry->script(), aEntry->pc());
    MOZ_ASSERT(filename);

    char buffer[128]; // Enough to fit longest js file name from the tree

    // Some script names are in the form "foo -> bar -> baz".
    // Here we find the origin of these redirected scripts.
    const char* basename = GetPathAfterComponent(filename, " -> ");
    if (basename) {
      filename = basename;
    }

    basename = GetFullPathForScheme(filename, "chrome://");
    if (!basename) {
      basename = GetFullPathForScheme(filename, "resource://");
    }
    if (!basename) {
      // If the (add-on) script is located under the {profile}/extensions
      // directory, extract the path after the /extensions/ part.
      basename = GetPathAfterComponent(filename, "/extensions/");
    }
    if (!basename) {
      // Only keep the file base name for paths outside the above formats.
      basename = strrchr(filename, '/');
      basename = basename ? basename + 1 : filename;
      // Look for Windows path separator as well.
      filename = strrchr(basename, '\\');
      if (filename) {
        basename = filename + 1;
      }
    }

    size_t len = SprintfLiteral(buffer, "%s:%u", basename, lineno);
    if (len < sizeof(buffer)) {
      if (mStackToFill->IsSameAsEntry(aPrevLabel, buffer)) {
        return aPrevLabel;
      }

      // Keep track of the required buffer size
      aAvailableBufferSize -= (len + 1);
      if (aAvailableBufferSize >= 0) {
        // Buffer is big enough.
        return mStackToFill->InfallibleAppendViaBuffer(buffer, len);
      }
      // Buffer is not big enough; fall through to using static label below.
    }
    // snprintf failed or buffer is not big enough.
    label = "(chrome script)";
  } else {
    label = "(content script)";
  }

  if (mStackToFill->IsSameAsEntry(aPrevLabel, label)) {
    return aPrevLabel;
  }
  mStackToFill->infallibleAppend(label);
  return label;
}
예제 #15
0
  void Print(const char* aName, LogLevel aLevel, const char* aFmt, va_list aArgs)
  {
    const size_t kBuffSize = 1024;
    char buff[kBuffSize];

    char* buffToWrite = buff;

    // For backwards compat we need to use the NSPR format string versions
    // of sprintf and friends and then hand off to printf.
    va_list argsCopy;
    va_copy(argsCopy, aArgs);
    size_t charsWritten = PR_vsnprintf(buff, kBuffSize, aFmt, argsCopy);
    va_end(argsCopy);

    if (charsWritten == kBuffSize - 1) {
      // We may have maxed out, allocate a buffer instead.
      buffToWrite = PR_vsmprintf(aFmt, aArgs);
      charsWritten = strlen(buffToWrite);
    }

    // Determine if a newline needs to be appended to the message.
    const char* newline = "";
    if (charsWritten == 0 || buffToWrite[charsWritten - 1] != '\n') {
      newline = "\n";
    }

    FILE* out = stderr;

    // In case we use rotate, this ensures the FILE is kept alive during
    // its use.  Increased before we load mOutFile.
    ++mPrintEntryCount;

    detail::LogFile* outFile = mOutFile;
    if (outFile) {
      out = outFile->File();
    }

    // This differs from the NSPR format in that we do not output the
    // opaque system specific thread pointer (ie pthread_t) cast
    // to a long. The address of the current PR_Thread continues to be
    // prefixed.
    //
    // Additionally we prefix the output with the abbreviated log level
    // and the module name.
    PRThread *currentThread = PR_GetCurrentThread();
    const char *currentThreadName = (mMainThread == currentThread)
      ? "Main Thread"
      : PR_GetThreadName(currentThread);

    char noNameThread[40];
    if (!currentThreadName) {
      SprintfLiteral(noNameThread, "Unnamed thread %p", currentThread);
      currentThreadName = noNameThread;
    }

    if (!mAddTimestamp) {
      fprintf_stderr(out,
                     "[%s]: %s/%s %s%s",
                     currentThreadName, ToLogStr(aLevel),
                     aName, buffToWrite, newline);
    } else {
      PRExplodedTime now;
      PR_ExplodeTime(PR_Now(), PR_GMTParameters, &now);
      fprintf_stderr(
          out,
          "%04d-%02d-%02d %02d:%02d:%02d.%06d UTC - [%s]: %s/%s %s%s",
          now.tm_year, now.tm_month + 1, now.tm_mday,
          now.tm_hour, now.tm_min, now.tm_sec, now.tm_usec,
          currentThreadName, ToLogStr(aLevel),
          aName, buffToWrite, newline);
    }

    if (mIsSync) {
      fflush(out);
    }

    if (buffToWrite != buff) {
      PR_smprintf_free(buffToWrite);
    }

    if (mRotate > 0 && outFile) {
      int32_t fileSize = ftell(out);
      if (fileSize > mRotate) {
        uint32_t fileNum = outFile->Num();

        uint32_t nextFileNum = fileNum + 1;
        if (nextFileNum >= kRotateFilesNumber) {
          nextFileNum = 0;
        }

        // And here is the trick.  The current out-file remembers its order
        // number.  When no other thread shifted the global file number yet,
        // we are the thread to open the next file.
        if (mOutFileNum.compareExchange(fileNum, nextFileNum)) {
          // We can work with mToReleaseFile because we are sure the
          // mPrintEntryCount can't drop to zero now - the condition
          // to actually delete what's stored in that member.
          // And also, no other thread can enter this piece of code
          // because mOutFile is still holding the current file with
          // the non-shifted number.  The compareExchange() above is
          // a no-op for other threads.
          outFile->mNextToRelease = mToReleaseFile;
          mToReleaseFile = outFile;

          mOutFile = OpenFile(false, nextFileNum);
        }
      }
    }

    if (--mPrintEntryCount == 0 && mToReleaseFile) {
      // We were the last Print() entered, if there is a file to release
      // do it now.  exchange() is atomic and makes sure we release the file
      // only once on one thread.
      detail::LogFile* release = mToReleaseFile.exchange(nullptr);
      delete release;
    }
  }
예제 #16
0
 void RemoveFile(uint32_t aFileNum)
 {
   char buf[2048];
   SprintfLiteral(buf, "%s.%d", mOutFilePath.get(), aFileNum);
   remove(buf);
 }
예제 #17
0
  /**
   * Loads config from env vars if present.
   */
  void Init()
  {
    bool shouldAppend = false;
    bool addTimestamp = false;
    bool isSync = false;
    int32_t rotate = 0;
    const char* modules = PR_GetEnv("MOZ_LOG");
    if (!modules || !modules[0]) {
      modules = PR_GetEnv("MOZ_LOG_MODULES");
      if (modules) {
        NS_WARNING("MOZ_LOG_MODULES is deprecated."
            "\nPlease use MOZ_LOG instead.");
      }
    }
    if (!modules || !modules[0]) {
      modules = PR_GetEnv("NSPR_LOG_MODULES");
      if (modules) {
        NS_WARNING("NSPR_LOG_MODULES is deprecated."
            "\nPlease use MOZ_LOG instead.");
      }
    }

    NSPRLogModulesParser(modules,
        [&shouldAppend, &addTimestamp, &isSync, &rotate]
            (const char* aName, LogLevel aLevel, int32_t aValue) mutable {
          if (strcmp(aName, "append") == 0) {
            shouldAppend = true;
          } else if (strcmp(aName, "timestamp") == 0) {
            addTimestamp = true;
          } else if (strcmp(aName, "sync") == 0) {
            isSync = true;
          } else if (strcmp(aName, "rotate") == 0) {
            rotate = (aValue << 20) / kRotateFilesNumber;
          } else {
            LogModule::Get(aName)->SetLevel(aLevel);
          }
    });

    // Rotate implies timestamp to make the files readable
    mAddTimestamp = addTimestamp || rotate > 0;
    mIsSync = isSync;
    mRotate = rotate;

    if (rotate > 0 && shouldAppend) {
      NS_WARNING("MOZ_LOG: when you rotate the log, you cannot use append!");
    }

    const char* logFile = PR_GetEnv("MOZ_LOG_FILE");
    if (!logFile || !logFile[0]) {
      logFile = PR_GetEnv("NSPR_LOG_FILE");
    }

    if (logFile && logFile[0]) {
      static const char kPIDToken[] = "%PID";
      const char* pidTokenPtr = strstr(logFile, kPIDToken);
      char buf[2048];
      if (pidTokenPtr &&
          SprintfLiteral(buf, "%.*s%d%s",
                         static_cast<int>(pidTokenPtr - logFile), logFile,
                         detail::log_pid(),
                         pidTokenPtr + strlen(kPIDToken)) > 0)
      {
        logFile = buf;
      }

      mOutFilePath.reset(strdup(logFile));

      if (mRotate > 0) {
        // Delete all the previously captured files, including non-rotated
        // log files, so that users don't complain our logs eat space even
        // after the rotate option has been added and don't happen to send
        // us old large logs along with the rotated files.
        remove(mOutFilePath.get());
        for (uint32_t i = 0; i < kRotateFilesNumber; ++i) {
          RemoveFile(i);
        }
      }

      mOutFile = OpenFile(shouldAppend, mOutFileNum);
    }
  }