C++程序  |  136行  |  3.44 KB

/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include "Log.h"
#include "StringUtil.h"
#include "FileUtil.h"


// This class is used by Log. So we cannot use LOG? macros here.
#define _LOGD_(x...) do { fprintf(stderr, x); fprintf(stderr, "\n"); } while(0)

// reported generated under reports/YYYY_MM_DD_HH_MM_SS dir
const char reportTopDir[] = "reports";
android::String8 FileUtil::mDirPath;

bool FileUtil::prepare(android::String8& dirPath)
{
    if (mDirPath.length() != 0) {
        dirPath = mDirPath;
        _LOGD_("mDirPath %s", mDirPath.string());
        return true;
    }

    time_t timeNow = time(NULL);
    if (timeNow == ((time_t)-1)) {
        _LOGD_("time error");
       return false;
    }
    // tm is allocated in static buffer, and should not be freed.
    struct tm* tm = localtime(&timeNow);
    if (tm == NULL) {
        _LOGD_("localtime error");
        return false;
    }
    int result = mkdir(reportTopDir, S_IRWXU);
    if ((result == -1) && (errno != EEXIST)) {
        _LOGD_("mkdir of topdir failed, error %d", errno);
        return false;
    }
    android::String8 path;
    if (path.appendFormat("%s/%04d_%02d_%02d_%02d_%02d_%02d", reportTopDir,tm->tm_year + 1900,
            tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec) != 0) {
        return false;
    }
    result = mkdir(path.string(), S_IRWXU);
    if ((result == -1) && (errno != EEXIST)) {
        _LOGD_("mkdir of report dir failed, error %d", errno);
        return false;
    }
    mDirPath = path;
    dirPath = path;

    return true;
}

FileUtil::FileUtil()
{

}

FileUtil::~FileUtil()
{
    if (mFile.is_open()) {
        mFile.close();
    }
}

bool FileUtil::init(const char* fileName)
{
    if (fileName == NULL) {
        return true;
    }

    mFile.open(fileName, std::ios::out | std::ios::trunc);
    if (!mFile.is_open()) {
            return false;
        }
    return true;
}

bool FileUtil::doVprintf(bool fileOnly, int loglevel, const char *fmt, va_list ap)
{
    // prevent messed up log in multi-thread env. Still multi-line logs can be messed up.
    android::Mutex::Autolock lock(mWriteLock);
    int start = 0;
    if (loglevel != -1) {
        mBuffer[0] = '0' + loglevel;
        mBuffer[1] = '>';
        start = 2;
    }
    int size;
    size = vsnprintf(mBuffer + start, BUFFER_SIZE - start - 2, fmt, ap); // 2 for \n\0
    if (size < 0) {
        fprintf(stderr, "FileUtil::vprintf failed");
        return false;
    }
    size += start;
    mBuffer[size] = '\n';
    size++;
    mBuffer[size] = 0;

    if (!fileOnly) {
        fprintf(stdout, "%s", mBuffer);
    }
    if (mFile.is_open()) {
        mFile<<mBuffer;
    }
    return true;
}

bool FileUtil::doPrintf(const char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    bool result = doVprintf(false, -1, fmt, ap);
    va_end(ap);
    return result;
}