Error opening physical file with _Ropen - c++

I'm trying to put physical file on IFS.
So trying to open file just to guarantee its presence on source.
This is how I do it:
errno=0;
if ( ((pf = _Ropen(pfname, "rr, nullcap=Y")) == NULL) || (errno!=0) )
{
printf("\nError: Cannot open file %s\n",pfname);
//...
}
However, the file not gets opened with pf = SPP:*NULL result
That won't be the issue, but I can't also view errno.
The eval errno gives Syntax error occurred. without any clue what has happened.
I'm still able to view contents of pfname: it looks like 'MYLIB/MYFILE'
Absolute path was also tried:
'/QSYS.LIB/MYLIB.LIB/MYFILE.FILE', without any difference - same error persists.
IBM IFS explorer clearly shows contents of MYLIB and there is a MYFILE inside this lib.
UPD
I've added some debug logging just to extcact error description or error code:
numbytes = sprintf( (char *)NULL, "%s", strerror(errno) );
ret = (char *)malloc( ( numbytes + 1 ) * sizeof( char ) );
sprintf( ret, "%s", strerror(errno) );
And the result of ret is SPP:*NULL.
Any ideas to try?

It turned out to be super simple - null byte was missing so _Ropen can not really access the file thus no error to be passed as well.
To handle this the argument of null-terminated byte array needs to be passed from caller.
In case of rpg solution looks like 'MYFILE/MYLIB' + X'00'

Related

Unable to successfully instantiate BreakIterator even after u_setDataDirectory was set

I am using ICU's BreakIterator (icu 68.2) for word segmentation.
I have used u_setDataDirectory to initialise the data path as mentioned in below code snippet's 1st line.
But when I check the status of createWordInstance(), I am getting U_MISSING_RESOURCE_ERROR. This kind of error should be solved by calling u_setDataDirectory. I have used that, but the problem is still there.
u_setDataDirectory;
UErrorCode status = U_ZERO_ERROR;
BreakIterator *wordIterator = BreakIterator::createWordInstance(Locale("zh"), status);
if (U_FAILURE(status))
{
std::cout<<"failed to create break iterator. status = "<<u_errorName(status)<<std::endl;
exit 1;
}
UnicodeString text = "sample input string";
wordIterator->setText(text);
delete wordIterator;
If u_setDataDirectory is the only cause for your error, you must call it with the correct path to the data directory.
change your first line from
u_setDataDirectory;
to (on Linux/Unix)
u_setDataDirectory( "/path/to/ICU/data/" );
or on Windows to
u_setDataDirectory( "C:\\Path\\To\\ICU\\Data\\" );
Unfortunately I don't know where are the data files of ICU. You need to correct the path string to the correct path on your system.
But from the reading of the ICU documentation https://unicode-org.github.io/icu-docs/apidoc/dev/icu4c/putil_8h.html#a550ea8502df5fed47ae4359be7f8e6a2
I guess, this is not enough to solve your problem.
If the call above does not solve your problem, you can try to call u_init( UErrorCode *status ) as the very first statment:
UErrorCode status = U_ZERO_ERROR;
u_init( &status );
if (U_FAILURE(status))
{
std::cout<<"failed to init. status = "<<u_errorName(status)<<std::endl;
std::exit( 1 );
}
and then check what is the problem.
EDIT
A second root cause can be that the "Locale("zh")" is missing.
Does it work with other locales? Like change it to "en_US" ?
You can also test if the Locale works by this:
if( Locale("zh").isBogus() )
{
std::cout << "Locale is not working!" << std::endl;
std::exit( 1 );
}

Libzip - Error: Error while opening the archive : no error

I'm trying to find out the solution to solve a problem;
In fact, i'm writing my own tool to make saves using libzip in C++ to compress the files.
Absolutly not finished but i wanted to make some tests, then i do and obtain a "funny" error from the log.
Here's my function:
void save(std::vector<std::string> filepath, std::string savepath){
int err;
savepath += time(NULL);
zip* saveArchive = zip_open(savepath.c_str(), ZIP_CREATE , &err);
if(err != ZIP_ER_OK) throw xif::sys_error("Error while opening the archive", zip_strerror(saveArchive));
for(int i = 0; i < filepath.size(); i++){
if(filepath[i].find("/") == std::string::npos){}
if(filepath[i].find(".cfg") == std::string::npos){
err = (int) zip_file_add(saveArchive, filepath[i].c_str(), NULL, NULL);
if(err == -1) throw xif::sys_error("Error while adding the files", zip_strerror(saveArchive));
}
}
if(zip_close(saveArchive) == -1) throw xif::sys_error("Error while closing the archive", zip_strerror(saveArchive));
}
I get a => Error : Error while opening the archive : No error
And, of course, i didn't have any .zip written.
If you could help me, thanks to you !
The documentation for zip_open says that it only sets *errorp if the open fails. Either test for saveArchive == nullptr or initialize err to
ZIP_ER_OK.
P.S. The search for '/' does nothing. Did you mean to put a continue in that block?
The other problematic line is:
savepath += time(NULL);
If that is the standard time function, that returns a time in seconds since the epoch. That will probably get truncated to a char, and then that char appended to the file name. That will cause strange characters to appear in the filename! I suggest using std::chrono to convert to text.

Time-of-Check, Time-of-Use issues involving access(), faccessat(), stat(), lstat(), fstat(), open(), and fopen()

I don't post here often, so bear with me while I try to decide how to solve this problem.
I'm updating a code base that hasn't been touched for between 10 - 20 years. The code was written without adherence to best practices, and by many authors with sometimes incomplete understandings of security conventions, or perhaps even before those conventions were common practice. The compiler used on this code is c++98 or c++03, but not more recent. The code is also cross platform between Linux and Windows.
All of that said, I need the help of some C++ veterans understanding the proper use of access(), stat() and open() and their perversions as it relates to TOCTOU issues.
Here is an example block of code illustrating the TOCTOU issue:
#ifdef WIN32
struct _stat buf;
#else
struct stat buf;
#endif //WIN32
FILE *fp;
char data[2560];
// Make sure file exists and is readable
#ifdef WIN32
if (_access(file.c_str(), R_OK) == -1) {
#else
if (access(file.c_str(), R_OK) == -1) {
#endif //WIN32
/* This is a fix from a previous
Stack-based Buffer Overflow
issue. I tried to keep the original
code as close to possible while
dealing with the potential security
issue, as I can't be certain of how
my change might effect the system. */
std::string checkStr("File ");
checkStr += file.c_str();
checkStr += " Not Found or Not Readable";
if(checkStr.length() >= 2560)
throw checkStr.c_str();
char message[2560];
sprintf(message, "File '%s' Not Found or Not Readable", file.c_str());
//DISPLAY_MSG_ERROR( this, message, "GetFileContents", "System" );
throw message;
}
// Get the file status information
#ifdef WIN32
if (_stat(file.c_str(), &buf) != 0) {
#else
if (stat(file.c_str(), &buf) != 0) {
#endif //WIN32
/* Same story here. */
std::string checkStr("File ");
checkStr += file.c_str();
checkStr += " No Status Available";
if(checkStr.length() >= 2560)
throw checkStr.c_str();
char message[2560];
sprintf(message, "File '%s' No Status Available", file.c_str());
//DISPLAY_MSG_ERROR( this, message, "GetFileContents", "System" );
throw message;
}
// Open the file for reading
fp = fopen(file.c_str(), "r");
if (fp == NULL) {
char message[2560];
sprintf(message, "File '%s' Cound Not be Opened", file.c_str());
//DISPLAY_MSG_ERROR( this, message, "GetFileContents", "System" );
throw message;
}
// Read the file
MvString s, ss;
while (fgets(data, sizeof(data), fp) != (char *)0) {
s = data;
s.trimBoth();
if (s.compare( 0, 5, "GROUP" ) == 0) {
//size_t t = s.find_last_of( ":" );
size_t t = s.find( ":" );
if (t != string::npos) {
ss = s.substr( t+1 ).c_str();
ss.trimBoth();
ss = ss.substr( 1, ss.length() - 3 ).c_str();
group_list.push_back( ss );
}
}
}
// Close the file
fclose(fp);
}
As you can see, the previous developer(s) wanted to make sure the user had access to "file", stat-ed "file", and then opened it without re-access()-ing and without re-stat()-ing "file" after fopen()-ing it. I understand why this is a TOCTOU problem, but I'm not sure of how to fix it.
From what I've researched, open() is preferred over fopen() and fstat() over stat(), but where does lstat() fit in? and if I do a stat, do I even need access() or faccessat()?
And to compound that, this needs to be compatable with a Windows compiler, and I've found articles saying that fopen() is better because it is cross platform while open() is not, making open() potentially unusable; this also seems to be the same for variations of stat() and access(), but I'm not certain.
If you've gotten this far, thank you for reading it all, and I welcome any criticism about the post and help.

luaL_dofile Error

Error at line "luaL_dofile" and debugger doesn't show anything about error.
I can use command "luaL_dostring" but I don't know why I can't dofile.
My code is following:
const char* file = "/app_home/data/minigames/mg_hint_machine_2.lua";
ret = luaL_dofile(LS, file);
if(ret != 0){
PRINTF("Error occurs when calling luaL_dofile() Hint Machine 0x%x\n",ret);
}
else PRINT("\nDOFILE SUCCESS");
and debugger shows error in this line and "ret" still not get returned value from dofile.
If you want to see about error in debugger
02C2D304 7C21016A stdux r1,r1,r0 03 (02C2D300) REG PIPE LSU
Debugger points in this line and I can't understand it.
As an elaboration on superzilla's answer (upvote that answer rather than this one),
to get the error message your code needs to look like this:
const char* file = "/app_home/data/minigames/mg_hint_machine_2.lua";
ret = luaL_dofile(LS, file);
if(ret != 0){
PRINTF("Error occurs when calling luaL_dofile() Hint Machine 0x%x\n",ret);
PRINTF("Error: %s", lua_tostring(LS,-1));
}
else PRINT("\nDOFILE SUCCESS");
Your change (in the comments) changed the luaL_dofile to a luaL_dostring, which is why you're getting unexpected error message ( as mentioned here ).
Putting this in the body of your if statement will help us narrow down the problem:
printf("%s\\n",lua_tostring(LS,-1));
It'll tell us what Lua is reporting when it crashes.

Starting a program fails with error code 1

I made an application and a dll, which are working this way:
I have to register the dll. After registering the dll if i right click on an .exe file, the pop-up menu appears, and i have inserted into this menu one line ("Start MyApp"), and if i click there, it should start MyApp. MyApp has one parameter which is the full path of the selected .exe file. After starting MyApp with this path it should create a process with CreateProcessWithLogonW(). This application reads the username, password and the domain from an .ini file. My problem is, that after MyApp starts, it fails always, because it can't find the ini file. Errorcode is: 1 (Incorrect function).
If i start MyApp manually, than it works fine.
Does anyone has any idea why is this, and how could i fix this problem?
Thanks in advance!
kampi
Update1:
Here is the code which reads from the ini file.
int main ( int argc, char *argv[] )
{
int i, slash = 0, j;
char application[size];
wchar_t wuser[65], wdomain[33], wpass[129];
memset( user, 0, sizeof ( user ) );
memset( password, 0, sizeof ( password ) );
memset( domain, 0, sizeof ( domain ) );
file_exists( "RunAs.ini" );
readfile( "RunAs.ini" );
....
....
....
}
void file_exists( const char * filename )
{
if (FILE * file = fopen(filename, "r"))
{
fclose(file);
}
else
{
printf("\nCan't find %s!\n",filename);
getch();
exit(1);
}
}//file_exists
void readfile( char * filename )
{
FILE *inifile;
char tmp[256], buf[256], what[128];
int i, j;
inifile = fopen( "RunAs.ini", "r" );
while ( fgets(tmp, sizeof tmp, inifile) != NULL )
{
if ( tmp[ strlen(tmp) - 1 ] == '\n' )
{
tmp[ strlen(tmp) - 1 ] = '\0';
}//if
memset ( buf, 0, sizeof( buf ) );
for ( i = 0; tmp[i]!= '='; i++ )
{
buf[i] = tmp[i];
}
buf[i] = '\0';
i++;
// memset ( what, 0, sizeof( what ) );
SecureZeroMemory( what, sizeof(what) * 128 );
for ( j = 0; i != strlen(tmp); i++ )
{
what[j] = tmp[i];
j++;
}
what[j] = '\0';
upcase( buf );
removespace( what );
if ( strcmp( buf, "USERNAME" ) == 0 )
{
strcpy( user, what );
}
if ( strcmp( buf, "PASSWORD" ) == 0 )
{
strcpy( password, what );
}
if ( strcmp( buf, "DOMAIN" ) == 0 )
{
strcpy( domain, what );
}
}//while
fclose (inifile);
}//readfile
As others have said, your problem is here:
file_exists( "RunAs.ini" );
readfile( "RunAs.ini" );
Neither of the function calls provides a path. You're expecting the current working directory to be the folder where your application is located, but it doesn't have to be (in fact, you should never assume that it is). The context menu isn't setting the working directory first.
Your safest bet is to retrieve the path to your folder using the path provided in argv[] (the 0th element is the fully qualified path and name of the application itself, and you can extract the path from that). You'll then have exact knowledge of where the file is located, and can append the name of the ini file to that path.
I suspect you're looking for the ini file in the wrong folder. I would try changing the ini file name in the application to the fully qualified name of the ini file. (i.e from "foo.ini" to "c:\\temp\\foo.ini")
(Please note that I've doubled the backslashes because without this, the single backslash may change the meaning of the next character or the backslash may be ignored.)
Are you providing an absolute path or a relative path? Your CWD may be different on startup.
When starting your application directly, the current path is the path that your application is installed to.
However, when starting it from that context menu, the current path is something else.
There are two ways to resolve this. First, don't use an ini file. Instead, store your information to the registry. That way you don't care where the program is started from.
Alternatively, your app will have to locate the directory where it was actually installed, then load the ini file from there.
Obviously the first choice is the easiest path.
Have you checked whether file path for the ini is valid ?