]> wimlib.net Git - wimlib/blobdiff - src/xml.c
xml: (style) use u32 instead of uint32_t
[wimlib] / src / xml.c
index 60643756ac7f1dde86c559bb20ee2af5455f3585..5c806cb46d06d9c41dd9776512a2262095206682 100644 (file)
--- a/src/xml.c
+++ b/src/xml.c
@@ -342,6 +342,32 @@ alloc_wim_xml_info(void)
        return info;
 }
 
+static bool
+parse_index(xmlChar **pp, u32 *index_ret)
+{
+       xmlChar *p = *pp;
+       u32 index = 0;
+
+       *p++ = '\0'; /* overwrite '[' */
+       while (*p >= '0' && *p <= '9') {
+               u32 n = (index * 10) + (*p++ - '0');
+               if (n < index)
+                       return false;
+               index = n;
+       }
+       if (index == 0)
+               return false;
+       if (*p != ']')
+               return false;
+       p++;
+       if (*p != '/' && *p != '\0')
+               return false;
+
+       *pp = p;
+       *index_ret = index;
+       return true;
+}
+
 static int
 do_xml_path_walk(xmlNode *node, const xmlChar *path, bool create,
                 xmlNode **result_ret)
@@ -362,34 +388,44 @@ do_xml_path_walk(xmlNode *node, const xmlChar *path, bool create,
 
        if (*p == '/')
                goto bad_syntax;
-       if (strchr(p, '[')) /* reserved for future use */
-               goto bad_syntax;
        c = *p;
 
        while (c != '\0') {
                const xmlChar *name;
                xmlNode *child;
+               u32 index = 1;
 
                /* We have another path component.  */
 
                /* Parse the element name.  */
                name = p;
-               while (*p != '/' && *p != '\0')
+               while (*p != '/' && *p != '\0' && *p != '[')
                        p++;
                if (p == name) /* empty name?  */
                        goto bad_syntax;
+
+               /* Handle a bracketed index, if one was specified.  */
+               if (*p == '[' && !parse_index(&p, &index))
+                       goto bad_syntax;
+
                c = *p;
                *p = '\0';
 
                /* Look for a matching child.  */
                node_for_each_child(node, child)
-                       if (node_is_element(child, name))
+                       if (node_is_element(child, name) && !--index)
                                goto next_step;
 
                /* No child matched the path.  If create=false, the lookup
                 * failed.  If create=true, create the needed element.  */
                if (!create)
                        return 0;
+
+               /* We can't create an element at index 'n' if indices 1...n-1
+                * didn't already exist.  */
+               if (index != 1)
+                       return WIMLIB_ERR_INVALID_PARAM;
+
                child = xmlNewChild(node, NULL, name, NULL);
                if (!child)
                        return WIMLIB_ERR_NOMEM;
@@ -476,37 +512,6 @@ xml_set_ttext_by_path(xmlNode *root, const xmlChar *path, const tchar *ttext)
        }
 }
 
-/* Sets a string property for the specified WIM image.  */
-static int
-set_image_property(WIMStruct *wim, int image, const xmlChar *name,
-                  const tchar *value)
-{
-       struct wim_xml_info *info = wim->xml_info;
-
-       if (image < 1 || image > info->image_count)
-               return WIMLIB_ERR_INVALID_IMAGE;
-
-       return xml_set_ttext_by_path(info->images[image - 1], name, value);
-}
-
-/* Gets a string property for the specified WIM image as a 'tchar' string.
- * Returns a pointer to the property value if found; NULL if the image doesn't
- * exist; or 'default_value' if the property doesn't exist in the image or if
- * the property value could not be translated to a 'tchar' string.  */
-static const tchar *
-get_image_property(const WIMStruct *wim, int image, const xmlChar *name,
-                  const tchar *default_value)
-{
-       struct wim_xml_info *info = wim->xml_info;
-       const tchar *value;
-
-       if (image < 1 || image > info->image_count)
-               return NULL;
-
-       value = xml_get_ttext_by_path(info, info->images[image - 1], name);
-       return value ? value : default_value;
-}
-
 /* Unlink and return the node which represents the INDEX attribute of the
  * specified IMAGE element.  */
 static xmlAttr *
@@ -667,8 +672,8 @@ xml_set_wimboot(struct wim_xml_info *info, int image)
 }
 
 /*
- * Calculate what to put in the FILECOUNT, DIRCOUNT, TOTALBYTES, and
- * HARDLINKBYTES elements of the specified WIM image.
+ * Update the DIRCOUNT, FILECOUNT, TOTALBYTES, HARDLINKBYTES, and
+ * LASTMODIFICATIONTIME elements for the specified WIM image.
  *
  * Note: since these stats are likely to be used for display purposes only, we
  * no longer attempt to duplicate WIMGAPI's weird bugs when calculating them.
@@ -684,8 +689,8 @@ xml_update_image_info(WIMStruct *wim, int image)
        u64 total_bytes = 0;
        u64 hard_link_bytes = 0;
        u64 size;
-       xmlNode *filecount_node;
        xmlNode *dircount_node;
+       xmlNode *filecount_node;
        xmlNode *totalbytes_node;
        xmlNode *hardlinkbytes_node;
        xmlNode *lastmodificationtime_node;
@@ -716,7 +721,6 @@ xml_update_image_info(WIMStruct *wim, int image)
                xmlFreeNode(totalbytes_node);
                xmlFreeNode(hardlinkbytes_node);
                xmlFreeNode(lastmodificationtime_node);
-               WARNING("Failed to update image information!");
                return WIMLIB_ERR_NOMEM;
        }
 
@@ -773,9 +777,9 @@ err:
  * Make a copy of the XML information for the image with index @src_image in the
  * @src_info XML document and append it to the @dest_info XML document.
  *
- * In the process, the image's name and description will be changed to the
- * values specified by @dest_image_name and @dest_image_description.  Either or
- * both may be NULL, which indicates that the corresponding element will not be
+ * In the process, change the image's name and description to the values
+ * specified by @dest_image_name and @dest_image_description.  Either or both
+ * may be NULL, which indicates that the corresponding element will not be
  * included in the destination image.
  */
 int
@@ -809,7 +813,10 @@ xml_export_image(const struct wim_xml_info *src_info, int src_image,
 
        xmlFreeProp(unlink_index_attribute(dest_node));
 
-       return append_image_node(dest_info, dest_node);
+       ret = append_image_node(dest_info, dest_node);
+       if (ret)
+               goto err;
+       return 0;
 
 err:
        xmlFreeNode(dest_node);
@@ -856,6 +863,7 @@ xml_delete_image(struct wim_xml_info *info, int image)
 #define PROCESSOR_ARCHITECTURE_MSIL            8
 #define PROCESSOR_ARCHITECTURE_AMD64           9
 #define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64   10
+#define PROCESSOR_ARCHITECTURE_ARM64           12
 
 static const tchar *
 describe_arch(u64 arch)
@@ -866,6 +874,7 @@ describe_arch(u64 arch)
                [PROCESSOR_ARCHITECTURE_ARM]   = T("ARM"),
                [PROCESSOR_ARCHITECTURE_IA64]  = T("ia64"),
                [PROCESSOR_ARCHITECTURE_AMD64] = T("x86_64"),
+               [PROCESSOR_ARCHITECTURE_ARM64] = T("ARM64"),
        };
 
        if (arch < ARRAY_LEN(descriptions) && descriptions[arch] != NULL)
@@ -920,11 +929,12 @@ print_windows_info(struct wim_xml_info *info, xmlNode *image_node)
 
                tprintf(T("Languages:              "));
                node_for_each_child(langs_node, lang_node) {
-                       if (node_is_element(lang_node, "LANGUAGE")) {
-                               tfputs(node_get_ttext(info, lang_node), stdout);
-                               tputchar(T(' '));
-                       }
-
+                       if (!node_is_element(lang_node, "LANGUAGE"))
+                               continue;
+                       text = node_get_ttext(info, lang_node);
+                       if (!text)
+                               continue;
+                       tprintf(T("%"TS" "), text);
                }
                tputchar(T('\n'));
 
@@ -1016,10 +1026,11 @@ xml_print_image_info(struct wim_xml_info *info, int image)
  *                      Reading and writing the XML data                      *
  *----------------------------------------------------------------------------*/
 
-static unsigned
+static int
 image_node_get_index(const xmlNode *node)
 {
-       return node_get_number((const xmlNode *)xmlHasProp(node, "INDEX"), 10);
+       u64 v = node_get_number((const xmlNode *)xmlHasProp(node, "INDEX"), 10);
+       return min(v, INT_MAX);
 }
 
 /* Prepare the 'images' array from the XML document tree.  */
@@ -1027,8 +1038,8 @@ static int
 setup_images(struct wim_xml_info *info, xmlNode *root)
 {
        xmlNode *child;
-       unsigned index;
-       unsigned max_index = 0;
+       int index;
+       int max_index = 0;
        int ret;
 
        info->images = NULL;
@@ -1346,8 +1357,8 @@ wimlib_extract_xml_data(WIMStruct *wim, FILE *fp)
        return ret;
 }
 
-WIMLIBAPI bool
-wimlib_image_name_in_use(const WIMStruct *wim, const tchar *name)
+static bool
+image_name_in_use(const WIMStruct *wim, const tchar *name, int excluded_image)
 {
        const struct wim_xml_info *info = wim->xml_info;
        const xmlChar *name_utf8;
@@ -1361,6 +1372,8 @@ wimlib_image_name_in_use(const WIMStruct *wim, const tchar *name)
        if (tstr_get_utf8(name, &name_utf8))
                return false;
        for (int i = 0; i < info->image_count && !found; i++) {
+               if (i + 1 == excluded_image)
+                       continue;
                found = xmlStrEqual(name_utf8, xml_get_text_by_path(
                                                    info->images[i], "NAME"));
        }
@@ -1368,35 +1381,89 @@ wimlib_image_name_in_use(const WIMStruct *wim, const tchar *name)
        return found;
 }
 
+WIMLIBAPI bool
+wimlib_image_name_in_use(const WIMStruct *wim, const tchar *name)
+{
+       return image_name_in_use(wim, name, WIMLIB_NO_IMAGE);
+}
+
 WIMLIBAPI const tchar *
 wimlib_get_image_name(const WIMStruct *wim, int image)
 {
-       return get_image_property(wim, image, "NAME", T(""));
+       const struct wim_xml_info *info = wim->xml_info;
+       const tchar *name;
+
+       if (image < 1 || image > info->image_count)
+               return NULL;
+       name = wimlib_get_image_property(wim, image, T("NAME"));
+       return name ? name : T("");
 }
 
 WIMLIBAPI const tchar *
 wimlib_get_image_description(const WIMStruct *wim, int image)
 {
-       return get_image_property(wim, image, "DESCRIPTION", NULL);
+       return wimlib_get_image_property(wim, image, T("DESCRIPTION"));
+}
+
+WIMLIBAPI const tchar *
+wimlib_get_image_property(const WIMStruct *wim, int image,
+                         const tchar *property_name)
+{
+       const xmlChar *name;
+       const tchar *value;
+       struct wim_xml_info *info = wim->xml_info;
+
+       if (!property_name || !*property_name)
+               return NULL;
+       if (image < 1 || image > info->image_count)
+               return NULL;
+       if (tstr_get_utf8(property_name, &name))
+               return NULL;
+       value = xml_get_ttext_by_path(info, info->images[image - 1], name);
+       tstr_put_utf8(name);
+       return value;
 }
 
 WIMLIBAPI int
 wimlib_set_image_name(WIMStruct *wim, int image, const tchar *name)
 {
-       if (wimlib_image_name_in_use(wim, name))
-               return WIMLIB_ERR_IMAGE_NAME_COLLISION;
-
-       return set_image_property(wim, image, "NAME", name);
+       return wimlib_set_image_property(wim, image, T("NAME"), name);
 }
 
 WIMLIBAPI int
 wimlib_set_image_descripton(WIMStruct *wim, int image, const tchar *description)
 {
-       return set_image_property(wim, image, "DESCRIPTION", description);
+       return wimlib_set_image_property(wim, image, T("DESCRIPTION"), description);
 }
 
 WIMLIBAPI int
 wimlib_set_image_flags(WIMStruct *wim, int image, const tchar *flags)
 {
-       return set_image_property(wim, image, "FLAGS", flags);
+       return wimlib_set_image_property(wim, image, T("FLAGS"), flags);
+}
+
+WIMLIBAPI int
+wimlib_set_image_property(WIMStruct *wim, int image, const tchar *property_name,
+                         const tchar *property_value)
+{
+       const xmlChar *name;
+       struct wim_xml_info *info = wim->xml_info;
+       int ret;
+
+       if (!property_name || !*property_name)
+               return WIMLIB_ERR_INVALID_PARAM;
+
+       if (image < 1 || image > info->image_count)
+               return WIMLIB_ERR_INVALID_IMAGE;
+
+       if (!tstrcmp(property_name, T("NAME")) &&
+           image_name_in_use(wim, property_value, image))
+               return WIMLIB_ERR_IMAGE_NAME_COLLISION;
+
+       ret = tstr_get_utf8(property_name, &name);
+       if (ret)
+               return ret;
+       ret = xml_set_ttext_by_path(info->images[image - 1], name, property_value);
+       tstr_put_utf8(name);
+       return ret;
 }