]> git.saurik.com Git - apple/boot.git/blobdiff - i386/libsaio/stringTable.c
boot-122.tar.gz
[apple/boot.git] / i386 / libsaio / stringTable.c
index 8fafe9bcd284efb72082d5d286bf022dd50097b7..65ef09ec8a1f73cd6422e1055a5f1c87ec48d017 100644 (file)
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Portions Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights
  * Reserved.  This file contains Original Code and/or Modifications of
  * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License").  You may not use this file
+ * Source License Version 2.0 (the "License").  You may not use this file
  * except in compliance with the License.  Please obtain a copy of the
  * License at http://www.apple.com/publicsource and read it before using
  * this file.
  * All rights reserved.
  */
 
+#include "bootstruct.h"
 #include "libsaio.h"
-#include "kernBootStruct.h"
 #include "stringConstants.h"
 #include "legacy/configTablePrivate.h"
+#include "xml.h"
 
-extern KERNBOOTSTRUCT *kernBootStruct;
 extern char *Language;
 extern char *LoadableFamilies;
 
-static void eatThru(char val, char **table_p);
+static TagPtr gConfigDict;
+
+static void eatThru(char val, const char **table_p);
 
 static inline int isspace(char c)
 {
@@ -46,7 +48,7 @@ static inline int isspace(char c)
  * Compare a string to a key with quoted characters
  */
 static inline int
-keyncmp(char *str, char *key, int n)
+keyncmp(const char *str, const char *key, int n)
 {
     int c;
     while (n--) {
@@ -76,9 +78,9 @@ keyncmp(char *str, char *key, int n)
     return 0;
 }
 
-static void eatThru(char val, char **table_p)
+static void eatThru(char val, const char **table_p)
 {
-       register char *table = *table_p;
+       register const char *table = *table_p;
        register BOOL found = NO;
 
        while (*table && !found)
@@ -93,6 +95,8 @@ static void eatThru(char val, char **table_p)
        *table_p = table;
 }
 
+#if UNUSED
+
 /* Remove key and its associated value from the table. */
 
 BOOL
@@ -148,6 +152,7 @@ newStringFromList(
     char *begin = *list, *end;
     char *newstr;
     int newsize = *size;
+    int bufsize;
     
     while (*begin && newsize && isspace(*begin)) {
        begin++;
@@ -160,17 +165,20 @@ newStringFromList(
     }
     if (begin == end)
        return 0;
-    newstr = malloc(end - begin + 1);
-    strncpy(newstr, begin, end - begin);
+    bufsize = end - begin + 1;
+    newstr = malloc(bufsize);
+    strlcpy(newstr, begin, bufsize);
     *list = end;
     *size = newsize;
     return newstr;
 }
 
+#endif
+
 /* 
  * compress == compress escaped characters to one character
  */
-int stringLength(char *table, int compress)
+int stringLength(const char *table, int compress)
 {
        int ret = 0;
 
@@ -191,53 +199,69 @@ int stringLength(char *table, int compress)
        return ret;
 }
 
-// looks in table for strings of format << "key" = "value"; >>
-// or << "key"; >>
-BOOL getValueForStringTableKey(char *table, char *key, char **val, int *size)
+BOOL getValueForConfigTableKey(const char *table, const char *key, const char **val, int *size)
 {
        int keyLength;
-       char *tableKey;
-
-       do
-       {
-               eatThru('\"',&table);
-               tableKey = table;
-               keyLength = strlen(key);
-               if (keyLength &&
-                   (stringLength(table,1) == keyLength) &&
-                   (keyncmp(key, table, keyLength) == 0))
-               {
-                       int c;
+       const char *tableKey;
+
+        if (gConfigDict != 0 ) {
+            /* Look up key in XML dictionary */
+            TagPtr value;
+            value = XMLGetProperty(gConfigDict, key);
+            if (value != 0) {
+                if (value->type != kTagTypeString) {
+                    error("Non-string tag '%s' found in config file\n",
+                          key);
+                    return NO;
+                }
+                *val = value->string;
+                *size = strlen(value->string);
+                return YES;
+            }
+        } else {
+            /* Legacy plist-style table */
+            do
+                {
+                    eatThru('\"',&table);
+                    tableKey = table;
+                    keyLength = strlen(key);
+                    if (keyLength &&
+                        (stringLength(table,1) == keyLength) &&
+                        (keyncmp(key, table, keyLength) == 0))
+                        {
+                            int c;
                        
-                       /* found the key; now look for either
-                        * '=' or ';'
-                        */
-                       while (c = *table) {
-                           ++table;
-                           if (c == '\\') {
-                               ++table;
-                               continue;
-                           } else if (c == '=' || c == ';') {
-                               break;
-                           }
-                       }
-                       if (c == ';') {
-                           table = tableKey;
-                       } else {
-                           eatThru('\"',&table);
-                       }
-                       *val = table;
-                       *size = stringLength(table,0);
-                       return YES;
-               }
-
-               eatThru(';',&table);
-
-       } while (*table);
+                            /* found the key; now look for either
+                             * '=' or ';'
+                             */
+                            while (c = *table) {
+                                ++table;
+                                if (c == '\\') {
+                                    ++table;
+                                    continue;
+                                } else if (c == '=' || c == ';') {
+                                    break;
+                                }
+                            }
+                            if (c == ';') {
+                                table = tableKey;
+                            } else {
+                                eatThru('\"',&table);
+                            }
+                            *val = table;
+                            *size = stringLength(table,0);
+                            return YES;
+                        }
+
+                    eatThru(';',&table);
+
+                } while (*table);
+        }
 
        return NO;
 }
 
+#if UNUSED
 
 /*
  * Returns a new malloc'ed string if one is found
@@ -249,11 +273,12 @@ char *newStringForStringTableKey(
        char *key
 )
 {
-    char *val, *newstr, *p;
+    const char *val;
+    char *newstr, *p;
     int size;
     
-    if (getValueForStringTableKey(table, key, &val, &size)) {
-       newstr = malloc(size+1);
+    if (getValueForConfigTableKey(table, key, &val, &size)) {
+       newstr = (char *)malloc(size+1);
        for (p = newstr; size; size--, p++, val++) {
            if ((*p = *val) == '\\') {
                switch (*++val) {
@@ -280,15 +305,18 @@ char *newStringForStringTableKey(
     }
 }
 
+#endif
+
 char *
 newStringForKey(char *key)
 {
-    char *val, *newstr;
+    const char *val;
+    char *newstr;
     int size;
     
     if (getValueForKey(key, &val, &size) && size) {
-       newstr = malloc(size + 1);
-       strncpy(newstr, val, size);
+       newstr = (char *)malloc(size + 1);
+       strlcpy(newstr, val, size + 1);
        return newstr;
     } else {
        return 0;
@@ -301,7 +329,7 @@ newStringForKey(char *key)
  * non-whitespace characters, or enclosed in quotes.
  */
 
-static char *getToken(char *line, char **begin, int *len)
+static const char *getToken(const char *line, const char **begin, int *len)
 {
     if (*line == '\"') {
        *begin = ++line;
@@ -317,10 +345,11 @@ static char *getToken(char *line, char **begin, int *len)
     return line;
 }
 
-BOOL getValueForBootKey(char *line, char *match, char **matchval, int *len)
+BOOL getValueForBootKey(const char *line, const char *match, const char **matchval, int *len)
 {
-    char *key, *value;
+    const char *key, *value;
     int key_len, value_len;
+    BOOL retval = NO;
     
     while (*line) {
        /* look for keyword or argument */
@@ -339,31 +368,41 @@ BOOL getValueForBootKey(char *line, char *match, char **matchval, int *len)
            && strncmp(match, key, key_len) == 0) {
            *matchval = value;
            *len = value_len;
-           return YES;
+           retval = YES;
+            /* Continue to look for this key; last one wins. */
        }
     }
-    return NO;
+    return retval;
 }
 
+/* Returns TRUE if a value was found, FALSE otherwise.
+ * The boolean value of the key is stored in 'val'.
+ */
 BOOL getBoolForKey(
-    char *key
+    const char *key,
+    BOOL *result_val
 )
 {
-    char *val;
+    const char *key_val;
     int size;
     
-    if (getValueForKey(key, &val, &size) && (size >= 1) &&
-       val[0] == 'Y' || val[0] == 'y')
-           return YES;
+    if (getValueForKey(key, &key_val, &size)) {
+        if ( (size >= 1) && (key_val[0] == 'Y' || key_val[0] == 'y') ) {
+            *result_val = YES;
+        } else {
+            *result_val = NO;
+        }
+        return YES;
+    }
     return NO;
 }
 
 BOOL getIntForKey(
-    char *key,
+    const char *key,
     int *value
 )
 {
-    char *val;
+    const char *val;
     int size, sum;
     
     if (getValueForKey(key, &val, &size)) {
@@ -377,107 +416,21 @@ BOOL getIntForKey(
 }
 
 BOOL getValueForKey(
-    char *key,
-    char **val,
+    const char *key,
+    const char **val,
     int *size
 )
 {
-    if (getValueForBootKey(kernBootStruct->bootString, key, val, size))
+    if (getValueForBootKey(bootArgs->bootString, key, val, size))
        return YES;
-    else if (getValueForStringTableKey(kernBootStruct->config, key, val, size))
+    else if (getValueForConfigTableKey(bootArgs->config, key, val, size))
        return YES;
 
     return NO;
 }
 
-#if 0
-#define        LOCALIZABLE_PATH \
-       "%s/%s.config/%s.lproj/%s.strings"
-char *
-loadLocalizableStrings(
-    char *name,
-    char *tableName
-)
-{
-    char buf[256], *config;
-    register int count, fd = -1;
-    char *device_dir = usrDevices();
-    
-    sprintf(buf, LOCALIZABLE_PATH, device_dir, name,
-           Language, tableName);
-    if ((fd = open(buf, 0)) < 0) {
-       sprintf(buf, LOCALIZABLE_PATH, device_dir, name,
-                "English", tableName);
-       if ((fd = open(buf,0)) < 0) {
-           return 0;
-       }
-    }
-    count = file_size(fd);
-    config = malloc(count);
-    count = read(fd, config, count);
-    close(fd);
-    if (count <= 0) {
-       free(config);
-       return 0;
-    }
-    return config;
-}
-#endif
-
-#if 0 // XXX
-char *
-bundleLongName(
-    char *bundleName,
-    char *tableName
-)
-{
-    char *table, *name, *version, *newName;
-    char *path = malloc(256);
-    
-#define LONG_NAME_FORMAT "%s (v%s)"
-    sprintf(path, "%s/%s.config/%s.table",
-       usrDevices(), bundleName, tableName ? tableName : "Default");
-    if (loadConfigFile(path, &table, YES) == 0) {
-       version = newStringForStringTableKey(table, "Version");
-       free(table);
-    } else {
-       version = newString("0.0");
-    }
-    table = loadLocalizableStrings(bundleName,
-       tableName ? tableName : "Localizable");
-    if (table) {
-       name = newStringForStringTableKey(table, "Long Name");
-       free(table);
-    } else {
-       name = newString(bundleName);
-    }
-    newName = malloc(strlen(name)+strlen(version)+strlen(LONG_NAME_FORMAT));
-    sprintf(newName, LONG_NAME_FORMAT, name, version);
-    free(name); free(version);
-    return newName;
-}
-#endif
-
 int sysConfigValid;
 
-void
-addConfig(
-    char *config
-)
-{
-    char *configPtr = kernBootStruct->configEnd;
-    int len = strlen(config);
-    
-    if ((configPtr - kernBootStruct->config) > CONFIG_SIZE) {
-       error("No room in memory for config files\n");
-       return;
-    }
-    strcpy(configPtr, config);
-    configPtr += (len + 1);
-    *configPtr = 0;
-    kernBootStruct->configEnd = configPtr;
-}
-
 #define TABLE_EXPAND_SIZE      192
 
 /*
@@ -488,33 +441,29 @@ addConfig(
  * Allocates an extra number of bytes for table expansion.
  */
 int
-loadConfigFile( char *configFile, char **table, BOOL allocTable)
+loadConfigFile(const char *configFile)
 {
-    char *configPtr = kernBootStruct->configEnd;
+    char *configPtr = bootArgs->config;
     int fd, count;
     
     /* Read config file into memory */
     if ((fd = open(configFile, 0)) >= 0)
     {
-       if (allocTable) {
-           configPtr = malloc(file_size(fd)+2+TABLE_EXPAND_SIZE);
-       } else {
-           if ((configPtr - kernBootStruct->config) > CONFIG_SIZE) {
-               error("No room in memory for config files\n");
-               close(fd);
-               return -1;
-           }
-           verbose("Reading configuration file '%s'.\n",configFile);       
-       }
-       if (table) *table = configPtr;
+        if ((configPtr - bootArgs->config) > CONFIG_SIZE) {
+            error("No room in memory for config files\n");
+            close(fd);
+            return -1;
+        }
+        verbose("Reading configuration file '%s'.\n",configFile);          
+
        count = read(fd, configPtr, IO_CONFIG_DATA_SIZE);
        close(fd);
 
        configPtr += count;
        *configPtr++ = 0;
        *configPtr = 0;
-       if (!allocTable)
-           kernBootStruct->configEnd = configPtr;
+
+        bootArgs->configEnd = configPtr;
 
        return 0;
     } else {
@@ -522,75 +471,75 @@ loadConfigFile( char *configFile, char **table, BOOL allocTable)
     }
 }
 
-/* Returns 0 if requested config files were loaded,
- *         1 if default files were loaded,
- *        -1 if no files were loaded.
- * Prints error message if files cannot be loaded.
- */
-int
-loadConfigDir(
-    char *bundleName,  // bundle directory name (e.g. "System")
-    BOOL useDefault,   // use Default.table instead of instance tables
-    char **table,      // returns pointer to config table
-    BOOL allocTable    // malloc the table and return in *table
-)
+#define LP '('
+#define RP ')'
+
+#define SYSTEM_CONFIG_DIR "/Library/Preferences/SystemConfiguration"
+#define SYSTEM_CONFIG_FILE "/com.apple.Boot.plist"
+#define LRE_CONFIG_FILE "/com.apple.lre.Boot.plist"
+#define SYSTEM_CONFIG_PATH SYSTEM_CONFIG_DIR SYSTEM_CONFIG_FILE
+#define CONFIG_EXT ".plist"
+
+#if UNUSED
+void
+printSystemConfig(void)
 {
-    char *buf;
-    int i, max, ret;
-    char *device_dir = usrDevices();
+    char *p1 = bootArgs->config;
+    char *p2 = p1, tmp;
+
+    while (*p1 != '\0') {
+       while (*p2 != '\0' && *p2 != '\n') p2++;
+       tmp = *p2;
+       *p2 = '\0';
+       printf("%s\n", p1);
+       *p2 = tmp;
+       if (tmp == '\0') break;
+       p1 = ++p2;
+    }
+}
+#endif
+
+//==========================================================================
+// ParseXMLFile
+// Modifies the input buffer.
+// Expects to see one dictionary in the XML file.
+// Puts the first dictionary it finds in the
+// tag pointer and returns 0, or returns -1 if not found
+// (and does not modify dict pointer).
+// Prints an error message if there is a parsing error.
+//
+static long
+ParseXMLFile( char * buffer, TagPtr * dict )
+{
+    long       length, pos;
+    TagPtr     tag;
+    pos = 0;
+    char       *configBuffer;
+  
+    configBuffer = malloc(strlen(buffer)+1);
+    strcpy(configBuffer, buffer);
+
+    while (1)
+    {
+        length = XMLParseNextTag(configBuffer + pos, &tag);
+        if (length == -1) break;
     
-    buf = malloc(256);
-    ret = 0;
+        pos += length;
     
-    // load up to 99 instance tables
-    if (allocTable)
-       max = 1;
-    else
-       max = 99;
-    for (i=0; i < max; i++) {
-       sprintf(buf, "%s/%s.config/Instance%d.table",
-               device_dir,
-               bundleName, i);
-       if (useDefault || (loadConfigFile(buf, table, allocTable) != 0)) {
-           if (i == 0) {
-               // couldn't load first instance table;
-               // try the default table
-               sprintf(buf, "%s/%s.config/%s",
-                       device_dir,
-                       bundleName,
-                       IO_DEFAULT_TABLE_FILENAME);
-               if (loadConfigFile(buf, table, allocTable) == 0) {
-                   ret = 1;
-               } else {
-                   if (!allocTable)
-                       error("Config file \"%s\" not found\n", buf);
-                   ret = -1;
-               }
-           }
-           // we must be done.
-           break;
-       }
+        if (tag == 0) continue;
+        if (tag->type == kTagTypeDict) break;
+    
+        XMLFreeTag(tag);
     }
-    free(buf);
-    return ret;
+    free(configBuffer);
+    if (length < 0) {
+        error ("Error parsing plist file");
+        return -1;
+    }
+    *dict = tag;
+    return 0;
 }
 
-
-#define USR_SYSTEM_CONFIG \
-       USR_DEVICES "/System.config"
-#define USR_SYSTEM_DEFAULT_FILE \
-       USR_SYSTEM_CONFIG "/Default.table"
-#define ARCH_SYSTEM_CONFIG \
-       ARCH_DEVICES "/System.config"
-#define ARCH_SYSTEM_DEFAULT_FILE \
-       ARCH_SYSTEM_CONFIG "/Default.table"
-#define SYSTEM_CONFIG "System"
-#define LP '('
-#define RP ')'
-
-static int sysconfig_dev;
-
 /* Returns 0 if requested config files were loaded,
  *         1 if default files were loaded,
  *        -1 if no files were loaded.
@@ -598,161 +547,72 @@ static int sysconfig_dev;
  */
 int
 loadSystemConfig(
-    char *which,
+    const char *which,
     int size
 )
 {
-    char *buf, *bp, *cp;
+    char *buf, *bp;
+    const char *cp;
     int ret, len, doDefault=0;
-    char *device_dir = usrDevices();
-
-#if 0
-               printf("In Load system config which=%d ; size=%d\n", which, size);
-               //sleep(1);
-#endif 1
-    buf = bp = malloc(256);
-    if (which && size)
-    {
-#if 0
-               printf("In Load system config alt\n");
-               //sleep(1);
-#endif 1
-       for(cp = which, len = size; len && *cp && *cp != LP; cp++, len--) ;
-       if (*cp == LP) {
-           while (len-- && *cp && *cp++ != RP) ;
-           /* cp now points past device */
-           strncpy(buf,which,cp - which);
-           bp += cp - which;
-       } else {
-           cp = which;
-           len = size;
-       }
-       if (*cp != '/') {
-           strcpy(bp, device_dir);
-           strcat(bp, "/System.config/");
-           strncat(bp, cp, len);
-           if (strncmp(cp + len - strlen(IO_TABLE_EXTENSION),
-                      IO_TABLE_EXTENSION, strlen(IO_TABLE_EXTENSION)) != 0)
-               strcat(bp, IO_TABLE_EXTENSION);
-       } else {
-           strncpy(bp, cp, len);
-           bp[size] = '\0';
-       }
-       if ((strcmp(bp, USR_SYSTEM_DEFAULT_FILE) == 0) ||
-           (strcmp(bp, ARCH_SYSTEM_DEFAULT_FILE) == 0))
-           doDefault = 1;
-       ret = loadConfigFile(bp = buf, 0, 0);
+
+    buf = bp = malloc(512);
+    if (which && size) {
+        for(cp = which, len = size; len && *cp && *cp != LP; cp++, len--) ;
+        if (*cp == LP) {
+            while (len-- && *cp && *cp++ != RP) ;
+            /* cp now points past device */
+            strlcpy(buf,which,cp - which + 1);
+            bp += cp - which;
+        } else {
+            cp = which;
+            len = size;
+        }
+        if (*cp != '/') {
+            strcpy(bp, systemConfigDir());
+            strcat(bp, "/");
+            strncat(bp, cp, len);
+            if (strncmp(cp + len - strlen(CONFIG_EXT),
+                        CONFIG_EXT, strlen(CONFIG_EXT)) != 0)
+                strcat(bp, CONFIG_EXT);
+        } else {
+            strlcpy(bp, cp, len + 1);
+        }
+        if ((strcmp(bp, SYSTEM_CONFIG_PATH) == 0)) {
+            doDefault = 1;
+        }
+        bp = buf;
+        ret = loadConfigFile(bp);
     } else {
-#if 0
-               printf("In default SYSTEM_CONFIG LOAD\n");
-               //sleep(1);
-#endif 1
-       ret = loadConfigDir((bp = SYSTEM_CONFIG), 0, 0, 0);
-#if 0
-               printf("come back from SYSTEM_CONFIG loadConfigDir\n");
-               //sleep(1);
-#endif 1
-   }
-    sysconfig_dev = currentdev();
+        /* First try LRE file */
+        strcpy(bp, systemConfigDir());
+        strcat(bp, LRE_CONFIG_FILE);
+        ret = loadConfigFile(bp);
+
+        if (ret < 0) {
+            /* If not found, try default file */
+            strcpy(bp, systemConfigDir());
+            strcat(bp, SYSTEM_CONFIG_FILE);
+            ret = loadConfigFile(bp);
+        }
+    }
     if (ret < 0) {
        error("System config file '%s' not found\n", bp);
-    } else
+       sleep(1);
+    } else {
        sysConfigValid = 1;
+        // Check for XML file;
+        // if not XML, gConfigDict will remain 0.
+        ParseXMLFile(bootArgs->config, &gConfigDict);
+    }
     free(buf);
     return (ret < 0 ? ret : doDefault);
 }
 
-#ifdef DISABLED
-int
-loadOtherConfigs(
-    int useDefault
-)
-{
-    char *val, *table;
-    char *path = malloc(256);
-    char *hintTable;
-    char *installVersion = NULL, *thisVersion;
-    char *longName, *tableName;
-    int count;
-    char *string;
-    int  ret;
-    int old_dev = currentdev();
-
-    if (sysconfig_dev)
-       switchdev(sysconfig_dev);
-    if (getValueForKey( "Boot Drivers", &val, &count))
-    {
-#if 0
-       printf("Loading Boot Drivers\n");
-       sleep(1);
-#endif 1
-       while (string = newStringFromList(&val, &count)) {
-           /* Check installation hints... */
-           sprintf(path, "%s/System.config/" INSTALL_HINTS
-                         "/%s.table", usrDevices(), string);
-
-           if (getBoolForKey("Ignore Hints") == NO &&
-                   loadConfigFile(path, &hintTable, YES) == 0) {
-               installVersion = newStringForStringTableKey(
-                   hintTable, "Version");
-               longName = newStringForStringTableKey(
-                   hintTable, "Long Name");
-               tableName = newStringForStringTableKey(
-                   hintTable, "Default Table");
-               free(hintTable);
-           } else {
-               installVersion = longName = tableName = NULL;
-           }
-
-           ret = loadConfigDir(string, useDefault, &table, YES);
-           if (ret >= 0) {
-               thisVersion = newStringForStringTableKey(
-                   table, "Version");
-               if (installVersion && thisVersion &&
-                   (strcmp(thisVersion, installVersion) != 0)) {
-                   /* Versions do not match */
-                   driverIsMissing(string, installVersion, longName, 
-                        tableName, DRIVER_VERSION_MISMATCH);
-               } else {
-                   struct driver_load_data dl;
-                   
-                   dl.name = string;
-                   if ((openDriverReloc(&dl)) >= 0) {
-                       verbose("Loading binary for %s device driver.\n",string);
-                       if (loadDriver(&dl) < 0) /// need to stop if error
-                           error("Error loading %s device driver.\n",string);
-#if 0
-               printf("Calling link driver for %s\n", string);
-#endif 1
-                       if (linkDriver(&dl) < 0)
-                           error("Error linking %s device Driver.\n",string);
-                   }
-                   loadConfigDir(string, useDefault, NULL, NO);
-                   driverWasLoaded(string, table, NULL);
-                   free(table);
-                   free(string);
-                   free(installVersion); free(longName);
-                   free(tableName);
-               }
-               free(thisVersion);
-           } else {
-                /* driver not found */
-               driverIsMissing(string, installVersion, longName, 
-                    tableName, DRIVER_NOT_FOUND);
-           }
-#if 0
-           if (ret == 1)
-               useDefault = 1; // use defaults from now on
-#endif
-       }
-    } else {
-       error("Warning: No Boot drivers specified in system config.\n");
-    }
 
-    kernBootStruct->first_addr0 =
-           (int)kernBootStruct->configEnd + 1024;
-    free(path);
-    switchdev(old_dev);
-    return 0;
+char * newString(const char * oldString)
+{
+    if ( oldString )
+        return strcpy(malloc(strlen(oldString)+1), oldString);
+    else
+        return NULL;
 }
-#endif /* DISABLED */