[libvirt] [PATCH] Eliminate use of large buffer on stack in virFileMakePath.
Daniel Veillard
veillard at redhat.com
Mon Jan 25 14:36:30 UTC 2010
On Fri, Jan 22, 2010 at 02:04:19PM -0500, Laine Stump wrote:
> virFileMakePath is a recursive function that was creates a buffer
> PATH_MAX bytes long for each recursion (one recursion for each element
> in the path). This changes it to have no buffers on the stack, and to
> allocate just one buffer total, no matter how many elements are in the
> path. Because the modified algorithm requires a char* to be passed in
> rather than const char *, it is now 2 functions - a toplevel API
> function that remains identical in function, and a 2nd helper function
> called for the recursions, which 1) doesn't allocate anything, and 2)
> takes a char* arg, so it can modify the contents.
>
> src/util/util.c: rewrite virFileMakePath
> ---
> src/util/util.c | 58 +++++++++++++++++++++++++++++++++++++++++++-----------
> 1 files changed, 46 insertions(+), 12 deletions(-)
>
> diff --git a/src/util/util.c b/src/util/util.c
> index 08d74a3..0ce5026 100644
> --- a/src/util/util.c
> +++ b/src/util/util.c
> @@ -1443,34 +1443,68 @@ int virDirCreate(const char *path, mode_t mode,
> }
> #endif
>
> -int virFileMakePath(const char *path)
> -{
> +static int virFileMakePathHelper(char *path) {
> struct stat st;
> - char parent[PATH_MAX];
> - char *p;
> + char *p = NULL;
> int err;
>
> if (stat(path, &st) >= 0)
> return 0;
>
> - if (virStrcpyStatic(parent, path) == NULL)
> - return EINVAL;
> -
> - if (!(p = strrchr(parent, '/')))
> + if ((p = strrchr(path, '/')) == NULL)
> return EINVAL;
>
> - if (p != parent) {
> + if (p != path) {
> *p = '\0';
> - if ((err = virFileMakePath(parent)))
> + err = virFileMakePathHelper(path);
> + *p = '/';
> + if (err != 0)
> return err;
> }
>
> - if (mkdir(path, 0777) < 0 && errno != EEXIST)
> + if (mkdir(path, 0777) < 0 && errno != EEXIST) {
> return errno;
> -
> + }
> return 0;
> }
>
> +int virFileMakePath(const char *path)
> +{
> + struct stat st;
> + char *parent = NULL;
> + char *p;
> + int err = 0;
> +
> + if (stat(path, &st) >= 0)
> + goto cleanup;
> +
> + if ((parent = strdup(path)) == NULL) {
> + err = ENOMEM;
> + goto cleanup;
> + }
> +
> + if ((p = strrchr(parent, '/')) == NULL) {
> + err = EINVAL;
> + goto cleanup;
> + }
> +
> + if (p != parent) {
> + *p = '\0';
> + if ((err = virFileMakePathHelper(parent)) != 0) {
> + goto cleanup;
> + }
> + }
> +
> + if (mkdir(path, 0777) < 0 && errno != EEXIST) {
> + err = errno;
> + goto cleanup;
> + }
> +
> +cleanup:
> + VIR_FREE(parent);
> + return err;
> +}
> +
> /* Build up a fully qualfiied path for a config file to be
> * associated with a persistent guest or network */
> int virFileBuildPath(const char *dir,
ACK, good catch !
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
More information about the libvir-list
mailing list