From: Stephen Powell on
On Wed, 14 Apr 2010 23:10:55 -0400 (EDT), Boyd Stephen Smith Jr. wrote:
> On Tuesday 13 April 2010 17:16:03 Stephen Powell wrote:
>> What I need to do is to have two structures overlay each other; so that
>> they occupy the same storage. To be specific, here is a structure which
>> describes the volume label for an OS-formatted disk:
>>
>> struct __attribute__ ((packed)) volume_label {
>> char volkey[4]; /* volume key = volume label */
>> ...
>> };
>>
>> And here is a structure which describes the volume label for a
>> CMS-formatted disk:
>>
>> struct __attribute__ ((packed)) cms_label {
>> char label_id[4]; /* Label identifier */
>> ...
>> };
>>
>
> union any_label {
> struct volume_label vl;
> struct cms_label cl;
> };
>>
>> Note that both structures have as their first member a character variable
>> of length 4. In the case of the "volume_label" structure it is "volkey"
>> and in the case of the "cms_label" structure it is "label_id". If the
>> value of this variable is "VOL1" (in EBCDIC) then it is the first structure
>> which maps the storage. If the value of this variable is "CMS1" (in
>> EBCDIC) then it is the second structure which maps the storage. The
>> volume_label structure is apparently a based structure, as references to
>> the volkey variable look something like this:
>
> union any_label *label = /* Initialize somehow */;
> struct volume_label *maybe_vl = &label->vl;
> struct cms_label *maybe_cl = &label->cl;
>
> if (strncmp(maybe_vl->volkey, "VOL1", 4) == 0) {
> maybe_cl = NULL;
> /* Use maybe_vl all you want, e.g. */
> maybe_vl->security = 0xFF;
> } else if (strncmp(maybe_cl->label_id, "CMS1", 4) == 0) {
> maybe_vl = NULL;
> /* Use maybe_cl all you want, e.g. */
> printf("%lu\n", (unsigned long) maybe_cl->disk_offset);
> } else {
> assert(("Unrecognized disk!", 0));
> }
>
> Hope that helps.

Thanks, Boyd. Your response comes the closest so far to what I'm looking
for. Based on what I know from other programming languages, I don't think
it's going to be necessary to explicitly declare a union. They will
overlap each other implicitly because their pointers are the same. Both
structure mappings occupy exactly 80 bytes of storage. And the storage for
one of them is already allocated somehow. What I need to do
is associate a pointer with the new structure and assign a value to the pointer that
matches the pointer for the other structure. That will implicitly cause the
two structures to overlap in storage. Here are examples from two
other languages that I do know: s390 assembler language and PL/I.
Here is the assembler example:

----------

...
CLC LABELIDA,=C'VOL1' Is this structure type A?
BE VOL1CODE Yes - branch to label VOL1CODE
LA 3,STRUCTA No - load the address of STRUCTA into register 3
USING STRUCTB,3 Tell the assembler that the address of STRUCTB is in register 3
L 4,FIELDB2 Load the fullword at FIELDB2 into register 4
... Perform additional processing
DROP 3 Tell the assembler that it can no longer assume that register 3 points to STRUCTB
B COMCODE Rejoin common code
VOL1CODE DS 0H
... Proceed with processing for structure type A
COMCODE DS 0H
...
STRUCTA DS 0CL12
LABELIDA DS CL4
FIELDA1 DS CL8
...
STRUCTB DSECT , Start a dummy control section (based structure)
LABELIDB DS CL4
FIELDB1 DS F
FIELDB2 DS F
...

----------

Here is the PL/I example:

----------

DCL 1 STRUCTA,
2 LABELIDA CHAR (4),
2 FIELDA1 CHAR (8);

DCL ADDR BUILTIN;
DCL B_PTR POINTER;

DCL 1 STRUCTB BASED (B_PTR),
2 LABELIDB CHAR (4),
2 FIELDB1 FIXED BINARY (31,0),
2 FIELDB2 FIXED BINARY (31,0);
...
IF LABELIDA = 'VOL1' THEN
DO;
/* Processing that refers to elements of STRUCTA */
END;
ELSE
DO;
B_PTR = ADDR(STRUCTA);
/* Processing that refers to elements of STRUCTB */
END;

----------

Now back to C.
At the point in the code where I need to make a reference to the "disk_offset"
member of the "cms_label" structure, I know that I can validly reference the
"volkey" variable of the "volume_label" structure like this:

disk_specific->anchor->vlabel->volkey

What I need to do is declare that "cms_label" is a based structure and
associate a pointer variable, say "cms_ptr", with it. But I don't want
any storage to be allocated for the structure: only for the pointer.
Storage should be allocated for the pointer, but it should not be initialized
to anything. Then I can assign a value to the pointer, with something like:

cms_ptr = disk_specific->anchor->vlabel;

Then I can make references to members of the cms_label structure implicitly
using the cms_ptr pointer variable. No storage is ever allocated to the
"cms_label" structure. It overlays the "volume_label" structure implicitly
via the assignment of a value to its associated pointer variable. I know
how to do something like this in s390 assembler language and PL/I. Surely
there must be a way to do this in C, right?

In short, I need to (a) declare "cms_label" as a based structure, (b)
declare a pointer variable called "cms_ptr" and associate it with the
"cms_label" structure, (c) make sure that the compiler does not attempt
to allocate any storage for the "cms_label" structure, (d) make sure that
the compiler automatically acquires storage for the "cms_ptr" pointer
variable itself, (e) assign the address of the "volume_label" structure
to the "cms_ptr" pointer variable at an appropriate point in the code,
and (f) make references to the members of the cms_label structure.
How do I do this? (Man, I wish I knew C!)

--
.''`. Stephen Powell
: :' :
`. `'`
`-


--
To UNSUBSCRIBE, email to debian-user-REQUEST(a)lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster(a)lists.debian.org
Archive: http://lists.debian.org/749326468.47646.1271357760265.JavaMail.root(a)md01.wow.synacor.com
From: Boyd Stephen Smith Jr. on
On Thursday 15 April 2010 13:56:00 Stephen Powell wrote:
> On Wed, 14 Apr 2010 23:10:55 -0400 (EDT), Boyd Stephen Smith Jr. wrote:
> > On Tuesday 13 April 2010 17:16:03 Stephen Powell wrote:
> >> What I need to do is to have two structures overlay each other; so that
> >> they occupy the same storage. To be specific, here is a structure
> >> which describes the volume label for an OS-formatted disk:
> >>
> >> struct __attribute__ ((packed)) volume_label {
> >> char volkey[4]; /* volume key = volume label */
> >> ...
> >> };
> >>
> >> And here is a structure which describes the volume label for a
> >> CMS-formatted disk:
> >>
> >> struct __attribute__ ((packed)) cms_label {
> >> char label_id[4]; /* Label identifier */
> >> ...
> >> };
> >
> > union any_label {
> > struct volume_label vl;
> > struct cms_label cl;
> > };
> >
> >> Note that both structures have as their first member a character
> >> variable of length 4. In the case of the "volume_label" structure it is
> >> "volkey" and in the case of the "cms_label" structure it is "label_id".
> >> If the value of this variable is "VOL1" (in EBCDIC) then it is the first
> >> structure which maps the storage. If the value of this variable is
> >> "CMS1" (in EBCDIC) then it is the second structure which maps the
> >> storage.
> >
> > union any_label *label = /* Initialize somehow */;
> > struct volume_label *maybe_vl = &label->vl;
> > struct cms_label *maybe_cl = &label->cl;
> >
> > if (strncmp(maybe_vl->volkey, "VOL1", 4) == 0) {
> > maybe_cl = NULL;
> > /* Use maybe_vl all you want, e.g. */
> > maybe_vl->security = 0xFF;
> > } else if (strncmp(maybe_cl->label_id, "CMS1", 4) == 0) {
> > maybe_vl = NULL;
> > /* Use maybe_cl all you want, e.g. */
> > printf("%lu\n", (unsigned long) maybe_cl->disk_offset);
> > } else {
> > assert(("Unrecognized disk!", 0));
> > }
>
> Thanks, Boyd. Your response comes the closest so far to what I'm looking
> for. Based on what I know from other programming languages, I don't think
> it's going to be necessary to explicitly declare a union.

It's possible, but I would generally do it for clarity. I like using the
types of variables/arguments as documentation, so I would store any data where
the real type was unknown in the union. Then access it though a "struct
cms_label *" or "struct volume_label *" one I had determined the correct type.

Since C unions are not tagged, a C union is the same size as it's largest
member. (NB: Not really sure how __attribute__((__packed__)) changes things,
if at all; it's possible you need it on the union to prevent padding from
being added after the space occupied by the largest member.)

> In short, I need to (a) declare "cms_label" as a based structure,

(above; timmmed)

> (b)
> declare a pointer variable called "cms_ptr" and associate it with the
> "cms_label" structure,

struct cms_label *cms_ptr;

Initialization optional, but recommended.

> (c) make sure that the compiler does not attempt
> to allocate any storage for the "cms_label" structure,

Since you are declaring a pointer to a structure, and not declaring an object
with type "struct cms_label", no space will be allocated for a cms_label.

> (d) make sure that
> the compiler automatically acquires storage for the "cms_ptr" pointer
> variable itself,

Make your declaration a definition and that'll be handled. (Declarations and
definitions look very similar for non-function types; the code given above is
actually a definition if it is not within a struct/union type.)

> (e) assign the address of the "volume_label" structure
> to the "cms_ptr" pointer variable at an appropriate point in the code,
> and

struct volume_label vl;
struct cms_label *cms_ptr;

/* Load data into vl */
/* Determine that the data is actually a cms_label */
cms_ptr = (void *) &vl;

Or, in your specific case, you should be able to do something like:

struct cms_label *cms_ptr = (void *) disk_specific->anchor->vlabel;

Since you are already dealing with a "struct volume_label *", there's no need
for the address-of operator (&).

> (f) make references to the members of the cms_label structure.

cms_ptr->label_id; /* Or any other member. */

> How do I do this? (Man, I wish I knew C!)

Examples above good? Please let me know if I can provide further assistance.
--
Boyd Stephen Smith Jr. ,= ,-_-. =.
bss(a)iguanasuicide.net ((_/)o o(\_))
ICQ: 514984 YM/AIM: DaTwinkDaddy `-'(. .)`-'
http://iguanasuicide.net/ \_/
From: Stephen Powell on
On Thu, 15 Apr 2010 17:39:42 -0400 (EDT), Boyd Stephen Smith Jr. wrote:
> Stephen Powell wrote:
>> In short, I need to
>> (a) declare "cms_label" as a based structure,
>
> (above; trimmmed)
>>
>> (b)
>> declare a pointer variable called "cms_ptr" and associate it with the
>> "cms_label" structure,
>
> struct cms_label *cms_ptr;
>
> Initialization optional, but recommended.
>>
>> (c)
>> make sure that the compiler does not attempt
>> to allocate any storage for the "cms_label" structure,
>
> Since you are declaring a pointer to a structure, and not declaring an object
> with type "struct cms_label", no space will be allocated for a cms_label.
>>
>> (d)
>> make sure that the compiler automatically acquires storage for the
>> "cms_ptr" pointer variable itself,
>
> Make your declaration a definition and that'll be handled. (Declarations and
> definitions look very similar for non-function types; the code given above is
> actually a definition if it is not within a struct/union type.)
>>
>> (e)
>> assign the address of the "volume_label" structure
>> to the "cms_ptr" pointer variable at an appropriate point in the code,
>> and
>
> struct volume_label vl;
> struct cms_label *cms_ptr;
>
> /* Load data into vl */
> /* Determine that the data is actually a cms_label */
> cms_ptr = (void *) &vl;
>
> Or, in your specific case, you should be able to do something like:
>
> struct cms_label *cms_ptr = (void *) disk_specific->anchor->vlabel;
>
> Since you are already dealing with a "struct volume_label *", there's no need
> for the address-of operator (&).
>>
>> (f)
>> make references to the members of the cms_label structure.
>
> cms_ptr->label_id; /* Or any other member. */
>>
>> How do I do this? (Man, I wish I knew C!)
>
> Examples above good? Please let me know if I can provide further assistance.

Yahoo! It works! Thanks a bunch, Boyd.

I'm going to be filing a bug report against parted for (a) miscalculating the starting
block of the implicit partition on an ldl (Linux Disk Layout) formatted disk on the
s390 architecture when the block size is other than 4096, and (b) no support for
CMS-formatted disks. I'm going to include my patch files for the fix in the bug
report. Would you like to be in the credits? Or would you prefer to remain anonymous?

--
.''`. Stephen Powell
: :' :
`. `'`
`-


--
To UNSUBSCRIBE, email to debian-user-REQUEST(a)lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster(a)lists.debian.org
Archive: http://lists.debian.org/1876691691.55741.1271378240260.JavaMail.root(a)md01.wow.synacor.com
From: Ron Johnson on
On 2010-04-15 19:37, Stephen Powell wrote:
[snip]
>
> I'm going to be filing a bug report against parted for (a) miscalculating the starting
> block of the implicit partition on an ldl (Linux Disk Layout) formatted disk on the
> s390 architecture when the block size is other than 4096, and (b) no support for
> CMS-formatted disks.

If practical, I hope you file 2 bugs.

--
Dissent is patriotic, remember?


--
To UNSUBSCRIBE, email to debian-user-REQUEST(a)lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster(a)lists.debian.org
Archive: http://lists.debian.org/4BC7B2A9.3070904(a)cox.net
From: Stephen Powell on
On Thu, 15 Apr 2010 20:43:21 -0400 (EDT), Ron Johnson wrote:
> On 2010-04-15 19:37, Stephen Powell wrote:
>>
>> I'm going to be filing a bug report against parted for (a) miscalculating
>> the starting block of the implicit partition on an ldl (Linux Disk Layout)
>> formatted disk on the s390 architecture when the block size is other than
>> 4096, and (b) no support for CMS-formatted disks.
>
> If practical, I hope you file 2 bugs.

I hear you. I'll have to look at the code to see if that's easily separated
out. I started with the purpose of adding an enhancement to support CMS
formatted disks. I stumbled across the bug in the starting block calculation
for ldl formatted disks in the process. CMS formatted disks are handled
*exactly* the same as ldl formatted disks if the disk is not reserved. I
would have had to fix that bug anyway to add support for CMS disks, since
I wanted the CMS support to be correct. The only wrinkle was correctly
handling reserved CMS disks. To do that I had to access the reserved block
offset in the CMS label, which prompted this thread.

All of this is specific to the s390 architecture and has no bearing on i386,
amd64, ia64, etc. I hope upstream (GNU, I believe) will accept the fix.
I have no reason to believe that they won't.

--
.''`. Stephen Powell
: :' :
`. `'`
`-


--
To UNSUBSCRIBE, email to debian-user-REQUEST(a)lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster(a)lists.debian.org
Archive: http://lists.debian.org/65674052.56609.1271380183436.JavaMail.root(a)md01.wow.synacor.com