need help with this JNI code

M

Mikey

I think I must have a bug somewhere in this code. Sometimes, it will
return -1. While I realize that I've programmed it to do so if the
lstat fails, I'm curious as to why it fails. I've also seen what I
believe to be the wrong file permissions returned on one occasion (it
returned 755, but from everything I can see, the permissions have
never been anything but 644, and it usually returns that). Any help
would be appreciated.

#include <jni.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "FileStat.h"

/*
* compile with:
* gcc -G -I/usr/java/include/ -I/usr/java/include/solaris \
* FileStatImp.c -o libjstat.so
*/

JNIEXPORT jint JNICALL Java_ssm_FileStat_getOwner
(JNIEnv *env, jobject obj, jstring file) {
int retval;
char buf[128];
const char *str = (*env)->GetStringUTFChars(env, file, 0);
struct stat *buffer;
buffer = (struct stat *) malloc(sizeof(struct stat));
(*env)->ReleaseStringUTFChars(env, file, str);

if(lstat(str, buffer) == 0) {
retval = buffer->st_uid;
}
else {
retval = -1;
}

return retval;
}

JNIEXPORT jint JNICALL Java_ssm_FileStat_getGroup
(JNIEnv *env, jobject obj, jstring file) {
int retval;
char buf[128];
const char *str = (*env)->GetStringUTFChars(env, file, 0);
struct stat *buffer;
buffer = (struct stat *) malloc(sizeof(struct stat));
(*env)->ReleaseStringUTFChars(env, file, str);

if(lstat(str, buffer) == 0) {
retval = buffer->st_gid;
}
else {
retval = -1;
}

return retval;
}

JNIEXPORT jint JNICALL Java_ssm_FileStat_getMode
(JNIEnv *env, jobject obj, jstring file) {
int retval;
char mode[5];
char buf[128];
const char *str = (*env)->GetStringUTFChars(env, file, 0);
struct stat *buffer;
buffer = (struct stat *) malloc(sizeof(struct stat));
(*env)->ReleaseStringUTFChars(env, file, str);

if(lstat(str, buffer) == 0) {
sprintf(mode, "%04o", buffer->st_mode & 07777);
retval = atoi(mode);
}
else {
retval = -1;
}

return retval;
}
 
G

Gordon Beaton

I think I must have a bug somewhere in this code. Sometimes, it will
return -1. While I realize that I've programmed it to do so if the
lstat fails, I'm curious as to why it fails. I've also seen what I
believe to be the wrong file permissions returned on one occasion
(it returned 755, but from everything I can see, the permissions
have never been anything but 644, and it usually returns that). Any
help would be appreciated.

If you get -1 when you call lstat(), check the value of errno to see
the reason. In fact, why not throw an IOException in that case, and
use the value of strerror(errno) as the error message?

There is no need to allocate the stat buffer dynamically in any of the
three functions. Declare the variable like this instead:

struct stat buffer;

then pass the address of this struct when you invoke lstat:

lstat(str,&buffer);

Note that you have neglected to free() the allocated buffer in each
case, so you have a leak in your code. Declaring the buffer like I've
suggested here solves that.

In the last function I cannot understand why you are converting the
mode from (for example) 644 octal to 644 decimal (which is what your
sprintf/atoi combination does). Why don't you return (buffer->st_mode
& 07777) directly? If you want to *display* the octal value in java,
convert the integer to an octal string with Integer.toString(n,8) or
Integer.toOctalString(n). That said, I'm not certain that your "mode"
buffer is large enough for all possible values.

/gordon
 
M

Mikey

Gordon Beaton said:
If you get -1 when you call lstat(), check the value of errno to see
the reason. In fact, why not throw an IOException in that case, and
use the value of strerror(errno) as the error message?

There is no need to allocate the stat buffer dynamically in any of the
three functions. Declare the variable like this instead:

struct stat buffer;

then pass the address of this struct when you invoke lstat:

lstat(str,&buffer);

Note that you have neglected to free() the allocated buffer in each
case, so you have a leak in your code. Declaring the buffer like I've
suggested here solves that.

In the last function I cannot understand why you are converting the
mode from (for example) 644 octal to 644 decimal (which is what your
sprintf/atoi combination does). Why don't you return (buffer->st_mode
& 07777) directly? If you want to *display* the octal value in java,
convert the integer to an octal string with Integer.toString(n,8) or
Integer.toOctalString(n). That said, I'm not certain that your "mode"
buffer is large enough for all possible values.

/gordon

Admittedly, I really don't know any C and all of this is just hacked
together. So, the answer to any questions relating to why I'm doing
something would be because I have no clue. :O) I actually managed to
ask myself why the heck I was malloc'ing on that stat buffer as well
before I saw your post. Thanks a bunch for the tips!
 
M

Mikey

Gordon Beaton said:
If you get -1 when you call lstat(), check the value of errno to see
the reason. In fact, why not throw an IOException in that case, and
use the value of strerror(errno) as the error message?

After adding a perror() in there which prints the filename and
(obviously) the error, I'm seeing the following:

ö<¨: No such file or directory


So, it looks like I'm dealing with garbage at times, corrrect? I
don't really understand where the garbage could be coming from though.
Ideas? The thing is, the java code that executes this says something
like:

FileStat fs = new FileStat();
for(int i = 0; i < files.length; i++) {
foo = fs.getMode(files) + "-" + fs.getOwner(files) + ":" +
fs.getGroup(files)
}

and the other executions (i.e. getting the owner and group) work fine.
So, I'd say I'm not passing in a bad value, right? I'm confused.
Any help would be appreciated.
 
N

nos

Mikey said:
Gordon Beaton <[email protected]> wrote in message
If you get -1 when you call lstat(), check the value of errno to see
the reason. In fact, why not throw an IOException in that case, and
use the value of strerror(errno) as the error message?

After adding a perror() in there which prints the filename and
(obviously) the error, I'm seeing the following:

ö<¨: No such file or directory


So, it looks like I'm dealing with garbage at times, corrrect? I
don't really understand where the garbage could be coming from though.
Ideas? The thing is, the java code that executes this says something
like:

FileStat fs = new FileStat();
for(int i = 0; i < files.length; i++) {
foo = fs.getMode(files) + "-" + fs.getOwner(files) + ":" +
fs.getGroup(files)
}

and the other executions (i.e. getting the owner and group) work fine.
So, I'd say I'm not passing in a bad value, right? I'm confused.
Any help would be appreciated.


you should check the return codes of all method
invocations to be sure they return what you expect
 
C

Chris Uppal

Mikey said:
JNIEXPORT jint JNICALL Java_ssm_FileStat_getOwner
(JNIEnv *env, jobject obj, jstring file) {
int retval;
char buf[128];
const char *str = (*env)->GetStringUTFChars(env, file, 0);
struct stat *buffer;
buffer = (struct stat *) malloc(sizeof(struct stat));
(*env)->ReleaseStringUTFChars(env, file, str);

if(lstat(str, buffer) == 0) {
retval = buffer->st_uid;

You realise that you've done a ReleaseStringUTFChars() *before* you actually
use them ? That makes it quite likely that the JVM will reclaim or recycle the
chunk of store that "str" is pointing to before you use it as an argument to
lstat().

-- chris
 
M

Mikey

Chris Uppal said:
Mikey said:
JNIEXPORT jint JNICALL Java_ssm_FileStat_getOwner
(JNIEnv *env, jobject obj, jstring file) {
int retval;
char buf[128];
const char *str = (*env)->GetStringUTFChars(env, file, 0);
struct stat *buffer;
buffer = (struct stat *) malloc(sizeof(struct stat));
(*env)->ReleaseStringUTFChars(env, file, str);

if(lstat(str, buffer) == 0) {
retval = buffer->st_uid;

You realise that you've done a ReleaseStringUTFChars() *before* you actually
use them ? That makes it quite likely that the JVM will reclaim or recycle the
chunk of store that "str" is pointing to before you use it as an argument to
lstat().

-- chris


I swear. Sometimes I get so busy looking at snippets of code to piece
together to get something working that I lose myself in it all. Thank
you, that would surely explain the inconsistent garbage characters.

Sincerely,
Dummy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,125
Latest member
VinayKumar Nevatia_
Top