* [Qemu-devel] [PATCH] [REPOST] Simplily linux-user/path.c
@ 2007-02-19 13:04 Kirill A. Shutemov
2007-02-23 16:58 ` Thiemo Seufer
0 siblings, 1 reply; 4+ messages in thread
From: Kirill A. Shutemov @ 2007-02-19 13:04 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1.1: Type: text/plain, Size: 62 bytes --]
Fixed version of the patch in the attacment. Please, comment.
[-- Attachment #1.2: qemu-0.8.2-alt-path.patch --]
[-- Type: text/plain, Size: 4519 bytes --]
--- qemu-0.8.2/linux-user/path.c.orig 2006-12-21 17:16:03 +0200
+++ qemu-0.8.2/linux-user/path.c 2006-12-21 17:14:08 +0200
@@ -1,147 +1,37 @@
/* Code to mangle pathnames into those matching a given prefix.
eg. open("/lib/foo.so") => open("/usr/gnemul/i386-linux/lib/foo.so");
-
- The assumption is that this area does not change.
-*/
+ */
#include <sys/types.h>
-#include <dirent.h>
+#include <sys/stat.h>
#include <unistd.h>
-#include <stdlib.h>
#include <string.h>
-#include <errno.h>
#include <stdio.h>
#include "qemu.h"
-struct pathelem
-{
- /* Name of this, eg. lib */
- char *name;
- /* Full path name, eg. /usr/gnemul/x86-linux/lib. */
- char *pathname;
- struct pathelem *parent;
- /* Children */
- unsigned int num_entries;
- struct pathelem *entries[0];
-};
-
-static struct pathelem *base;
-
-/* First N chars of S1 match S2, and S2 is N chars long. */
-static int strneq(const char *s1, unsigned int n, const char *s2)
-{
- unsigned int i;
-
- for (i = 0; i < n; i++)
- if (s1[i] != s2[i])
- return 0;
- return s2[i] == 0;
-}
-
-static struct pathelem *add_entry(struct pathelem *root, const char *name);
-
-static struct pathelem *new_entry(const char *root,
- struct pathelem *parent,
- const char *name)
-{
- struct pathelem *new = malloc(sizeof(*new));
- new->name = strdup(name);
- asprintf(&new->pathname, "%s/%s", root, name);
- new->num_entries = 0;
- return new;
-}
-
-#define streq(a,b) (strcmp((a), (b)) == 0)
-
-static struct pathelem *add_dir_maybe(struct pathelem *path)
-{
- DIR *dir;
-
- if ((dir = opendir(path->pathname)) != NULL) {
- struct dirent *dirent;
-
- while ((dirent = readdir(dir)) != NULL) {
- if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){
- path = add_entry(path, dirent->d_name);
- }
- }
- closedir(dir);
- }
- return path;
-}
-
-static struct pathelem *add_entry(struct pathelem *root, const char *name)
-{
- root->num_entries++;
-
- root = realloc(root, sizeof(*root)
- + sizeof(root->entries[0])*root->num_entries);
-
- root->entries[root->num_entries-1] = new_entry(root->pathname, root, name);
- root->entries[root->num_entries-1]
- = add_dir_maybe(root->entries[root->num_entries-1]);
- return root;
-}
-
-/* This needs to be done after tree is stabalized (ie. no more reallocs!). */
-static void set_parents(struct pathelem *child, struct pathelem *parent)
-{
- unsigned int i;
-
- child->parent = parent;
- for (i = 0; i < child->num_entries; i++)
- set_parents(child->entries[i], child);
-}
+static char* pref;
void init_paths(const char *prefix)
{
if (prefix[0] != '/' ||
- prefix[0] == '\0' ||
- !strcmp(prefix, "/"))
+ prefix[0] == '\0' ||
+ !strcmp(prefix, "/"))
return;
- base = new_entry("", NULL, prefix+1);
- base = add_dir_maybe(base);
- if (base->num_entries == 0) {
- free (base);
- base = NULL;
- } else {
- set_parents(base, base);
- }
-}
-
-/* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */
-static const char *
-follow_path(const struct pathelem *cursor, const char *name)
-{
- unsigned int i, namelen;
-
- name += strspn(name, "/");
- namelen = strcspn(name, "/");
-
- if (namelen == 0)
- return cursor->pathname;
-
- if (strneq(name, namelen, ".."))
- return follow_path(cursor->parent, name + namelen);
-
- if (strneq(name, namelen, "."))
- return follow_path(cursor, name + namelen);
-
- for (i = 0; i < cursor->num_entries; i++)
- if (strneq(name, namelen, cursor->entries[i]->name))
- return follow_path(cursor->entries[i], name + namelen);
-
- /* Not found */
- return NULL;
+ pref = strdup(prefix);
}
/* Look for path in emulation dir, otherwise return name. */
const char *path(const char *name)
{
+ char *newname = (char *) alloca(strlen(pref)+strlen(name)+1);
+ struct stat buf;
/* Only do absolute paths: quick and dirty, but should mostly be OK.
Could do relative by tracking cwd. */
- if (!base || name[0] != '/')
- return name;
+ if (!pref || name[0] != '/')
+ return name;
+
+ strcpy(newname,pref);
+ strcat(newname,name);
- return follow_path(base, name) ?: name;
+ return stat(newname,&buf) ? name : strdup(newname);
}
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [PATCH] [REPOST] Simplily linux-user/path.c
2007-02-19 13:04 [Qemu-devel] [PATCH] [REPOST] Simplily linux-user/path.c Kirill A. Shutemov
@ 2007-02-23 16:58 ` Thiemo Seufer
2007-03-20 14:41 ` Kirill A. Shutemov
0 siblings, 1 reply; 4+ messages in thread
From: Thiemo Seufer @ 2007-02-23 16:58 UTC (permalink / raw)
To: Kirill A. Shutemov; +Cc: qemu-devel
Kirill A. Shutemov wrote:
> Fixed version of the patch in the attacment. Please, comment.
[snip]
> /* Look for path in emulation dir, otherwise return name. */
> const char *path(const char *name)
> {
> + char *newname = (char *) alloca(strlen(pref)+strlen(name)+1);
> + struct stat buf;
> /* Only do absolute paths: quick and dirty, but should mostly be OK.
> Could do relative by tracking cwd. */
> - if (!base || name[0] != '/')
> - return name;
> + if (!pref || name[0] != '/')
> + return name;
> +
> + strcpy(newname,pref);
> + strcat(newname,name);
>
> - return follow_path(base, name) ?: name;
> + return stat(newname,&buf) ? name : strdup(newname);
> }
This leaks memory allocated by strdup(). Also, the old code tries to
avoid syscalls by memorizing the paths. AFAICS we should do some
caching here.
Thiemo
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [PATCH] [REPOST] Simplily linux-user/path.c
2007-02-23 16:58 ` Thiemo Seufer
@ 2007-03-20 14:41 ` Kirill A. Shutemov
0 siblings, 0 replies; 4+ messages in thread
From: Kirill A. Shutemov @ 2007-03-20 14:41 UTC (permalink / raw)
To: Thiemo Seufer; +Cc: qemu-devel
[-- Attachment #1.1: Type: text/plain, Size: 1194 bytes --]
On [Fri, 23.02.2007 16:58], Thiemo Seufer wrote:
> Kirill A. Shutemov wrote:
> > Fixed version of the patch in the attacment. Please, comment.
> [snip]
> > /* Look for path in emulation dir, otherwise return name. */
> > const char *path(const char *name)
> > {
> > + char *newname = (char *) alloca(strlen(pref)+strlen(name)+1);
> > + struct stat buf;
> > /* Only do absolute paths: quick and dirty, but should mostly be OK.
> > Could do relative by tracking cwd. */
> > - if (!base || name[0] != '/')
> > - return name;
> > + if (!pref || name[0] != '/')
> > + return name;
> > +
> > + strcpy(newname,pref);
> > + strcat(newname,name);
> >
> > - return follow_path(base, name) ?: name;
> > + return stat(newname,&buf) ? name : strdup(newname);
> > }
>
> This leaks memory allocated by strdup(). Also, the old code tries to
> avoid syscalls by memorizing the paths. AFAICS we should do some
> caching here.
Rewritten patch with caching in the attachment. Please, review.
--
Regards, Kirill A. Shutemov
+ Belarus, Minsk
+ Velesys LLC, http://www.velesys.com/
+ ALT Linux Team, http://www.altlinux.com/
[-- Attachment #1.2: qemu-0.9.0-alt-path.patch --]
[-- Type: text/plain, Size: 5632 bytes --]
--- ../qemu/linux-user/path.c 2007-03-20 12:54:22 +0200
+++ qemu-0.9.0.cvs20070320/linux-user/path.c 2007-03-20 16:02:43 +0200
@@ -1,147 +1,75 @@
/* Code to mangle pathnames into those matching a given prefix.
eg. open("/lib/foo.so") => open("/usr/gnemul/i386-linux/lib/foo.so");
-
- The assumption is that this area does not change.
-*/
+ */
#include <sys/types.h>
-#include <dirent.h>
+#include <sys/stat.h>
#include <unistd.h>
-#include <stdlib.h>
#include <string.h>
-#include <errno.h>
#include <stdio.h>
#include "qemu.h"
-struct pathelem
-{
- /* Name of this, eg. lib */
- char *name;
- /* Full path name, eg. /usr/gnemul/x86-linux/lib. */
- char *pathname;
- struct pathelem *parent;
- /* Children */
- unsigned int num_entries;
- struct pathelem *entries[0];
-};
-
-static struct pathelem *base;
-
-/* First N chars of S1 match S2, and S2 is N chars long. */
-static int strneq(const char *s1, unsigned int n, const char *s2)
-{
- unsigned int i;
-
- for (i = 0; i < n; i++)
- if (s1[i] != s2[i])
- return 0;
- return s2[i] == 0;
-}
-
-static struct pathelem *add_entry(struct pathelem *root, const char *name);
-
-static struct pathelem *new_entry(const char *root,
- struct pathelem *parent,
- const char *name)
-{
- struct pathelem *new = malloc(sizeof(*new));
- new->name = strdup(name);
- asprintf(&new->pathname, "%s/%s", root, name);
- new->num_entries = 0;
- return new;
-}
-
-#define streq(a,b) (strcmp((a), (b)) == 0)
-
-static struct pathelem *add_dir_maybe(struct pathelem *path)
-{
- DIR *dir;
+struct path_list_head {
+ struct path_list_head *next;
- if ((dir = opendir(path->pathname)) != NULL) {
- struct dirent *dirent;
-
- while ((dirent = readdir(dir)) != NULL) {
- if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){
- path = add_entry(path, dirent->d_name);
- }
- }
- closedir(dir);
- }
- return path;
-}
-
-static struct pathelem *add_entry(struct pathelem *root, const char *name)
-{
- root->num_entries++;
-
- root = realloc(root, sizeof(*root)
- + sizeof(root->entries[0])*root->num_entries);
-
- root->entries[root->num_entries-1] = new_entry(root->pathname, root, name);
- root->entries[root->num_entries-1]
- = add_dir_maybe(root->entries[root->num_entries-1]);
- return root;
-}
-
-/* This needs to be done after tree is stabalized (ie. no more reallocs!). */
-static void set_parents(struct pathelem *child, struct pathelem *parent)
-{
- unsigned int i;
+ char* orig_path;
+ char* dest_path;
+};
- child->parent = parent;
- for (i = 0; i < child->num_entries; i++)
- set_parents(child->entries[i], child);
-}
+static struct path_list_head* list_head;
void init_paths(const char *prefix)
{
if (prefix[0] != '/' ||
- prefix[0] == '\0' ||
- !strcmp(prefix, "/"))
+ prefix[0] == '\0' ||
+ !strcmp(prefix, "/"))
return;
- base = new_entry("", NULL, prefix+1);
- base = add_dir_maybe(base);
- if (base->num_entries == 0) {
- free (base);
- base = NULL;
- } else {
- set_parents(base, base);
- }
-}
-
-/* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */
-static const char *
-follow_path(const struct pathelem *cursor, const char *name)
-{
- unsigned int i, namelen;
+ list_head = malloc(sizeof(struct path_list_head));
- name += strspn(name, "/");
- namelen = strcspn(name, "/");
-
- if (namelen == 0)
- return cursor->pathname;
-
- if (strneq(name, namelen, ".."))
- return follow_path(cursor->parent, name + namelen);
-
- if (strneq(name, namelen, "."))
- return follow_path(cursor, name + namelen);
-
- for (i = 0; i < cursor->num_entries; i++)
- if (strneq(name, namelen, cursor->entries[i]->name))
- return follow_path(cursor->entries[i], name + namelen);
-
- /* Not found */
- return NULL;
+ /* first element of list is prefix */
+ list_head->orig_path = strdup("/");
+ list_head->dest_path = strdup(prefix);
+ list_head->next = NULL;
}
/* Look for path in emulation dir, otherwise return name. */
const char *path(const char *name)
{
+ struct path_list_head *tmp = list_head;
+
/* Only do absolute paths: quick and dirty, but should mostly be OK.
Could do relative by tracking cwd. */
- if (!base || name[0] != '/')
- return name;
+ if (!list_head || name[0] != '/')
+ return name;
+
+ /* look for place where path should be present */
+ while ( tmp->next && (strcmp(tmp->next->orig_path, name) < 0) )
+ tmp = tmp->next;
+
+ /* if there is no path in list */
+ if ( !tmp->next || strcmp(tmp->next->orig_path, name) )
+ {
+ struct stat buf;
+ struct path_list_head *new;
+ int path_length = strlen(list_head->dest_path) + strlen(name) + 1;
+ char *newname = malloc(path_length);
+
+ strncpy(newname, list_head->dest_path, path_length);
+ strncat(newname, name, path_length);
+
+ new = malloc(sizeof(struct path_list_head));
+
+ new->orig_path = strdup(name);
+ /* new->dest_path contains path in emulation dir, otherwise NULL */
+ new->dest_path = stat(newname, &buf) ? NULL : newname;
+
+ /* freeing memory if no path in emulation dir */
+ if (new->dest_path == NULL)
+ free(newname);
+
+ new->next = tmp->next;
+ tmp->next = new;
+ }
- return follow_path(base, name) ?: name;
+ return tmp->next->dest_path ? tmp->next->dest_path : name;
}
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* [Qemu-devel] [PATCH] [REPOST] Simplily linux-user/path.c
@ 2007-02-19 14:02 Kirill A. Shutemov
0 siblings, 0 replies; 4+ messages in thread
From: Kirill A. Shutemov @ 2007-02-19 14:02 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 60 bytes --]
Fixed version of patch in the attaechment. Please, comment.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-03-20 14:43 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-19 13:04 [Qemu-devel] [PATCH] [REPOST] Simplily linux-user/path.c Kirill A. Shutemov
2007-02-23 16:58 ` Thiemo Seufer
2007-03-20 14:41 ` Kirill A. Shutemov
2007-02-19 14:02 Kirill A. Shutemov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.