checkpoint - simpler namei interface
This commit is contained in:
parent
ef30c2c749
commit
e2a620da49
4 changed files with 136 additions and 122 deletions
6
defs.h
6
defs.h
|
@ -128,12 +128,14 @@ void itrunc(struct inode*);
|
||||||
void idecref(struct inode*);
|
void idecref(struct inode*);
|
||||||
struct inode* iincref(struct inode*);
|
struct inode* iincref(struct inode*);
|
||||||
void iput(struct inode*);
|
void iput(struct inode*);
|
||||||
struct inode* namei(char*, int, uint*, char**, struct inode**);
|
struct inode* namei(char*);
|
||||||
|
struct inode* nameiparent(char*, char**, int*);
|
||||||
void stati(struct inode*, struct stat*);
|
void stati(struct inode*, struct stat*);
|
||||||
int readi(struct inode*, char*, uint, uint);
|
int readi(struct inode*, char*, uint, uint);
|
||||||
int writei(struct inode*, char*, uint, uint);
|
int writei(struct inode*, char*, uint, uint);
|
||||||
struct inode* mknod(char*, short, short, short);
|
struct inode* mknod(char*, short, short, short);
|
||||||
struct inode* mknod1(struct inode*, char*, short, short, short);
|
struct inode* dircreat(struct inode*, char*, int, short, short, short);
|
||||||
|
int dirlookup(struct inode*, char*, int, uint*, uint*);
|
||||||
int unlink(char*);
|
int unlink(char*);
|
||||||
void iupdate(struct inode*);
|
void iupdate(struct inode*);
|
||||||
int link(char*, char*);
|
int link(char*, char*);
|
||||||
|
|
158
fs.c
158
fs.c
|
@ -465,7 +465,7 @@ writei(struct inode *ip, char *src, uint off, uint n)
|
||||||
// set *poff to the byte offset of the directory entry
|
// set *poff to the byte offset of the directory entry
|
||||||
// set *pinum to the inode number
|
// set *pinum to the inode number
|
||||||
// return 0.
|
// return 0.
|
||||||
static int
|
int
|
||||||
dirlookup(struct inode *dp, char *name, int namelen, uint *poff, uint *pinum)
|
dirlookup(struct inode *dp, char *name, int namelen, uint *poff, uint *pinum)
|
||||||
{
|
{
|
||||||
uint off;
|
uint off;
|
||||||
|
@ -485,7 +485,9 @@ dirlookup(struct inode *dp, char *name, int namelen, uint *poff, uint *pinum)
|
||||||
if(memcmp(name, de->name, namelen) == 0 &&
|
if(memcmp(name, de->name, namelen) == 0 &&
|
||||||
(namelen == DIRSIZ || de->name[namelen]== 0)){
|
(namelen == DIRSIZ || de->name[namelen]== 0)){
|
||||||
// entry matches path element
|
// entry matches path element
|
||||||
|
if(poff)
|
||||||
*poff = off + (uchar*)de - bp->data;
|
*poff = off + (uchar*)de - bp->data;
|
||||||
|
if(pinum)
|
||||||
*pinum = de->inum;
|
*pinum = de->inum;
|
||||||
brelse(bp);
|
brelse(bp);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -499,9 +501,9 @@ dirlookup(struct inode *dp, char *name, int namelen, uint *poff, uint *pinum)
|
||||||
// Write a new directory entry (name, ino) into the directory dp.
|
// Write a new directory entry (name, ino) into the directory dp.
|
||||||
// Caller must have locked dp.
|
// Caller must have locked dp.
|
||||||
void
|
void
|
||||||
dirwrite(struct inode *dp, char *name, uint ino)
|
dirwrite(struct inode *dp, char *name, int namelen, uint ino)
|
||||||
{
|
{
|
||||||
int i, off;
|
int off;
|
||||||
struct dirent de;
|
struct dirent de;
|
||||||
|
|
||||||
// Look for an empty dirent.
|
// Look for an empty dirent.
|
||||||
|
@ -513,15 +515,37 @@ dirwrite(struct inode *dp, char *name, uint ino)
|
||||||
}
|
}
|
||||||
|
|
||||||
de.inum = ino;
|
de.inum = ino;
|
||||||
for(i = 0; i < DIRSIZ && name[i]; i++)
|
if(namelen > DIRSIZ)
|
||||||
de.name[i] = name[i];
|
namelen = DIRSIZ;
|
||||||
for(; i < DIRSIZ; i++)
|
memmove(de.name, name, namelen);
|
||||||
de.name[i] = '\0';
|
memset(de.name+namelen, 0, DIRSIZ-namelen);
|
||||||
|
|
||||||
if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
|
if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
|
||||||
panic("dirwrite");
|
panic("dirwrite");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new inode named name inside dp
|
||||||
|
// and return its locked inode structure.
|
||||||
|
// If name already exists, return 0.
|
||||||
|
struct inode*
|
||||||
|
dircreat(struct inode *dp, char *name, int namelen, short type, short major, short minor)
|
||||||
|
{
|
||||||
|
struct inode *ip;
|
||||||
|
|
||||||
|
ip = ialloc(dp->dev, type);
|
||||||
|
if(ip == 0)
|
||||||
|
return 0;
|
||||||
|
ip->major = major;
|
||||||
|
ip->minor = minor;
|
||||||
|
ip->size = 0;
|
||||||
|
ip->nlink = 1;
|
||||||
|
iupdate(ip);
|
||||||
|
|
||||||
|
dirwrite(dp, name, namelen, ip->inum);
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
// Paths
|
// Paths
|
||||||
|
|
||||||
// Skip over the next path element in path,
|
// Skip over the next path element in path,
|
||||||
|
@ -564,21 +588,13 @@ skipelem(char *path, char **name, int *len)
|
||||||
// NAMEI_DELETE: return locked parent inode, offset of dirent in *ret_off.
|
// NAMEI_DELETE: return locked parent inode, offset of dirent in *ret_off.
|
||||||
// return 0 if name doesn't exist.
|
// return 0 if name doesn't exist.
|
||||||
struct inode*
|
struct inode*
|
||||||
namei(char *path, int mode, uint *ret_off,
|
_namei(char *path, int parent, char **pname, int *pnamelen)
|
||||||
char **ret_last, struct inode **ret_ip)
|
|
||||||
{
|
{
|
||||||
struct inode *dp;
|
struct inode *dp;
|
||||||
char *name;
|
char *name;
|
||||||
int namelen;
|
int namelen;
|
||||||
uint off, dev, inum;
|
uint off, dev, inum;
|
||||||
|
|
||||||
if(ret_off)
|
|
||||||
*ret_off = 0xffffffff;
|
|
||||||
if(ret_last)
|
|
||||||
*ret_last = 0;
|
|
||||||
if(ret_ip)
|
|
||||||
*ret_ip = 0;
|
|
||||||
|
|
||||||
if(*path == '/')
|
if(*path == '/')
|
||||||
dp = igetroot();
|
dp = igetroot();
|
||||||
else {
|
else {
|
||||||
|
@ -594,23 +610,15 @@ namei(char *path, int mode, uint *ret_off,
|
||||||
if(dp->type != T_DIR)
|
if(dp->type != T_DIR)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if(dirlookup(dp, name, namelen, &off, &inum) < 0){
|
if(parent && *path == '\0'){
|
||||||
if(mode == NAMEI_CREATE && *path == '\0'){
|
// Stop one level early.
|
||||||
*ret_last = name;
|
*pname = name;
|
||||||
|
*pnamelen = namelen;
|
||||||
return dp;
|
return dp;
|
||||||
}
|
}
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mode == NAMEI_DELETE && *path == '\0'){
|
if(dirlookup(dp, name, namelen, &off, &inum) < 0)
|
||||||
// can't unlink . and ..
|
|
||||||
if((namelen == 1 && memcmp(name, ".", 1) == 0) ||
|
|
||||||
(namelen == 2 && memcmp(name, "..", 2) == 0)){
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
|
||||||
*ret_off = off;
|
|
||||||
return dp;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev = dp->dev;
|
dev = dp->dev;
|
||||||
iput(dp);
|
iput(dp);
|
||||||
|
@ -618,58 +626,46 @@ namei(char *path, int mode, uint *ret_off,
|
||||||
if(dp->type == 0 || dp->nlink < 1)
|
if(dp->type == 0 || dp->nlink < 1)
|
||||||
panic("namei");
|
panic("namei");
|
||||||
}
|
}
|
||||||
|
if(parent)
|
||||||
if(mode == NAMEI_LOOKUP)
|
|
||||||
return dp;
|
|
||||||
if(mode == NAMEI_CREATE && ret_ip){
|
|
||||||
*ret_ip = dp;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
return dp;
|
||||||
goto fail;
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
iput(dp);
|
iput(dp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct inode*
|
||||||
|
namei(char *path)
|
||||||
|
{
|
||||||
|
return _namei(path, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct inode*
|
||||||
|
nameiparent(char *path, char **name, int *namelen)
|
||||||
|
{
|
||||||
|
return _namei(path, 1, name, namelen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Create the path and return its locked inode structure.
|
// Create the path and return its locked inode structure.
|
||||||
// If cp already exists, return 0.
|
// If cp already exists, return 0.
|
||||||
struct inode*
|
struct inode*
|
||||||
mknod(char *path, short type, short major, short minor)
|
mknod(char *path, short type, short major, short minor)
|
||||||
{
|
{
|
||||||
struct inode *ip, *dp;
|
struct inode *ip, *dp;
|
||||||
char *last;
|
char *name;
|
||||||
|
int namelen;
|
||||||
|
|
||||||
if((dp = namei(path, NAMEI_CREATE, 0, &last, 0)) == 0)
|
if((dp = nameiparent(path, &name, &namelen)) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
if(dirlookup(dp, name, namelen, 0, 0) >= 0){
|
||||||
ip = mknod1(dp, last, type, major, minor);
|
|
||||||
|
|
||||||
iput(dp);
|
iput(dp);
|
||||||
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new inode named name inside dp
|
|
||||||
// and return its locked inode structure.
|
|
||||||
// If name already exists, return 0.
|
|
||||||
struct inode*
|
|
||||||
mknod1(struct inode *dp, char *name, short type, short major, short minor)
|
|
||||||
{
|
|
||||||
struct inode *ip;
|
|
||||||
|
|
||||||
ip = ialloc(dp->dev, type);
|
|
||||||
if(ip == 0)
|
|
||||||
return 0;
|
return 0;
|
||||||
ip->major = major;
|
}
|
||||||
ip->minor = minor;
|
ip = dircreat(dp, name, namelen, type, major, minor);
|
||||||
ip->size = 0;
|
iput(dp);
|
||||||
ip->nlink = 1;
|
|
||||||
|
|
||||||
iupdate(ip); // write new inode to disk
|
|
||||||
|
|
||||||
dirwrite(dp, name, ip->inum);
|
|
||||||
|
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -680,12 +676,15 @@ unlink(char *path)
|
||||||
struct inode *ip, *dp;
|
struct inode *ip, *dp;
|
||||||
struct dirent de;
|
struct dirent de;
|
||||||
uint off, inum, dev;
|
uint off, inum, dev;
|
||||||
|
char *name;
|
||||||
|
int namelen;
|
||||||
|
|
||||||
dp = namei(path, NAMEI_DELETE, &off, 0, 0);
|
if((dp = nameiparent(path, &name, &namelen)) == 0)
|
||||||
if(dp == 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
if(dirlookup(dp, name, namelen, &off, 0) < 0){
|
||||||
dev = dp->dev;
|
iput(dp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de) || de.inum == 0)
|
if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de) || de.inum == 0)
|
||||||
panic("unlink no entry");
|
panic("unlink no entry");
|
||||||
|
@ -702,16 +701,13 @@ unlink(char *path)
|
||||||
if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
|
if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
|
||||||
panic("unlink dir write");
|
panic("unlink dir write");
|
||||||
|
|
||||||
iupdate(dp);
|
dev = dp->dev;
|
||||||
iput(dp);
|
iput(dp);
|
||||||
|
|
||||||
ip = iget(dev, inum);
|
ip = iget(dev, inum);
|
||||||
|
|
||||||
if(ip->nlink < 1)
|
if(ip->nlink < 1)
|
||||||
panic("unlink nlink < 1");
|
panic("unlink nlink < 1");
|
||||||
|
|
||||||
ip->nlink--;
|
ip->nlink--;
|
||||||
|
|
||||||
iupdate(ip);
|
iupdate(ip);
|
||||||
iput(ip);
|
iput(ip);
|
||||||
|
|
||||||
|
@ -720,21 +716,26 @@ unlink(char *path)
|
||||||
|
|
||||||
// Create the path new as a link to the same inode as old.
|
// Create the path new as a link to the same inode as old.
|
||||||
int
|
int
|
||||||
link(char *name1, char *name2)
|
link(char *old, char *new)
|
||||||
{
|
{
|
||||||
struct inode *ip, *dp;
|
struct inode *ip, *dp;
|
||||||
char *last;
|
char *name;
|
||||||
|
int namelen;
|
||||||
|
|
||||||
if((ip = namei(name1, NAMEI_LOOKUP, 0, 0, 0)) == 0)
|
if((ip = namei(old)) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
if(ip->type == T_DIR){
|
if(ip->type == T_DIR){
|
||||||
iput(ip);
|
iput(ip);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
iunlock(ip);
|
iunlock(ip);
|
||||||
|
|
||||||
if((dp = namei(name2, NAMEI_CREATE, 0, &last, 0)) == 0) {
|
if((dp = nameiparent(new, &name, &namelen)) == 0){
|
||||||
|
idecref(ip);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(dirlookup(dp, name, namelen, 0, 0) >= 0){
|
||||||
|
iput(dp);
|
||||||
idecref(ip);
|
idecref(ip);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -744,11 +745,12 @@ link(char *name1, char *name2)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LOCKING ERROR HERE! TWO LOCKS HELD AT ONCE.
|
||||||
ilock(ip);
|
ilock(ip);
|
||||||
ip->nlink++;
|
ip->nlink++;
|
||||||
iupdate(ip);
|
iupdate(ip);
|
||||||
|
|
||||||
dirwrite(dp, last, ip->inum);
|
dirwrite(dp, name, namelen, ip->inum);
|
||||||
iput(dp);
|
iput(dp);
|
||||||
iput(ip);
|
iput(ip);
|
||||||
|
|
||||||
|
|
13
proc.c
13
proc.c
|
@ -203,7 +203,6 @@ scheduler(void)
|
||||||
void
|
void
|
||||||
sched(void)
|
sched(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(cp->state == RUNNING)
|
if(cp->state == RUNNING)
|
||||||
panic("sched running");
|
panic("sched running");
|
||||||
if(!holding(&proc_table_lock))
|
if(!holding(&proc_table_lock))
|
||||||
|
@ -219,7 +218,6 @@ sched(void)
|
||||||
void
|
void
|
||||||
yield(void)
|
yield(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
acquire(&proc_table_lock);
|
acquire(&proc_table_lock);
|
||||||
cp->state = RUNNABLE;
|
cp->state = RUNNABLE;
|
||||||
sched();
|
sched();
|
||||||
|
@ -422,9 +420,10 @@ procdump(void)
|
||||||
[RUNNING] "run ",
|
[RUNNING] "run ",
|
||||||
[ZOMBIE] "zombie"
|
[ZOMBIE] "zombie"
|
||||||
};
|
};
|
||||||
int i;
|
int i, j;
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
char *state;
|
char *state;
|
||||||
|
uint pc[10];
|
||||||
|
|
||||||
for(i = 0; i < NPROC; i++) {
|
for(i = 0; i < NPROC; i++) {
|
||||||
p = &proc[i];
|
p = &proc[i];
|
||||||
|
@ -434,7 +433,13 @@ procdump(void)
|
||||||
state = states[p->state];
|
state = states[p->state];
|
||||||
else
|
else
|
||||||
state = "???";
|
state = "???";
|
||||||
cprintf("%d %s %s\n", p->pid, state, p->name);
|
cprintf("%d %s %s", p->pid, state, p->name);
|
||||||
|
if(p->state == SLEEPING) {
|
||||||
|
getcallerpcs((uint*)p->jmpbuf.ebp+2, pc);
|
||||||
|
for(j=0; j<10 && pc[j] != 0; j++)
|
||||||
|
cprintf(" %p", pc[j]);
|
||||||
|
}
|
||||||
|
cprintf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
67
sysfile.c
67
sysfile.c
|
@ -115,34 +115,41 @@ int
|
||||||
sys_open(void)
|
sys_open(void)
|
||||||
{
|
{
|
||||||
struct inode *ip, *dp;
|
struct inode *ip, *dp;
|
||||||
char *path;
|
char *path, *name;
|
||||||
|
int namelen;
|
||||||
int omode;
|
int omode;
|
||||||
int fd;
|
int fd, dev;
|
||||||
|
uint inum;
|
||||||
struct file *f;
|
struct file *f;
|
||||||
char *last;
|
|
||||||
|
|
||||||
if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
|
if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(omode & O_CREATE){
|
switch(omode & O_CREATE){
|
||||||
dp = namei(path, NAMEI_CREATE, 0, &last, &ip);
|
default:
|
||||||
if(dp){
|
case 0: // regular open
|
||||||
ip = mknod1(dp, last, T_FILE, 0, 0);
|
if((ip = namei(path)) == 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case O_CREATE:
|
||||||
|
if((dp = nameiparent(path, &name, &namelen)) == 0)
|
||||||
|
return -1;
|
||||||
|
if(dirlookup(dp, name, namelen, 0, &inum) >= 0){
|
||||||
|
dev = dp->dev;
|
||||||
iput(dp);
|
iput(dp);
|
||||||
if(ip == 0)
|
ip = iget(dev, inum);
|
||||||
return -1;
|
|
||||||
} else if(ip == 0){
|
|
||||||
return -1;
|
|
||||||
} else if(ip->type == T_DIR){
|
|
||||||
iput(ip);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}else{
|
}else{
|
||||||
ip = namei(path, NAMEI_LOOKUP, 0, 0, 0);
|
if((ip = dircreat(dp, name, namelen, T_FILE, 0, 0)) == 0){
|
||||||
if(ip == 0)
|
iput(dp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(ip->type == T_DIR && ((omode & O_RDWR) || (omode & O_WRONLY))){
|
iput(dp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ip->type == T_DIR && (omode & (O_RDWR|O_WRONLY|O_CREATE))){
|
||||||
iput(ip);
|
iput(ip);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -201,18 +208,22 @@ sys_mkdir(void)
|
||||||
{
|
{
|
||||||
struct inode *nip;
|
struct inode *nip;
|
||||||
struct inode *dp;
|
struct inode *dp;
|
||||||
char *path;
|
char *name, *path;
|
||||||
struct dirent de;
|
struct dirent de;
|
||||||
char *last;
|
int namelen;
|
||||||
|
|
||||||
if(argstr(0, &path) < 0)
|
if(argstr(0, &path) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
dp = namei(path, NAMEI_CREATE, 0, &last, 0);
|
dp = nameiparent(path, &name, &namelen);
|
||||||
if(dp == 0)
|
if(dp == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
if(dirlookup(dp, name, namelen, 0, 0) >= 0){
|
||||||
|
iput(dp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
nip = mknod1(dp, last, T_DIR, 0, 0);
|
nip = dircreat(dp, name, namelen, T_DIR, 0, 0);
|
||||||
if(nip == 0){
|
if(nip == 0){
|
||||||
iput(dp);
|
iput(dp);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -245,22 +256,17 @@ sys_chdir(void)
|
||||||
if(argstr(0, &path) < 0)
|
if(argstr(0, &path) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if((ip = namei(path, NAMEI_LOOKUP, 0, 0, 0)) == 0)
|
if((ip = namei(path)) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(ip == cp->cwd) {
|
|
||||||
iput(ip);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ip->type != T_DIR) {
|
if(ip->type != T_DIR) {
|
||||||
iput(ip);
|
iput(ip);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iunlock(ip);
|
||||||
idecref(cp->cwd);
|
idecref(cp->cwd);
|
||||||
cp->cwd = ip;
|
cp->cwd = ip;
|
||||||
iunlock(cp->cwd);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,8 +330,7 @@ sys_exec(void)
|
||||||
if(argstr(0, &path) < 0 || argint(1, (int*)&argv) < 0)
|
if(argstr(0, &path) < 0 || argint(1, (int*)&argv) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ip = namei(path, NAMEI_LOOKUP, 0, 0, 0);
|
if((ip = namei(path)) == 0)
|
||||||
if(ip == 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
|
if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
|
||||||
|
|
Loading…
Reference in a new issue