Пример #1
0
void fm_path_init()
{
	const char* sep, *name;
	FmPath* tmp, *parent;

	/* path object of root dir */
	root = fm_path_new_child(NULL, "/");
	home_dir = g_get_home_dir();
	home_len = strlen(home_dir);

	/* build path object for home dir */
	name = home_dir + 1; /* skip leading / */
	parent = root;
	while( sep = strchr(name, '/') )
	{
		int len = (sep - name);
		/* ref counting is not a problem here since this path component
		 * will exist till the termination of the program. So mem leak is ok. */
		tmp = fm_path_new_child_len(parent, name, len);
		name = sep + 1;
		parent = tmp;
	}
	home = fm_path_new_child(parent, name);

	desktop_dir = g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP);
	desktop_len = strlen(desktop_dir);

	/* build path object for desktop dir */
	name = desktop_dir + home_len + 1; /* skip home dir part / */
	parent = home;
	while( sep = strchr(name, '/') )
	{
		int len = (sep - name);
		/* ref counting is not a problem here since this path component
		 * will exist till the termination of the program. So mem leak is ok. */
		tmp = fm_path_new_child_len(parent, name, len);
		name = sep + 1;
		parent = tmp;
	}
	desktop = fm_path_new_child(parent, name);

	/* build path object for trash can */
    /* FIXME: currently there are problems with URIs. using trash:/ here will cause problems. */
	trash_root = fm_path_new_child(NULL, "trash:///");
	trash_root->flags |= (FM_PATH_IS_TRASH|FM_PATH_IS_VIRTUAL|FM_PATH_IS_LOCAL);

    apps_root = fm_path_new_child(NULL, "applications:///");
	apps_root->flags |= (FM_PATH_IS_VIRTUAL);
}
Пример #2
0
/**
 * fm_path_new_child
 * @parent: a parent path
 * @basename: basename of a direct child of @parent directory in glib
 * filename encoding.  (can be non-UTF-8).
 *
 * Returns: a newly created FmPath for the path. You have to call
 * fm_path_unref () when it's no longer needed.
 */
FmPath *fm_path_new_child (FmPath *parent, const char *basename)
{
    if (G_LIKELY (basename && *basename))
    {
        int baselen = strlen (basename);
        return fm_path_new_child_len (parent, basename, baselen);
    }
    
    return G_LIKELY (parent) ? fm_path_ref (parent) : NULL;
}
Пример #3
0
/**
 * fm_path_new_relative
 * @parent: a parent path
 * @rel: a path relative to @parent in glib filename encoding.  (can be
 * non-UTF-8). However this should not be a escaped ASCII string used in
 * URI. If you're building a relative path for a URI, and the relative
 * path is escaped, you have to unescape it first.
 *
 * For example, if @parent is "http://wiki.lxde.org/" and @rel is
 * "zh/%E9%A6%96%E9%A0%81", you have to unescape the relative path
 * prior to passing it to fm_path_new_relative ().
 *
 * If @parent is NULL, this works the same as fm_path_new_for_str (@rel)
 *
 * Returns: a newly created FmPath for the path. You have to call
 * fm_path_unref () when it's no longer needed.
 */
FmPath *fm_path_new_relative (FmPath *parent, const char *rel)
{
    FmPath *path;
    
    if (G_UNLIKELY (!rel || !*rel)) // relative path is empty
        return parent ? fm_path_ref (parent) : fm_path_ref (root_path); // return parent

    if (G_LIKELY (parent))
    {
        char *sep;
        
        // remove leading slashes
        while (*rel == '/')
            ++rel;
        
        if (!*rel)
            path = fm_path_ref (parent);
        else
        {
#if 0       // FIXME_pcm: Let's optimize this later. Make things working first is more important.
            // use some pre-defined paths when possible
            if (G_UNLIKELY (parent == root_path))
            {
                if (strcmp (home_dir + 1, rel) == 0)
                    return fm_path_ref (home_path);
                if (strcmp (desktop_dir + 1, rel) == 0)
                    return fm_path_ref (desktop_dir);
            }
#endif

            sep = strchr (rel, '/');
            if (sep)
            {
                FmPath *new_parent = fm_path_new_child_len (parent, rel, sep - rel);
                path = fm_path_new_relative (new_parent, sep + 1);
                fm_path_unref (new_parent);
            }
            else
            {
                path = fm_path_new_child (parent, rel);
            }
        }
    }
    else // this is actaully a full path
        path = fm_path_new_for_str (rel);
    
    return path;
}
Пример #4
0
FmPath* fm_path_new(const char* path)
{
	const char* sep;
    /* FIXME: need to canonicalize paths */

    if( path[0] == '/' ) /* if this is a absolute native path */
    {
        if (path[1])
            return fm_path_new_relative(root, path + 1);
        else
            /* special case: handle root dir */
            return fm_path_ref( root );
    }
    else if ( path[0] == '~' && (path[1] == '\0' || path[1]=='/') ) /* home dir */
    {
        ++path;
        return *path ? fm_path_new_relative(home, path) : fm_path_ref(home);
    }
	else /* then this should be a URL */
	{
        FmPath* parent, *ret;
        char* colon = strchr(path, ':');
        char* hier_part;
        char* rest;
        int root_len;

        if( !colon ) /* this shouldn't happen */
            return NULL; /* invalid path FIXME: should we treat it as relative path? */

        /* FIXME: convert file:/// to local native path */
        hier_part = colon+1;
        if( hier_part[0] == '/' )
        {
            if(hier_part[1] == '/') /* this is a scheme:// form URI */
                rest = hier_part + 2;
            else /* a malformed URI */
                rest = hier_part + 1;

            if(*rest == '/') /* :/// means there is no authoraty part */
                ++rest;
            else /* we are now at autority part, something like <username>@domain/ */
            {
                while( *rest && *rest != '/' )
                    ++rest;
                if(*rest == '/')
                    ++rest;
            }

            if( strncmp(path, "trash:", 6) == 0 ) /* in trash:// */
            {
                if(*rest)
                    return fm_path_new_relative(trash_root, rest);
                else
                    return fm_path_ref(trash_root);
            }
            /* other URIs */
        }
        else /* this URI doesn't have //, like mailto: */
        {
            /* FIXME: is this useful to file managers? */
            rest = colon + 1;
        }
        root_len = (rest - path);
        parent = fm_path_new_child_len(NULL, path, root_len);
        if(*rest)
        {
            ret = fm_path_new_relative(parent, rest);
            fm_path_unref(parent);
        }
        else
            ret = parent;
        return ret;
	}
	return fm_path_new_relative(NULL, path);
}
Пример #5
0
FmPath* fm_path_new_relative(FmPath* parent, const char* relative_path)
{
	FmPath* path;
	const char* sep;
	gsize name_len;

    /* FIXME: need to canonicalize paths */
	if(parent == root)
	{
		if( 0 == strncmp(relative_path, home_dir + 1, home_len - 1) ) /* in home dir */
		{
			if( relative_path[home_len - 1] == '\0' ) /* this is the home dir */
            {
				if(G_LIKELY(home))
					return fm_path_ref(home);
				else
					goto _resolve_relative_path;
            }
			if( 0 == strncmp(relative_path, desktop_dir + home_len + 1, desktop_len - home_len -1) ) /* in desktop dir */
			{
				if(relative_path[desktop_len - 1] == '\0') /* this is the desktop dir */
					return fm_path_ref(desktop);
				return fm_path_new_relative(desktop, relative_path + desktop_len + 1);
			}
		}
	}
_resolve_relative_path:
	sep = strchr(relative_path, '/');
	if(sep)
	{
        char* end = sep;

        while(*end && *end == '/') /* prevent tailing slash or duplicated slashes. */
            ++end;

        name_len = (sep - relative_path);
        if(relative_path[0] == '.' && (name_len == 1 || (name_len == 2  && relative_path[1] == '.')) ) /* . or .. */
        {
            if(name_len == 1) /* . => current dir */
            {
                relative_path = end;
                if(*end == '\0')
                    return fm_path_ref(parent); /* . is the last component */
                else
                {
                    relative_path = end; /* skip this component */
                    goto _resolve_relative_path;
                }
            }
            else /* .. jump to parent dir => */
            {
                if(parent->parent)
                    parent = fm_path_ref(parent->parent);
            }
        }
        else
            parent = fm_path_new_child_len(parent, relative_path, name_len);

        if(*end != '\0')
        {
            relative_path = end;
            path = fm_path_new_relative(parent, relative_path);
            fm_path_unref(parent);
        }
        else /* this is tailing slash */
            path = parent;
	}
	else /* this is the last component in the path */
	{
		name_len = strlen(relative_path);
        if(relative_path[0] == '.' && (name_len == 1 || (name_len == 2  && relative_path[1] == '.')) ) /* . or .. */
        {
            if(name_len == 1) /* . => current dir */
                path = fm_path_ref(parent); /* . is the last component */
            else /* .. jump to parent dir => */
            {
                if(parent->parent)
                    path = fm_path_ref(parent->parent);
                else
                    path = fm_path_ref(parent);
            }
        }
        else
    		path = fm_path_new_child_len(parent, relative_path, name_len);
	}
	return path;
}
Пример #6
0
FmPath* fm_path_new_child(FmPath* parent, const char* basename)
{
	int baselen = strlen(basename);
	return fm_path_new_child_len(parent, basename, baselen);
}