From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1HYIPo-0000xv-59 for qemu-devel@nongnu.org; Mon, 02 Apr 2007 05:01:28 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1HYIPn-0000xX-5C for qemu-devel@nongnu.org; Mon, 02 Apr 2007 05:01:27 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1HYIPm-0000xO-SX for qemu-devel@nongnu.org; Mon, 02 Apr 2007 05:01:27 -0400 Received: from partizan.velesys.com ([213.184.230.195]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1HYIMk-0003cO-Rr for qemu-devel@nongnu.org; Mon, 02 Apr 2007 04:58:19 -0400 Date: Mon, 2 Apr 2007 11:48:03 +0300 From: "Kirill A. Shutemov" Message-ID: <20070402084803.GB17276@localhost.localdomain> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="PuGuTyElPB9bOcsM" Content-Disposition: inline Subject: [Qemu-devel] [PATCH] Rewriten linux-user/path.c Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org --PuGuTyElPB9bOcsM Content-Type: multipart/mixed; boundary="3uo+9/B/ebqu+fSQ" Content-Disposition: inline --3uo+9/B/ebqu+fSQ Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Patch to linux-user/path.c in the attachment. It's almost totally rewritten. This version of path.c has very simple and quick init_paths() so emulated programs will start quicker. New init_path() solves problem with symlink recursion in the emulated dir. Rewritten path() use stat(2) to check if a path present in the emulated dir. Memory allocated for new path tracked using simple linked list. New path() follow changing of emulation dir. Please, comment it. --=20 Regards, Kirill A. Shutemov + Belarus, Minsk + Velesys LLC, http://www.velesys.com/ + ALT Linux Team, http://www.altlinux.com/ --3uo+9/B/ebqu+fSQ 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 +++ qemu/linux-user/path.c @@ -1,147 +1,81 @@ /* 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]; +struct path_list_head { + struct path_list_head *next; + char* path; }; =20 -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; - - 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; - - 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); - } -} + list_head =3D malloc(sizeof(struct path_list_head)); =20 -/* 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 +=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->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 *list =3D list_head; + int path_length =3D strlen(list_head->path) + strlen(name) + 1; + char *newname =3D malloc(path_length); + struct stat buf; + const char * result =3D name; + /* 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; - - return follow_path(base, name) ?: name; + if (!list_head || result[0] !=3D '/') + goto exit; + + strncpy(newname, list_head->path, path_length); + strncat(newname, name, path_length); + + /* look for place where path should be present */ + while ( list->next && (strcmp(list->next->path, newname) < 0) ) + list =3D list->next; + + /* if there is no path in list */ + if ( !list->next || strcmp(list->next->path, newname) ) { + /* add element to list if path exist in emulation dir */ + if ( !stat(newname, &buf) ) + { + struct path_list_head *new; + + new =3D malloc(sizeof(struct path_list_head)); + new->path =3D strdup(newname); + new->next =3D list->next; + list->next =3D new; + result =3D new->path; + } + + } else if ( stat(list->next->path, &buf) ) { + /* remove element from list if path doesn't exist in emulation dir */ + struct path_list_head* tmp; + + tmp =3D list->next; + list->next =3D tmp->next; + free(tmp->path); + free(tmp); + } else + result =3D list->next->path; + +exit: + free(newname); + return result; } --3uo+9/B/ebqu+fSQ-- --PuGuTyElPB9bOcsM 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) iD8DBQFGEMNabWYnhzC5v6oRAmY2AKCJaCjUU/UHUp0O+nN0Pg528ZorlACeKBay Z6Iow7TycKzRZQzI0wURTaQ= =rw9I -----END PGP SIGNATURE----- --PuGuTyElPB9bOcsM--