]> wimlib.net Git - wimlib/blobdiff - src/xml.c
xml.c: Fix writing XML data for one image only
[wimlib] / src / xml.c
index 24fb32875da07b10bb9f00f15493ab3796494be7..0fb6472342d43c8396eea152087bc76107939595 100644 (file)
--- a/src/xml.c
+++ b/src/xml.c
@@ -896,15 +896,16 @@ xml_write_time(xmlTextWriter *writer, const char *element_name, u64 time)
 
 /* Writes an <IMAGE> element to the XML document. */
 static int
-xml_write_image_info(xmlTextWriter *writer, const struct image_info *image_info)
+xml_write_image_info(xmlTextWriter *writer, const struct image_info *image_info,
+                    int index)
 {
        int rc;
+
        rc = xmlTextWriterStartElement(writer, "IMAGE");
        if (rc < 0)
                return rc;
 
-       rc = xmlTextWriterWriteFormatAttribute(writer, "INDEX", "%d",
-                                              image_info->index);
+       rc = xmlTextWriterWriteFormatAttribute(writer, "INDEX", "%d", index);
        if (rc < 0)
                return rc;
 
@@ -1163,79 +1164,25 @@ xml_set_memory_allocator(void *(*malloc_func)(size_t),
 }
 
 static int
-calculate_dentry_statistics(struct wim_dentry *dentry, void *arg)
+calculate_dentry_statistics(struct wim_dentry *dentry, void *_info)
 {
-       struct image_info *info = arg;
+       struct image_info *info = _info;
        const struct wim_inode *inode = dentry->d_inode;
 
-       /* Update directory count and file count.
-        *
-        * Each dentry counts as either a file or a directory, but not both.
-        * The root directory is an exception: it is not counted at all.
-        *
-        * Symbolic links and junction points (and presumably other reparse
-        * points) count as regular files.  This is despite the fact that
-        * junction points have FILE_ATTRIBUTE_DIRECTORY set.
-        */
-
-       if (!dentry_is_root(dentry)) {
-               if (inode_is_directory(inode))
-                       info->dir_count++;
-               else
-                       info->file_count++;
-       }
+       if (inode_is_directory(inode))
+               info->dir_count++;
+       else
+               info->file_count++;
 
-       /*
-        * Update total bytes and hard link bytes.
-        *
-        * We try to act the same as the MS implementation, even though there
-        * are some inconsistencies/bugs in the way it operates.
-        *
-        * If there are no alternate data streams in the image, the "total
-        * bytes" is the sum of the size of the un-named data stream of each
-        * inode times the link count of that inode.  In other words, it would
-        * be the total number of bytes of regular files you would have if you
-        * extracted the full image without any hard-links.  The "hard link
-        * bytes" is equal to the "total bytes" minus the size of the un-named
-        * data stream of each inode.  In other words, the "hard link bytes"
-        * counts the size of the un-named data stream for all the links to each
-        * inode except the first one.
-        *
-        * Reparse points and directories don't seem to be counted in either the
-        * total bytes or the hard link bytes.
-        *
-        * And now we get to the most confusing part, the alternate data
-        * streams.  They are not counted in the "total bytes".  However, if the
-        * link count of an inode with alternate data streams is 2 or greater,
-        * the size of all the alternate data streams is included in the "hard
-        * link bytes", and this size is multiplied by the link count (NOT one
-        * less than the link count).
-        */
-       if (!(inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
-                                    FILE_ATTRIBUTE_REPARSE_POINT)))
-       {
-               struct blob_descriptor *blob;
-
-               blob = inode_get_blob_for_unnamed_data_stream(inode,
-                                                             info->blob_table);
-               if (blob) {
-                       info->total_bytes += blob->size;
-                       if (!dentry_is_first_in_inode(dentry))
-                               info->hard_link_bytes += blob->size;
-               }
+       for (unsigned i = 0; i < inode->i_num_streams; i++) {
+               const struct blob_descriptor *blob;
 
-               if (inode->i_nlink >= 2 && dentry_is_first_in_inode(dentry)) {
-                       for (unsigned i = 0; i < inode->i_num_streams; i++) {
-                               if (stream_is_named_data_stream(&inode->i_streams[i])) {
-                                       blob = stream_blob(&inode->i_streams[i],
-                                                          info->blob_table);
-                                       if (blob) {
-                                               info->hard_link_bytes += inode->i_nlink *
-                                                                        blob->size;
-                                       }
-                               }
-                       }
-               }
+               blob = stream_blob(&inode->i_streams[i], info->blob_table);
+               if (!blob)
+                       continue;
+               info->total_bytes += blob->size;
+               if (!dentry_is_first_in_inode(dentry))
+                       info->hard_link_bytes += blob->size;
        }
        return 0;
 }
@@ -1243,6 +1190,9 @@ calculate_dentry_statistics(struct wim_dentry *dentry, void *arg)
 /*
  * Calculate what to put in the <FILECOUNT>, <DIRCOUNT>, <TOTALBYTES>, and
  * <HARDLINKBYTES> elements of 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.
  */
 void
 xml_update_image_info(WIMStruct *wim, int image)
@@ -1428,7 +1378,6 @@ prepare_wim_xml_data(WIMStruct *wim, int image, u64 total_bytes,
        xmlOutputBuffer *outbuf;
        xmlTextWriter *writer;
        int ret;
-       int first, last;
        const xmlChar *content;
        int len;
        u8 *xml_data;
@@ -1490,20 +1439,23 @@ prepare_wim_xml_data(WIMStruct *wim, int image, u64 total_bytes,
        }
 
        if (image == WIMLIB_ALL_IMAGES) {
-               first = 1;
-               last = wim->hdr.image_count;
-       } else {
-               first = image;
-               last = image;
-       }
-
-       for (int i = first; i <= last; i++) {
-               ret = xml_write_image_info(writer, &wim->wim_info->images[i - 1]);
-               if (ret) {
+               for (int i = 0; i < wim->hdr.image_count; i++) {
+                       ret = xml_write_image_info(writer,
+                                                  &wim->wim_info->images[i],
+                                                  i + 1);
                        if (ret < 0)
                                goto out_write_error;
-                       goto out_free_text_writer;
+                       if (ret > 0)
+                               goto out_free_text_writer;
                }
+       } else {
+               ret = xml_write_image_info(writer,
+                                          &wim->wim_info->images[image - 1],
+                                          1);
+               if (ret < 0)
+                       goto out_write_error;
+               if (ret > 0)
+                       goto out_free_text_writer;
        }
 
        ret = xmlTextWriterEndElement(writer);
@@ -1631,7 +1583,7 @@ wimlib_get_xml_data(WIMStruct *wim, void **buf_ret, size_t *bufsize_ret)
        const struct wim_reshdr *xml_reshdr;
 
        if (wim->filename == NULL && filedes_is_seekable(&wim->in_fd))
-               return WIMLIB_ERR_INVALID_PARAM;
+               return WIMLIB_ERR_NO_FILENAME;
 
        if (buf_ret == NULL || bufsize_ret == NULL)
                return WIMLIB_ERR_INVALID_PARAM;