From: Dave Chinner Date: Thu, 8 Sep 2016 00:22:19 +0000 (+1000) Subject: db: write via array indexing doesn't work X-Git-Tag: v4.8.0-rc1~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4222d000ed3b198976db7e5acdf2bdd350298ebd;p=thirdparty%2Fxfsprogs-dev.git db: write via array indexing doesn't work This command to write a specific AGFL index: # xfs_db -x -c "agfl 0" -c "write -d bno[32] 78" /dev/ram0 doesn't write to array index 32 - it incorrectly writes to /somewhere/ in the entire array range. The issue here is that the write_struct() code assumes that the object it is printing always a structure member and any array indexes will be exposed as children of the parent type. This works just fine for structures with internal arrays, but when the type being decoded is an array, we get a direct reference to the offset to be written in the parent object. Hence we need to take into account the array index returned by the parent object parsing when calculating the size of the region to be modified rather than using fcount() as that results in the size always being set to the size of the entire array and the modification being written to the wrong place. Signed-off-by: Dave Chinner Signed-off-by: Dave Chinner --- diff --git a/db/write.c b/db/write.c index 82a0c746c..5c83874f1 100644 --- a/db/write.c +++ b/db/write.c @@ -701,8 +701,24 @@ write_struct( sfl = sfl->child; } + /* + * For structures, fsize * fcount tells us the size of the region we are + * modifying, which is usually a single structure member and is pointed + * to by the last child in the list. + * + * However, if the base structure is an array and we have a direct index + * into the array (e.g. write bno[5]) then we are returned a single + * flist object with the offset pointing directly at the location we + * need to modify. The length of the object we are modifying is then + * determined by the size of the individual array entry (fsize) and the + * indexes defined in the object, not the overall size of the array + * (which is what fcount returns). + */ bit_length = fsize(sfl->fld, iocur_top->data, parentoffset, 0); - bit_length *= fcount(sfl->fld, iocur_top->data, parentoffset); + if (sfl->fld->flags & FLD_ARRAY) + bit_length *= sfl->high - sfl->low + 1; + else + bit_length *= fcount(sfl->fld, iocur_top->data, parentoffset); /* convert this to a generic conversion routine */ /* should be able to handle str, num, or even labels */