noux: calculate inode value from path
There are programms that use struct stat's st_ino field to check certain conditions. Since we are using multiple filesystems in a noux session we cannot use the inode number which the actual filesystem provides. Therefore we calculate a random inode number by hashing the stated path. Fixes #299.
This commit is contained in:
parent
bde7e24820
commit
8b8e3ef7a5
|
@ -168,6 +168,14 @@ namespace Noux {
|
||||||
h; h = h->next())
|
h; h = h->next())
|
||||||
h->handle_interrupt();
|
h->handle_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path of the file associated with the I/O channel
|
||||||
|
*
|
||||||
|
* This function is used to simplify the implemenation of SYSCALL_FSTAT
|
||||||
|
* and is only implemented by Vfs_io_channel.
|
||||||
|
*/
|
||||||
|
virtual bool path(char *path, size_t len) { return false; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,23 @@ namespace Noux {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is used to generate inode values from the given
|
||||||
|
* path using the FNV-1a algorithm.
|
||||||
|
*/
|
||||||
|
inline uint32_t hash_path(const char *path, size_t len)
|
||||||
|
{
|
||||||
|
const unsigned char * p = reinterpret_cast<const unsigned char*>(path);
|
||||||
|
uint32_t hash = 2166136261U;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
hash ^= p[i];
|
||||||
|
hash *= 16777619;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -195,6 +212,13 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
||||||
case SYSCALL_STAT:
|
case SYSCALL_STAT:
|
||||||
case SYSCALL_LSTAT: /* XXX implement difference between 'lstat' and 'stat' */
|
case SYSCALL_LSTAT: /* XXX implement difference between 'lstat' and 'stat' */
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* We calculate the inode by hashing the path because there is
|
||||||
|
* no inode registry in noux.
|
||||||
|
*/
|
||||||
|
size_t path_len = strlen(_sysio->stat_in.path);
|
||||||
|
uint32_t path_hash = hash_path(_sysio->stat_in.path, path_len);
|
||||||
|
|
||||||
bool result = root_dir()->stat(_sysio, _sysio->stat_in.path);
|
bool result = root_dir()->stat(_sysio, _sysio->stat_in.path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -204,14 +228,35 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
||||||
if (result) {
|
if (result) {
|
||||||
_sysio->stat_out.st.uid = user_info()->uid;
|
_sysio->stat_out.st.uid = user_info()->uid;
|
||||||
_sysio->stat_out.st.gid = user_info()->gid;
|
_sysio->stat_out.st.gid = user_info()->gid;
|
||||||
|
|
||||||
|
_sysio->stat_out.st.inode = path_hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SYSCALL_FSTAT:
|
case SYSCALL_FSTAT:
|
||||||
|
{
|
||||||
|
Shared_pointer<Io_channel> io = _lookup_channel(_sysio->fstat_in.fd);
|
||||||
|
|
||||||
return _lookup_channel(_sysio->fstat_in.fd)->fstat(_sysio);
|
bool result = io->fstat(_sysio);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
Sysio::Path path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only actual fd's are valid fstat targets.
|
||||||
|
*/
|
||||||
|
if (io->path(path, sizeof (path))) {
|
||||||
|
size_t path_len = strlen(path);
|
||||||
|
uint32_t path_hash = hash_path(path, path_len);
|
||||||
|
|
||||||
|
_sysio->stat_out.st.inode = path_hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
case SYSCALL_FCNTL:
|
case SYSCALL_FCNTL:
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,14 @@ namespace Noux {
|
||||||
return _fh->fs()->check_unblock(_fh, rd, wr, ex);
|
return _fh->fs()->check_unblock(_fh, rd, wr, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool path(char *path, size_t len)
|
||||||
|
{
|
||||||
|
strncpy(path, _path.base(), len);
|
||||||
|
path[len - 1] = '\0';
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************
|
/**************************************
|
||||||
** Signal_dispatcher_base interface **
|
** Signal_dispatcher_base interface **
|
||||||
**************************************/
|
**************************************/
|
||||||
|
@ -183,7 +191,6 @@ namespace Noux {
|
||||||
{
|
{
|
||||||
Io_channel::invoke_all_notifiers();
|
Io_channel::invoke_all_notifiers();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user