From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1HTfYa-0002wj-Tk for qemu-devel@nongnu.org; Tue, 20 Mar 2007 10:43:24 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1HTfYY-0002wX-IM for qemu-devel@nongnu.org; Tue, 20 Mar 2007 10:43:23 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1HTfYY-0002wU-Ca for qemu-devel@nongnu.org; Tue, 20 Mar 2007 09:43:22 -0500 Received: from partizan.velesys.com ([213.184.230.195]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1HTfWx-00061I-4s for qemu-devel@nongnu.org; Tue, 20 Mar 2007 10:41:44 -0400 Date: Tue, 20 Mar 2007 16:41:12 +0200 From: "Kirill A. Shutemov" Subject: Re: [Qemu-devel] [PATCH] [REPOST] Simplily linux-user/path.c Message-ID: <20070320144112.GA9266@localhost.localdomain> References: <20070219130409.GD25556@localhost.localdomain> <20070223165856.GC2521@networkno.de> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="dc+cDN39EJAMEtIO" Content-Disposition: inline In-Reply-To: <20070223165856.GC2521@networkno.de> Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Thiemo Seufer Cc: qemu-devel@nongnu.org --dc+cDN39EJAMEtIO Content-Type: multipart/mixed; boundary="n8g4imXOkfNTN/H1" Content-Disposition: inline --n8g4imXOkfNTN/H1 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable 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 =3D (char *) alloca(strlen(pref)+strlen(name)+1); > > + struct stat buf; > > /* Only do absolute paths: quick and dirty, but should mostly be O= K. > > Could do relative by tracking cwd. */ > > - if (!base || name[0] !=3D '/') > > - return name; > > + if (!pref || name[0] !=3D '/') > > + return name; > > + > > + strcpy(newname,pref); > > + strcat(newname,name); > > =20 > > - return follow_path(base, name) ?: name; > > + return stat(newname,&buf) ? name : strdup(newname); > > } >=20 > 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. --=20 Regards, Kirill A. Shutemov + Belarus, Minsk + Velesys LLC, http://www.velesys.com/ + ALT Linux Team, http://www.altlinux.com/ --n8g4imXOkfNTN/H1 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="qemu-0.9.0-alt-path.patch" Content-Transfer-Encoding: quoted-printable --- ../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") =3D> open("/usr/gnemul/i386-linux/lib/foo.so"); - - The assumption is that this area does not change. -*/ + */ #include -#include +#include #include -#include #include -#include #include #include "qemu.h" =20 -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 =3D 0; i < n; i++) - if (s1[i] !=3D s2[i]) - return 0; - return s2[i] =3D=3D 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 =3D malloc(sizeof(*new)); - new->name =3D strdup(name); - asprintf(&new->pathname, "%s/%s", root, name); - new->num_entries =3D 0; - return new; -} - -#define streq(a,b) (strcmp((a), (b)) =3D=3D 0) - -static struct pathelem *add_dir_maybe(struct pathelem *path) -{ - DIR *dir; +struct path_list_head { + struct path_list_head *next; =20 - if ((dir =3D opendir(path->pathname)) !=3D NULL) { - struct dirent *dirent; - - while ((dirent =3D readdir(dir)) !=3D NULL) { - if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){ - path =3D 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 =3D realloc(root, sizeof(*root) - + sizeof(root->entries[0])*root->num_entries); - - root->entries[root->num_entries-1] =3D new_entry(root->pathname, root,= name); - root->entries[root->num_entries-1] - =3D 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; +}; =20 - child->parent =3D parent; - for (i =3D 0; i < child->num_entries; i++) - set_parents(child->entries[i], child); -} +static struct path_list_head* list_head; =20 void init_paths(const char *prefix) { if (prefix[0] !=3D '/' || - prefix[0] =3D=3D '\0' || - !strcmp(prefix, "/")) + prefix[0] =3D=3D '\0' || + !strcmp(prefix, "/")) return; =20 - base =3D new_entry("", NULL, prefix+1); - base =3D add_dir_maybe(base); - if (base->num_entries =3D=3D 0) { - free (base); - base =3D 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 =3D malloc(sizeof(struct path_list_head)); =20 - name +=3D strspn(name, "/"); - namelen =3D strcspn(name, "/"); - - if (namelen =3D=3D 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 =3D 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 =3D strdup("/"); + list_head->dest_path =3D strdup(prefix); + list_head->next =3D NULL; } =20 /* Look for path in emulation dir, otherwise return name. */ const char *path(const char *name) { + struct path_list_head *tmp =3D list_head; + /* Only do absolute paths: quick and dirty, but should mostly be OK. Could do relative by tracking cwd. */ - if (!base || name[0] !=3D '/') - return name; + if (!list_head || name[0] !=3D '/') + return name; + + /* look for place where path should be present */ + while ( tmp->next && (strcmp(tmp->next->orig_path, name) < 0) ) + tmp =3D 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 =3D strlen(list_head->dest_path) + strlen(name) + 1; + char *newname =3D malloc(path_length); + + strncpy(newname, list_head->dest_path, path_length); + strncat(newname, name, path_length); + + new =3D malloc(sizeof(struct path_list_head)); + + new->orig_path =3D strdup(name); + /* new->dest_path contains path in emulation dir, otherwise NULL */ + new->dest_path =3D stat(newname, &buf) ? NULL : newname; + + /* freeing memory if no path in emulation dir */ + if (new->dest_path =3D=3D NULL) + free(newname); + + new->next =3D tmp->next; + tmp->next =3D new; + } =20 - return follow_path(base, name) ?: name; + return tmp->next->dest_path ? tmp->next->dest_path : name; } --n8g4imXOkfNTN/H1-- --dc+cDN39EJAMEtIO Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) iD8DBQFF//KfbWYnhzC5v6oRAjA5AJ40rIalBJvc/EpkENA6xbRTdQEIGQCgjnYy /C0U/V745a+E43PazYNJamk= =I3vM -----END PGP SIGNATURE----- --dc+cDN39EJAMEtIO--