as per previous.

i've implemented semantics i feel generally ok for use by any parts of 
wm, but tweak as needed.

i think i fscked up some whitespace things, would you please, carlos :)

>From 5f4420be79ab73258aaf85592003f8d05a8e8bcb Mon Sep 17 00:00:00 2001
From: Tamas TEVESZ <[email protected]>
Date: Mon, 15 Mar 2010 19:49:14 +0100
Subject: [PATCH] - add a new helper function, WMMkDirHier(), which creates 
directory
   hierarchies under $GNUSTEP_USER_ROOT

- make WMWritePropListToFile() use this

readily solves the "run dialog history vs nonexistent state dir" case.

if other consumers are found for this, just de-static and move the
prototype to WUtil.h or some other appropriate place.
---
 WINGs/proplist.c |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/WINGs/proplist.c b/WINGs/proplist.c
index 79bb298..51329bc 100644
--- a/WINGs/proplist.c
+++ b/WINGs/proplist.c
@@ -50,6 +50,7 @@ static WMPropList *getPLData(PLData * pldata);
 static WMPropList *getPLArray(PLData * pldata);
 static WMPropList *getPLDictionary(PLData * pldata);
 static WMPropList *getPropList(PLData * pldata);
+static int WMMkDirHier(char * path);
 
 typedef unsigned (*hashFunc) (const void *);
 typedef Bool(*isEqualFunc) (const void *, const void *);
@@ -1555,6 +1556,9 @@ Bool WMWritePropListToFile(WMPropList * plist, char 
*path, Bool atomically)
        char *desc;
        FILE *theFile;
 
+       if (!WMMkDirHier(path))
+               return False;
+
        if (atomically) {
 #ifdef HAVE_MKSTEMP
                int fd, mask;
@@ -1629,3 +1633,69 @@ Bool WMWritePropListToFile(WMPropList * plist, char 
*path, Bool atomically)
 
        return False;
 }
+
+/*
+ * create a directory hierarchy
+ *
+ * if the last octet of `path' is `/', the full path is
+ * assumed to be a directory; otherwise path is assumed to be a
+ * file, and the last component is stripped off. the rest is the
+ * the hierarchy to be created.
+ *
+ * refuses to create anything outside $GNUSTEP_USER_ROOT
+ *
+ * returns 1 on success, 0 on failure
+ */
+int WMMkDirHier(char *path)
+{
+        char *t, *thePath = NULL, buf[1024];
+        size_t p, plen;
+        struct stat st;
+
+        /* Only create directories under $GNUSTEP_USER_ROOT */
+        if ((t = wusergnusteppath()) == NULL)
+                return 0;
+        if (strncmp(path, t, strlen(t)) != 0)
+                return 0;
+
+       thePath = wstrdup(path);
+        /* Strip the trailing component if it is a file */
+        p = strlen(thePath);
+        while (p && thePath[p] != '/')
+                thePath[p--] = '\0';
+
+        thePath[p] = '\0';
+
+       /* Shortcut if it already exists */
+       if (stat(thePath, &st) == 0) {
+               wfree(thePath);
+               if (S_ISDIR(st.st_mode)) {
+                       /* Is a directory alright */
+                       return 1;
+               } else {
+                       /* Exists, but not a directory, the caller
+                        * might just as well abort now */
+                       return 0;
+               }
+       }
+
+        memset(buf, 0, sizeof(buf));
+        strncpy(buf, t, sizeof(buf) - 1);
+       p = strlen(buf);
+       plen = strlen(thePath);
+
+       do {
+               while (p++ < plen && thePath[p] != '/')
+                       ;
+
+               strncpy(buf, thePath, p);
+               if (mkdir(buf, 0777) == -1) {
+                       wsyserror(_("Could not create %s"), buf);
+                       wfree(thePath);
+                       return 0;
+               }
+       } while (p < plen);
+
+       wfree(thePath);
+       return 1;
+}
-- 
1.7.0


-- 
[-]

mkdir /nonexistent
From 5f4420be79ab73258aaf85592003f8d05a8e8bcb Mon Sep 17 00:00:00 2001
From: Tamas TEVESZ <[email protected]>
Date: Mon, 15 Mar 2010 19:49:14 +0100
Subject: [PATCH] - add a new helper function, WMMkDirHier(), which creates directory
   hierarchies under $GNUSTEP_USER_ROOT

- make WMWritePropListToFile() use this

readily solves the "run dialog history vs nonexistent state dir" case.

if other consumers are found for this, just de-static and move the
prototype to WUtil.h or some other appropriate place.
---
 WINGs/proplist.c |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/WINGs/proplist.c b/WINGs/proplist.c
index 79bb298..51329bc 100644
--- a/WINGs/proplist.c
+++ b/WINGs/proplist.c
@@ -50,6 +50,7 @@ static WMPropList *getPLData(PLData * pldata);
 static WMPropList *getPLArray(PLData * pldata);
 static WMPropList *getPLDictionary(PLData * pldata);
 static WMPropList *getPropList(PLData * pldata);
+static int WMMkDirHier(char * path);
 
 typedef unsigned (*hashFunc) (const void *);
 typedef Bool(*isEqualFunc) (const void *, const void *);
@@ -1555,6 +1556,9 @@ Bool WMWritePropListToFile(WMPropList * plist, char *path, Bool atomically)
 	char *desc;
 	FILE *theFile;
 
+	if (!WMMkDirHier(path))
+		return False;
+
 	if (atomically) {
 #ifdef	HAVE_MKSTEMP
 		int fd, mask;
@@ -1629,3 +1633,69 @@ Bool WMWritePropListToFile(WMPropList * plist, char *path, Bool atomically)
 
 	return False;
 }
+
+/*
+ * create a directory hierarchy
+ *
+ * if the last octet of `path' is `/', the full path is
+ * assumed to be a directory; otherwise path is assumed to be a
+ * file, and the last component is stripped off. the rest is the
+ * the hierarchy to be created.
+ *
+ * refuses to create anything outside $GNUSTEP_USER_ROOT
+ *
+ * returns 1 on success, 0 on failure
+ */
+int WMMkDirHier(char *path)
+{
+        char *t, *thePath = NULL, buf[1024];
+        size_t p, plen;
+        struct stat st;
+
+        /* Only create directories under $GNUSTEP_USER_ROOT */
+        if ((t = wusergnusteppath()) == NULL)
+                return 0;
+        if (strncmp(path, t, strlen(t)) != 0)
+                return 0;
+
+	thePath = wstrdup(path);
+        /* Strip the trailing component if it is a file */
+        p = strlen(thePath);
+        while (p && thePath[p] != '/')
+                thePath[p--] = '\0';
+
+        thePath[p] = '\0';
+
+	/* Shortcut if it already exists */
+	if (stat(thePath, &st) == 0) {
+		wfree(thePath);
+		if (S_ISDIR(st.st_mode)) {
+			/* Is a directory alright */
+			return 1;
+		} else {
+			/* Exists, but not a directory, the caller
+			 * might just as well abort now */
+			return 0;
+		}
+	}
+
+        memset(buf, 0, sizeof(buf));
+        strncpy(buf, t, sizeof(buf) - 1);
+	p = strlen(buf);
+	plen = strlen(thePath);
+
+	do {
+		while (p++ < plen && thePath[p] != '/')
+			;
+
+		strncpy(buf, thePath, p);
+		if (mkdir(buf, 0777) == -1) {
+			wsyserror(_("Could not create %s"), buf);
+			wfree(thePath);
+			return 0;
+		}
+	} while (p < plen);
+
+	wfree(thePath);
+	return 1;
+}
-- 
1.7.0

Reply via email to