In article <82b9qt$8uv$[EMAIL PROTECTED]> you wrote:
> I am trying to find a way to get the full pathname from a dentry
> refering a file. I tried d_path, and in one occasion I got
> nothing, and in the other I got rubbish, then the path
> I was expecting, and then (deleted).
I implemented that. Any comment ? It seems to work in my application
(albeit I couldn't test locking and parallelism issues).
/* NAME
* dentry_get_path
* DESCRIPTION
* Writes the complete NUL terminated path, including /,
* to the given buffer, in the usual order. The function
* doesn't sleep. The buffer is a kernel-space buffer,
* which can be accessed directly.
* RESULT
* 0 operation succeeded.
* -ENOMEM buffer was too small, buffer can't be considered.
* -EIO integrity failure when evaluating path, buffer can't be
* considered.
* NOTES
* - We do not lock the dentries since we assume we will not
* sleep at all. This is maybe wrong in SMP.
* - We remove all the leading /.
* BUGS
* TODO
*/
static int dentry_get_path(mfs_dentry_t *dentry,
char *buffer,
int buffer_length);
static int dentry_get_path(mfs_dentry_t *dentry,
char *buffer,
int buffer_length) {
char *after_buffer_address = buffer + buffer_length; /* is OUTSIDE ! */
char *last_address = after_buffer_address;
while (dentry) {
int element_size = dentry->d_name.len + 1;
/* The +1 either accounts for the preceeding / or the last NUL */
if (element_size == 1) {
return -EIO;
}
else if (element_size > buffer_length) {
return -ENOMEM;
}
else {
after_buffer_address -= element_size;
/* Thus, we now reserved from current..last_current */
buffer_length -= element_size;
memcpy(after_buffer_address + 1,
dentry->d_name.name,
dentry->d_name.len);
*after_buffer_address = '/';
printk("[%s] %d\n", dentry->d_name.name, dentry->d_name.len);
}
if (dentry == dentry->d_parent) {
dentry = NULL;
}
else {
dentry = dentry->d_parent;
}
}
/* Now shift the buffer, ignoring all the first / */
while ((after_buffer_address < last_address)
&& (*after_buffer_address == '/')) {
after_buffer_address++;
}
/* We could have used memcpy if we were sure it was supporting
* overlapped copies.
*/
while (after_buffer_address < last_address) {
*buffer = *after_buffer_address;
buffer++;
after_buffer_address++;
}
*buffer = '\0'; /* and finish the buffer. There is room because of the
* initial removed /.
*/
return 0;
}