潜水很久了,第一次发帖,OSchina是个好地方
这几天做一个VPN的管理系统,遇到了这样一个题目,就是要读取/var/run/utmp这个文件,获取登入信息。
utmp是一个二进制文件,who命令就读取了这个文件,参考源代码后,发现C下读取utmp文件特别简单
struct utmp current_record;//一个缓冲区
int utmpfd; //文件描述符
int reclen = sizeof(current_record);
if ((utmpfd = open(UTMP_FILE, O_RDONLY)) == -1) {
perror(UTMP_FILE);
return 1;
}
while (read(utmpfd, ¤t_record, reclen) == reclen)
show_info(¤t_record); //显示utmp的内容
close(utmpfd);
其中 utmp 结构体的定义如下
struct utmp
{
short int ut_type; /* Type of login. */
pid_t ut_pid; /* Process ID of login process. */
char ut_line[UT_LINESIZE]; /* Devicename. */
char ut_id[4]; /* Inittab ID. */
char ut_user[UT_NAMESIZE]; /* Username. */
char ut_host[UT_HOSTSIZE]; /* Hostname for remote login. */
struct exit_status ut_exit; /* Exit status of a process marked
as DEAD_PROCESS. */
/* The ut_session and ut_tv fields must be the same size when compiled
32- and 64-bit. This allows data files and shared memory to be
shared between 32- and 64-bit applications. */
#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
int32_t ut_session; /* Session ID, used for windowing. */
struct
{
int32_t tv_sec; /* Seconds. */
int32_t tv_usec; /* Microseconds. */
} ut_tv; /* Time entry was made. */
#else
long int ut_session; /* Session ID, used for windowing. */
struct timeval ut_tv; /* Time entry was made. */
#endif
int32_t ut_addr_v6[4]; /* Internet address of remote host. */
char __unused[20]; /* Reserved for future use. */
};
在java下,我想使用randomaccessfile来读取这个文件,
先定义utmp
public class utmp {
static final int UTMPSIZE = 384;
static final int UT_LINESIZE = 32;
static final int UT_NAMESIZE = 32;
static final int UT_HOSTSIZE = 256;
short ut_type; /* Type of login. */
int ut_pid; /* Process ID of login process. */
byte ut_line[]; /* Devicename. */
byte ut_id[]; /* Inittab ID. */
byte ut_user[]; /* Username. */
byte ut_host[]; /* Hostname for remote login. */
class exit_status /* Exit status of a process marked as DEAD_PROCESS. */
{
short e_termination; /* Process termination status. */
short e_exit; /* Process exit status. */
exit_status() {
e_termination = -1;
}
}
exit_status ut_exit;
int ut_session; /* Session ID, used for windowing. */
class timeval /* Time entry was made. */
{
int tv_sec; /* Seconds. */
int tv_usec; /* Microseconds. */
}
timeval ut_tv;
int ut_addr_v6[]; /* Internet address of remote host. */
byte __unused[]; /* Reserved for future use. */
utmp() {
ut_line = new byte[UT_LINESIZE];
ut_id = new byte[4];
ut_user = new byte[UT_NAMESIZE];
ut_host = new byte[UT_HOSTSIZE];
ut_addr_v6 = new int[4];
__unused = new byte[20];
}
}
然后考虑c的内存对齐问题,在读取的时候
for (int i = 0; i < in.length() / utmp.UTMPSIZE; i++) {
utmp tem = new utmp();
int loc=0;
in.seek(loc+44);
tem.ut_type = in.readShort();
//System.out.println(in.getFilePointer());
in.seek(loc+48);
tem.ut_pid = in.readInt();
//System.out.println(in.getFilePointer());
in.seek(loc+52);
for (int j = 0; j < utmp.UT_LINESIZE; j++)
tem.ut_line[j] = in.readByte();
in.seek(loc+84);
for (int j = 0; j < 4; j++)
tem.ut_id[j] = in.readByte();
in.seek(loc+88);
for (int j = 0; j < utmp.UT_NAMESIZE; j++)
tem.ut_user[j] = in.readByte();
in.seek(loc+120);
for (int j = 0; j < utmp.UT_HOSTSIZE; j++)
tem.ut_host[j] = in.readByte();
没到一个位置就使用seek函数调整指针(对齐偏移printf("pid^%d^\n",(unsigned int)&utbufp->ut_pid-(unsigned int)&utbufp)通过上面这个printf获得)
但是最终结果令人失望,读取失败,求大大帮忙指点下哪里有问题啊
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
-**--*-
咋失败的呢?
######
咋失败的呢?
读取的数据不对啊,比较囧,难道是位置不对
######
咋失败的呢?
utmp结构的 ut_type项,也就是第一项,相对位置就是44,表示很不理解
######代码分享中也找不到读取utmp的java代码,哈哈这是新血液啊,求集思广益,解决问题
######搜了下google,有一个问题很相似
I have to code a Java program that will receive messages from network and display their content to the user. The problem is that the messages that I receive are simply binary dumps of C structures. Add to this some of the messages are coming from little endian machines and some from big endian without the fields being converted to network byte order. One way I have is to use JNI and convert c structs to some XML string and then de serialize this XML string to a Java Object. This is a laborous job since there about 122 different structs and each one of them contains more than 20 fields. I wonder if there is a library/tool/methodology which could make my job a bit easy ?
Swig will handle a lot of the tedious repetitive work for you in terms of mapping the C structs to Java objects. Check out the Swig/Java manual and the entry on wrapping C structures.
There is a library called Preon that was designed to help you with this type of task: Preon site Basically, they try to keep all the logic for reading your pojo's from the binary stream in annotations tied to each field in your pojo.
An example from their docs where you control the size of the int you are reading:
class Rectangle
{
@BoundNumber(size="16") private int x1;
@BoundNumber(size="16") private int y1;
@BoundNumber(size="16") private int x2;
@BoundNumber(size="16") private int y2;
}
or to specify endianness:
class Rectangle
{
@BoundNumber(byteOrder=LittleEndian) private int x1;
@BoundNumber(byteOrder=LittleEndian) private int y1;
@BoundNumber(byteOrder=LittleEndian) private int x2;
@BoundNumber(byteOrder=LittleEndian) private int y2;
}
You can even use mini-equations with references to values in previous fields to specify size / length, etc.
@BoundList(size="width * height") byte[] pixels;
@BoundNumber(size="nrBits * 2") int value;
Oh, and they also offer conditional logic, all in annotations.
java.nio has ByteBuffer, which supports flipping byte order when reading and writing, on-the-fly if necessary.
######结贴结贴 问题已解决