HPE Community read-only access December 15, 2018
This is a maintenance upgrade. You will be able to read articles and posts, but not post or reply.
Hours:
Dec 15, 4:00 am to 10:00 am UTC
Dec 14, 10:00 pm CST to Dec 15, 4:00 am CST
Dec 14, 8:00 pm PST to Dec 15, 2:00 am PST
Operating System - OpenVMS
cancel
Showing results for 
Search instead for 
Did you mean: 

lstat and case-sensitivity

 
mpradhan
Advisor

lstat and case-sensitivity

 Hi,

I have set "SET PROCESS=/PARSE_STYLE=EXTENDED" and "SET PROCESS/CASE_LOOKUP=SENSITIVE". By doing so, I can now I have file names with two diffenent cases, e.g. FILE.TXT;1 and file.txt;1 under a directory DIR

when I use lstat([DIR]FILE.TXT) it works, but when I use lstat([DIR]file.txt) it fails with ENOENT. I can do sys$open() on both paths successfully. 

I tried setting sys$set_process_propertiesw (0, 0, PPROP$C_PARSE_STYLE_TEMP, PARSE_STYLE$C_EXTENDED, 0, 0, 0) and sys$set_process_propertiesw (0, 0, PPROP$C_CASE_LOOKUP_TEMP, PPROP$K_CASE_SENSITIVE, 0, 0, 0) but lstat() still fails. 

 

Question -

do these above set_process_propertiesw work for lstat()? 

what else should be done so that lstat() treats filenames as case-sensistive?

15 REPLIES
Hoff
Honored Contributor

Re: lstat and case-sensitivity

Two different files, differing only by case?   Okay.   Not something I'd recommend., but enable the DECC$EFS_CASE_PRESERVE feature, if you really want to do that.   Details are in the docs.

Steven Schweda
Honored Contributor

Re: lstat and case-sensitivity

> do these above set_process_propertiesw work for lstat()?

   Apparently not. As "HELP SET PROCESS /PARSE_STYLE" says:

        Setting a particular parse style tells DCL how it should handle
        command syntax. User programs can also examine the state of this
        setting if they need to use different parse rules.

   lstat() behavior is a CRTL question, not a DCL question, so it's the
DECC$ stuff which affects it.

mpradhan
Advisor

Re: lstat and case-sensitivity

I have tried this.

under my test directory both OUT.TXT;2 and out.txt;2 exist however only one out.txt;4 exist.

this is my test program.

#define ENABLE TRUE
#define DISABLE 0

static int set_feature_default(const char *name, int value)
{
int index = decc$feature_get_index(name);;
if (index > 0)
index = decc$feature_set_value (index, 0, value);
return index;
}
static void show_feature_default(const char* name)
{
int index = decc$feature_get_index(name);
if(index > 0)
{
int value = decc$feature_get_value(index, 0);
cout << name << " has value " << value << endl;
}
}

 

 

int
main(int argc, char** argv)
{
string sFilePath;
cout << "Enter Path: ";
cin >> sFilePath;
struct stat st;
int iRet(0);

int iCaseSensitive(0);
cout << "Case Sensitive (1/0): ";
cin >> iCaseSensitive;
if(iCaseSensitive)
{
int prev_value = set_feature_default("DECC$ARGV_PARSE_STYLE", ENABLE);
if(0 != prev_value)
cout << "Failed to set DECC$ARGV_PARSE_STYLE," << " errno=" << strerror(errno) << endl;
prev_value = set_feature_default("DECC$EFS_CASE_PRESERVE", ENABLE);
if(0 != prev_value)
cout << "Failed to set DECC$EFS_CASE_PRESERVE," << " errno=" << strerror(errno) << endl;
}
show_feature_default("DECC$ARGV_PARSE_STYLE");
show_feature_default("DECC$EFS_CASE_PRESERVE");
//decc$feature_show_all();

if((iRet = lstat(sFilePath.c_str(), &st)) < 0)
{
cout << "lstat(" << sFilePath << ") failed, error=" << strerror(errno) << endl;
}
else
cout << "lstat(" << sFilePath << ") OK" << endl;
exit(0);
}

 

when I run this on OUT.TXT;2 or out.txt;2, it does not matter what case-sensitivity is set to, lstat works.

$ test_stat
Enter Path: dka0:[ssq]out.txt;2
Case Sensitive (1/0): 1 
DECC$ARGV_PARSE_STYLE has value 1
DECC$EFS_CASE_PRESERVE has value 1
lstat(dka0:[ssq]out.txt;2) OK
$ test_stat
Enter Path: dka0:[ssq]OUT.TXT;2
Case Sensitive (1/0): 1
DECC$ARGV_PARSE_STYLE has value 1
DECC$EFS_CASE_PRESERVE has value 1
lstat(dka0:[ssq]OUT.TXT;2) OK
$ test_stat
Enter Path: dka0:[ssq]out.txt;2
Case Sensitive (1/0): 0
DECC$ARGV_PARSE_STYLE has value 0
DECC$EFS_CASE_PRESERVE has value 0
lstat(dka0:[ssq]out.txt;2) OK
$ test_stat
Enter Path: dka0:[ssq]OUT.TXT;2
Case Sensitive (1/0): 0
DECC$ARGV_PARSE_STYLE has value 0
DECC$EFS_CASE_PRESERVE has value 0
lstat(dka0:[ssq]OUT.TXT;2) OK

 

but when I run this with out.txt;3, it does not matter what settings I have for case-sensitive, it always fails with ENOENT

$ test_stat
Enter Path: dka0:[ssq]out.txt;4
Case Sensitive (1/0): 1
DECC$ARGV_PARSE_STYLE has value 1
DECC$EFS_CASE_PRESERVE has value 1
lstat(dka0:[ssq]out.txt;4) failed, error=no such file or directory
$ test_stat
Enter Path: dka0:[ssq]out.txt;4
Case Sensitive (1/0): 0
DECC$ARGV_PARSE_STYLE has value 0
DECC$EFS_CASE_PRESERVE has value 0
lstat(dka0:[ssq]out.txt;4) failed, error=no such file or directory

 

I am doing somethign wrong?

 

Steven Schweda
Honored Contributor

Re: lstat and case-sensitivity

> main(int argc, char** argv)
> {
> [...]
> int prev_value = set_feature_default("DECC$ARGV_PARSE_STYLE", ENABLE);

   Too late.

      http://h71000.www7.hp.com/doc/83final/5763/5763pro_004.html

[...]
DECC$ARGV_PARSE_STYLE
With DECC$ARGV_PARSE_STYLE enabled, case is preserved in command-line
arguments when the process has been set up for extended DCL parsing
using SET PROCESS/PARSE_STYLE=EXTENDED.

DECC$ARGV_PARSE_STYLE must be defined externally as a logical name or
set in a function called using the LIB$INITIALIZE mechanism because it
is evaluated before function main is called.
[...]

    But I don't see you doing anything with argv[], so this may only
waste time (and brain-space) without affecting the result.

> under my test directory both OUT.TXT;2 and out.txt;2 exist however
> only one out.txt;4 exist.

   I would trust actual DIRECTORY output more than your description of
DIRECTORY output, especially when I see things like the following:

> but when I run this with out.txt;3, it does not matter what settings I
> have for case-sensitive, it always fails with ENOENT
>
> $ test_stat
> Enter Path: dka0:[ssq]out.txt;4

Hoff
Honored Contributor

Re: lstat and case-sensitivity

If this code is ever going to be transferred off of this OpenVMS server and used on other and end-user servers, then this full-on case-sensitivity approach is a really bad idea, and this almost certainly will cause problems and problem reports.   That even once this code is working.   Very few OpenVMS systems have case sensitivity enabled, and most OpenVMS software does not expect this and has not been tested with this.    Officially and per the HPE folks: "HP strongly recommends that you use caution when enabling case sensitivity in your processes."

As for your question, this is typically a UNIX-oriented configuration, so you'll likely want to avoid version support.   Quite possibly also OpenVMS filename processing, and use UNIX naming. Or set the UNIX compatibility level to a much higher value.   That UNIX level controls the settings of a group of features.  More than a little of this is experimentation, based on your local requirements and expectations, and the particular character set in use for the filenames.

That you're possibly working with symbolic links (as lstat expressly supports) also likely means a trip through the related OpenVMS documentation and recent patches, as there are some wrinkles in this area — there was link support added into the last OpenVMS version or two, and it's potentially going to be a little different setup than what might be expected by a UNIX or Linux or BSD developer.

That posted C++ code appears incomplete, too.   23 errors result from a direct compilation.   I also can't tell which files are present in your test configuration.    If you want us to look at the C++ code, please attach the complete C++ code and the associated build procedure; enough details that I might reproduce this, and test it here.   I didn't bother troubleshooting that C++ code, and wrote a simpler C reproducer with rather fewer knobs.

I'm testing with a somewhat shorter example, get what I expect to see with case sensitivity enabled.  (But I don't yet know what files exist in your configuration.)

#include <stat.h>

#include <stdio.h>

#include <stdlib.h>

#include  <string.h>

 

int

main(int argc, char** argv) {

  struct stat statbuf;

  int RetStat;

  if ( argc != 2 )

     return EXIT_FAILURE;

  RetStat = lstat( argv[1], &statbuf );

  if ( RetStat )

    strerror( RetStat );

  return EXIT_SUCCESS;  

}

And things seem to work as expected with a couple of test files on a scratch LD disk set for ODS-5.

Rough sequence used follows...

ld create filespec/size=8192

ld connect filespec LDA256

init LDA256: scratch/STRUCT=5

mount LDA256: scratch

DEFINE DECC$EFS_CASE_PRESERVE TRUE

CC X/DEBUG/NOOPT

LINK X/DEBUG/NOOPT

set process/parse=extended/case=sens

create LDA256:[000000]TEST.TMP

create LDA256:[000000]test.tmp

X LDA256:[000000]TEST.TMP

X LDA256:[000000]test.tmp

etc.

 

But as mentioned above, please attach full source code and enough that somebody here can reproduce the reported behavior.

mpradhan
Advisor

Re: lstat and case-sensitivity

the only piece that was missing from the code was header, here are they.

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <time.h>
#include <errno.h>
#include <unixlib.h>

// VMS Headers
#include <atrdef.h>
#include <descrip.h>
//#include "fatdef.h"
#include <rms>
#include <starlet>
#include <ssdef.h>
#include <descrip.h>
#include <fabdef.h>

#include <descrip.h>
#include <atrdef.h>
#include <ppropdef.h>
#include <fibdef.h>
#include <iodef.h>
#include <sbkdef.h>
//#include "vmstime.h"

typedef struct fibdef FIB;
//#include "fatdef.h"
#include "sys$examples:bapidef.h"

 

This is a purely VMS test.

As noted above setting these dec$* looks to be too late, this has a code http://antinode.info/ftp/cdrtools/cdrtools-2_01_01a11/libvms/vms_init.c. But I cannot link this code it keeps complaing about undefined lib$initialize.

Anyways. 

One interesting thing that I saw while doing this is. when I use lstat and print time-stamps, those donot match to what dir /full will print (ctime and mtime/atime are swapped). lstat even reports ctime < mtime, which is weird. 

int
main(int argc, char** argv)
{
string sFilePath;
cout << "Enter Path: ";
cin >> sFilePath;
struct stat st;

int iNewCode(false);
cout << "use mystat(1/0): ";
cin >> iNewCode;
if(!iNewCode)
{
if((iRet = lstat(sFilePath.c_str(), &st)) < 0)
{
cout << "lstat(" << sFilePath << ") failed, error=" << strerror(errno) << endl;
}
else
{
cout << "lstat(" << sFilePath << ") OK" << endl;
cout << "ctime: " << st.st_ctime << " mtime: " << st.st_mtime << " atime: " << st.st_atime << " size: " << st.st_size << " mode: " << st.st_mode << endl;
}
}
else
my_stat(sFilePath.c_str());

exit(0);
}

 

$ test_stat
Enter Path: dka0:[ssq]out.txt;2
DECC$ARGV_PARSE_STYLE has value 0
DECC$EFS_CASE_PRESERVE has value 0
use mystat(1/0): 0
lstat(dka0:[ssq]out.txt;2) OK
ctime: 1337117482 mtime: 1337117572 atime: 1337117572 size: 1018 mode: 33256

$ dir /full dka0:[ssq]out.txt;2

Directory DKA0:[SSQ]

OUT.TXT;2 File ID: (19005,4,0)
Size: 2/32 Owner: [SYSTEM]
Created: 15-MAY-2012 17:31:22.29
Revised: 15-MAY-2012 17:32:52.87 (1)
Expires: 10-MAR-2017 14:07:20.31
Backup: <No backup recorded>
Effective: <None specified>
Recording: <None specified>
Accessed: 15-MAY-2012 17:31:22.29
Attributes: 15-MAY-2012 17:32:52.87
Modified: 15-MAY-2012 17:31:22.29
Linkcount: 1
File organization: Sequential
Shelved state: Online
Caching attribute: Writethrough
File attributes: Allocation: 32, Extend: 0, Global buffer count: 0
Version limit: 3
Record format: VFC, 2 byte header, maximum 0 bytes, longest 107 bytes
Record attributes: Print file carriage control
RMS attributes: None
Journaling enabled: None
File protection: System:RWED, Owner:RWED, Group:RE, World:
Access Cntrl List: (IDENTIFIER=[150,*],ACCESS=READ)
Client attributes: None

Total of 1 file, 2/32 blocks.

 

convert above time-stamps (ones from lstat) to EST

to me looks like lstat() has a bug in this regard, or may be I am hallucinating

mpradhan
Advisor

Re: lstat and case-sensitivity

actual directory output

 

$ dir dka0:[ssq]

Directory DKA0:[SSQ]

OUT.SAV;1 out.t;1 OUT.TXT;3 OUT.TXT;2
OUT.TXT;1 out.txt;4 out.txt;3 out.txt;2
OUT_ORIG.SAV;1 out_rest.sav;1 OUT_RESTORE.TXT;1 RESTORE.TXT;1
TESTIDX.ISM;1 This_file^_is_not_OK.txt;1
This_file^%is_not_OK.txt;1 This_file^+is_not_OK.txt;1
This_file^.is_OK.txt;1 This_file^=is_not_OK.txt;1

Total of 18 files.
$

H.Becker
Honored Contributor

Re: lstat and case-sensitivity

>>> As noted above setting these dec$* looks to be too late, this has a code http://antinode.info/ftp/cdrtools/cdrtools-2_01_01a11/libvms/vms_init.c. But I cannot link this code it keeps complaing about undefined lib$initialize.

LIB$INITIALIZE is in SYS$COMMON:[SYSLIB]STARLET.OLB, which the linker processes by default. You may want to show the full link command and the exact linker message. 

Steven Schweda
Honored Contributor

Re: lstat and case-sensitivity

> As noted above setting these dec$* looks to be too late, this has a
> code http://antinode.info/ftp/cdrtools/cdrtools-2_01_01a11/libvms/vms_init.c.
> But I cannot link this code it keeps complaing about undefined
> lib$initialize.

   That's C code, not C++, and I can't see how you're trying to use it.
(There's more, similar code in Zip and UnZip, if you're looking for more
C examples, by the way.  But if I did it, it probably looks very
similar.)

   "I cannot" is not a useful problem description. It does not say what
you did. It does not say what happened when you did it.  As usual,
showing actual commands with their actual output can be more helpful
than vague descriptions or interpretations.

   LIB$INITIALIZE is easier to use in C (where I have done it) than in
C++ (where I haven't done it).  But if you do not use argv[], then who
cares about DECC$ARGV_PARSE_STYLE?  (Other such things can be set later,
so you wouldn't need LIB$INITIALIZE for them, only for
DECC$ARGV_PARSE_STYLE.)

    If you _were_ using argv[], then the easy way to test
DECC$ARGV_PARSE_STYLE would be to define the logical name, and forget
about trying to do it in your program (until you determine that you
really need to use it).

Steven Schweda
Honored Contributor

Re: lstat and case-sensitivity

> LIB$INITIALIZE is in SYS$COMMON:[SYSLIB]STARLET.OLB, which the linker
> processes by default.

   Not much use if you're trying to supply your own.

> You may want to show the full link command and the
> exact linker message.

   No argument there.  As I recall, C++ tends to use/hijack
LIB$INITIALIZE for its own purposes, so, to use it with C++, you need to
create a separate shared image with your own LIB$INITIALIZE, and ask the
linker to get yours, too.  But, as I said, I've never done it.  A Forum
or Web search (for: C++ LIB$INITIALIZE) might find some details.  If you
actually care.

H.Becker
Honored Contributor

Re: lstat and case-sensitivity

..>> LIB$INITIALIZE is in SYS$COMMON:[SYSLIB]STARLET.OLB, which the linker
>> processes by default.

>Not much use if you're trying to supply your own.

Your own what? The OP said,  "undefined lib$initialize". Which may be a real linker message or not. If that undefined symbol is LIB$INITIALIZE, it is defined in SYS$COMMON:[SYSLIB]STARLET.OLB. You can not have your own symbol LIB$INITIALIZE to get the image initialization done. You have to have your own PSECT LIB$INITIALIZE merged into the pre-fabricated wrappers from the object module  LIB$INITIALIZE, which is part of STARLET.OLB.

Edit: Actually, you don't need the symbol LIB$INITIALIZE at all. You only need to include the object module LIB$INITIALIZE.

> ... As I recall, C++ tends to use/hijack
> LIB$INITIALIZE for its own purposes, so, to use it with C++, you need to
> create a separate shared image with your own LIB$INITIALIZE, and ask the
> linker to get yours, too. But, as I said, I've never done it. A Forum
> or Web search (for: C++ LIB$INITIALIZE) might find some details. If you
> actually care.

I wouldn't say hijack. C++ and its RTL (on I64 if I remember correctly) uses the LIB$INITIALIZE mechanism as well. To get your own image initialization done before the RTL's shareable image ones, you have to have a shareable image with your init code which the image activator activates before the C++ RTL. The image activator followes the list of shareable images as the linker sets it up. That is, your link command has to ensure that your (init code in your) shareable image is "in front of" the C++ RTL's one. 

 

Hoff
Honored Contributor

Re: lstat and case-sensitivity

As others have correctly noted, this utterly non-modular and nonsensical and ill-considered "design" of the C run-time library means either defining the logical names ahead of image invocation, or — if you want to use the API — invoking the feature set calls in the initialization PSECT, ahead of the main() call.   (The main() call invokes the C library initialization code, and which is also why you see that "type GO to get to the start of the main program" in the debugger. )

This scheme all makes sense if you know how the OpenVMS image initialization actually works, but pragmaticallt it's a design that's user-hostile and non-modular at best, and some of the alternative user interfaces possible here could have made this vastly easiler and better.

(If you've inferred that I might not be a proponent of this "design", you probably don't know the half of what I think about this particular and fetid heap of vomitus.  This was a Bad Idea when it was built, and the imbroglio has only increased as settings accreted.  But I digress.)

When logging bug reports, posting full details and a reproducer really helps — saves folks from guessing what has happened — and it requires less effort on the part of those that might help you to get to the answer that you want and need.   Attaching a zip here can work nicely too, as that can contain the entirety of the reproducer.

mpradhan
Advisor

Re: lstat and case-sensitivity

OK. First I would like to point out what behavior I see with lstat (this is simple nothing do with case-sensitivity, something I just stumbled upon).

this is cpp program using lstat() and printing ctime, atime, mtime.

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <time.h>
#include <errno.h>
#include <unixlib.h>

using namespace std;


int
main(int argc, char** argv)
{
string sFilePath;
cout << "Enter Path: ";
cin >> sFilePath;
struct stat st;
int iRet(0);

if((iRet = lstat(sFilePath.c_str(), &st)) < 0)
{
cerr << "lstat(" << sFilePath << ") failed, error=" << strerror(errno) << endl;
exit(-1);
}
cout << "ctime: " << asctime(localtime(&st.st_ctime));
cout << "mtime: " << asctime(localtime(&st.st_mtime));
cout << "atime: " << asctime(localtime(&st.st_atime));
exit(0);
}

this is the result using this program.

$ test_stat
Enter Path: dka0:[ssq]out.txt;2
ctime: Tue May 15 17:31:22 2012
mtime: Tue May 15 17:32:52 2012
atime: Tue May 15 17:32:52 2012

and this is dir /full result on the same file

$ dir /full dka0:[ssq]out.txt;2

Directory DKA0:[SSQ]

OUT.TXT;2 File ID: (19005,4,0)
Size: 2/32 Owner: [SYSTEM]
Created: 15-MAY-2012 17:31:22.29
Revised: 15-MAY-2012 17:32:52.87 (1)
Expires: 10-MAR-2017 14:07:20.31
Backup: <No backup recorded>
Effective: <None specified>
Recording: <None specified>
Accessed: 15-MAY-2012 17:31:22.29
Attributes: 15-MAY-2012 17:32:52.87
Modified: 15-MAY-2012 17:31:22.29
Linkcount: 1
File organization: Sequential
Shelved state: Online
Caching attribute: Writethrough
File attributes: Allocation: 32, Extend: 0, Global buffer count: 0
Version limit: 3
Record format: VFC, 2 byte header, maximum 0 bytes, longest 107 bytes
Record attributes: Print file carriage control
RMS attributes: None
Journaling enabled: None
File protection: System:RWED, Owner:RWED, Group:RE, World:
Access Cntrl List: (IDENTIFIER=[150,*],ACCESS=READ)
Client attributes: None

Total of 1 file, 2/32 blocks.
$

 

so this is the lstat() bug that I talked about.

 

Second. I dont really need DEC$ARGV_PARSE_STYLE but I need DEC$EFS_CASE_PRESERVE instead, I think, to instruct lstat() to treat filename case-sensitively.

So this is the lstat() program (same above program silghtly changed) for case-sensitivity test. 

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <time.h>
#include <errno.h>
#include <unixlib.h>

using namespace std;

#define ENABLE TRUE
#define DISABLE 0

static int set_feature_default(const char *name, int value)
{
int index = decc$feature_get_index(name);;
if (index > 0)
index = decc$feature_set_value (index, 0, value);
return index;
}

static void show_feature_default(const char* name)
{
int index = decc$feature_get_index(name);
if(index > 0)
{
int value = decc$feature_get_value(index, 0);
cout << name << " has value " << value << endl;
}
}


int
main(int argc, char** argv)
{
string sFilePath;
cout << "Enter Path: ";
cin >> sFilePath;
int iCaseSensitive(0);
int prev_value = set_feature_default("DECC$EFS_CASE_PRESERVE", ENABLE);
if(0 != prev_value)
cerr << "Failed to set DECC$EFS_CASE_PRESERVE," << " errno=" << strerror(errno) << endl;
show_feature_default("DECC$EFS_CASE_PRESERVE");
struct stat st;
int iRet(0);

if((iRet = lstat(sFilePath.c_str(), &st)) < 0)
{
cerr << "lstat(" << sFilePath << ") failed, error=" << strerror(errno) << endl;
exit(-1);
}
cout << "ctime: " << asctime(localtime(&st.st_ctime));
cout << "mtime: " << asctime(localtime(&st.st_mtime));
cout << "atime: " << asctime(localtime(&st.st_atime));
exit(0);
}

dir listing on the directory.

$ dir dka0:[ssq]

Directory DKA0:[SSQ]

OUT.SAV;1 out.t;1 OUT.TXT;3 OUT.TXT;2
OUT.TXT;1 out.txt;4 out.txt;3 out.txt;2
OUT_ORIG.SAV;1 out_rest.sav;1 OUT_RESTORE.TXT;1 RESTORE.TXT;1
TESTIDX.ISM;1 This_file^_is_not_OK.txt;1
This_file^%is_not_OK.txt;1 This_file^+is_not_OK.txt;1
This_file^.is_OK.txt;1 This_file^=is_not_OK.txt;1

Total of 18 files.
$

note above, only out.txt;4 exits but both out.txt;2 and OUT.TXT;2 exist. Now trying this program 

$ test_stat
Enter Path: dka0:[ssq]out.txt;4
DECC$EFS_CASE_PRESERVE has value 1
lstat(dka0:[ssq]out.txt;4) failed, error=no such file or directory
$ test_stat
Enter Path: dka0:[ssq]out.txt;2
DECC$EFS_CASE_PRESERVE has value 1
ctime: Tue May 15 17:31:22 2012
mtime: Tue May 15 17:32:52 2012
atime: Tue May 15 17:32:52 2012

$ test_stat
Enter Path: dka0:[ssq]OUT.TXT;2
DECC$EFS_CASE_PRESERVE has value 1
ctime: Tue May 15 17:31:22 2012
mtime: Tue May 15 17:32:52 2012
atime: Tue May 15 17:32:52 2012
$

 

Also note that these are on IA64, we dont have Alpha or VAX. 

 

Rationale on why I am doing this - In my program (the real bigger one), I have a vital place where I need to do a lstat() on a file to grab some attributes (I am primarily a UNIX programmer making some code transition to OpenVMS, hence UNIX C-api come handy to me always). This is where it came to my notice that lstat() always fails when the volume has case-sensitivity enabled and there is a file with lower case only. Also, to note, that a subsequent sys$open() on the same full actually works. 

mpradhan
Advisor

Re: lstat and case-sensitivity

this is the full link command

$ CXXLINK/exe=test_stat.exe test_stat.obj,SYS$SHARE:STARLET.OLB
%ILINK-E-INVLDHDR, invalid ELF header; field 'ehdr$b_ei_mag0' has invalid value %X09
module: <unassigned>
file: SYS$COMMON:[SYSLIB]STARLET.OLB;1
%ILINK-W-NUDFSYMS, 1 undefined symbol:
%ILINK-I-UDFSYM, int lib$initialize()
%ILINK-W-USEUNDEF, undefined symbol int lib$initialize() referenced
source code name: "lib$initialize()"
section: .sdata
offset: %X0000000000000010
module: TEST_STAT
file: DNFS1:[cxunix.source.CommClient.ClProxyConnAPI.Client.backup]TEST_STAT.OBJ;32

the highlighted line is what I am curious about. 

 

H.Becker
Honored Contributor

Re: lstat and case-sensitivity

> $ CXXLINK/exe=test_stat.exe test_stat.obj,SYS$SHARE:STARLET.OLB

> %ILINK-E-INVLDHDR, invalid ELF header; field 'ehdr$b_ei_mag0' has invalid value %X09

Without any qualifier, the linker expects object files as arguments. STARLET.OLB is an object library. If you want to resolve from a library, you need to add the /LIBRARY qualifier to the object library. However, as already mentioned, this object library is already processed, by default. You may end up with "%ILINK-W-MULDEF" warning messages.

On the other hand, you are using CXXLINK, which does some postprocessing on the VMS linker output: something like "%ILINK-I-UDFSYM, LIB$INITIALIZE__XV" is converted to "%ILINK-I-UDFSYM, int lib$initialize()" - these examples are taken from Alpha, so the mangled name on I64 may be slightly different.. The linker resolves mangled names, CXXLINK hides these names and shows the demangled names. Essentially you have an unresolved symbol like "LIB$INITIALIZE__XV", which is not defined in any object module in STARLET.OLB, as the wanted, real name in that library and its module is "LIB$INITIALIZE." In other words, you need to wrap the "extern int lib$initialize();" with `extern "C" {  ...  }.'

For many VMS programmers, referencing the symbol LIB$INITIALIZE is just more convenient - as STARLET.OLB is searched by default for that symbol, than explicitly including the needed object module with a linker command string like "SYS$SHARE:STARLET/LIB/INCL=LIB$INITIALIZE".