lhp = IH_OPEN(V_linkHandle(vp));
if (!lhp)
return EIO;
-#ifdef AFS_NT40_ENV
- *lc = nt_GetLinkCount(lhp, fdP->fd_ih->ih_ino, 0);
-#else
- *lc = namei_GetLinkCount(lhp, fdP->fd_ih->ih_ino, 0);
-#endif
+ *lc = namei_GetLinkCount(lhp, fdP->fd_ih->ih_ino, 0, 0, 1);
FDH_CLOSE(lhp);
if (*lc < 0)
return -1;
$(INCFILEDIR)\afs\fssync.h \
$(INCFILEDIR)\afs\ihandle.h \
$(INCFILEDIR)\afs\nfs.h \
+ $(INCFILEDIR)\afs\namei_ops.h \
$(INCFILEDIR)\afs\ntops.h \
$(INCFILEDIR)\afs\partition.h \
$(INCFILEDIR)\afs\viceinode.h \
$(OUT)\fssync-client.obj \
$(OUT)\fssync-server.obj \
$(OUT)\daemon_com.obj \
+ $(OUT)\namei_ops.obj \
$(OUT)\ntops.obj \
$(OUT)\nuke.obj \
$(OUT)\partition.obj \
$(OUT)\fssync-client_mt.obj \
$(OUT)\fssync-server_mt.obj \
$(OUT)\daemon_com_mt.obj \
+ $(OUT)\namei_ops.obj \
$(OUT)\ntops.obj \
$(OUT)\nuke_mt.obj \
$(OUT)\partition_mt.obj \
$(OUT)\fssync-client_dafs.obj \
$(OUT)\fssync-server_dafs.obj \
$(OUT)\daemon_com_dafs.obj \
+ $(OUT)\namei_ops.obj \
$(OUT)\ntops.obj \
$(OUT)\nuke_dafs.obj \
$(OUT)\partition_dafs.obj \
}
#endif /* AFS_NAMEI_ENV */
-
-#ifndef AFS_NT40_ENV
afs_sfsize_t
-ih_size(int fd)
+ih_size(FD_t fd)
{
+#ifdef AFS_NT40_ENV
+ LARGE_INTEGER size;
+ if (!GetFileSizeEx(fd, &size))
+ return -1;
+ return size.QuadPart;
+#else
struct afs_stat status;
if (afs_fstat(fd, &status) < 0)
return -1;
return status.st_size;
-}
#endif
+}
#ifndef HAVE_PIO
ssize_t
* FDH_REALLYCLOSE - Close a file descriptor, do not return to the cache
* FDH_SYNC - Unconditionally sync an open file.
* FDH_TRUNC - Truncate a file
+ * FDH_LOCKFILE - Lock a whole file
+ * FDH_UNLOCKFILE - Unlock a whole file
*
* status information:
* FDH_SIZE - returns the size of the file.
*/
#ifdef AFS_NT40_ENV
typedef HANDLE FD_t;
+#define INVALID_FD INVALID_HANDLE_VALUE
#else
typedef int FD_t;
-#endif
#define INVALID_FD ((FD_t)-1)
+#endif
/* file descriptor handle */
typedef struct FdHandle_s {
#ifdef AFS_NAMEI_ENV
#ifdef AFS_NT40_ENV
#include "ntops.h"
-#else
-#include "namei_ops.h"
#endif
+#include "namei_ops.h"
+
extern void ih_clear(IHandle_t * h);
extern Inode ih_create(IHandle_t * h, int dev, char *part, Inode nI, int p1,
int p2, int p3, int p4);
#ifdef AFS_NAMEI_ENV
#ifdef AFS_NT40_ENV
-#define IH_CREATE(H, D, P, N, P1, P2, P3, P4) \
- nt_icreate(H, P, P1, P2, P3, P4)
-
-#define OS_IOPEN(H) nt_iopen(H)
#define OS_OPEN(F, M, P) nt_open(F, M, P)
#define OS_CLOSE(FD) nt_close(FD)
#define OS_SYNC(FD) nt_fsync(FD)
#define OS_TRUNC(FD, L) nt_ftruncate(FD, L)
-#define OS_SIZE(FD) nt_size(FD)
-
-#define IH_INC(H, I, P) nt_inc(H, I, P)
-#define IH_DEC(H, I, P) nt_dec(H, I, P)
-#define IH_IREAD(H, O, B, S) nt_iread(H, O, B, S)
-#define IH_IWRITE(H, O, B, S) nt_iwrite(H, O, B, S)
#else /* AFS_NT40_ENV */
extern afs_sfsize_t IH_IWRITE(IHandle_t * H, afs_foff_t O, void *B,
afs_fsize_t S);
#ifdef O_LARGEFILE
-extern off64_t OS_SEEK(int FD, off64_t O, int F);
-extern int OS_TRUNC(int FD, off64_t L);
-#else /* !O_LARGEFILE */
-extern off_t OS_SEEK(int FD, off_t O, int F);
-extern int OS_TRUNC(int FD, off_t L);
-#endif /* !O_LARGEFILE */
-#endif /*S_SPLINT_S */
+#define OFFT off64_t
+#else
+#define OFFT off_t
+#endif
-#define IH_CREATE(H, D, P, N, P1, P2, P3, P4) \
- namei_icreate(H, P, P1, P2, P3, P4)
+extern OFFT OS_SEEK(int FD, OFFT O, int F);
+extern int OS_TRUNC(int FD, OFFT L);
+#endif /*S_SPLINT_S */
-#define OS_IOPEN(H) namei_iopen(H)
#ifdef O_LARGEFILE
#define OS_OPEN(F, M, P) open64(F, M, P)
#else /* !O_LARGEFILE */
#define OS_WRITE(FD, B, S) write(FD, B, S)
#ifdef O_LARGEFILE
#define OS_SEEK(FD, O, F) lseek64(FD, (off64_t) (O), F)
+#define OS_TRUNC(FD, L) ftruncate64(FD, (off64_t) (L))
#else /* !O_LARGEFILE */
#define OS_SEEK(FD, O, F) lseek(FD, (off_t) (O), F)
+#define OS_TRUNC(FD, L) ftruncate(FD, (off_t) (L))
#endif /* !O_LARGEFILE */
#define OS_SYNC(FD) fsync(FD)
-#ifdef O_LARGEFILE
-#define OS_TRUNC(FD, L) ftruncate64(FD, (off64_t) (L))
-#else /* !O_LARGEFILE */
-#define OS_TRUNC(FD, L) ftruncate(FD, (off_t) (L))
-#endif /* !O_LARGEFILE */
-#define OS_SIZE(FD) ih_size(FD)
-extern afs_sfsize_t ih_size(int fd);
+/*@=fcnmacros =macrofcndecl@*/
+#endif /* AFS_NT40_ENV */
#define IH_INC(H, I, P) namei_inc(H, I, P)
#define IH_DEC(H, I, P) namei_dec(H, I, P)
#define IH_IREAD(H, O, B, S) namei_iread(H, O, B, S)
#define IH_IWRITE(H, O, B, S) namei_iwrite(H, O, B, S)
-/*@=fcnmacros =macrofcndecl@*/
-#endif /* AFS_NT40_ENV */
+#define IH_CREATE(H, D, P, N, P1, P2, P3, P4) \
+ namei_icreate(H, P, P1, P2, P3, P4)
+#define OS_IOPEN(H) namei_iopen(H)
+
#else /* AFS_NAMEI_ENV */
extern Inode ih_icreate(IHandle_t * ih, int dev, char *part, Inode nI, int p1,
#ifdef O_LARGEFILE
#define OS_SEEK(FD, O, F) lseek64(FD, (off64_t) (O), F)
+#define OS_TRUNC(FD, L) ftruncate64(FD, (off64_t) (L))
#else /* !O_LARGEFILE */
#define OS_SEEK(FD, O, F) lseek(FD, (off_t) (O), F)
+#define OS_TRUNC(FD, L) ftruncate(FD, (off_t) (L))
#endif /* !O_LARGEFILE */
#define OS_SYNC(FD) fsync(FD)
-#ifdef O_LARGEFILE
-#define OS_TRUNC(FD, L) ftruncate64(FD, (off64_t) (L))
-#else /* !O_LARGEFILE */
-#define OS_TRUNC(FD, L) ftruncate(FD, (off_t) (L))
-#endif /* !O_LARGEFILE */
-#define OS_SIZE(FD) ih_size(FD)
-extern afs_sfsize_t ih_size(int fd);
#ifdef AFS_LINUX22_ENV
#define IH_INC(H, I, P) -1
#endif /* AFS_NAMEI_ENV */
+#define OS_SIZE(FD) ih_size(FD)
+extern afs_sfsize_t ih_size(FD_t);
#ifndef AFS_NT40_ENV
#define FDH_READV(H, I, N) readv((H)->fd_fd, I, N)
#define FDH_SYNC(H) ((H->fd_ih!=NULL) ? ( H->fd_ih->ih_synced = 1) - 1 : 1)
#define FDH_TRUNC(H, L) OS_TRUNC((H)->fd_fd, L)
#define FDH_SIZE(H) OS_SIZE((H)->fd_fd)
+#define FDH_LOCKFILE(H, O) OS_LOCKFILE((H)->fd_fd, O)
+#define FDH_UNLOCKFILE(H, O) OS_UNLOCKFILE((H)->fd_fd, O)
#endif /* _IHANDLE_H_ */
#ifdef AFS_NAMEI_ENV
#include <stdio.h>
#include <stdlib.h>
+#ifndef AFS_NT40_ENV
#include <unistd.h>
+#else
+#define DELETE_ZLC
+#include <io.h>
+#include <windows.h>
+#include <winnt.h>
+#include <winbase.h>
+#endif
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
+#ifdef AFS_NT40_ENV
+#include <direct.h>
+#else
+#include <sys/file.h>
+#include <sys/param.h>
+#endif
#include <dirent.h>
#include <afs/afs_assert.h>
#include <string.h>
-#include <sys/file.h>
-#include <sys/param.h>
#include <lock.h>
-#if defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV)
-#include <unistd.h>
-#endif
#include <afs/afsutil.h>
#include <lwp.h>
#include "nfs.h"
#include "volume_inline.h"
#include "common.h"
#include <afs/errors.h>
+#ifdef AFS_NT40_ENV
+#include <afs/errmap_nt.h>
+#endif
/*@+fcnmacros +macrofcndecl@*/
#ifdef O_LARGEFILE
#endif /*S_SPLINT_S */
#define afs_stat stat64
#define afs_fstat fstat64
+#ifdef AFS_NT40_ENV
+#define afs_open nt_open
+#else
#define afs_open open64
+#endif
#define afs_fopen fopen64
#else /* !O_LARGEFILE */
#ifdef S_SPLINT_S
#endif /*S_SPLINT_S */
#define afs_stat stat
#define afs_fstat fstat
+#ifdef AFS_NT40_ENV
+#define afs_open nt_open
+#else
#define afs_open open
+#endif
#define afs_fopen fopen
#endif /* !O_LARGEFILE */
/*@=fcnmacros =macrofcndecl@*/
#include <vol/vol-salvage.h>
#endif
-#ifndef HAVE_FLOCK
+#if !defined(HAVE_FLOCK) && !defined(AFS_NT40_ENV)
#include <fcntl.h>
/*
+#ifdef AFS_NT40_ENV
+/* Inode number format:
+ * low 32 bits - if a regular file or directory, the vnode. Else the type.
+ * 32-36 - unquifier tag and index into counts array for this vnode. Only
+ * two of the available bits are currently used. The rest are
+ * present in case we ever increase the number of types of volumes
+ * in the volume group.
+ * bit 37 : 1 == special, 0 == regular
+ */
+#define NAMEI_VNODEMASK 0x00ffffffff
+#define NAMEI_TAGSHIFT 32
+#define NAMEI_INODESPECIAL 0x2000000000
+#define NAMEI_SPECDIR "R"
+#else
/* Inode number format:
* low 26 bits - vnode number - all 1's if volume special file.
* next 3 bits - tag
* high 32 bits - uniquifier (regular) or type if spare
*/
#define NAMEI_VNODEMASK 0x003ffffff
-#define NAMEI_TAGMASK 0x7
#define NAMEI_TAGSHIFT 26
#define NAMEI_UNIQMASK 0xffffffff
#define NAMEI_UNIQSHIFT 32
#define NAMEI_INODESPECIAL ((Inode)NAMEI_VNODEMASK)
-#define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
-
/* dir1 is the high 8 bits of the 26 bit vnode */
#define VNO_DIR1(vno) ((vno >> 14) & 0xff)
/* dir2 is the next 9 bits */
#define VNO_DIR2(vno) ((vno >> 9) & 0x1ff)
/* "name" is the low 9 bits of the vnode, the 3 bit tag and the uniq */
-
#define NAMEI_SPECDIR "special"
+#endif
+#define NAMEI_TAGMASK 0x7
+#define NAMEI_VNODESPECIAL NAMEI_VNODEMASK
+
#define NAMEI_SPECDIRLEN (sizeof(NAMEI_SPECDIR)-1)
#define NAMEI_MAXVOLS 5 /* Maximum supported number of volumes per volume
int ogm_mode;
} namei_ogm_t;
-static int namei_GetLinkCount2(FdHandle_t * h, Inode ino, int lockit, int fixup, int nowrite);
-
static int GetFreeTag(IHandle_t * ih, int vno);
/* namei_HandleToInodeDir
* Format: /<vicepx>/INODEDIR
*
*/
+#ifdef AFS_NT40_ENV
+static void
+namei_HandleToInodeDir(namei_t * name, IHandle_t * ih)
+{
+ memset(name, '\0', sizeof(*name));
+ nt_DevToDrive(name->n_drive, ih->ih_dev);
+ strlcpy(name->n_path, name->n_drive, sizeof(name->n_path));
+}
+
+#else
+/* Format: /<vicepx>/INODEDIR */
#define PNAME_BLEN 64
static void
namei_HandleToInodeDir(namei_t * name, IHandle_t * ih)
strlcpy(name->n_base + offset, INODEDIR, sizeof(name->n_base) - offset);
strlcpy(name->n_path, name->n_base, sizeof(name->n_path));
}
+#endif
#define addtoname(N, C) \
do { \
- strlcat((N)->n_path, "/", sizeof((N)->n_path)); \
+ strlcat((N)->n_path, OS_DIRSEP, sizeof((N)->n_path)); \
strlcat((N)->n_path, (C), sizeof((N)->n_path)); \
} while(0)
+#ifdef AFS_NT40_ENV
+static void
+namei_HandleToVolDir(namei_t * name, IHandle_t * ih)
+{
+ /* X:\Vol_XXXXXXX.data */
+ b32_string_t str1;
+ char *namep;
+
+ namei_HandleToInodeDir(name, ih);
+ addtoname(name, name->n_drive);
+ namep = name->n_voldir;
+ (void)memcpy(namep, "\\Vol_", 5);
+ namep += 5;
+ (void)strcpy(namep, int_to_base32(str1, ih->ih_vid));
+ namep += strlen(namep);
+ memcpy(namep, ".data", 5);
+ namep += 5;
+ *namep = '\0';
+ addtoname(name, name->n_voldir);
+}
+#else
static void
namei_HandleToVolDir(namei_t * name, IHandle_t * ih)
{
strlcpy(name->n_voldir2, tmp, sizeof(name->n_voldir2));
addtoname(name, name->n_voldir2);
}
+#endif
/* namei_HandleToName
*
* Constructs a file name for the fully qualified handle.
- * Note that special files end up in /vicepX/InodeDir/Vxx/V*.data/special
*/
+#ifdef AFS_NT40_ENV
+/* Note that special files end up in X:\Vol_XXXXXXX.data\R */
void
namei_HandleToName(namei_t * name, IHandle_t * ih)
{
- lb64_string_t str;
int vno = (int)(ih->ih_ino & NAMEI_VNODEMASK);
+ int tag = (int)((ih->ih_ino >> NAMEI_TAGSHIFT) & NAMEI_TAGMASK);
+ b32_string_t str1;
+ char *namep;
+ namei_HandleToVolDir(name, ih);
+
+ if (vno == NAMEI_VNODESPECIAL) {
+ name->n_dir[0] = 'R';
+ } else {
+ if (vno & 0x1)
+ name->n_dir[0] = 'Q';
+ else
+ name->n_dir[0] = ((vno & 0x1f) >> 1) + 'A';
+
+ }
+ name->n_dir[1] = '\0';
+ addtoname(name, name->n_dir);
+ /* X:\Vol_XXXXXXX.data\X\V_XXXXXXX.XXX */
+ namep = name->n_inode;
+ (void)memcpy(namep, "\\V_", 3);
+ namep += 3;
+ (void)strcpy(namep, int_to_base32(str1, vno));
+ namep += strlen(namep);
+ *(namep++) = '.';
+ (void)strcpy(namep, int_to_base32(str1, tag));
+ namep += strlen(namep);
+ addtoname(name, name->n_inode);
+}
+#else
+/* Note that special files end up in /vicepX/InodeDir/Vxx/V*.data/special */
+void
+namei_HandleToName(namei_t * name, IHandle_t * ih)
+{
+ int vno = (int)(ih->ih_ino & NAMEI_VNODEMASK);
+ lb64_string_t str;
namei_HandleToVolDir(name, ih);
strlcpy(name->n_inode, str, sizeof(name->n_inode));
addtoname(name, name->n_inode);
}
+#endif
+#ifndef AFS_NT40_ENV
/* The following is a warning to tell sys-admins to not muck about in this
* name space.
*/
}
return (errno);
}
+#endif
+/* namei_CreateDataDirectories
+ *
+ * If creating the file failed because of ENOENT or ENOTDIR, try
+ * creating all the directories first.
+ */
+#ifdef AFS_NT40_ENV
+static int
+namei_CreateDataDirectories(namei_t * name, int *created)
+{
+ char tmp[256];
+ char *s;
+ int i;
+
+ *created = 0;
+ afs_snprintf(tmp, 256, "%s\\%s", name->n_drive, name->n_voldir);
+ if (mkdir(tmp) < 0) {
+ if (errno != EEXIST)
+ return -1;
+ } else
+ *created = 1;
+
+ s = tmp;
+ s += strlen(tmp);
+
+ *s++ = '\\';
+ *(s + 1) = '\0';
+ for (i = 'A'; i <= 'R'; i++) {
+ *s = (char)i;
+ if (mkdir(tmp) < 0 && errno != EEXIST)
+ return -1;
+ }
+ return 0;
+}
+#else
#define create_dir() \
do { \
if (mkdir(tmp, 0700)<0) { \
strcat(tmp, "/"); strcat(tmp, A); create_dir(); \
} while(0)
-/* namei_CreateDataDirectories
- *
- * If creating the file failed because of ENOENT or ENOTDIR, try
- * creating all the directories first.
- */
static int
namei_CreateDataDirectories(namei_t * name, int *created)
{
}
return 0;
}
+#endif
+#ifndef AFS_NT40_ENV
/* delTree(): Deletes an entire tree of directories (no files)
* Input:
* root : Full path to the subtree. Should be big enough for PATH_MAX
return 0;
}
+#endif
/* namei_RemoveDataDirectories
* Return Values:
* Returns 0 on success.
- * Returns -1 on error. Typically, callers ignore this error bcause we
+ * Returns -1 on error. Typically, callers ignore this error because we
* can continue running if the removes fail. The salvage process will
- * finish tidying up for us. We only use the n_base and n_voldir1 entries
- * and only do rmdir's.
+ * finish tidying up for us.
*/
+#ifdef AFS_NT40_ENV
+static int
+namei_RemoveDataDirectories(namei_t * name)
+{
+ int code = 0;
+ char *path;
+ char tmp[256];
+ int i;
+
+ afs_snprintf(tmp, 256, "%s\\%s", name->n_drive, name->n_voldir);
+
+ path = tmp;
+ path += strlen(path);
+ *path++ = '\\';
+ *(path + 1) = '\0';
+ for (i = 'A'; i <= 'R'; i++) {
+ *path = (char)i;
+ if (rmdir(name->n_path) < 0 && errno != ENOENT)
+ code = -1;
+ }
+
+ if (!code) {
+ /* Delete the Vol_NNNNNN.data directory. */
+ path--;
+ *path = '\0';
+ if (rmdir(name->n_path) < 0 && errno != ENOENT) {
+ code = -1;
+ }
+ }
+ return code;
+}
+#else
+/*
+ * We only use the n_base and n_voldir1 entries
+ * and only do rmdir's.
+ */
static int
namei_RemoveDataDirectories(namei_t * name)
{
- char pbuf[MAXPATHLEN], *path = pbuf;
+ int code = 0;
+ char *path;
int prefixlen = strlen(name->n_base), err = 0;
+ char pbuf[MAXPATHLEN];
+
+ path = pbuf;
strlcpy(path, name->n_path, sizeof(pbuf));
path = path + prefixlen + 1; /* skip over the trailing / */
/* now delete all dirs upto path */
- return delTree(pbuf, path, &err);
-
+ code = delTree(pbuf, path, &err);
+
+ /* We've now deleted everything under /n_base/n_voldir1/n_voldir2 that
+ * we could. Do not delete /n_base/n_voldir1, since doing such might
+ * interrupt another thread trying to create a volume. We could introduce
+ * some locking to make this safe (or only remove it for whole-partition
+ * salvages), but by not deleting it we only leave behind a maximum of
+ * 256 empty directories. So at least for now, don't bother. */
+ return code;
}
+#endif
/* Create the file in the name space.
*
{
Inode ino;
ino = NAMEI_INODESPECIAL;
+#ifdef AFS_NT40_ENV
+ ino |= type;
+#else
type &= NAMEI_TAGMASK;
ino |= ((Inode) type) << NAMEI_TAGSHIFT;
ino |= ((Inode) volid) << NAMEI_UNIQSHIFT;
+#endif
return ino;
}
-/* SetOGM - set owner group and mode bits from parm and tag
- *
+/* SetOGM - set owner group and mode bits from parm and tag */
+static int
+SetOGM(FD_t fd, int parm, int tag)
+{
+#ifndef AFS_NT40_ENV
+/*
* owner - low 15 bits of parm.
* group - next 15 bits of parm.
* mode - 2 bits of parm, then lowest = 3 bits of tag.
*/
-static int
-SetOGM(int fd, int parm, int tag)
-{
int owner, group, mode;
owner = parm & 0x7fff;
mode |= tag & 0x7;
if (fchmod(fd, mode) < 0)
return -1;
-
+#endif
return 0;
-
}
+#ifdef AFS_NT40_ENV
+static int
+CheckOGM(namei_t *name, FdHandle_t *fdP, int p1)
+{
+ WIN32_FIND_DATA info;
+ HANDLE dirH;
+
+ dirH =
+ FindFirstFileEx(name->n_path, FindExInfoStandard, &info,
+ FindExSearchNameMatch, NULL,
+ FIND_FIRST_EX_CASE_SENSITIVE);
+
+ if (!dirH)
+ return -1; /* Can't get info, leave alone */
+
+ FindClose(dirH);
+
+ if (info.ftCreationTime.dwHighDateTime != (unsigned int)p1)
+ return -1;
+
+ return 0;
+}
+#else
/* GetOGM - get parm and tag from owner, group and mode bits. */
static void
GetOGMFromStat(struct afs_stat *status, int *parm, int *tag)
}
static int
-GetOGM(int fd, int *parm, int *tag)
+CheckOGM(namei_t *name, FdHandle_t *fdP, int p1)
{
struct afs_stat status;
- if (afs_fstat(fd, &status) < 0)
+ int parm, tag;
+ if (afs_fstat(fdP->fd_fd, &status) < 0)
+ return -1;
+
+ GetOGMFromStat(&status, &parm, &tag);
+ if (parm != p1)
return -1;
- GetOGMFromStat(&status, parm, tag);
return 0;
}
+#endif
int big_vno = 0; /* Just in case we ever do 64 bit vnodes. */
/* Derive the name and create it O_EXCL. If that fails we have an error.
* Get the tag from a free column in the link table.
*/
+#ifdef AFS_NT40_ENV
Inode
-namei_icreate(IHandle_t * lh, char *part, int p1, int p2, int p3, int p4)
+namei_icreate(IHandle_t * lh, char *part, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4)
+{
+ namei_t name;
+ FD_t fd = INVALID_FD;
+ int code = 0;
+ int created_dir = 0;
+ IHandle_t tmp;
+ FdHandle_t *fdP;
+ FdHandle_t tfd;
+ int tag, i;
+ FILETIME ftime;
+ char *p;
+ b32_string_t str1;
+
+ memset((void *)&tmp, 0, sizeof(IHandle_t));
+
+ tmp.ih_dev = nt_DriveToDev(part);
+ if (tmp.ih_dev == -1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (p2 == -1) {
+ /* Parameters for special file:
+ * p1 - volume id - goes into owner/group/mode
+ * p2 - vnode == -1
+ * p3 - type
+ * p4 - parent volume id
+ */
+ ftime.dwHighDateTime = p1;
+ ftime.dwLowDateTime = p2;
+ tag = p3;
+ tmp.ih_vid = p4; /* Use parent volume id, where this file will be. */
+ tmp.ih_ino = namei_MakeSpecIno(p1, p3);
+ } else {
+ int vno = p2 & NAMEI_VNODEMASK;
+ /* Parameters for regular file:
+ * p1 - volume id
+ * p2 - vnode
+ * p3 - uniq
+ * p4 - dv
+ */
+
+ if (vno != p2) {
+ big_vno++;
+ errno = EINVAL;
+ return -1;
+ }
+
+ tmp.ih_vid = p1;
+ tmp.ih_ino = (Inode) p2;
+ ftime.dwHighDateTime = p3;
+ ftime.dwLowDateTime = p4;
+ }
+
+ namei_HandleToName(&name, &tmp);
+ p = strrchr((char *)&name.n_path, '.');
+ p++;
+ for (i = 0; i < NAMEI_MAXVOLS; i++) {
+ *p = *int_to_base32(str1, i);
+ fd = nt_open((char *)&name.n_path, O_CREAT | O_RDWR | O_TRUNC | O_EXCL, 0666);
+ if (fd != INVALID_FD)
+ break;
+ if (p2 == -1 && p3 == VI_LINKTABLE)
+ break;
+ }
+ if (fd == INVALID_FD) {
+ code = -1;
+ goto bad;
+ }
+ tmp.ih_ino &= ~((Inode) NAMEI_TAGMASK << NAMEI_TAGSHIFT);
+ tmp.ih_ino |= ((Inode) i << NAMEI_TAGSHIFT);
+
+ if (!code) {
+ if (!SetFileTime((HANDLE) fd, &ftime, NULL, NULL)) {
+ errno = OS_ERROR(EBADF);
+ code = -1;
+ }
+ }
+
+ if (!code) {
+ if (p2 != -1) {
+ if (fd == INVALID_FD) {
+ errno = ENOENT;
+ code = nt_unlink((char *)&name.n_path);
+ code = -1;
+ goto bad;
+ }
+ fdP = IH_OPEN(lh);
+ if (fdP == NULL) {
+ code = -1;
+ goto bad;
+ }
+ code = namei_SetLinkCount(fdP, tmp.ih_ino, 1, 0);
+ FDH_CLOSE(fdP);
+ } else if (p2 == -1 && p3 == VI_LINKTABLE) {
+ if (fd == INVALID_FD)
+ goto bad;
+ /* hack at tmp to setup for set link count call. */
+ tfd.fd_fd = fd;
+ code = namei_SetLinkCount(&tfd, (Inode) 0, 1, 0);
+ }
+ }
+
+bad:
+ if (fd != INVALID_FD)
+ nt_close(fd);
+
+ if (code || (fd == INVALID_FD)) {
+ if (p2 != -1) {
+ fdP = IH_OPEN(lh);
+ if (fdP) {
+ namei_SetLinkCount(fdP, tmp.ih_ino, 0, 0);
+ FDH_CLOSE(fdP);
+ }
+ }
+
+ if (created_dir) {
+ int save_errno = errno;
+ namei_RemoveDataDirectories(&name);
+ errno = save_errno;
+ }
+ }
+ return (code || (fd == INVALID_FD)) ? (Inode) - 1 : tmp.ih_ino;
+}
+#else
+Inode
+namei_icreate(IHandle_t * lh, char *part, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4)
{
namei_t name;
int fd = -1;
int tag;
int ogm_parm;
-
memset((void *)&tmp, 0, sizeof(IHandle_t));
-
tmp.ih_dev = volutil_GetPartitionID(part);
if (tmp.ih_dev == -1) {
errno = EINVAL;
* p4 - parent volume id
*/
ogm_parm = p1;
- tag = p3;
+ tag = p3;
tmp.ih_vid = p4; /* Use parent volume id, where this file will be. */
tmp.ih_ino = namei_MakeSpecIno(p1, p3);
} else {
if (tag < 0)
goto bad;
- /* name is <uniq(p3)><tag><vno(p2)> */
tmp.ih_vid = p1;
tmp.ih_ino = (Inode) p2;
+ /* name is <uniq(p3)><tag><vno(p2)> */
tmp.ih_ino |= ((Inode) tag) << NAMEI_TAGSHIFT;
tmp.ih_ino |= ((Inode) p3) << NAMEI_UNIQSHIFT;
}
return (code || (fd < 0)) ? (Inode) - 1 : tmp.ih_ino;
}
-
+#endif
/* namei_iopen */
-int
+FD_t
namei_iopen(IHandle_t * h)
{
- int fd;
+ FD_t fd;
namei_t name;
/* Convert handle to file name. */
namei_HandleToName(&name, h);
- fd = afs_open(name.n_path, O_RDWR, 0666);
+ fd = afs_open((char *)&name.n_path, O_RDWR, 0666);
return fd;
}
if ((ino & NAMEI_INODESPECIAL) == NAMEI_INODESPECIAL) {
IHandle_t *tmp;
- int inode_p1, tag;
int type = (int)((ino >> NAMEI_TAGSHIFT) & NAMEI_TAGMASK);
/* Verify this is the right file. */
IH_INIT(tmp, ih->ih_dev, ih->ih_vid, ino);
+ namei_HandleToName(&name, tmp);
+
fdP = IH_OPEN(tmp);
if (fdP == NULL) {
IH_RELEASE(tmp);
- errno = EINVAL;
+ errno = OS_ERROR(ENOENT);
return -1;
}
- if ((GetOGM(fdP->fd_fd, &inode_p1, &tag) < 0) || (inode_p1 != p1)) {
+ if (CheckOGM(&name, fdP, p1) < 0) {
FDH_REALLYCLOSE(fdP);
IH_RELEASE(tmp);
- errno = EINVAL;
+ errno = OS_ERROR(EINVAL);
return -1;
}
/* If it's the link table itself, decrement the link count. */
if (type == VI_LINKTABLE) {
- if ((count = namei_GetLinkCount(fdP, (Inode) 0, 1)) < 0) {
+ if ((count = namei_GetLinkCount(fdP, (Inode) 0, 1, 0, 1)) < 0) {
FDH_REALLYCLOSE(fdP);
IH_RELEASE(tmp);
return -1;
}
}
- namei_HandleToName(&name, tmp);
- if ((code = unlink(name.n_path)) == 0) {
+ if ((code = OS_UNLINK(name.n_path)) == 0) {
if (type == VI_LINKTABLE) {
/* Try to remove directory. If it fails, that's ok.
* Salvage will clean up.
return -1;
}
- if ((count = namei_GetLinkCount(fdP, ino, 1)) < 0) {
+ if ((count = namei_GetLinkCount(fdP, ino, 1, 0, 1)) < 0) {
FDH_REALLYCLOSE(fdP);
return -1;
}
namei_HandleToName(&name, th);
IH_RELEASE(th);
- code = unlink(name.n_path);
+ code = OS_UNLINK(name.n_path);
}
FDH_CLOSE(fdP);
}
return -1;
}
- if ((count = namei_GetLinkCount(fdP, ino, 1)) < 0)
+ if ((count = namei_GetLinkCount(fdP, ino, 1, 0, 1)) < 0)
code = -1;
else {
count++;
if (count > 7) {
- errno = EINVAL;
+ errno = OS_ERROR(EINVAL);
code = -1;
count = 7;
}
return code;
}
+#ifndef AFS_NT40_ENV
int
namei_replace_file_by_hardlink(IHandle_t *hLink, IHandle_t *hTarget)
{
}
return code;
}
+#endif
/************************************************************************
* File Name Structure
* Organization" below for more information on the tag. The tag is
* required in the name of the file to ensure a unique name.
*
+ * ifdef AFS_NT40_ENV
+ * The data for each volume group is in a separate directory. The name of the
+ * volume is of the form: Vol_NNNNNN.data, where NNNNNN is a base 32
+ * representation of the RW volume ID (even where the RO is the only volume
+ * on the partition). Below that are separate subdirectories for the
+ * AFS directories and special files. There are also 16 directories for files,
+ * hashed on the low 5 bits (recall bit0 is always 0) of the vnode number.
+ * These directories are named:
+ * A - P - 16 file directories.
+ * Q ----- data directory
+ * R ----- special files directory
+ *
+ * The vnode is hashed into the directory using the low bits of the
+ * vnode number.
+ *
+ * The format of a file name for a regular file is:
+ * Y:\Vol_NNNNNN.data\X\V_IIIIII.J
+ * Y - partition encoded as drive letter, starting with D
+ * NNNNNN - base 32 encoded volume number of RW volume
+ * X - hash directory, as above
+ * IIIIII - base 32 encoded vnode number
+ * J - base 32 encoded tag
+ *
+ * uniq is stored in the dwHighDateTime creation time field
+ * dv is stored in the dwLowDateTime creation time field
+ *
+ * Special inodes are always in the R directory, as above, and are
+ * encoded:
+ * True child volid is stored in the dwHighDateTime creation time field
+ * vnode number is always -1 (Special)
+ * type is the IIIIII part of the filename
+ * uniq is the J part of the filename
+ * parent volume id is implied in the containing directory
+ *
+ * else
* We can store data in the uid, gid and mode bits of the files, provided
* the directories have root only access. This gives us 15 bits for each
* of uid and gid (GNU chown considers 65535 to mean "don't change").
* as possible, leading to faster discards of incorrect matches in the
* lookup code.
*
+ * endif
+ *
*/
* different version of the file (or a different uniquifer) for the BU volume.
* Then one column would be holding the link count of 2 for the RW and RO
* and a different column would hold the link count of 1 for the BU volume.
+ * # ifdef AFS_NT40_ENV
+ * The column used is determined for NT by the uniquifier tag applied to
+ * generate a unique file name in the NTFS namespace. The file name is
+ * of the form "V_<vno>.<tag>" . And the <tag> is also the column number
+ * in the link table.
+ * # else
* Note that we allow only 5 volumes per file, giving 15 bits used in the
* short.
+ * # endif
*/
#define LINKTABLE_WIDTH 2
#define LINKTABLE_SHIFT 1 /* log 2 = 1 */
*
* @internal
*/
-static int
-namei_GetLinkCount2(FdHandle_t * h, Inode ino, int lockit, int fixup, int nowrite)
+int
+namei_GetLinkCount(FdHandle_t * h, Inode ino, int lockit, int fixup, int nowrite)
{
unsigned short row = 0;
afs_foff_t offset;
int index;
/* there's no linktable yet. the salvager will create one later */
- if (h->fd_fd == -1 && fixup)
+ if (h->fd_fd == INVALID_FD && fixup)
return 1;
namei_GetLCOffsetAndIndexFromIno(ino, &offset, &index);
if (lockit) {
- if (flock(h->fd_fd, LOCK_EX) < 0)
+ if (FDH_LOCKFILE(h, offset) != 0)
return -1;
}
* in order to make MT-safe, truncation (extension really)
* must happen under a mutex
*/
- struct stat st;
NAMEI_GLC_LOCK;
- if (fstat(h->fd_fd, &st) || st.st_size >= offset+sizeof(row)) {
+ if (FDH_SIZE(h) >= offset+sizeof(row)) {
NAMEI_GLC_UNLOCK;
goto bad_getLinkByte;
}
bad_getLinkByte:
if (lockit)
- flock(h->fd_fd, LOCK_UN);
+ FDH_UNLOCKFILE(h, offset);
return -1;
}
int
-namei_GetLinkCount(FdHandle_t * h, Inode ino, int lockit)
+namei_SetNonZLC(FdHandle_t * h, Inode ino)
{
- return namei_GetLinkCount2(h, ino, lockit, 0, 1);
+ return namei_GetLinkCount(h, ino, 0, 1, 0);
}
/* Return a free column index for this vnode. */
return -1;
/* Only one manipulates at a time. */
- if (flock(fdP->fd_fd, LOCK_EX) < 0) {
+ if (FDH_LOCKFILE(fdP, offset) != 0) {
FDH_REALLYCLOSE(fdP);
return -1;
}
goto badGetFreeTag;
}
FDH_SYNC(fdP);
- flock(fdP->fd_fd, LOCK_UN);
+ FDH_UNLOCKFILE(fdP, offset);
FDH_REALLYCLOSE(fdP);
return col;;
badGetFreeTag:
- flock(fdP->fd_fd, LOCK_UN);
+ FDH_UNLOCKFILE(fdP, offset);
FDH_REALLYCLOSE(fdP);
return -1;
}
afs_foff_t offset;
int index;
unsigned short row;
- int junk;
+ int bytesRead;
ssize_t nBytes = -1;
namei_GetLCOffsetAndIndexFromIno(ino, &offset, &index);
if (!locked) {
- if (flock(fdP->fd_fd, LOCK_EX) < 0) {
+ if (FDH_LOCKFILE(fdP, offset) != 0) {
return -1;
}
}
nBytes = FDH_PREAD(fdP, (char *)&row, sizeof(row), offset);
if (nBytes != sizeof(row)) {
if (nBytes != 0) {
- errno = EBADF;
+ errno = OS_ERROR(EBADF);
goto bad_SetLinkCount;
}
row = 0;
}
- junk = 7 << index;
+ bytesRead = 7 << index;
count <<= index;
- row &= (unsigned short)~junk;
+ row &= (unsigned short)~bytesRead;
row |= (unsigned short)count;
if (FDH_PWRITE(fdP, (char *)&row, sizeof(short), offset) != sizeof(short)) {
- errno = EBADF;
+ errno = OS_ERROR(EBADF);
goto bad_SetLinkCount;
}
FDH_SYNC(fdP);
bad_SetLinkCount:
- flock(fdP->fd_fd, LOCK_UN);
+ FDH_UNLOCKFILE(fdP, offset);
- return nBytes;
+ /* disallowed above 7, so... */
+ return (int)nBytes;
}
static int
WriteInodeInfo(FILE * fp, struct ViceInodeInfo *info, char *dir, char *name)
{
- int n;
+ size_t n;
n = fwrite(info, sizeof(*info), 1, fp);
return (n == 1) ? 0 : -2;
}
IHandle_t ih;
namei_t name;
int ninodes = 0;
- DIR *dirp1, *dirp2;
- struct dirent *dp1, *dp2;
+ DIR *dirp1;
+ struct dirent *dp1;
+#ifndef AFS_NT40_ENV
+ DIR *dirp2;
+ struct dirent *dp2;
char path2[512];
+#endif
#ifdef DELETE_ZLC
static void FreeZLCList(void);
#endif
memset((void *)&ih, 0, sizeof(IHandle_t));
+#ifdef AFS_NT40_ENV
+ ih.ih_dev = nt_DriveToDev(dev);
+#else
ih.ih_dev = volutil_GetPartitionID(dev);
+#endif
if (singleVolumeNumber) {
ih.ih_vid = singleVolumeNumber;
if (!dirp1)
return 0;
while ((dp1 = readdir(dirp1))) {
+#ifdef AFS_NT40_ENV
+ /* Heirarchy is one level on Windows */
+ if (!DecodeVolumeName(dp1->d_name, &ih.ih_vid)) {
+ ninodes +=
+ namei_ListAFSSubDirs(&ih, writeFun, fp, judgeFun,
+ 0, rock);
+ }
+#else
if (*dp1->d_name == '.')
continue;
afs_snprintf(path2, sizeof(path2), "%s/%s", name.n_path,
}
closedir(dirp2);
}
+#endif
}
closedir(dirp1);
}
"%s/%s", path1, dname);
linkHandle->fd_fd = afs_open(path2, Testing ? O_RDONLY : O_RDWR, 0666);
info.linkCount =
- namei_GetLinkCount2(linkHandle, (Inode) 0, 1, 1, Testing);
+ namei_GetLinkCount(linkHandle, (Inode) 0, 1, 1, Testing);
}
if (!judgeFun ||
int ret = 0;
struct ViceInodeInfo info;
#ifdef DELETE_ZLC
- int i; /* XXX this isn't set anywhere, nor was it set in
- * namei_ListAFSSubdirs. wtf? */
+ int i; /* Windows-only (one level hash dir) */
#endif
if (DecodeInode(path3, dname, &info, myIH->ih_vid) < 0) {
}
info.linkCount =
- namei_GetLinkCount2(linkHandle,
+ namei_GetLinkCount(linkHandle,
info.inodeNumber, 1, 1, Testing);
if (info.linkCount == 0) {
#ifdef DELETE_ZLC
int code = 0, ret = 0;
IHandle_t myIH = *dirIH;
namei_t name;
- char path1[512], path2[512], path3[512];
+ char path1[512], path3[512];
DIR *dirp1, *dirp2, *dirp3;
- struct dirent *dp1, *dp2, *dp3;
+#ifndef AFS_NT40_ENV
+ struct dirent *dp2;
+ char path2[512];
+#endif
+ struct dirent *dp1, *dp3;
FdHandle_t linkHandle;
int ninodes = 0;
struct listsubdirs_work_node work;
/* Do the directory containing the special files first to pick up link
* counts.
*/
- (void)strcat(path1, "/");
+ (void)strcat(path1, OS_DIRSEP);
(void)strcat(path1, NAMEI_SPECDIR);
- linkHandle.fd_fd = -1;
+ linkHandle.fd_fd = INVALID_FD;
#ifdef AFS_SALSRV_ENV
osi_Assert(pthread_once(&wq_once, _namei_wq_keycreate) == 0);
dirp1 = opendir(path1);
if (dirp1) {
while ((dp1 = readdir(dirp1))) {
+#ifndef AFS_NT40_ENV
if (*dp1->d_name == '.')
continue;
+#endif
if (!strcmp(dp1->d_name, NAMEI_SPECDIR))
continue;
+#ifndef AFS_NT40_ENV /* This level missing on Windows */
/* Now we've got a next level subdir. */
afs_snprintf(path2, sizeof(path2), "%s/%s", path1, dp1->d_name);
dirp2 = opendir(path2);
/* Now we've got to the actual data */
afs_snprintf(path3, sizeof(path3), "%s/%s", path2,
dp2->d_name);
-
+#else
+ /* Now we've got to the actual data */
+ afs_snprintf(path3, sizeof(path3), "%s\\%s", path1,
+ dp1->d_name);
+#endif
dirp3 = opendir(path3);
if (dirp3) {
while ((dp3 = readdir(dirp3))) {
+#ifndef AFS_NT40_ENV
if (*dp3->d_name == '.')
continue;
+#endif
#ifdef AFS_SALSRV_ENV
if (error) {
}
closedir(dirp3);
}
+#ifndef AFS_NT40_ENV /* This level missing on Windows */
}
closedir(dirp2);
}
+#endif
}
closedir(dirp1);
}
}
_namei_listsubdirs_cleanup_results(&resultlist);
#endif
- if (linkHandle.fd_fd >= 0)
- close(linkHandle.fd_fd);
+ if (linkHandle.fd_fd != INVALID_FD)
+ OS_CLOSE(linkHandle.fd_fd);
if (!ret) {
ret = ninodes;
/*@}*/
+#ifdef AFS_NT40_ENV
+static int
+DecodeVolumeName(char *name, unsigned int *vid)
+{
+ /* Name begins with "Vol_" and ends with .data. See nt_HandleToVolDir() */
+ char stmp[32];
+ size_t len;
+
+ len = strlen(name);
+ if (len <= 9)
+ return -1;
+ if (strncmp(name, "Vol_", 4))
+ return -1;
+ if (strcmp(name + len - 5, ".data"))
+ return -1;
+ strcpy(stmp, name);
+ stmp[len - 5] = '\0';
+ *vid = base32_to_int(stmp + 4);
+ return 0;
+}
+#else
static int
DecodeVolumeName(char *name, unsigned int *vid)
{
*vid = (unsigned int)flipbase64_to_int64(name);
return 0;
}
+#endif
/* DecodeInode
*
* Get the inode number from the name.
- * Get
+ *
*/
+#ifdef AFS_NT40_ENV
+static int
+DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
+ unsigned int volid)
+{
+ char fpath[512];
+ int tag, vno;
+ WIN32_FIND_DATA data;
+ HANDLE dirH;
+ char *s, *t;
+ char stmp[16];
+ FdHandle_t linkHandle;
+ char dirl;
+
+ afs_snprintf(fpath, sizeof(fpath), "%s\\%s", dpath, name);
+
+ dirH = FindFirstFileEx(fpath, FindExInfoStandard, &data,
+ FindExSearchNameMatch, NULL,
+ FIND_FIRST_EX_CASE_SENSITIVE);
+ if (dirH == INVALID_HANDLE_VALUE)
+ return -1;
+
+ (void)strcpy(stmp, name);
+ s = strrchr(stmp, '_');
+ if (!s)
+ return -1;
+ s++;
+ t = strrchr(s, '.');
+ if (!t)
+ return -1;
+
+ *t = '\0';
+ vno = base32_to_int(s);
+ tag = base32_to_int(t+1);
+ info->inodeNumber = (Inode) tag << NAMEI_TAGSHIFT;
+ info->inodeNumber |= (Inode) vno;
+ info->byteCount = data.nFileSizeLow;
+
+ dirl = dpath[strlen(dpath)-1];
+ if (dirl == 'R') { /* Special inode. */
+ info->inodeNumber |= NAMEI_INODESPECIAL;
+ info->u.param[0] = data.ftCreationTime.dwHighDateTime;
+ info->u.param[1] = data.ftCreationTime.dwLowDateTime;
+ info->u.param[2] = tag;
+ info->u.param[3] = volid;
+ if (tag != VI_LINKTABLE)
+ info->linkCount = 1;
+ else {
+ /* Open this handle */
+ char lpath[1024];
+ (void)sprintf(lpath, "%s\\%s", fpath, data.cFileName);
+ linkHandle.fd_fd = nt_open(lpath, O_RDONLY, 0666);
+ info->linkCount =
+ namei_GetLinkCount(&linkHandle, (Inode) 0, 0, 0, 0);
+ }
+ } else {
+ info->linkCount =
+ namei_GetLinkCount(&linkHandle, info->inodeNumber, 0, 0, 0);
+ if (info->linkCount == 0) {
+#ifdef DELETE_ZLC
+ Log("Found 0 link count file %s\\%s, deleting it.\n",
+ fpath, data.cFileName);
+ AddToZLCDeleteList(dirl, data.cFileName);
+#else
+ Log("Found 0 link count file %s\\%s.\n", path,
+ data.cFileName);
+#endif
+ } else {
+ info->u.param[2] = data.ftCreationTime.dwHighDateTime;
+ info->u.param[3] = data.ftCreationTime.dwLowDateTime;
+ info->u.param[1] = vno;
+ info->u.param[0] = volid;
+ }
+ }
+ return 0;
+}
+#else
static int
DecodeInode(char *dpath, char *name, struct ViceInodeInfo *info,
unsigned int volid)
}
return 0;
}
+#endif
/*
* Convert the VolumeInfo file from RO to RW
#ifdef FSSYNC_BUILD_CLIENT
static afs_int32
-convertVolumeInfo(int fdr, int fdw, afs_uint32 vid)
+convertVolumeInfo(FD_t fdr, FD_t fdw, afs_uint32 vid)
{
struct VolumeDiskData vd;
char *p;
- if (read(fdr, &vd, sizeof(struct VolumeDiskData)) !=
+ if (OS_READ(fdr, (char *)&vd, sizeof(struct VolumeDiskData)) !=
sizeof(struct VolumeDiskData)) {
Log("1 convertVolumeInfo: read failed for %lu with code %d\n",
afs_printable_uint32_lu(vid),
if (p && !strcmp(p, ".readonly")) {
memset(p, 0, 9);
}
- if (write(fdw, &vd, sizeof(struct VolumeDiskData)) !=
+ if (OS_WRITE(fdw, (char *)&vd, sizeof(struct VolumeDiskData)) !=
sizeof(struct VolumeDiskData)) {
Log("1 convertVolumeInfo: write failed for %lu with code %d\n",
afs_printable_uint32_lu(vid),
char smallSeen = 0;
char largeSeen = 0;
char linkSeen = 0;
- int fd, fd2;
+ FD_t fd, fd2;
char *p;
DIR *dirp;
Inode ino;
namei_HandleToName(&n, ih);
strlcpy(dir_name, n.n_path, sizeof(dir_name));
- p = strrchr(dir_name, '/');
+ p = strrchr(dir_name, OS_DIRSEPC);
*p = 0;
dirp = opendir(dir_name);
if (!dirp) {
while ((dp = readdir(dirp))) {
/* struct ViceInodeInfo info; */
-
+#ifndef AFS_NT40_ENV
if (*dp->d_name == '.')
continue;
+#endif
if (DecodeInode(dir_name, dp->d_name, &info, ih->ih_vid) < 0) {
Log("1 namei_ConvertROtoRWvolume: DecodeInode failed for %s/%s\n",
dir_name, dp->d_name);
t_ih.ih_dev = ih->ih_dev;
t_ih.ih_vid = ih->ih_vid;
- (void)afs_snprintf(oldpath, sizeof oldpath, "%s/%s", dir_name, infoName);
+ (void)afs_snprintf(oldpath, sizeof oldpath, "%s" OS_DIRSEP "%s", dir_name,
+ infoName);
fd = afs_open(oldpath, O_RDWR, 0);
if (fd < 0) {
Log("1 namei_ConvertROtoRWvolume: could not open RO info file: %s\n",
fd2 = afs_open(n.n_path, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0);
if (fd2 < 0) {
Log("1 namei_ConvertROtoRWvolume: could not create RW info file: %s\n", n.n_path);
- close(fd);
+ OS_CLOSE(fd);
code = -1;
goto done;
}
code = convertVolumeInfo(fd, fd2, ih->ih_vid);
- close(fd);
+ OS_CLOSE(fd);
if (code) {
- close(fd2);
- unlink(n.n_path);
+ OS_CLOSE(fd2);
+ OS_UNLINK(n.n_path);
code = -1;
goto done;
}
SetOGM(fd2, ih->ih_vid, 1);
- close(fd2);
+ OS_CLOSE(fd2);
t_ih.ih_ino = namei_MakeSpecIno(ih->ih_vid, VI_SMALLINDEX);
namei_HandleToName(&n, &t_ih);
- (void)afs_snprintf(newpath, sizeof newpath, "%s/%s", dir_name, smallName);
+ (void)afs_snprintf(newpath, sizeof newpath, "%s" OS_DIRSEP "%s", dir_name,
+ smallName);
fd = afs_open(newpath, O_RDWR, 0);
if (fd < 0) {
Log("1 namei_ConvertROtoRWvolume: could not open SmallIndex file: %s\n", newpath);
goto done;
}
SetOGM(fd, ih->ih_vid, 2);
- close(fd);
+ OS_CLOSE(fd);
+#ifdef AFS_NT40_ENV
+ MoveFileEx(n.n_path, newpath, MOVEFILE_WRITE_THROUGH);
+#else
link(newpath, n.n_path);
unlink(newpath);
+#endif
t_ih.ih_ino = namei_MakeSpecIno(ih->ih_vid, VI_LARGEINDEX);
namei_HandleToName(&n, &t_ih);
- (void)afs_snprintf(newpath, sizeof newpath, "%s/%s", dir_name, largeName);
+ (void)afs_snprintf(newpath, sizeof newpath, "%s" OS_DIRSEP "%s", dir_name,
+ largeName);
fd = afs_open(newpath, O_RDWR, 0);
if (fd < 0) {
Log("1 namei_ConvertROtoRWvolume: could not open LargeIndex file: %s\n", newpath);
goto done;
}
SetOGM(fd, ih->ih_vid, 3);
- close(fd);
+ OS_CLOSE(fd);
+#ifdef AFS_NT40_ENV
+ MoveFileEx(n.n_path, newpath, MOVEFILE_WRITE_THROUGH);
+#else
link(newpath, n.n_path);
unlink(newpath);
+#endif
- unlink(oldpath);
+ OS_UNLINK(oldpath);
h.id = h.parent;
h.volumeInfo_hi = h.id;
if (!s)
s = result;
- (void)afs_snprintf(s, sizeof(afs_ino_str_t), "%llu", (afs_uintmax_t) ino);
+ (void)afs_snprintf(s, sizeof(afs_ino_str_t), "%" AFS_UINT64_FMT, (afs_uintmax_t) ino);
return s;
}
}
}
- (void)sprintf(zlcCur->zlc_names[zlcCur->zlc_n], "%c\\%s", dir, name);
+ if (dir)
+ (void)sprintf(zlcCur->zlc_names[zlcCur->zlc_n], "%c\\%s", dir, name);
+ else
+ (void)sprintf(zlcCur->zlc_names[zlcCur->zlc_n], "%s", name);
+
zlcCur->zlc_n++;
}
for (z = zlcAnchor; z; z = z->zlc_next) {
for (i = 0; i < z->zlc_n; i++) {
- (void)sprintf(fname, "%s\\%s", path, z->zlc_names[i]);
+ if (path)
+ (void)sprintf(fname, "%s\\%s", path, z->zlc_names[i]);
+ else
+ (void)sprintf(fname, "%s", z->zlc_names[i]);
if (namei_unlink(fname) < 0) {
Log("ZLC: Can't unlink %s, dos error = %d\n", fname,
GetLastError());
#ifdef AFS_NAMEI_ENV
-#ifdef notdef
-/* We don't include Unix afssyscalls.h, so: */
-#define VALID_INO(I) ((I != (__int64)-1) && (I != (__int64)0))
-
-/* minimum size of string to hand to PrintInode */
-#define AFS_INO_STR_LENGTH 32
-typedef char afs_ino_str_t[AFS_INO_STR_LENGTH];
-
-char *PrintInode(char *s, Inode ino);
-#endif
-
/* Basic file operations */
extern FILE *namei_fdopen(IHandle_t * h, char *fdperms);
extern int namei_unlink(char *name);
/* Inode operations */
extern Inode namei_MakeSpecIno(int volid, int type);
-extern Inode namei_icreate(IHandle_t * h, char *p, int p1, int p2, int p3,
- int p4);
+extern Inode namei_icreate(IHandle_t * lh, char *part, afs_uint32 p1,
+ afs_uint32 p2, afs_uint32 p3, afs_uint32 p4);
extern FD_t namei_iopen(IHandle_t * h);
extern int namei_irelease(IHandle_t * h);
afs_sfsize_t namei_iread(IHandle_t * h, afs_foff_t offset, char *buf,
afs_fsize_t size);
extern int namei_dec(IHandle_t * h, Inode ino, int p1);
extern int namei_inc(IHandle_t * h, Inode ino, int p1);
-extern int namei_GetLinkCount(FdHandle_t * h, Inode ino, int lockit);
+extern int namei_GetLinkCount(FdHandle_t * h, Inode ino, int lockit, int fixup, int nowrite);
extern int namei_SetLinkCount(FdHandle_t * h, Inode ino, int count, int locked);
extern int namei_ViceREADME(char *partition);
#include "nfs.h"
afs_uint32 singleVolumeNumber, int *forcep, int forceR,
char *wpath, void *rock);
-
#define NAMEI_LCOMP_LEN 32
-#define NAMEI_SCOMP_LEN 12
#define NAMEI_PATH_LEN 256
+
+#ifdef AFS_NT40_ENV
+#define NAMEI_DRIVE_LEN 3
+#define NAMEI_HASH_LEN 2
+#define NAMEI_COMP_LEN 18
+typedef struct {
+ char n_drive[NAMEI_DRIVE_LEN];
+ char n_voldir[NAMEI_COMP_LEN];
+ char n_dir[NAMEI_HASH_LEN];
+ char n_inode[NAMEI_COMP_LEN];
+ char n_path[NAMEI_PATH_LEN];
+} namei_t;
+#else
+#define NAMEI_SCOMP_LEN 12
typedef struct {
char n_base[NAMEI_LCOMP_LEN];
char n_voldir1[NAMEI_SCOMP_LEN];
char n_inode[NAMEI_LCOMP_LEN];
char n_path[NAMEI_PATH_LEN];
} namei_t;
+#endif
void namei_HandleToName(namei_t * name, IHandle_t * h);
int namei_ConvertROtoRWvolume(char *pname, afs_uint32 volumeId);
#define BASEFILEATTRIBUTE FILE_ATTRIBUTE_NORMAL
-int Testing = 0;
-
-static void AddToZLCDeleteList(char dir, char *name);
-
/* nt_unlink - unlink a case sensitive name.
*
* nt_unlink supports the nt_dec call.
return (ssize_t)nbytes;
}
-int
-nt_iread(IHandle_t * h, int offset, char *buf, int size)
-{
- int nBytes;
- FdHandle_t *fdP;
-
- fdP = IH_OPEN(h);
- if (fdP == NULL)
- return -1;
-
- nBytes = FDH_PREAD(fdP, buf, size, offset);
- FDH_CLOSE(fdP);
- return nBytes;
-}
-
-int
-nt_iwrite(IHandle_t * h, int offset, char *buf, int size)
-{
- int nBytes;
- FdHandle_t *fdP;
-
- fdP = IH_OPEN(h);
- if (fdP == NULL)
- return -1;
-
- nBytes = FDH_PWRITE(fdP, buf, size, offset);
- FDH_CLOSE(fdP);
- return nBytes;
-}
-
-
int
nt_size(FD_t fd)
{
return code;
}
-
-/* Inode number format:
- * low 32 bits - if a regular file or directory, the vnode. Else the type.
- * 32-36 - unquifier tag and index into counts array for this vnode. Only
- * two of the available bits are currently used. The rest are
- * present in case we ever increase the number of types of volumes
- * in the volume grou.
- * bit 37 : 1 == special, 0 == regular
- */
-#define NT_VNODEMASK 0x00ffffffff
-/* While the TAGMASK is 7, note that we are leaving 1 more bit available. */
-#define NT_TAGMASK 0x7
-#define NT_TAGSHIFT 32
-#define NT_INODESPECIAL 0x2000000000
-
-#define NT_MAXVOLS 5 /* Maximum supported number of volumes per volume
- * group, not counting temporary (move) volumes.
- * This is the number of separate files, all having
- * the same vnode number, which can occur in a volume
- * group at once.
- */
-
-
-int nt_SetLinkCount(FdHandle_t * h, Inode ino, int count, int locked);
-
-
/* nt_DevToDrive
* converts a device number (2-25) into a drive letter name.
*
* Returns pointer to end of drive if successful, else NULL.
*
*/
-char *
+void
nt_DevToDrive(char *drive, int dev)
{
if (dev < 2 || dev > 25) {
errno = EINVAL;
- return NULL; /* Invalid drive */
+ return; /* Invalid drive */
}
drive[0] = (char)('A' + dev);
drive[1] = ':';
drive[2] = '\0';
- return drive + 2;
-
-}
-
-/* Returns pointer to end of name if successful, else NULL. */
-char *
-nt_HandleToVolDir(char *name, IHandle_t * h)
-{
- b32_string_t str1;
-
- if (!(name = nt_DevToDrive(name, h->ih_dev)))
- return NULL;
-
- (void)memcpy(name, "\\Vol_", 5);
- name += 5;
- (void)strcpy(name, int_to_base32(str1, h->ih_vid));
- name += strlen(name);
- memcpy(name, ".data", 5);
- name += 5;
- *name = '\0';
-
- return name;
-}
-
-/* nt_HandleToName
- *
- * Constructs a file name for the fully qualified handle.
- */
-int
-nt_HandleToName(char *name, IHandle_t * h)
-{
- b32_string_t str1;
- int tag = (int)((h->ih_ino >> NT_TAGSHIFT) & NT_TAGMASK);
- int vno = (int)(h->ih_ino & NT_VNODEMASK);
-
- if (!(name = nt_HandleToVolDir(name, h)))
- return -1;
-
- str1[0] = '\\';
- if (h->ih_ino & NT_INODESPECIAL)
- str1[1] = 'R';
- else {
- if (vno & 0x1)
- str1[1] = 'Q';
- else
- str1[1] = ((vno & 0x1f) >> 1) + 'A';
- }
-
- memcpy(name, str1, 2);
- name += 2;
- (void)memcpy(name, "\\V_", 3);
- name += 3;
- (void)strcpy(name, int_to_base32(str1, vno));
- name += strlen(name);
- *(name++) = '.';
- (void)strcpy(name, int_to_base32(str1, tag));
- name += strlen(name);
- *name = '\0';
-
- return 0;
-}
-
-/* nt_CreateDataDirectories
- *
- * The data for each volume is in a separate directory. The name of the
- * volume is of the form: Vol_NNNNNN.data, where NNNNNN is a base 32
- * representation of the RW volume ID (even where the RO is the only volume
- * on the partition). Below that are separate subdirectories for the
- * AFS directories and special files. There are also 16 directories for files,
- * hashed on the low 5 bits (recall bit0 is always 0) of the vnode number.
- * These directories are named:
- * A - P - 16 file directories.
- * Q ----- data directory
- * R ----- special files directory
- */
-static int
-nt_CreateDataDirectories(IHandle_t * h, int *created)
-{
- char name[128];
- char *s;
- int i;
-
- if (!(s = nt_HandleToVolDir(name, h)))
- return -1;
-
- if (mkdir(name) < 0) {
- if (errno != EEXIST)
- return -1;
- } else
- *created = 1;
+ return;
- *s++ = '\\';
- *(s + 1) = '\0';
- for (i = 'A'; i <= 'R'; i++) {
- *s = (char)i;
- if (mkdir(name) < 0 && errno != EEXIST)
- return -1;
- }
- return 0;
}
-/* nt_RemoveDataDirectories
+/* nt_DriveToDev
+ * converts a drive letter to a device number (2-25)
*
- * Returns -1 on error. Typically, callers ignore this error bcause we
- * can continue running if the removes fail. The salvage process will
- * finish tidying up for us.
- */
-static int
-nt_RemoveDataDirectories(IHandle_t * h)
-{
- char name[128];
- char *s;
- int i;
-
- if (!(s = nt_HandleToVolDir(name, h)))
- return -1;
-
- *s++ = '\\';
- *(s + 1) = '\0';
- for (i = 'A'; i <= 'R'; i++) {
- *s = (char)i;
- if (rmdir(name) < 0 && errno != ENOENT)
- return -1;
- }
-
- /* Delete the Vol_NNNNNN.data directory. */
- s--;
- *s = '\0';
- if (rmdir(name) < 0 && errno != ENOENT) {
- return -1;
- }
-
- return 0;
-}
-
-
-/* Create the file in the name space.
- *
- * Parameters stored as follows:
- * Regular files:
- * p1 - volid - implied in containing directory.
- * p2 - vnode - name is <vnode>.<tag> where tag is a file name unqiquifier.
- * p3 - uniq -- creation time - dwHighDateTime
- * p4 - dv ---- creation time - dwLowDateTime
- * Special files:
- * p1 - volid - creation time - dwHighDateTime
- * p2 - vnode - -1 means special, file goes in "S" subdirectory.
- * p3 - type -- name is <type>.<tag> where tag is a file name unqiquifier.
- * p4 - parid - parent volume id - implied in containing directory.
+ * Arguments:
+ * drive - assumes drive is a pointer to a string at least 3 bytes long.
*
- * Return value is the inode number or (Inode)-1 if error.
- * We "know" there is only one link table, so return EEXIST if there already
- * is a link table. It's up to the calling code to test errno and increment
- * the link count.
- */
-
-/* nt_MakeSpecIno
+ * Return Value:
+ * dev - drive number 2-25 if successful (A-C already in use), else -1
*
- * This function is called by VCreateVolume to hide the implementation
- * details of the inode numbers.
- */
-Inode
-nt_MakeSpecIno(int type)
-{
- return ((Inode) type | (Inode) NT_INODESPECIAL);
-}
-
-Inode
-nt_icreate(IHandle_t * h, char *part, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4)
-{
- char filename[128];
- b32_string_t str1;
- char *p;
- int i;
- FD_t fd;
- int created_dir = 0;
- int code = 0;
- FILETIME ftime;
- IHandle_t tmp;
- FdHandle_t *fdP;
- FdHandle_t tfd;
- int save_errno;
-
- memset((void *)&tmp, 0, sizeof(IHandle_t));
-
-
- tmp.ih_dev = tolower(*part) - 'a';
-
- if (p2 == -1) {
- tmp.ih_vid = p4; /* Use parent volume id, where this file will be. */
-
- if (nt_CreateDataDirectories(&tmp, &created_dir) < 0)
- goto bad;
-
- tmp.ih_ino = nt_MakeSpecIno(p3);
- ftime.dwHighDateTime = p1;
- ftime.dwLowDateTime = p2;
- } else {
- /* Regular file or directory.
- * Encoding: p1 -> dir, p2 -> name, p3,p4 -> Create time
- */
- tmp.ih_ino = (Inode) p2;
- tmp.ih_vid = p1;
-
- ftime.dwHighDateTime = p3;
- ftime.dwLowDateTime = p4;
- }
-
- /* Now create file. */
- if ((code = nt_HandleToName(filename, &tmp)) < 0)
- goto bad;
-
- p = filename + strlen(filename);
- p--;
- for (i = 0; i < NT_MAXVOLS; i++) {
- *p = *int_to_base32(str1, i);
- fd = nt_open(filename, O_CREAT | O_RDWR | O_TRUNC | O_EXCL, 0666);
- if (fd != INVALID_FD)
- break;
- if (p2 == -1 && p3 == VI_LINKTABLE)
- break;
- }
- if (fd == INVALID_FD) {
- code = -1;
- goto bad;
- }
-
- tmp.ih_ino &= ~((Inode) NT_TAGMASK << NT_TAGSHIFT);
- tmp.ih_ino |= ((Inode) i << NT_TAGSHIFT);
-
- if (!code) {
- if (!SetFileTime((HANDLE) fd, &ftime, NULL, NULL)) {
- errno = EBADF;
- code = -1;
- }
- }
-
- if (!code) {
- if (p2 != -1) {
- if (fd == INVALID_FD) {
- errno = ENOENT;
- code = nt_unlink(filename);
- if (code == -1) {
- }
- code = -1;
- goto bad;
- }
- fdP = IH_OPEN(h);
- if (fdP == NULL) {
- code = -1;
- goto bad;
- }
- code = nt_SetLinkCount(fdP, tmp.ih_ino, 1, 0);
- FDH_CLOSE(fdP);
- } else if (p2 == -1 && p3 == VI_LINKTABLE) {
- if (fd == INVALID_FD)
- goto bad;
- /* hack at tmp to setup for set link count call. */
- tfd.fd_fd = fd;
- code = nt_SetLinkCount(&tfd, (Inode) 0, 1, 0);
- }
- }
-
- bad:
- if (fd != INVALID_FD)
- nt_close(fd);
-
- if (code && created_dir) {
- save_errno = errno;
- nt_RemoveDataDirectories(&tmp);
- errno = save_errno;
- }
- return code ? (Inode) - 1 : tmp.ih_ino;
-}
-
-
-FD_t
-nt_iopen(IHandle_t * h)
-{
- FD_t fd;
- char name[128];
-
- /* Convert handle to file name. */
- if (nt_HandleToName(name, h) < 0)
- return INVALID_FD;
-
- fd = nt_open(name, O_RDWR, 0666);
- return fd;
-}
-
-/* Need to detect vol special file and just unlink. In those cases, the
- * handle passed in _is_ for the inode. We only check p1 for the special
- * files.
*/
int
-nt_dec(IHandle_t * h, Inode ino, int p1)
+nt_DriveToDev(char *drive)
{
- int count = 0;
- char name[128];
- int code = 0;
- FdHandle_t *fdP;
-
- if (ino & NT_INODESPECIAL) {
- IHandle_t *tmp;
- int was_closed = 0;
- WIN32_FIND_DATA info;
- HANDLE dirH;
-
- /* Verify this is the right file. */
- IH_INIT(tmp, h->ih_dev, h->ih_vid, ino);
-
- if (nt_HandleToName(name, tmp) < 0) {
- IH_RELEASE(tmp);
- errno = EINVAL;
- return -1;
- }
-
- dirH =
- FindFirstFileEx(name, FindExInfoStandard, &info,
- FindExSearchNameMatch, NULL,
- FIND_FIRST_EX_CASE_SENSITIVE);
- if (!dirH) {
- IH_RELEASE(tmp);
- errno = ENOENT;
- return -1; /* Can't get info, leave alone */
- }
+ int dev = -1;
- FindClose(dirH);
- if (info.ftCreationTime.dwHighDateTime != (unsigned int)p1) {
- IH_RELEASE(tmp);
- return -1;
- }
-
- /* If it's the link table itself, decrement the link count. */
- if ((ino & NT_VNODEMASK) == VI_LINKTABLE) {
- fdP = IH_OPEN(tmp);
- if (fdP == NULL) {
- IH_RELEASE(tmp);
- return -1;
- }
-
- if ((count = nt_GetLinkCount(fdP, (Inode) 0, 1)) < 0) {
- FDH_REALLYCLOSE(fdP);
- IH_RELEASE(tmp);
- return -1;
- }
-
- count--;
- if (nt_SetLinkCount(fdP, (Inode) 0, count < 0 ? 0 : count, 1) < 0) {
- FDH_REALLYCLOSE(fdP);
- IH_RELEASE(tmp);
- return -1;
- }
-
- FDH_REALLYCLOSE(fdP);
- if (count > 0) {
- IH_RELEASE(tmp);
- return 0;
- }
- }
-
- if ((code = nt_unlink(name)) == 0) {
- if ((ino & NT_VNODEMASK) == VI_LINKTABLE) {
- /* Try to remove directory. If it fails, that's ok.
- * Salvage will clean up.
- */
- (void)nt_RemoveDataDirectories(tmp);
- }
- }
-
- IH_RELEASE(tmp);
- } else {
- /* Get a file descriptor handle for this Inode */
- fdP = IH_OPEN(h);
- if (fdP == NULL) {
- return -1;
- }
-
- if ((count = nt_GetLinkCount(fdP, ino, 1)) < 0) {
- FDH_REALLYCLOSE(fdP);
- return -1;
- }
-
- count--;
- if (count >= 0) {
- if (nt_SetLinkCount(fdP, ino, count, 1) < 0) {
- FDH_REALLYCLOSE(fdP);
- return -1;
- }
- }
- if (count == 0) {
- IHandle_t th = *h;
- th.ih_ino = ino;
- nt_HandleToName(name, &th);
- code = nt_unlink(name);
- }
- FDH_CLOSE(fdP);
- }
-
- return code;
-}
-
-int
-nt_inc(IHandle_t * h, Inode ino, int p1)
-{
- int count;
- int code = 0;
- FdHandle_t *fdP;
-
- if (ino & NT_INODESPECIAL) {
- if ((ino & NT_VNODEMASK) != VI_LINKTABLE)
- return 0;
- ino = (Inode) 0;
- }
-
- /* Get a file descriptor handle for this Inode */
- fdP = IH_OPEN(h);
- if (fdP == NULL) {
+ if (drive)
+ dev = toupper(*drive) - 'A';
+ if ((dev < 2) || (dev > 25))
return -1;
- }
-
- if ((count = nt_GetLinkCount(fdP, ino, 1)) < 0)
- code = -1;
- else {
- count++;
- if (count > 7) {
- errno = EINVAL;
- code = -1;
- count = 7;
- }
- if (nt_SetLinkCount(fdP, ino, count, 1) < 0)
- code = -1;
- }
- if (code) {
- FDH_REALLYCLOSE(fdP);
- } else {
- FDH_CLOSE(fdP);
- }
- return code;
}
-
-
-
-/************************************************************************
- * Link Table Organization
- ************************************************************************
- *
- * The link table volume special file is used to hold the link counts that
- * are held in the inodes in inode based AFS vice filesystems. Since NTFS
- * doesn't provide us that access, the link counts are being kept in a separate
- * volume special file. The file begins with the usual version stamp
- * information and is then followed by one row per vnode number. vnode 0
- * is used to hold the link count of the link table itself. That is because
- * the same link table is shared among all the volumes of the volume group
- * and is deleted only when the last volume of a volume group is deleted.
- *
- * Within each row, the columns are 3 bits wide. They can each hold a 0 based
- * link count from 0 through 7. Each colume represents a unique instance of
- * that vnode. Say we have a file shared between the RW and a RO and a
- * different version of the file (or a different uniquifer) for the BU volume.
- * Then one column would be holding the link count of 2 for the RW and RO
- * and a different column would hold the link count of 1 for the BU volume.
- * The column used is determined for NT by the uiquifier tag applied to
- * generate a unique file name in the NTFS namespace. The file name is
- * of the form "V_<vno>.<tag>" . And the <tag> is also the column number
- * in the link table.
- */
-#define LINKTABLE_WIDTH 2
-#define LINKTABLE_SHIFT 1 /* log 2 = 1 */
-
-static void
-nt_GetLCOffsetAndIndexFromIno(Inode ino, int *offset, int *index)
-{
- int toff = (int)(ino & NT_VNODEMASK);
- int tindex = (int)((ino >> NT_TAGSHIFT) & NT_TAGMASK);
-
- *offset = (toff << LINKTABLE_SHIFT) + 8; /* *2 + sizeof stamp */
- *index = (tindex << 1) + tindex;
-}
-
-
-/* nt_GetLinkCount
- * If lockit is set, lock the file and leave it locked upon a successful
- * return.
- */
-static int
-nt_GetLinkCountInternal(FdHandle_t * h, Inode ino, int lockit, int fixup)
-{
- unsigned short row = 0;
- DWORD bytesRead, bytesWritten;
- int offset, index;
-
- /* there's no linktable yet. the salvager will create one later */
- if (h->fd_fd == INVALID_HANDLE_VALUE && fixup)
- return 1;
-
- nt_GetLCOffsetAndIndexFromIno(ino, &offset, &index);
-
- if (lockit) {
- if (!LockFile(h->fd_fd, offset, 0, 2, 0))
- return -1;
- }
-
- if (!SetFilePointer(h->fd_fd, (LONG) offset, NULL, FILE_BEGIN))
- goto bad_getLinkByte;
-
- if (!ReadFile(h->fd_fd, (void *)&row, 2, &bytesRead, NULL))
- goto bad_getLinkByte;
-
- if (bytesRead == 0 && fixup) {
- LARGE_INTEGER size;
-
- if (!GetFileSizeEx(h->fd_fd, &size) || size.QuadPart >= offset+sizeof(row))
- goto bad_getLinkByte;
- FDH_TRUNC(h, offset+sizeof(row));
- row = 1 << index;
- rewrite:
- WriteFile(h->fd_fd, (char *)&row, sizeof(row), &bytesWritten, NULL);
- }
-
- if (fixup && !((row >> index) & NT_TAGMASK)) {
- row |= 1<<index;
- goto rewrite;
- }
-
- return (int)((row >> index) & NT_TAGMASK);
-
- bad_getLinkByte:
- if (lockit)
- UnlockFile(h->fd_fd, offset, 0, 2, 0);
- return -1;
-}
-
-int
-nt_GetLinkCount(FdHandle_t * h, Inode ino, int lockit)
-{
- return nt_GetLinkCountInternal(h, ino, lockit, 0);
-}
-
-void
-nt_SetNonZLC(FdHandle_t * h, Inode ino)
-{
- (void)nt_GetLinkCountInternal(h, ino, 0, 1);
-}
-
-
-/* nt_SetLinkCount
- * If locked is set, assume file is locked. Otherwise, lock file before
- * proceeding to modify it.
- */
-int
-nt_SetLinkCount(FdHandle_t * h, Inode ino, int count, int locked)
-{
- int offset, index;
- unsigned short row;
- DWORD bytesRead, bytesWritten;
- int code = -1;
-
- nt_GetLCOffsetAndIndexFromIno(ino, &offset, &index);
-
-
- if (!locked) {
- if (!LockFile(h->fd_fd, offset, 0, 2, 0)) {
- errno = nterr_nt2unix(GetLastError(), EBADF);
- return -1;
- }
- }
- if (!SetFilePointer(h->fd_fd, (LONG) offset, NULL, FILE_BEGIN)) {
- errno = nterr_nt2unix(GetLastError(), EBADF);
- goto bad_SetLinkCount;
- }
-
-
- if (!ReadFile(h->fd_fd, (void *)&row, 2, &bytesRead, NULL)) {
- errno = nterr_nt2unix(GetLastError(), EBADF);
- goto bad_SetLinkCount;
- }
- if (bytesRead == 0)
- row = 0;
-
- bytesRead = 7 << index;
- count <<= index;
- row &= (unsigned short)~bytesRead;
- row |= (unsigned short)count;
-
- if (!SetFilePointer(h->fd_fd, (LONG) offset, NULL, FILE_BEGIN)) {
- errno = nterr_nt2unix(GetLastError(), EBADF);
- goto bad_SetLinkCount;
- }
-
- if (!WriteFile(h->fd_fd, (void *)&row, 2, &bytesWritten, NULL)) {
- errno = nterr_nt2unix(GetLastError(), EBADF);
- goto bad_SetLinkCount;
- }
-
- code = 0;
-
-
- bad_SetLinkCount:
- UnlockFile(h->fd_fd, offset, 0, 2, 0);
-
- return code;
-}
-
-
-/* ListViceInodes - write inode data to a results file. */
-static int DecodeInodeName(char *name, int *p1, int *p2);
-static int DecodeVolumeName(char *name, afs_uint32 *vid);
-static int nt_ListAFSSubDirs(IHandle_t * dirIH,
- int (*write_fun) (FILE *, struct ViceInodeInfo *,
- char *, char *), FILE * fp,
- int (*judgeFun) (struct ViceInodeInfo *,
- afs_uint32 vid, void *rock),
- afs_uint32 singleVolumeNumber, void *rock);
-
-
-/* WriteInodeInfo
- *
- * Write the inode data to the results file.
- *
- * Returns -2 on error, 0 on success.
- *
- * This is written as a callback simply so that other listing routines
- * can use the same inode reading code.
- */
-static int
-WriteInodeInfo(FILE * fp, struct ViceInodeInfo *info, char *dir, char *name)
-{
- int n;
- n = fwrite(info, sizeof(*info), 1, fp);
- return (n == 1) ? 0 : -2;
-}
-
-
-/* ListViceInodes
- * Fill the results file with the requested inode information.
- *
- * Return values:
- * 0 - success
- * -1 - complete failure, salvage should terminate.
- * -2 - not enough space on partition, salvager has error message for this.
- *
- * This code optimizes single volume salvages by just looking at that one
- * volume's directory.
- *
- * If the inodeFile is NULL, then don't call the write routine.
- */
-int
-ListViceInodes(char *devname, char *mountedOn, FILE *inodeFile,
- int (*judgeInode) (struct ViceInodeInfo * info, afs_uint32 vid, void *rock),
- afs_uint32 singleVolumeNumber, int *forcep, int forceR, char *wpath,
- void *rock)
-{
- int ninodes;
- struct stat status;
-
- ninodes =
- nt_ListAFSFiles(wpath, WriteInodeInfo, inodeFile, judgeInode,
- singleVolumeNumber, rock);
-
- if (!inodeFile)
- return ninodes;
-
- if (ninodes < 0) {
- return ninodes;
- }
-
- if (fflush(inodeFile) == EOF) {
- Log("Unable to successfully flush inode file for %s\n", mountedOn);
- return -2;
- }
- if (fsync(fileno(inodeFile)) == -1) {
- Log("Unable to successfully fsync inode file for %s\n", mountedOn);
- return -2;
- }
-
- /*
- * Paranoia: check that the file is really the right size
- */
- if (fstat(fileno(inodeFile), &status) == -1) {
- Log("Unable to successfully stat inode file for %s\n", mountedOn);
- return -2;
- }
- if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
- Log("Wrong size (%d instead of %d) in inode file for %s\n",
- status.st_size, ninodes * sizeof(struct ViceInodeInfo),
- mountedOn);
- return -2;
- }
- return 0;
-}
-
-
-/* nt_ListAFSFiles
- *
- * Collect all the matching AFS files on the drive.
- * If singleVolumeNumber is non-zero, just return files for that volume.
- *
- * Returns <0 on error, else number of files found to match.
- */
-int
-nt_ListAFSFiles(char *dev,
- int (*writeFun) (FILE *, struct ViceInodeInfo *, char *,
- char *), FILE * fp,
- int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
- afs_uint32 singleVolumeNumber, void *rock)
-{
- IHandle_t h;
- char name[MAX_PATH];
- int ninodes = 0;
- DIR *dirp;
- struct dirent *dp;
- static void FreeZLCList(void);
-
- memset((void *)&h, 0, sizeof(IHandle_t));
- h.ih_dev = toupper(*dev) - 'A';
-
- if (singleVolumeNumber) {
- h.ih_vid = singleVolumeNumber;
- if (!nt_HandleToVolDir(name, &h))
- return -1;
- ninodes =
- nt_ListAFSSubDirs(&h, writeFun, fp, judgeFun, singleVolumeNumber, rock);
- if (ninodes < 0)
- return ninodes;
- } else {
- /* Find all Vol_*.data directories and descend through them. */
- if (!nt_DevToDrive(name, h.ih_dev))
- return -1;
- ninodes = 0;
- dirp = opendir(name);
- if (!dirp)
- return -1;
- while (dp = readdir(dirp)) {
- if (!DecodeVolumeName(dp->d_name, &h.ih_vid)) {
- ninodes += nt_ListAFSSubDirs(&h, writeFun, fp, judgeFun, 0, rock);
- }
- }
- }
- FreeZLCList();
- return ninodes;
-}
-
-
-
-/* nt_ListAFSSubDirs
- *
- * List the S, F, and D subdirectories of this volume's directory.
- *
- * Return values:
- * < 0 - an error
- * > = 0 - number of AFS files found.
- */
-static int
-nt_ListAFSSubDirs(IHandle_t * dirIH,
- int (*writeFun) (FILE *, struct ViceInodeInfo *, char *,
- char *), FILE * fp,
- int (*judgeFun) (struct ViceInodeInfo *, afs_uint32, void *),
- afs_uint32 singleVolumeNumber, void *rock)
-{
- int i;
- IHandle_t myIH = *dirIH;
- HANDLE dirH;
- WIN32_FIND_DATA data;
- char path[1024];
- char basePath[1024];
- char *s;
- char findPath[1024];
- struct ViceInodeInfo info;
- int tag, vno;
- FdHandle_t linkHandle;
- int ninodes = 0;
- static void DeleteZLCFiles(char *path);
-
- s = nt_HandleToVolDir(path, &myIH);
- strcpy(basePath, path);
- if (!s)
- return -1;
- *s = '\\';
- s++;
- *(s + 1) = '\0';
-
- /* Do the directory containing the special files first to pick up link
- * counts.
- */
- for (i = 'R'; i >= 'A'; i--) {
- *s = (char)i;
- (void)strcpy(findPath, path);
- (void)strcat(findPath, "\\*");
- dirH =
- FindFirstFileEx(findPath, FindExInfoStandard, &data,
- FindExSearchNameMatch, NULL,
- FIND_FIRST_EX_CASE_SENSITIVE);
- if (dirH == INVALID_HANDLE_VALUE)
- continue;
- while (1) {
- /* Store the vice info. */
- memset((void *)&info, 0, sizeof(info));
- if (*data.cFileName == '.')
- goto next_file;
- if (DecodeInodeName(data.cFileName, &vno, &tag) < 0) {
- Log("Error parsing %s\\%s\n", path, data.cFileName);
- } else {
- info.inodeNumber = (Inode) tag << NT_TAGSHIFT;
- info.inodeNumber |= (Inode) vno;
- info.byteCount = data.nFileSizeLow;
-
- if (i == 'R') { /* Special inode. */
- info.inodeNumber |= NT_INODESPECIAL;
- info.u.param[0] = data.ftCreationTime.dwHighDateTime;
- info.u.param[1] = data.ftCreationTime.dwLowDateTime;
- info.u.param[2] = vno;
- info.u.param[3] = dirIH->ih_vid;
- if (info.u.param[2] != VI_LINKTABLE) {
- info.linkCount = 1;
- } else {
- /* Open this handle */
- char lpath[1024];
- (void)sprintf(lpath, "%s\\%s", path, data.cFileName);
- linkHandle.fd_fd = nt_open(lpath, O_RDONLY, 0666);
- info.linkCount =
- nt_GetLinkCount(&linkHandle, (Inode) 0, 0);
- }
- } else { /* regular file. */
- info.linkCount =
- nt_GetLinkCount(&linkHandle, info.inodeNumber, 0);
- if (info.linkCount == 0) {
-#ifdef notdef
- Log("Found 0 link count file %s\\%s, deleting it.\n",
- path, data.cFileName);
- AddToZLCDeleteList((char)i, data.cFileName);
-#else
- Log("Found 0 link count file %s\\%s.\n", path,
- data.cFileName);
#endif
- goto next_file;
- }
- info.u.param[0] = dirIH->ih_vid;
- info.u.param[1] = vno;
- info.u.param[2] = data.ftCreationTime.dwHighDateTime;
- info.u.param[3] = data.ftCreationTime.dwLowDateTime;
- }
- if (judgeFun && !(*judgeFun) (&info, singleVolumeNumber, rock))
- goto next_file;
- if ((*writeFun) (fp, &info, path, data.cFileName) < 0) {
- nt_close(linkHandle.fd_fd);
- FindClose(dirH);
- return -1;
- }
- ninodes++;
- }
- next_file:
- if (!FindNextFile(dirH, &data)) {
- break;
- }
- }
- FindClose(dirH);
- }
- nt_close(linkHandle.fd_fd);
- DeleteZLCFiles(basePath);
- if (!ninodes) {
- /* Then why does this directory exist? Blow it away. */
- nt_RemoveDataDirectories(dirIH);
- }
-
- return ninodes;
-}
-
-/* The name begins with "Vol_" and ends with .data. See nt_HandleToVolDir() */
-static int
-DecodeVolumeName(char *name, afs_uint32 *vid)
-{
- char stmp[32];
- int len;
-
- len = strlen(name);
- if (len <= 9)
- return -1;
- if (strncmp(name, "Vol_", 4))
- return -1;
- if (strcmp(name + len - 5, ".data"))
- return -1;
- strcpy(stmp, name);
- stmp[len - 5] = '\0';
- *vid = base32_to_int(stmp + 4);
- return 0;
-}
-
-/* Recall that the name beings with a "V_" */
-static int
-DecodeInodeName(char *name, int *p1, int *p2)
-{
- char *s, *t;
- char stmp[16];
-
- (void)strcpy(stmp, name);
- s = strrchr(stmp, '_');
- if (!s)
- return -1;
- s++;
- t = strrchr(s, '.');
- if (!t)
- return -1;
-
- *t = '\0';
- *p1 = base32_to_int(s);
- *p2 = base32_to_int(t + 1);
- return 0;
-}
-
-
-/* PrintInode
- *
- * returns a static string used to print either 32 or 64 bit inode numbers.
- */
-char *
-PrintInode(char *s, Inode ino)
-{
- static afs_ino_str_t result;
- if (!s)
- s = result;
-
- (void)sprintf((char *)s, "%I64u", ino);
-
- return (char *)s;
-}
-
-
-/* Routines to facilitate removing zero link count files. */
-#define MAX_ZLC_NAMES 32
-#define MAX_ZLC_NAMELEN 16
-typedef struct zlcList_s {
- struct zlcList_s *zlc_next;
- int zlc_n;
- char zlc_names[MAX_ZLC_NAMES][MAX_ZLC_NAMELEN];
-} zlcList_t;
-
-static zlcList_t *zlcAnchor = NULL;
-static zlcList_t *zlcCur = NULL;
-
-static void
-AddToZLCDeleteList(char dir, char *name)
-{
- osi_Assert(strlen(name) <= MAX_ZLC_NAMELEN - 3);
-
- if (!zlcCur || zlcCur->zlc_n >= MAX_ZLC_NAMES) {
- if (zlcCur && zlcCur->zlc_next)
- zlcCur = zlcCur->zlc_next;
- else {
- zlcList_t *tmp = (zlcList_t *) malloc(sizeof(zlcList_t));
- if (!tmp)
- return;
- if (!zlcAnchor) {
- zlcAnchor = tmp;
- } else {
- zlcCur->zlc_next = tmp;
- }
- zlcCur = tmp;
- zlcCur->zlc_n = 0;
- zlcCur->zlc_next = NULL;
- }
- }
-
- (void)sprintf(zlcCur->zlc_names[zlcCur->zlc_n], "%c\\%s", dir, name);
- zlcCur->zlc_n++;
-}
-
-static void
-DeleteZLCFiles(char *path)
-{
- zlcList_t *z;
- int i;
- char fname[1024];
-
- for (z = zlcAnchor; z; z = z->zlc_next) {
- for (i = 0; i < z->zlc_n; i++) {
- (void)sprintf(fname, "%s\\%s", path, z->zlc_names[i]);
- if (nt_unlink(fname) < 0) {
- Log("ZLC: Can't unlink %s, dos error = %d\n", fname,
- GetLastError());
- }
- }
- z->zlc_n = 0; /* Can reuse space. */
- }
- zlcCur = zlcAnchor;
-}
-
-static void
-FreeZLCList(void)
-{
- zlcList_t *tnext;
- zlcList_t *i;
-
- i = zlcAnchor;
- while (i) {
- tnext = i->zlc_next;
- free(i);
- i = tnext;
- }
- zlcCur = zlcAnchor = NULL;
-}
-
-#endif /* AFS_NT40_ENV */
#ifndef _NTOPS_H_
#define _NTOPS_H_
-
-/* We don't include Unix afssyscalls.h, so: */
+#ifdef AFS_NT40_ENV
+/* We don't include Unix afssyscalls.h on Windows, so: */
#define VALID_INO(I) ((I != (__int64)-1) && (I != (__int64)0))
/* minimum size of string to hand to PrintInode */
#define AFS_INO_STR_LENGTH 32
typedef char afs_ino_str_t[AFS_INO_STR_LENGTH];
-char *PrintInode(char *s, Inode ino);
+extern char *PrintInode(char *, Inode);
+#endif
/* Basic file operations */
extern FD_t nt_open(char *name, int flags, int mode);
extern FILE *nt_fdopen(IHandle_t * h, char *fdperms);
extern int nt_unlink(char *name);
-/* Inode operations */
-extern Inode nt_MakeSpecIno(int type);
-extern Inode nt_icreate(IHandle_t * h, char *p, afs_uint32 p1, afs_uint32 p2,
- afs_uint32 p3, afs_uint32 p4);
-extern FD_t nt_iopen(IHandle_t * h);
-extern int nt_irelease(IHandle_t * h);
-int nt_iread(IHandle_t * h, int offset, char *buf, int size);
-int nt_iwrite(IHandle_t * h, int offset, char *buf, int size);
-extern int nt_dec(IHandle_t * h, Inode ino, int p1);
-extern int nt_inc(IHandle_t * h, Inode ino, int p1);
-extern int nt_GetLinkCount(FdHandle_t * h, Inode ino, int lockit);
-int nt_ListAFSFiles(char *dev,
- int (*write_fun) (FILE * fp, struct ViceInodeInfo *,
- char *dir, char *file), FILE * fp,
- int (*judge_fun) (struct ViceInodeInfo *, afs_uint32 vid, void *rock),
- afs_uint32 singleVolumeNumber, void *rock);
-int ListViceInodes(char *devname, char *mountedOn, FILE *inodeFile,
- int (*judgeInode) (struct ViceInodeInfo * info, afs_uint32 vid, void *rock),
- afs_uint32 singleVolumeNumber, int *forcep, int forceR,
- char *wpath, void *rock);
-
-
-int nt_HandleToName(char *name, IHandle_t * h);
-char *nt_HandleToVolDir(char *name, IHandle_t * h);
-
-extern int Testing;
-
+extern void nt_DevToDrive(char *drive, int dev);
+extern int nt_DriveToDev(char *drive);
#endif /* _NTOPS_H_ */
char *lastDevComp;
struct DiskPartition64 *dp;
#ifdef AFS_NAMEI_ENV
-#ifdef AFS_NT40_ENV
- char path[MAX_PATH];
-#else
char *path;
+
namei_t ufs_name;
-#endif
#endif /* AFS_NAMEI_ENV */
#ifndef AFS_NAMEI_ENV
char devName[64];
#ifdef AFS_NT40_ENV
IH_INIT(fileH, (int)(*lastDevComp - 'A'), avolid,
ti->inode[i]);
- nt_HandleToName(path, fileH);
#else
IH_INIT(fileH, (int)volutil_GetPartitionID(aname), avolid,
ti->inode[i]);
+#endif /* AFS_NT40_ENV */
namei_HandleToName(&ufs_name, fileH);
path = ufs_name.n_path;
-#endif /* AFS_NT40_ENV */
IH_RELEASE(fileH);
- if (unlink(path) < 0) {
+ if (OS_UNLINK(path) < 0) {
Log("Nuke: Failed to remove %s\n", path);
}
#else /* AFS_NAMEI_ENV */
{
#if defined(AFS_NAMEI_ENV)
IHandle_t *ihtmpp;
-#if !defined(AFS_NT40_ENV)
namei_t filename;
-#else
- char filename[MAX_PATH];
-#endif
#endif
afs_fsize_t fileLength;
#if defined(AFS_NAMEI_ENV)
if (PrintFileNames) {
IH_INIT(ihtmpp, V_device(vp), V_parentId(vp), ino);
-#if !defined(AFS_NT40_ENV)
namei_HandleToName(&filename, ihtmpp);
+#if !defined(AFS_NT40_ENV)
printf(" UFS-Filename: %s", filename.n_path);
#else
- nt_HandleToName(filename, ihtmpp);
- printf(" NTFS-Filename: %s", filename);
+ printf(" NTFS-Filename: %s", filename.n_path);
#endif
}
#endif
for (i = 0; i < nVols; i++) {
ip = allInodes + isp[i].index;
for (j = isp[i].nSpecialInodes; j < isp[i].nInodes; j++) {
-#ifdef AFS_NT40_ENV
- nt_SetLinkCount(fdP, ip[j].inodeNumber, 1, 1);
-#else
namei_SetLinkCount(fdP, ip[j].inodeNumber, 1, 1);
-#endif
}
}
}
IHandle_t *lh;
int code;
-#ifdef AFS_NT40_ENV
- *(p->inode) = nt_MakeSpecIno(VI_LINKTABLE);
-#else
*(p->inode) = namei_MakeSpecIno(vol.parentId, VI_LINKTABLE);
-#endif
IH_INIT(lh, device, parentId, *(p->inode));
fdP = IH_OPEN(lh);
if (fdP == NULL) {