X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=unfs3%2Flocate.c;fp=unfs3%2Flocate.c;h=c5ed21937fa546b05ab161a4191839a15c685c2a;hb=1ddb92b899989e26e26a4491251d4bc61be22918;hp=0000000000000000000000000000000000000000;hpb=af6b53b5ca2a8493dd5caca8a3a134a46b03272e;p=unfs3 diff --git a/unfs3/locate.c b/unfs3/locate.c new file mode 100644 index 0000000..c5ed219 --- /dev/null +++ b/unfs3/locate.c @@ -0,0 +1,171 @@ + +/* + * UNFS3 brute force file search + * (C) 2004, Pascal Schmidt + * see file LICENSE for license details + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_MNTENT_H == 1 +#include +#endif + +#if HAVE_SYS_MNTTAB_H == 1 +#include +#endif + +#include "nfs.h" +#include "fh.h" +#include "daemon.h" + +/* + * these are the brute-force file searching routines that are used + * when both the filehandle cache and the hashed path inside the + * filehandle are unable to locate the file + * + * this can only happen if a file was rename(3)'d across directories + * + * these routines are slow, but better than returning ESTALE to + * clients + */ + +#if HAVE_MNTENT_H == 1 || HAVE_SYS_MNTTAB_H == 1 + +/* + * locate file given prefix, device, and inode number + */ +static int locate_pfx(const char *pfx, uint32 dev, uint64 ino, char *result) +{ + char path[NFS_MAXPATHLEN]; + backend_dirstream *search; + struct dirent *ent; + struct stat buf; + int res; + + search = opendir(pfx); + if (!search) + return FALSE; + + while ((ent = readdir(search))) { + if (strlen(pfx) + strlen(ent->d_name) + 2 >= NFS_MAXPATHLEN) + continue; + + sprintf(path, "%s/%s", pfx, ent->d_name); + + res = lstat(path, &buf); + if (res != 0) + continue; + + /* check for matching object */ + if (buf.st_dev == dev && buf.st_ino == ino) { + strcpy(result, path); + st_cache = buf; + st_cache_valid = TRUE; + closedir(search); + return TRUE; + } + + /* descend into directories with same dev */ + if (buf.st_dev == dev && S_ISDIR(buf.st_mode) && + strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { + res = locate_pfx(path, dev, ino, result); + if (res == TRUE) { + closedir(search); + return TRUE; + } + } + } + + closedir(search); + return FALSE; +} +#endif + +/* + * locate file given device and inode number + * + * slow fallback in case other filehandle resolution functions fail + */ +char *locate_file(U(uint32 dev), U(uint64 ino)) +{ +#if HAVE_MNTENT_H == 1 || HAVE_SYS_MNTTAB_H == 1 + static char path[NFS_MAXPATHLEN]; + FILE *mtab; + struct stat buf; + int res; +#endif + +#if HAVE_MNTENT_H == 1 + struct mntent *ent; +#endif + +#if HAVE_SYS_MNTTAB_H == 1 + struct mnttab ent; + int found = FALSE; +#endif + + if (!opt_brute_force) + return NULL; + +#if HAVE_MNTENT_H == 1 + mtab = setmntent("/etc/mtab", "r"); + if (!mtab) + return NULL; + + /* + * look for mtab entry with matching device + */ + while ((ent = getmntent(mtab))) { + res = lstat(ent->mnt_dir, &buf); + + if (res == 0 && buf.st_dev == dev) + break; + } + endmntent(mtab); + + /* found matching entry? */ + if (ent) { + res = locate_pfx(ent->mnt_dir, dev, ino, path); + if (res == TRUE) + return path; + } +#endif + +#if HAVE_SYS_MNTTAB_H == 1 + mtab = fopen("/etc/mnttab", "r"); + if (!mtab) + return NULL; + + /* + * look for mnttab entry with matching device + */ + while (getmntent(mtab, &ent) == 0) { + res = lstat(ent.mnt_mountp, &buf); + + if (res == 0 && buf.st_dev == dev) { + found = TRUE; + break; + } + } + fclose(mtab); + + /* found matching entry? */ + if (found) { + res = locate_pfx(ent.mnt_mountp, dev, ino, path); + if (res == TRUE) + return path; + } +#endif + + return NULL; +}