+/* Returns: g_malloc() allocated absolute pathname string */
+gchar *captive_path_normalize(const gchar *raw_pathname)
+{
+gchar *r,*r_end,*s,*d;
+
+ g_return_val_if_fail(raw_pathname!=NULL,NULL);
+ g_return_val_if_fail(g_path_is_absolute(raw_pathname),NULL);
+
+ r=g_strdup(raw_pathname);
+
+ /* coalesce '/'es */
+ for (d=s=r;*s;s++) {
+ if (*s==G_DIR_SEPARATOR && d>r && d[-1]==G_DIR_SEPARATOR)
+ continue;
+ *d++=*s;
+ }
+ g_assert(d>r);
+ if (d>(r+1) && d[-1]==G_DIR_SEPARATOR)
+ d--;
+ *d++=G_DIR_SEPARATOR;
+ r_end=d;
+
+ /* 'r' is NOT NULL-terminated here! */
+
+ for (d=s=r+1;s<r_end;) {
+ if (!strncmp(s-1,"/./",3)) {
+ s+=2;
+ continue;
+ }
+ if (!strncmp(s-1,"/../",4)) {
+ s+=3;
+ g_assert(d[-1]==G_DIR_SEPARATOR);
+ if (d>r+1) {
+ do {
+ d--;
+ } while (d[-1]!=G_DIR_SEPARATOR);
+ }
+ continue;
+ }
+ *d++=*s++;
+ }
+ g_assert(d[-1]==G_DIR_SEPARATOR); /* trailing '/' */
+ if (d>r+1) /* leave at least "/" */
+ d--;
+ *d='\0';
+
+ g_assert(g_path_is_absolute(r));
+
+ return r;
+}
+