From patchwork Thu Jun 16 20:29:41 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Lezcano X-Patchwork-Id: 1998 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 95BB223E54 for ; Thu, 16 Jun 2011 20:31:50 +0000 (UTC) Received: from mail-vw0-f50.google.com (mail-vw0-f50.google.com [209.85.212.50]) by fiordland.canonical.com (Postfix) with ESMTP id 492BDA18585 for ; Thu, 16 Jun 2011 20:31:50 +0000 (UTC) Received: by mail-vw0-f50.google.com with SMTP id 14so1756035vws.37 for ; Thu, 16 Jun 2011 13:31:50 -0700 (PDT) Received: by 10.52.75.4 with SMTP id y4mr1869772vdv.167.1308256309874; Thu, 16 Jun 2011 13:31:49 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.52.183.130 with SMTP id em2cs211214vdc; Thu, 16 Jun 2011 13:31:49 -0700 (PDT) Received: by 10.216.188.20 with SMTP id z20mr1378378wem.66.1308256305386; Thu, 16 Jun 2011 13:31:45 -0700 (PDT) Received: from smtp.smtpout.orange.fr (smtp08.smtpout.orange.fr [80.12.242.130]) by mx.google.com with ESMTP id m30si5070493weq.66.2011.06.16.13.31.44; Thu, 16 Jun 2011 13:31:45 -0700 (PDT) Received-SPF: neutral (google.com: 80.12.242.130 is neither permitted nor denied by best guess record for domain of daniel.lezcano@linaro.org) client-ip=80.12.242.130; Authentication-Results: mx.google.com; spf=neutral (google.com: 80.12.242.130 is neither permitted nor denied by best guess record for domain of daniel.lezcano@linaro.org) smtp.mail=daniel.lezcano@linaro.org Received: from monster.dhcp.lxc ([92.134.76.78]) by mwinf5d16 with ME id wkXf1g0031hMfSL03kXkJi; Thu, 16 Jun 2011 22:31:44 +0200 From: Daniel Lezcano To: patches@linaro.org Subject: [PATCH 12/28] tree structure abstraction for directory hierarchies Date: Thu, 16 Jun 2011 22:29:41 +0200 Message-Id: <1308256197-29155-12-git-send-email-daniel.lezcano@linaro.org> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1308256197-29155-1-git-send-email-daniel.lezcano@linaro.org> References: <1308256197-29155-1-git-send-email-daniel.lezcano@linaro.org> Signed-off-by: Daniel Lezcano --- Makefile | 2 +- clocks.c | 7 ++ tree.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tree.h | 45 ++++++++++++ 4 files changed, 278 insertions(+), 1 deletions(-) create mode 100644 tree.c create mode 100644 tree.h diff --git a/Makefile b/Makefile index 295b7cb..d88b8ff 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ MANDIR=/usr/share/man/man8 CFLAGS?=-O1 -g -Wall -Wshadow CC?=gcc -OBJS = powerdebug.o sensor.o clocks.o regulator.o display.o +OBJS = powerdebug.o sensor.o clocks.o regulator.o display.o tree.o default: powerdebug diff --git a/clocks.c b/clocks.c index ecc72ea..8a2dc97 100644 --- a/clocks.c +++ b/clocks.c @@ -19,6 +19,7 @@ #include "powerdebug.h" #include "clocks.h" +#include "tree.h" #define MAX_LINES 120 @@ -41,6 +42,8 @@ struct clock_info { struct clock_info **children; } *clocks_info; +static struct tree *clock_tree; + static int locate_debugfs(char *clk_path) { const char *mtab = "/proc/mounts"; @@ -73,6 +76,10 @@ int clock_init(void) sprintf(clk_dir_path, "%s/clock", clk_dir_path); + clock_tree = tree_load(clk_dir_path, NULL); + if (!clock_tree) + return -1; + return access(clk_dir_path, F_OK); } diff --git a/tree.c b/tree.c new file mode 100644 index 0000000..e681f4f --- /dev/null +++ b/tree.c @@ -0,0 +1,225 @@ +/******************************************************************************* + * Copyright (C) 2010, Linaro Limited. + * + * This file is part of PowerDebug. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Author: + * Daniel Lezcano + * + *******************************************************************************/ + +#define _GNU_SOURCE +#include +#undef _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#include "tree.h" + +/* + * Allocate a tree structure and initialize the different fields. + * + * @path : the absolute path to the directory + * @depth : the depth in the tree + * Returns a tree structure on success, NULL otherwise + */ +static inline struct tree *tree_alloc(const char *path, int depth) +{ + struct tree *t; + + t = malloc(sizeof(*t)); + if (!t) + return NULL; + + /* Full pathname */ + t->path = strdup(path); + if (!t->path) { + free(t); + return NULL; + } + + /* Basename pointer on the full path name */ + t->name = strrchr(t->path, '/') + 1; + + t->depth = depth; + t->tail = t; + t->child = NULL; + t->parent = NULL; + t->next = NULL; + t->prev = NULL; + t->private = NULL; + + return t; +} + +/* + * Free a tree structure and the fields we allocated in the + * tree_alloc function. + * + * @t : the tree structure to be freed + */ +static inline void tree_free(struct tree *t) +{ + free(t->path); + free(t); +} + +/* + * Add at the end of the list the new list element. + * + * @head : the list to be appened + * @new : the new element to be added at the end of the list + */ +static inline void tree_add_tail(struct tree *head, struct tree *new) +{ + new->prev = head->tail; + head->tail->next = new; + head->tail = new; +} + +/* + * Add a child in to a parent list, at the end of this list. + * + * @parent : the parent list to add the child + * @child : the child to be added + */ +static inline void tree_add_child(struct tree *parent, struct tree *child) +{ + child->parent = parent; + + if (parent->child) + return tree_add_tail(parent->child, child); + + parent->child = child; +} + +/* + * This function will browse the directory structure and build a + * tree reflecting the content of the directory tree. + * + * @tree : the root node of the tree + * @filter : a callback to filter out the directories + * Returns 0 on success, -1 otherwise + */ +static int tree_scan(struct tree *tree, tree_filter_t filter) +{ + DIR *dir; + char *basedir, *newpath; + struct dirent dirent, *direntp; + struct stat s; + int ret = 0; + + dir = opendir(tree->path); + if (!dir) + return -1; + + while (!readdir_r(dir, &dirent, &direntp)) { + + struct tree *child; + + if (!direntp) + break; + + if (direntp->d_name[0] == '.') + continue; + + if (filter && filter(direntp->d_name)) + continue; + + ret = asprintf(&basedir, "%s", tree->path); + if (ret < 0) + return -1; + + ret = basename(basedir) ? 0 : -1; + if (ret < 0) + goto out_free_basedir; + + ret = asprintf(&newpath, "%s/%s", basedir, direntp->d_name); + if (ret < 0) + goto out_free_basedir; + + ret = stat(newpath, &s); + if (ret) + goto out_free_newpath; + + if (S_ISDIR(s.st_mode)) { + + ret = -1; + + child = tree_alloc(newpath, tree->depth + 1); + if (!child) + goto out_free_newpath; + + tree_add_child(tree, child); + + ret = tree_scan(child, filter); + } + + out_free_newpath: + free(newpath); + + out_free_basedir: + free(basedir); + + if (ret) + break; + } + + closedir(dir); + + return ret; +} + +/* + * This function takes the topmost directory path and populate the + * directory tree structures. + * + * @tree : a path to the topmost directory path + * Returns a tree structure corresponding to the root node of the + * directory tree representation on success, NULL otherwise + */ +struct tree *tree_load(const char *path, tree_filter_t filter) +{ + struct tree *tree; + + tree = tree_alloc(path, 0); + if (!tree) + return NULL; + + if (tree_scan(tree, filter)) { + tree_free(tree); + return NULL; + } + + return tree; +} + +/* + * This function will go over the tree passed as parameter and + * will call the callback passed as parameter for each node. + * + * @tree : the topmost node where we begin to browse the tree + * Returns 0 on success, < 0 otherwise + */ +int tree_for_each(struct tree *tree, tree_cb_t cb, void *data) +{ + if (!tree) + return 0; + + if (cb(tree, data)) + return -1; + + if (tree_for_each(tree->child, cb, data)) + return -1; + + return tree_for_each(tree->next, cb, data); +} diff --git a/tree.h b/tree.h new file mode 100644 index 0000000..57c70f8 --- /dev/null +++ b/tree.h @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (C) 2010, Linaro Limited. + * + * This file is part of PowerDebug. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Author: + * Daniel Lezcano + * + *******************************************************************************/ + +/* + * Structure describing a node of the clock tree + * + * tail : points to the last element in the list + * next : points to the next element in the list + * child : points to the child node + * parent : points to the parent node + * depth : the recursive level of the node + * path : absolute pathname of the directory + * name : basename of the directory + */ +struct tree { + struct tree *tail; + struct tree *next; + struct tree *prev; + struct tree *child; + struct tree *parent; + char *path; + char *name; + void *private; + unsigned char depth; +}; + +typedef int (*tree_cb_t)(struct tree *t, void *data); + +typedef int (*tree_filter_t)(const char *name); + +extern struct tree *tree_load(const char *path, tree_filter_t filter); + +extern int tree_for_each(struct tree *tree, tree_cb_t cb, void *data);