LogStatistics.cpp revision d966e226809bd446bb33651b71d7934887787c1d
134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn/*
234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * Copyright (C) 2014 The Android Open Source Project
334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn *
434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License");
534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * you may not use this file except in compliance with the License.
634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * You may obtain a copy of the License at
734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn *
834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn *      http://www.apache.org/licenses/LICENSE-2.0
934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn *
1034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * Unless required by applicable law or agreed to in writing, software
1134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS,
1234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * See the License for the specific language governing permissions and
1434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * limitations under the License.
1534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn */
1634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
179a03863e88da99ba010342c874252089dd771f7fMark Salyzyn#include <fcntl.h>
18b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn#include <pwd.h>
1997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <stdio.h>
2097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <string.h>
21b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn#include <sys/types.h>
2297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include <unistd.h>
2334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
249af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn#include <list>
259af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn
26aeaaf81c2cc8366ac4f66eb3d2fc85f9b8194982Mark Salyzyn#include <android/log.h>
2734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
2834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#include "LogStatistics.h"
2934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
307718778793b106498b931dd708a466cf3a6f6a0fMark SalyzynLogStatistics::LogStatistics() : enable(false) {
3197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
3297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        mSizes[id] = 0;
3397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        mElements[id] = 0;
3458b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn        mDroppedElements[id] = 0;
3597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        mSizesTotal[id] = 0;
3697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        mElementsTotal[id] = 0;
3734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
3834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
3934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
40720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynnamespace android {
41720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
4297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn// caller must own and free character string
4381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynchar *pidToName(pid_t pid) {
449a03863e88da99ba010342c874252089dd771f7fMark Salyzyn    char *retval = NULL;
45ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn    if (pid == 0) { // special case from auditd/klogd for kernel
46ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn        retval = strdup("logd");
4797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    } else {
489a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        char buffer[512];
499a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
509a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        int fd = open(buffer, O_RDONLY);
519a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        if (fd >= 0) {
529a03863e88da99ba010342c874252089dd771f7fMark Salyzyn            ssize_t ret = read(fd, buffer, sizeof(buffer));
539a03863e88da99ba010342c874252089dd771f7fMark Salyzyn            if (ret > 0) {
549a03863e88da99ba010342c874252089dd771f7fMark Salyzyn                buffer[sizeof(buffer)-1] = '\0';
559a03863e88da99ba010342c874252089dd771f7fMark Salyzyn                // frameworks intermediate state
560eeb06b932f185e10377e4494475d2cdd6adfa1bMark Salyzyn                if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
579a03863e88da99ba010342c874252089dd771f7fMark Salyzyn                    retval = strdup(buffer);
589a03863e88da99ba010342c874252089dd771f7fMark Salyzyn                }
599a03863e88da99ba010342c874252089dd771f7fMark Salyzyn            }
609a03863e88da99ba010342c874252089dd771f7fMark Salyzyn            close(fd);
619a03863e88da99ba010342c874252089dd771f7fMark Salyzyn        }
629a03863e88da99ba010342c874252089dd771f7fMark Salyzyn    }
639a03863e88da99ba010342c874252089dd771f7fMark Salyzyn    return retval;
649a03863e88da99ba010342c874252089dd771f7fMark Salyzyn}
659a03863e88da99ba010342c874252089dd771f7fMark Salyzyn
66720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn}
67720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
68758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynvoid LogStatistics::add(LogBufferElement *element) {
69758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    log_id_t log_id = element->getLogId();
70758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    unsigned short size = element->getMsgLen();
7197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    mSizes[log_id] += size;
7297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    ++mElements[log_id];
7334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
74a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn    if (element->getDropped()) {
75a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        ++mDroppedElements[log_id];
76a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn    } else {
77a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        // When caller adding a chatty entry, they will have already
78a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        // called add() and subtract() for each entry as they are
79a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        // evaluated and trimmed, thus recording size and number of
80a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        // elements, but we must recognize the manufactured dropped
81a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        // entry as not contributing to the lifetime totals.
82a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        mSizesTotal[log_id] += size;
83a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        ++mElementsTotal[log_id];
84a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn    }
85720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
86ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn    if (log_id == LOG_ID_KERNEL) {
87ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn        return;
88ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn    }
89ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn
90758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uidTable[log_id].add(element->getUid(), element);
91bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    if (element->getUid() == AID_SYSTEM) {
92bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        pidSystemTable[log_id].add(element->getPid(), element);
93bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
94ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn
95720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    if (!enable) {
96720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        return;
97720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
98720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
99758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    pidTable.add(element->getPid(), element);
100758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    tidTable.add(element->getTid(), element);
101344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
102758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uint32_t tag = element->getTag();
103344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    if (tag) {
104083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn        if (log_id == LOG_ID_SECURITY) {
105083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn            securityTagTable.add(tag, element);
106083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn        } else {
107083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn            tagTable.add(tag, element);
108083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn        }
109344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    }
11034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
11134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
112758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynvoid LogStatistics::subtract(LogBufferElement *element) {
113758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    log_id_t log_id = element->getLogId();
114758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    unsigned short size = element->getMsgLen();
11597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    mSizes[log_id] -= size;
11697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    --mElements[log_id];
11758b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    if (element->getDropped()) {
11858b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn        --mDroppedElements[log_id];
11958b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    }
12034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
121ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn    if (log_id == LOG_ID_KERNEL) {
122ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn        return;
123ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn    }
124ae4d928d816e30dbe57c2c321b0f0759d0567b3fMark Salyzyn
125758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uidTable[log_id].subtract(element->getUid(), element);
126bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    if (element->getUid() == AID_SYSTEM) {
127bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        pidSystemTable[log_id].subtract(element->getPid(), element);
128bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
12934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
130720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    if (!enable) {
131720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        return;
13234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
13334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
134758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    pidTable.subtract(element->getPid(), element);
135758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    tidTable.subtract(element->getTid(), element);
136344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
137758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uint32_t tag = element->getTag();
138344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    if (tag) {
139083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn        if (log_id == LOG_ID_SECURITY) {
140083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn            securityTagTable.subtract(tag, element);
141083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn        } else {
142083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn            tagTable.subtract(tag, element);
143083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn        }
144344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    }
145c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn}
146c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn
147ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn// Atomically set an entry to drop
148ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn// entry->setDropped(1) must follow this call, caller should do this explicitly.
149758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynvoid LogStatistics::drop(LogBufferElement *element) {
150758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    log_id_t log_id = element->getLogId();
151758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    unsigned short size = element->getMsgLen();
152ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    mSizes[log_id] -= size;
15358b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    ++mDroppedElements[log_id];
154ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
155758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uidTable[log_id].drop(element->getUid(), element);
156bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    if (element->getUid() == AID_SYSTEM) {
157bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        pidSystemTable[log_id].drop(element->getPid(), element);
158bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
159ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
160ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    if (!enable) {
161ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn        return;
162ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    }
163ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
164758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    pidTable.drop(element->getPid(), element);
165758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    tidTable.drop(element->getTid(), element);
1666a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn
1676a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    uint32_t tag = element->getTag();
1686a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    if (tag) {
1696a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        if (log_id == LOG_ID_SECURITY) {
1706a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn            securityTagTable.drop(tag, element);
1716a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        } else {
1726a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn            tagTable.drop(tag, element);
1736a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        }
1746a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    }
175ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn}
176ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
17797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn// caller must own and free character string
178758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynconst char *LogStatistics::uidToName(uid_t uid) const {
17997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // Local hard coded favourites
18097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    if (uid == AID_LOGD) {
18197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        return strdup("auditd");
18234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
18334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
184b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn    // Android system
185b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn    if (uid < AID_APP) {
186b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn        // in bionic, thread safe as long as we copy the results
187b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn        struct passwd *pwd = getpwuid(uid);
188b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn        if (pwd) {
189b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn            return strdup(pwd->pw_name);
19034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        }
19134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
19234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
19308739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn    // Parse /data/system/packages.list
194dff44709cf462a3af7eb5770c90e3ada492295b7Jeff Sharkey    uid_t userId = uid % AID_USER_OFFSET;
195758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    const char *name = android::uidToName(userId);
196023f51f360472f6bb9bad495e55cdb32b5411bc5Mark Salyzyn    if (!name && (userId > (AID_SHARED_GID_START - AID_APP))) {
197023f51f360472f6bb9bad495e55cdb32b5411bc5Mark Salyzyn        name = android::uidToName(userId - (AID_SHARED_GID_START - AID_APP));
198023f51f360472f6bb9bad495e55cdb32b5411bc5Mark Salyzyn    }
19908739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn    if (name) {
20008739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn        return name;
20108739ba71fc1f2659149be760405d622e5b68f06Mark Salyzyn    }
202720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
203b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn    // Android application
204b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn    if (uid >= AID_APP) {
205b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn        struct passwd *pwd = getpwuid(uid);
206b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn        if (pwd) {
207b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn            return strdup(pwd->pw_name);
208b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn        }
209b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn    }
210b8a95bd3c9502d48b203b9f1e5df9b84a5df6281Mark Salyzyn
211720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    // report uid -> pid(s) -> pidToName if unique
212758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    for(pidTable_t::const_iterator it = pidTable.begin(); it != pidTable.end(); ++it) {
213511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        const PidEntry &entry = it->second;
214720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
215720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        if (entry.getUid() == uid) {
216758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            const char *nameTmp = entry.getName();
217720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
218758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            if (nameTmp) {
219720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                if (!name) {
220758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                    name = strdup(nameTmp);
2210eeb06b932f185e10377e4494475d2cdd6adfa1bMark Salyzyn                } else if (fastcmp<strcmp>(name, nameTmp)) {
222758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                    free(const_cast<char *>(name));
223023f51f360472f6bb9bad495e55cdb32b5411bc5Mark Salyzyn                    name = NULL;
224023f51f360472f6bb9bad495e55cdb32b5411bc5Mark Salyzyn                    break;
225720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                }
226720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            }
227720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        }
228720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
229720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
23097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // No one
231720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    return name;
23234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
23334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
234758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynstd::string UidEntry::formatHeader(const std::string &name, log_id_t id) const {
235758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    bool isprune = worstUidEnabledForLogid(id);
236758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    return formatLine(android::base::StringPrintf(
237758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                          name.c_str(), android_log_id_to_name(id)),
238758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("Size"),
239c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                      std::string(isprune ? "+/-  Pruned" : ""))
240758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn         + formatLine(std::string("UID   PACKAGE"),
241758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("BYTES"),
242758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string(isprune ? "NUM" : ""));
243758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
244758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
245c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzynstd::string UidEntry::format(const LogStatistics &stat, log_id_t id) const {
246ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn    uid_t uid = getUid();
247758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string name = android::base::StringPrintf("%u", uid);
248758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    const char *nameTmp = stat.uidToName(uid);
249758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    if (nameTmp) {
250758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        name += android::base::StringPrintf(
251758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            "%*s%s", (int)std::max(6 - name.length(), (size_t)1),
252758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            "", nameTmp);
253758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        free(const_cast<char *>(nameTmp));
254758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
255758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
256758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string size = android::base::StringPrintf("%zu", getSizes());
257758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
258758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string pruned = "";
259c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn    if (worstUidEnabledForLogid(id)) {
260c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        size_t totalDropped = 0;
261c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        for (LogStatistics::uidTable_t::const_iterator it = stat.uidTable[id].begin();
262c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                it != stat.uidTable[id].end(); ++it) {
263c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            totalDropped += it->second.getDropped();
264c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        }
265c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        size_t sizes = stat.sizes(id);
266c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        size_t totalSize = stat.sizesTotal(id);
267c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        size_t totalElements = stat.elementsTotal(id);
268c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        float totalVirtualSize = (float)sizes + (float)totalDropped * totalSize
269c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                                / totalElements;
270c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        size_t entrySize = getSizes();
271c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        float virtualEntrySize = entrySize;
272c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        int realPermille = virtualEntrySize * 1000.0 / sizes;
273c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        size_t dropped = getDropped();
274c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        if (dropped) {
275c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            pruned = android::base::StringPrintf("%zu", dropped);
276c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            virtualEntrySize += (float)dropped * totalSize / totalElements;
277c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        }
278c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        int virtualPermille = virtualEntrySize * 1000.0 / totalVirtualSize;
279c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        int permille = (realPermille - virtualPermille) * 1000L
280c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                     / (virtualPermille ?: 1);
281c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        if ((permille < -1) || (1 < permille)) {
282c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            std::string change;
283c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            const char *units = "%";
284c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            const char *prefix = (permille > 0) ? "+" : "";
285c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn
286c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            if (permille > 999) {
287c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                permille = (permille + 1000) / 100; // Now tenths fold
288c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                units = "X";
289c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                prefix = "";
290c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            }
291c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            if ((-99 < permille) && (permille < 99)) {
292c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                change = android::base::StringPrintf("%s%d.%u%s",
293c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                    prefix,
294c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                    permille / 10,
295c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                    ((permille < 0) ? (-permille % 10) : (permille % 10)),
296c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                    units);
297c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            } else {
298c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                change = android::base::StringPrintf("%s%d%s",
299c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                    prefix,
300c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                    (permille + 5) / 10, units);
301c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            }
302c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            ssize_t spaces = EntryBaseConstants::pruned_len
303c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                           - 2 - pruned.length() - change.length();
304c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            if ((spaces <= 0) && pruned.length()) {
305c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                spaces = 1;
306c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            }
307d966e226809bd446bb33651b71d7934887787c1dMark Salyzyn            if (spaces > 0) {
308c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn                change += android::base::StringPrintf("%*s", (int)spaces, "");
309c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            }
310c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn            pruned = change + pruned;
311c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn        }
312758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
313758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
314bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    std::string output = formatLine(name, size, pruned);
315bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn
316bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    if (uid != AID_SYSTEM) {
317bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        return output;
318bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
319bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn
320bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    static const size_t maximum_sorted_entries = 32;
321bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    std::unique_ptr<const PidEntry *[]> sorted
322bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        = stat.pidSystemTable[id].sort(uid, (pid_t)0, maximum_sorted_entries);
323bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn
324bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    if (!sorted.get()) {
325bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        return output;
326bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
327bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    std::string byPid;
328bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    size_t index;
329bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    bool hasDropped = false;
330bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    for (index = 0; index < maximum_sorted_entries; ++index) {
331bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        const PidEntry *entry = sorted[index];
332bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        if (!entry) {
333bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn            break;
334bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        }
335bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        if (entry->getSizes() <= (getSizes() / 100)) {
336bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn            break;
337bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        }
338bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        if (entry->getDropped()) {
339bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn            hasDropped = true;
340bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        }
341bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        byPid += entry->format(stat, id);
342bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
343bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    if (index > 1) { // print this only if interesting
344bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        std::string ditto("\" ");
345bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        output += formatLine(std::string("  PID/UID   COMMAND LINE"),
346bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn                             ditto, hasDropped ? ditto : std::string(""));
347bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn        output += byPid;
348bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
349bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn
350bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    return output;
351758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
352758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
353758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynstd::string PidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
354758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    return formatLine(name,
355758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("Size"),
356758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("Pruned"))
357758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn         + formatLine(std::string("  PID/UID   COMMAND LINE"),
358758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("BYTES"),
359758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("NUM"));
360758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
361758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
362758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynstd::string PidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
363758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uid_t uid = getUid();
364ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn    pid_t pid = getPid();
365ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn    std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
366758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    const char *nameTmp = getName();
367758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    if (nameTmp) {
368758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        name += android::base::StringPrintf(
369758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
370758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            "", nameTmp);
371758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    } else if ((nameTmp = stat.uidToName(uid))) {
372758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        name += android::base::StringPrintf(
373758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
374758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            "", nameTmp);
375758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        free(const_cast<char *>(nameTmp));
376758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
377758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
378758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string size = android::base::StringPrintf("%zu",
379758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                                                   getSizes());
380758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
381758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string pruned = "";
382758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    size_t dropped = getDropped();
383758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    if (dropped) {
384758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        pruned = android::base::StringPrintf("%zu", dropped);
385758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
386758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
387758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    return formatLine(name, size, pruned);
388758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
389758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
390758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynstd::string TidEntry::formatHeader(const std::string &name, log_id_t /* id */) const {
391758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    return formatLine(name,
392758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("Size"),
393758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("Pruned"))
394758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn         + formatLine(std::string("  TID/UID   COMM"),
395758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("BYTES"),
396758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("NUM"));
397758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
398758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
399758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynstd::string TidEntry::format(const LogStatistics &stat, log_id_t /* id */) const {
400758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uid_t uid = getUid();
401758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string name = android::base::StringPrintf("%5u/%u",
402ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn                                                   getTid(), uid);
403758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    const char *nameTmp = getName();
404758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    if (nameTmp) {
405758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        name += android::base::StringPrintf(
406758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
407758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            "", nameTmp);
408758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    } else if ((nameTmp = stat.uidToName(uid))) {
409758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        // if we do not have a PID name, lets punt to try UID name?
410758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        name += android::base::StringPrintf(
411758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            "%*s%s", (int)std::max(12 - name.length(), (size_t)1),
412758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            "", nameTmp);
413758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        free(const_cast<char *>(nameTmp));
414758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        // We tried, better to not have a name at all, we still
415758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        // have TID/UID by number to report in any case.
416758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
417758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
418758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string size = android::base::StringPrintf("%zu",
419758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                                                   getSizes());
420758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
421758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string pruned = "";
422758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    size_t dropped = getDropped();
423758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    if (dropped) {
424758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        pruned = android::base::StringPrintf("%zu", dropped);
425758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
426758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
427758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    return formatLine(name, size, pruned);
428758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
429758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
430758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynstd::string TagEntry::formatHeader(const std::string &name, log_id_t id) const {
431758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    bool isprune = worstUidEnabledForLogid(id);
432758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    return formatLine(name,
433758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("Size"),
434758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string(isprune ? "Prune" : ""))
435758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn         + formatLine(std::string("    TAG/UID   TAGNAME"),
436758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string("BYTES"),
437758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                      std::string(isprune ? "NUM" : ""));
438758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
439758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
440758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynstd::string TagEntry::format(const LogStatistics & /* stat */, log_id_t /* id */) const {
441758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string name;
442758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    uid_t uid = getUid();
443758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    if (uid == (uid_t)-1) {
444758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        name = android::base::StringPrintf("%7u",
445758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                                           getKey());
446ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    } else {
447758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        name = android::base::StringPrintf("%7u/%u",
448758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                                           getKey(), uid);
449ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    }
450807e40ecc9786755e2f74a7a6a9b20c812588119Mark Salyzyn    size_t len = 0;
451807e40ecc9786755e2f74a7a6a9b20c812588119Mark Salyzyn    const char *nameTmp = getName(len);
452758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    if (nameTmp) {
453758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        name += android::base::StringPrintf(
454807e40ecc9786755e2f74a7a6a9b20c812588119Mark Salyzyn            "%*s%.*s", (int)std::max(14 - name.length(), (size_t)1),
455807e40ecc9786755e2f74a7a6a9b20c812588119Mark Salyzyn            "", (int)len, nameTmp);
456758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
457758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
458758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string size = android::base::StringPrintf("%zu",
459758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                                                   getSizes());
460758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
461758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string pruned = "";
4626a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    size_t dropped = getDropped();
4636a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    if (dropped) {
4646a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        pruned = android::base::StringPrintf("%zu", dropped);
4656a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    }
466758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
467758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    return formatLine(name, size, pruned);
46834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
46934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
470ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzynstd::string LogStatistics::format(uid_t uid, pid_t pid,
471ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn                                  unsigned int logMask) const {
4729a03863e88da99ba010342c874252089dd771f7fMark Salyzyn    static const unsigned short spaces_total = 19;
47334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
47497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // Report on total logging, current and for all time
47597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn
476decbcd9c418a4d076965971e74fd51fab497414bMark Salyzyn    std::string output = "size/num";
47734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    size_t oldLength;
47897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    short spaces = 1;
47934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
48097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
4819af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (!(logMask & (1 << id))) continue;
48297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        oldLength = output.length();
4839af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (spaces < 0) spaces = 0;
484decbcd9c418a4d076965971e74fd51fab497414bMark Salyzyn        output += android::base::StringPrintf("%*s%s", spaces, "",
485decbcd9c418a4d076965971e74fd51fab497414bMark Salyzyn                                              android_log_id_to_name(id));
48697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        spaces += spaces_total + oldLength - output.length();
48797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    }
4889af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    if (spaces < 0) spaces = 0;
4899af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    output += android::base::StringPrintf("%*sTotal", spaces, "");
490c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn
4919af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    static const char TotalStr[] = "\nTotal";
4929af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    spaces = 10 - strlen(TotalStr);
4939af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    output += TotalStr;
494c8a576c637ae00577273b778498019dd609fcd15Mark Salyzyn
4959af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    size_t totalSize = 0;
4969af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    size_t totalEls = 0;
49797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
4989af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (!(logMask & (1 << id))) continue;
49997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        oldLength = output.length();
5009af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (spaces < 0) spaces = 0;
5019af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        size_t szs = sizesTotal(id);
5029af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        totalSize += szs;
5039af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        size_t els = elementsTotal(id);
5049af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        totalEls += els;
5059af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
50697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        spaces += spaces_total + oldLength - output.length();
50734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
5089af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    if (spaces < 0) spaces = 0;
5099af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize, totalEls);
51034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
5119af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    static const char NowStr[] = "\nNow";
5129af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    spaces = 10 - strlen(NowStr);
5139af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    output += NowStr;
51434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
5159af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    totalSize = 0;
5169af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    totalEls = 0;
51797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
5189af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (!(logMask & (1 << id))) continue;
5199af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn
5209af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        size_t els = elements(id);
5219af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (els) {
5229af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            oldLength = output.length();
5239af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            if (spaces < 0) spaces = 0;
5249af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            size_t szs = sizes(id);
5259af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            totalSize += szs;
5269af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            totalEls += els;
5279af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", szs, els);
5289af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            spaces -= output.length() - oldLength;
52934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        }
5309af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        spaces += spaces_total;
5319af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    }
5329af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    if (spaces < 0) spaces = 0;
5339af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    output += android::base::StringPrintf("%*s%zu/%zu", spaces, "", totalSize, totalEls);
5349af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn
5359af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    static const char OverheadStr[] = "\nOverhead";
5369af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    spaces = 10 - strlen(OverheadStr);
5379af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    output += OverheadStr;
5389af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn
5399af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    totalSize = 0;
5409af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    log_id_for_each(id) {
5419af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (!(logMask & (1 << id))) continue;
54234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
54397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        size_t els = elements(id);
54434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        if (els) {
54597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            oldLength = output.length();
5469af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            if (spaces < 0) spaces = 0;
5479af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            // estimate the std::list overhead.
5489af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            static const size_t overhead =
5499af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn                ((sizeof(LogBufferElement) + sizeof(uint64_t) - 1) &
5509af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn                    -sizeof(uint64_t)) +
5519af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn                sizeof(std::list<LogBufferElement*>);
5529af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            size_t szs = sizes(id) + els * overhead;
5539af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            totalSize += szs;
5549af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn            output += android::base::StringPrintf("%*s%zu", spaces, "", szs);
55597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            spaces -= output.length() - oldLength;
55634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        }
55734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn        spaces += spaces_total;
55834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    }
5596d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn    totalSize += sizeOf();
5609af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    if (spaces < 0) spaces = 0;
5619af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn    output += android::base::StringPrintf("%*s%zu", spaces, "", totalSize);
56234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
56397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // Report on Chattiest
5648e72c5384b288bc11af60e12686a44e502633e3dMark Salyzyn
565758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string name;
566758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
56797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // Chattiest by application (UID)
56897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    log_id_for_each(id) {
5699af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (!(logMask & (1 << id))) continue;
5708e72c5384b288bc11af60e12686a44e502633e3dMark Salyzyn
571758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        name = (uid == AID_ROOT)
572758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            ? "Chattiest UIDs in %s log buffer:"
573758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            : "Logging for your UID in %s log buffer:";
574ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        output += uidTable[id].format(*this, uid, pid, name, id);
575720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
57697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn
577720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    if (enable) {
578ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        name = ((uid == AID_ROOT) && !pid)
579ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn            ? "Chattiest PIDs:"
580ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn            : "Logging for this PID:";
581ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        output += pidTable.format(*this, uid, pid, name);
582ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        name = "Chattiest TIDs";
5839af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (pid) name += android::base::StringPrintf(" for PID %d", pid);
584ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        name += ":";
585ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        output += tidTable.format(*this, uid, pid, name);
58617ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    }
58717ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn
588344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
589ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        name = "Chattiest events log buffer TAGs";
5909af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (pid) name += android::base::StringPrintf(" for PID %d", pid);
591ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        name += ":";
592ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS);
593344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    }
594344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
595083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn    if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
596ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        name = "Chattiest security log buffer TAGs";
5979af33ee78c395af715e7b861f4e32272559e1fe9Mark Salyzyn        if (pid) name += android::base::StringPrintf(" for PID %d", pid);
598ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        name += ":";
599ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        output += securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY);
600083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn    }
601083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn
60273160acc5cb5236b30327569e6b51dbfe73e4a0fMark Salyzyn    return output;
60334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn}
6044ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn
605720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynnamespace android {
606720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
607720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynuid_t pidToUid(pid_t pid) {
60897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    char buffer[512];
60997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    snprintf(buffer, sizeof(buffer), "/proc/%u/status", pid);
61097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    FILE *fp = fopen(buffer, "r");
61197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    if (fp) {
61297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        while (fgets(buffer, sizeof(buffer), fp)) {
61397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn            int uid;
614c32afdf913f082235b1e66f5a57678c7f0723129Mark Salyzyn            if (sscanf(buffer, "Uid: %d", &uid) == 1) {
61597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn                fclose(fp);
61697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn                return uid;
6174ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn            }
6184ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn        }
61997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn        fclose(fp);
6204ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn    }
621e3aeeeeccc260c29ca5907a444f8d746bcc2f8a5Mark Salyzyn    return AID_LOGD; // associate this with the logger
6224ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn}
623720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
624720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn}
625720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
626720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynuid_t LogStatistics::pidToUid(pid_t pid) {
627511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn    return pidTable.add(pid)->second.getUid();
628720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn}
629720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
630720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn// caller must free character string
631758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynconst char *LogStatistics::pidToName(pid_t pid) const {
632758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    // An inconvenient truth ... getName() can alter the object
633758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    pidTable_t &writablePidTable = const_cast<pidTable_t &>(pidTable);
634758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    const char *name = writablePidTable.add(pid)->second.getName();
63581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    if (!name) {
63681b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        return NULL;
637720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
63881b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    return strdup(name);
639720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn}
640