Re: g_file_write()



Soeren Sandmann <sandmann daimi au dk> writes:

> I think this is a serious problem. The file should be created with the
> umask permissions. You can do this:
> 
> #ifndef G_OS_WIN32
>  {
>    mode_t mode = umask (0);
>    umask (mode);
> 
>    chmod (filename, mode);
>  }
> #endif
> 
> but then there is a race condition with another thread setting
> umask. This can be avoided by doing it in a separate process:
> 
> pid = fork();
> 
> if (pid == -1)
> {
>    report error
> }
> else if (pid == 0)
> {
>    /* child */
>    umask/chmod ...
>    exit (errno);
> }
> else
> {
>    /* parent */
>    int err;
> 
>    waitpid(pid, &err, 0);
> 
>    if (err != 0)
>        ....;
> }
> 
> Is there a simpler way to do this?

If there is, I don't know it. I have put up a patch to do the chmod()
in a child process:

        http://www.daimi.au.dk/~sandmann/umask-fork.patch

In addition I took a look at the stdio output from libgsf. One thing
that may be worth considering adobting is the symlink following code
they have. Currently g_file_replace() will replace the symlink instead
of the linked file, which will probably surprise some people.

This is the function in question:

static char *
follow_symlinks (char const *filename, GError **error)
{
        gchar *followed_filename, *link;
        gint link_count = 0;

        g_return_val_if_fail (filename != NULL, NULL);

        followed_filename = g_strdup (filename);

        while ((link = g_file_read_link (followed_filename, NULL)) != NULL &&
                  ++link_count <= GSF_MAX_LINK_LEVEL) {
                if (g_path_is_absolute (link)) {
                        g_free (followed_filename);
                        followed_filename = link;
                } else {
                        /* If the linkname is not an absolute path name, append
                         * it to the directory name of the followed filename.  E.g.
                         * we may have /foo/bar/baz.lnk -> eek.txt, which really
                         * is /foo/bar/eek.txt.  
                         */
                        gchar *dir = g_path_get_dirname (followed_filename);
                        g_free (followed_filename);
                        followed_filename = g_build_filename (dir, link, NULL);
                        g_free (dir);
                        g_free (link);
                }
        }

        if (link == NULL)
                return followed_filename;

        /* Too many symlinks */
        if (error != NULL)
                *error = g_error_new_literal (gsf_output_error_id (), ELOOP,
                                              g_strerror (ELOOP));
        g_free (followed_filename);
        return NULL;
}

Maybe we could even add it as g_follow_symlik() to avoid duplication
of code in libgsf.


Søren





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]