158d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
258d4c6c35633437182289e3d226d156d31d3e801San Mehat * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
358d4c6c35633437182289e3d226d156d31d3e801San Mehat * Copyright (c) 1995 Martin Husemann
458d4c6c35633437182289e3d226d156d31d3e801San Mehat * Some structure declaration borrowed from Paul Popelka
558d4c6c35633437182289e3d226d156d31d3e801San Mehat * (paulp@uts.amdahl.com), see /sys/msdosfs/ for reference.
658d4c6c35633437182289e3d226d156d31d3e801San Mehat *
758d4c6c35633437182289e3d226d156d31d3e801San Mehat * Redistribution and use in source and binary forms, with or without
858d4c6c35633437182289e3d226d156d31d3e801San Mehat * modification, are permitted provided that the following conditions
958d4c6c35633437182289e3d226d156d31d3e801San Mehat * are met:
1058d4c6c35633437182289e3d226d156d31d3e801San Mehat * 1. Redistributions of source code must retain the above copyright
1158d4c6c35633437182289e3d226d156d31d3e801San Mehat *    notice, this list of conditions and the following disclaimer.
1258d4c6c35633437182289e3d226d156d31d3e801San Mehat * 2. Redistributions in binary form must reproduce the above copyright
1358d4c6c35633437182289e3d226d156d31d3e801San Mehat *    notice, this list of conditions and the following disclaimer in the
1458d4c6c35633437182289e3d226d156d31d3e801San Mehat *    documentation and/or other materials provided with the distribution.
1558d4c6c35633437182289e3d226d156d31d3e801San Mehat * 3. All advertising materials mentioning features or use of this software
1658d4c6c35633437182289e3d226d156d31d3e801San Mehat *    must display the following acknowledgement:
1758d4c6c35633437182289e3d226d156d31d3e801San Mehat *	This product includes software developed by Martin Husemann
1858d4c6c35633437182289e3d226d156d31d3e801San Mehat *	and Wolfgang Solfrank.
1958d4c6c35633437182289e3d226d156d31d3e801San Mehat * 4. Neither the name of the University nor the names of its contributors
2058d4c6c35633437182289e3d226d156d31d3e801San Mehat *    may be used to endorse or promote products derived from this software
2158d4c6c35633437182289e3d226d156d31d3e801San Mehat *    without specific prior written permission.
2258d4c6c35633437182289e3d226d156d31d3e801San Mehat *
2358d4c6c35633437182289e3d226d156d31d3e801San Mehat * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
2458d4c6c35633437182289e3d226d156d31d3e801San Mehat * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2558d4c6c35633437182289e3d226d156d31d3e801San Mehat * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2658d4c6c35633437182289e3d226d156d31d3e801San Mehat * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2758d4c6c35633437182289e3d226d156d31d3e801San Mehat * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2858d4c6c35633437182289e3d226d156d31d3e801San Mehat * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2958d4c6c35633437182289e3d226d156d31d3e801San Mehat * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3058d4c6c35633437182289e3d226d156d31d3e801San Mehat * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3158d4c6c35633437182289e3d226d156d31d3e801San Mehat * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3258d4c6c35633437182289e3d226d156d31d3e801San Mehat * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3358d4c6c35633437182289e3d226d156d31d3e801San Mehat */
3458d4c6c35633437182289e3d226d156d31d3e801San Mehat
3558d4c6c35633437182289e3d226d156d31d3e801San Mehat
3658d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <sys/cdefs.h>
3758d4c6c35633437182289e3d226d156d31d3e801San Mehat#ifndef lint
3858d4c6c35633437182289e3d226d156d31d3e801San Mehat__RCSID("$NetBSD: dir.c,v 1.14 1998/08/25 19:18:15 ross Exp $");
3958d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic const char rcsid[] =
4058d4c6c35633437182289e3d226d156d31d3e801San Mehat  "$FreeBSD: src/sbin/fsck_msdosfs/dir.c,v 1.3 2003/12/26 17:24:37 trhodes Exp $";
4158d4c6c35633437182289e3d226d156d31d3e801San Mehat#endif /* not lint */
4258d4c6c35633437182289e3d226d156d31d3e801San Mehat
4358d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <stdio.h>
4458d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <stdlib.h>
4558d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <string.h>
4658d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <ctype.h>
4758d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <stdio.h>
4858d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <unistd.h>
4958d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <time.h>
5058d4c6c35633437182289e3d226d156d31d3e801San Mehat
5158d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <sys/param.h>
5258d4c6c35633437182289e3d226d156d31d3e801San Mehat
5358d4c6c35633437182289e3d226d156d31d3e801San Mehat#include "ext.h"
5458d4c6c35633437182289e3d226d156d31d3e801San Mehat#include "fsutil.h"
5558d4c6c35633437182289e3d226d156d31d3e801San Mehat
5658d4c6c35633437182289e3d226d156d31d3e801San Mehat#define	SLOT_EMPTY	0x00		/* slot has never been used */
5758d4c6c35633437182289e3d226d156d31d3e801San Mehat#define	SLOT_E5		0x05		/* the real value is 0xe5 */
5858d4c6c35633437182289e3d226d156d31d3e801San Mehat#define	SLOT_DELETED	0xe5		/* file in this slot deleted */
5958d4c6c35633437182289e3d226d156d31d3e801San Mehat
6058d4c6c35633437182289e3d226d156d31d3e801San Mehat#define	ATTR_NORMAL	0x00		/* normal file */
6158d4c6c35633437182289e3d226d156d31d3e801San Mehat#define	ATTR_READONLY	0x01		/* file is readonly */
6258d4c6c35633437182289e3d226d156d31d3e801San Mehat#define	ATTR_HIDDEN	0x02		/* file is hidden */
6358d4c6c35633437182289e3d226d156d31d3e801San Mehat#define	ATTR_SYSTEM	0x04		/* file is a system file */
6458d4c6c35633437182289e3d226d156d31d3e801San Mehat#define	ATTR_VOLUME	0x08		/* entry is a volume label */
6558d4c6c35633437182289e3d226d156d31d3e801San Mehat#define	ATTR_DIRECTORY	0x10		/* entry is a directory name */
6658d4c6c35633437182289e3d226d156d31d3e801San Mehat#define	ATTR_ARCHIVE	0x20		/* file is new or modified */
6758d4c6c35633437182289e3d226d156d31d3e801San Mehat
6858d4c6c35633437182289e3d226d156d31d3e801San Mehat#define	ATTR_WIN95	0x0f		/* long name record */
6958d4c6c35633437182289e3d226d156d31d3e801San Mehat
7058d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
7158d4c6c35633437182289e3d226d156d31d3e801San Mehat * This is the format of the contents of the deTime field in the direntry
7258d4c6c35633437182289e3d226d156d31d3e801San Mehat * structure.
7358d4c6c35633437182289e3d226d156d31d3e801San Mehat * We don't use bitfields because we don't know how compilers for
7458d4c6c35633437182289e3d226d156d31d3e801San Mehat * arbitrary machines will lay them out.
7558d4c6c35633437182289e3d226d156d31d3e801San Mehat */
7658d4c6c35633437182289e3d226d156d31d3e801San Mehat#define DT_2SECONDS_MASK	0x1F	/* seconds divided by 2 */
7758d4c6c35633437182289e3d226d156d31d3e801San Mehat#define DT_2SECONDS_SHIFT	0
7858d4c6c35633437182289e3d226d156d31d3e801San Mehat#define DT_MINUTES_MASK		0x7E0	/* minutes */
7958d4c6c35633437182289e3d226d156d31d3e801San Mehat#define DT_MINUTES_SHIFT	5
8058d4c6c35633437182289e3d226d156d31d3e801San Mehat#define DT_HOURS_MASK		0xF800	/* hours */
8158d4c6c35633437182289e3d226d156d31d3e801San Mehat#define DT_HOURS_SHIFT		11
8258d4c6c35633437182289e3d226d156d31d3e801San Mehat
8358d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
8458d4c6c35633437182289e3d226d156d31d3e801San Mehat * This is the format of the contents of the deDate field in the direntry
8558d4c6c35633437182289e3d226d156d31d3e801San Mehat * structure.
8658d4c6c35633437182289e3d226d156d31d3e801San Mehat */
8758d4c6c35633437182289e3d226d156d31d3e801San Mehat#define DD_DAY_MASK		0x1F	/* day of month */
8858d4c6c35633437182289e3d226d156d31d3e801San Mehat#define DD_DAY_SHIFT		0
8958d4c6c35633437182289e3d226d156d31d3e801San Mehat#define DD_MONTH_MASK		0x1E0	/* month */
9058d4c6c35633437182289e3d226d156d31d3e801San Mehat#define DD_MONTH_SHIFT		5
9158d4c6c35633437182289e3d226d156d31d3e801San Mehat#define DD_YEAR_MASK		0xFE00	/* year - 1980 */
9258d4c6c35633437182289e3d226d156d31d3e801San Mehat#define DD_YEAR_SHIFT		9
9358d4c6c35633437182289e3d226d156d31d3e801San Mehat
9458d4c6c35633437182289e3d226d156d31d3e801San Mehat
9558d4c6c35633437182289e3d226d156d31d3e801San Mehat/* dir.c */
9658d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic struct dosDirEntry *newDosDirEntry(void);
9758d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic void freeDosDirEntry(struct dosDirEntry *);
9858d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic struct dirTodoNode *newDirTodo(void);
9958d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic void freeDirTodo(struct dirTodoNode *);
10058d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic char *fullpath(struct dosDirEntry *);
10158d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic u_char calcShortSum(u_char *);
10258d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic int delete(int, struct bootblock *, struct fatEntry *, cl_t, int,
10358d4c6c35633437182289e3d226d156d31d3e801San Mehat    cl_t, int, int);
10458d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic int removede(int, struct bootblock *, struct fatEntry *, u_char *,
10558d4c6c35633437182289e3d226d156d31d3e801San Mehat    u_char *, cl_t, cl_t, cl_t, char *, int);
10658d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic int checksize(struct bootblock *, struct fatEntry *, u_char *,
10758d4c6c35633437182289e3d226d156d31d3e801San Mehat    struct dosDirEntry *);
10858d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic int readDosDirSection(int, struct bootblock *, struct fatEntry *,
10958d4c6c35633437182289e3d226d156d31d3e801San Mehat    struct dosDirEntry *);
11058d4c6c35633437182289e3d226d156d31d3e801San Mehat
11158d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
11258d4c6c35633437182289e3d226d156d31d3e801San Mehat * Manage free dosDirEntry structures.
11358d4c6c35633437182289e3d226d156d31d3e801San Mehat */
11458d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic struct dosDirEntry *freede;
11558d4c6c35633437182289e3d226d156d31d3e801San Mehat
11658d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic struct dosDirEntry *
11758d4c6c35633437182289e3d226d156d31d3e801San MehatnewDosDirEntry(void)
11858d4c6c35633437182289e3d226d156d31d3e801San Mehat{
11958d4c6c35633437182289e3d226d156d31d3e801San Mehat	struct dosDirEntry *de;
12058d4c6c35633437182289e3d226d156d31d3e801San Mehat
12158d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (!(de = freede)) {
12258d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (!(de = (struct dosDirEntry *)malloc(sizeof *de)))
12358d4c6c35633437182289e3d226d156d31d3e801San Mehat			return 0;
12458d4c6c35633437182289e3d226d156d31d3e801San Mehat	} else
12558d4c6c35633437182289e3d226d156d31d3e801San Mehat		freede = de->next;
12658d4c6c35633437182289e3d226d156d31d3e801San Mehat	return de;
12758d4c6c35633437182289e3d226d156d31d3e801San Mehat}
12858d4c6c35633437182289e3d226d156d31d3e801San Mehat
12958d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic void
13058d4c6c35633437182289e3d226d156d31d3e801San MehatfreeDosDirEntry(struct dosDirEntry *de)
13158d4c6c35633437182289e3d226d156d31d3e801San Mehat{
13258d4c6c35633437182289e3d226d156d31d3e801San Mehat	de->next = freede;
13358d4c6c35633437182289e3d226d156d31d3e801San Mehat	freede = de;
13458d4c6c35633437182289e3d226d156d31d3e801San Mehat}
13558d4c6c35633437182289e3d226d156d31d3e801San Mehat
13658d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
13758d4c6c35633437182289e3d226d156d31d3e801San Mehat * The same for dirTodoNode structures.
13858d4c6c35633437182289e3d226d156d31d3e801San Mehat */
13958d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic struct dirTodoNode *freedt;
14058d4c6c35633437182289e3d226d156d31d3e801San Mehat
14158d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic struct dirTodoNode *
14258d4c6c35633437182289e3d226d156d31d3e801San MehatnewDirTodo(void)
14358d4c6c35633437182289e3d226d156d31d3e801San Mehat{
14458d4c6c35633437182289e3d226d156d31d3e801San Mehat	struct dirTodoNode *dt;
14558d4c6c35633437182289e3d226d156d31d3e801San Mehat
14658d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (!(dt = freedt)) {
14758d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (!(dt = (struct dirTodoNode *)malloc(sizeof *dt)))
14858d4c6c35633437182289e3d226d156d31d3e801San Mehat			return 0;
14958d4c6c35633437182289e3d226d156d31d3e801San Mehat	} else
15058d4c6c35633437182289e3d226d156d31d3e801San Mehat		freedt = dt->next;
15158d4c6c35633437182289e3d226d156d31d3e801San Mehat	return dt;
15258d4c6c35633437182289e3d226d156d31d3e801San Mehat}
15358d4c6c35633437182289e3d226d156d31d3e801San Mehat
15458d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic void
15558d4c6c35633437182289e3d226d156d31d3e801San MehatfreeDirTodo(struct dirTodoNode *dt)
15658d4c6c35633437182289e3d226d156d31d3e801San Mehat{
15758d4c6c35633437182289e3d226d156d31d3e801San Mehat	dt->next = freedt;
15858d4c6c35633437182289e3d226d156d31d3e801San Mehat	freedt = dt;
15958d4c6c35633437182289e3d226d156d31d3e801San Mehat}
16058d4c6c35633437182289e3d226d156d31d3e801San Mehat
16158d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
16258d4c6c35633437182289e3d226d156d31d3e801San Mehat * The stack of unread directories
16358d4c6c35633437182289e3d226d156d31d3e801San Mehat */
16458d4c6c35633437182289e3d226d156d31d3e801San Mehatstruct dirTodoNode *pendingDirectories = NULL;
16558d4c6c35633437182289e3d226d156d31d3e801San Mehat
16658d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
16758d4c6c35633437182289e3d226d156d31d3e801San Mehat * Return the full pathname for a directory entry.
16858d4c6c35633437182289e3d226d156d31d3e801San Mehat */
16958d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic char *
17058d4c6c35633437182289e3d226d156d31d3e801San Mehatfullpath(struct dosDirEntry *dir)
17158d4c6c35633437182289e3d226d156d31d3e801San Mehat{
17258d4c6c35633437182289e3d226d156d31d3e801San Mehat	static char namebuf[MAXPATHLEN + 1];
17358d4c6c35633437182289e3d226d156d31d3e801San Mehat	char *cp, *np;
17458d4c6c35633437182289e3d226d156d31d3e801San Mehat	int nl;
17558d4c6c35633437182289e3d226d156d31d3e801San Mehat
17658d4c6c35633437182289e3d226d156d31d3e801San Mehat	cp = namebuf + sizeof namebuf - 1;
17758d4c6c35633437182289e3d226d156d31d3e801San Mehat	*cp = '\0';
17858d4c6c35633437182289e3d226d156d31d3e801San Mehat	do {
17958d4c6c35633437182289e3d226d156d31d3e801San Mehat		np = dir->lname[0] ? dir->lname : dir->name;
18058d4c6c35633437182289e3d226d156d31d3e801San Mehat		nl = strlen(np);
18158d4c6c35633437182289e3d226d156d31d3e801San Mehat		if ((cp -= nl) <= namebuf + 1)
18258d4c6c35633437182289e3d226d156d31d3e801San Mehat			break;
18358d4c6c35633437182289e3d226d156d31d3e801San Mehat		memcpy(cp, np, nl);
18458d4c6c35633437182289e3d226d156d31d3e801San Mehat		*--cp = '/';
18558d4c6c35633437182289e3d226d156d31d3e801San Mehat	} while ((dir = dir->parent) != NULL);
18658d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (dir)
18758d4c6c35633437182289e3d226d156d31d3e801San Mehat		*--cp = '?';
18858d4c6c35633437182289e3d226d156d31d3e801San Mehat	else
18958d4c6c35633437182289e3d226d156d31d3e801San Mehat		cp++;
19058d4c6c35633437182289e3d226d156d31d3e801San Mehat	return cp;
19158d4c6c35633437182289e3d226d156d31d3e801San Mehat}
19258d4c6c35633437182289e3d226d156d31d3e801San Mehat
19358d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
19458d4c6c35633437182289e3d226d156d31d3e801San Mehat * Calculate a checksum over an 8.3 alias name
19558d4c6c35633437182289e3d226d156d31d3e801San Mehat */
19658d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic u_char
19758d4c6c35633437182289e3d226d156d31d3e801San MehatcalcShortSum(u_char *p)
19858d4c6c35633437182289e3d226d156d31d3e801San Mehat{
19958d4c6c35633437182289e3d226d156d31d3e801San Mehat	u_char sum = 0;
20058d4c6c35633437182289e3d226d156d31d3e801San Mehat	int i;
20158d4c6c35633437182289e3d226d156d31d3e801San Mehat
20258d4c6c35633437182289e3d226d156d31d3e801San Mehat	for (i = 0; i < 11; i++) {
20358d4c6c35633437182289e3d226d156d31d3e801San Mehat		sum = (sum << 7)|(sum >> 1);	/* rotate right */
20458d4c6c35633437182289e3d226d156d31d3e801San Mehat		sum += p[i];
20558d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
20658d4c6c35633437182289e3d226d156d31d3e801San Mehat
20758d4c6c35633437182289e3d226d156d31d3e801San Mehat	return sum;
20858d4c6c35633437182289e3d226d156d31d3e801San Mehat}
20958d4c6c35633437182289e3d226d156d31d3e801San Mehat
21058d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
21158d4c6c35633437182289e3d226d156d31d3e801San Mehat * Global variables temporarily used during a directory scan
21258d4c6c35633437182289e3d226d156d31d3e801San Mehat */
21358d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic char longName[DOSLONGNAMELEN] = "";
21458d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic u_char *buffer = NULL;
21558d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic u_char *delbuf = NULL;
21658d4c6c35633437182289e3d226d156d31d3e801San Mehat
21758d4c6c35633437182289e3d226d156d31d3e801San Mehatstruct dosDirEntry *rootDir;
21858d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic struct dosDirEntry *lostDir;
21958d4c6c35633437182289e3d226d156d31d3e801San Mehat
22058d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
22158d4c6c35633437182289e3d226d156d31d3e801San Mehat * Init internal state for a new directory scan.
22258d4c6c35633437182289e3d226d156d31d3e801San Mehat */
22358d4c6c35633437182289e3d226d156d31d3e801San Mehatint
22458d4c6c35633437182289e3d226d156d31d3e801San MehatresetDosDirSection(struct bootblock *boot, struct fatEntry *fat)
22558d4c6c35633437182289e3d226d156d31d3e801San Mehat{
22658d4c6c35633437182289e3d226d156d31d3e801San Mehat	int b1, b2;
22758d4c6c35633437182289e3d226d156d31d3e801San Mehat	cl_t cl;
22858d4c6c35633437182289e3d226d156d31d3e801San Mehat	int ret = FSOK;
22958d4c6c35633437182289e3d226d156d31d3e801San Mehat
23058d4c6c35633437182289e3d226d156d31d3e801San Mehat	b1 = boot->RootDirEnts * 32;
23158d4c6c35633437182289e3d226d156d31d3e801San Mehat	b2 = boot->SecPerClust * boot->BytesPerSec;
23258d4c6c35633437182289e3d226d156d31d3e801San Mehat
23358d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (!(buffer = malloc(b1 > b2 ? b1 : b2))
23458d4c6c35633437182289e3d226d156d31d3e801San Mehat	    || !(delbuf = malloc(b2))
23558d4c6c35633437182289e3d226d156d31d3e801San Mehat	    || !(rootDir = newDosDirEntry())) {
23658d4c6c35633437182289e3d226d156d31d3e801San Mehat		perror("No space for directory");
23758d4c6c35633437182289e3d226d156d31d3e801San Mehat		return FSFATAL;
23858d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
23958d4c6c35633437182289e3d226d156d31d3e801San Mehat	memset(rootDir, 0, sizeof *rootDir);
24058d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (boot->flags & FAT32) {
24158d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (boot->RootCl < CLUST_FIRST || boot->RootCl >= boot->NumClusters) {
24258d4c6c35633437182289e3d226d156d31d3e801San Mehat			pfatal("Root directory starts with cluster out of range(%u)",
24358d4c6c35633437182289e3d226d156d31d3e801San Mehat			       boot->RootCl);
24458d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSFATAL;
24558d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
24658d4c6c35633437182289e3d226d156d31d3e801San Mehat		cl = fat[boot->RootCl].next;
24758d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (cl < CLUST_FIRST
24858d4c6c35633437182289e3d226d156d31d3e801San Mehat		    || (cl >= CLUST_RSRVD && cl< CLUST_EOFS)
24958d4c6c35633437182289e3d226d156d31d3e801San Mehat		    || fat[boot->RootCl].head != boot->RootCl) {
25058d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (cl == CLUST_FREE)
25158d4c6c35633437182289e3d226d156d31d3e801San Mehat				pwarn("Root directory starts with free cluster\n");
25258d4c6c35633437182289e3d226d156d31d3e801San Mehat			else if (cl >= CLUST_RSRVD)
25358d4c6c35633437182289e3d226d156d31d3e801San Mehat				pwarn("Root directory starts with cluster marked %s\n",
25458d4c6c35633437182289e3d226d156d31d3e801San Mehat				      rsrvdcltype(cl));
25558d4c6c35633437182289e3d226d156d31d3e801San Mehat			else {
25658d4c6c35633437182289e3d226d156d31d3e801San Mehat				pfatal("Root directory doesn't start a cluster chain");
25758d4c6c35633437182289e3d226d156d31d3e801San Mehat				return FSFATAL;
25858d4c6c35633437182289e3d226d156d31d3e801San Mehat			}
25958d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (ask(1, "Fix")) {
26058d4c6c35633437182289e3d226d156d31d3e801San Mehat				fat[boot->RootCl].next = CLUST_FREE;
26158d4c6c35633437182289e3d226d156d31d3e801San Mehat				ret = FSFATMOD;
26258d4c6c35633437182289e3d226d156d31d3e801San Mehat			} else
26358d4c6c35633437182289e3d226d156d31d3e801San Mehat				ret = FSFATAL;
26458d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
26558d4c6c35633437182289e3d226d156d31d3e801San Mehat
26658d4c6c35633437182289e3d226d156d31d3e801San Mehat		fat[boot->RootCl].flags |= FAT_USED;
26758d4c6c35633437182289e3d226d156d31d3e801San Mehat		rootDir->head = boot->RootCl;
26858d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
26958d4c6c35633437182289e3d226d156d31d3e801San Mehat
27058d4c6c35633437182289e3d226d156d31d3e801San Mehat	return ret;
27158d4c6c35633437182289e3d226d156d31d3e801San Mehat}
27258d4c6c35633437182289e3d226d156d31d3e801San Mehat
27358d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
27458d4c6c35633437182289e3d226d156d31d3e801San Mehat * Cleanup after a directory scan
27558d4c6c35633437182289e3d226d156d31d3e801San Mehat */
27658d4c6c35633437182289e3d226d156d31d3e801San Mehatvoid
27758d4c6c35633437182289e3d226d156d31d3e801San MehatfinishDosDirSection(void)
27858d4c6c35633437182289e3d226d156d31d3e801San Mehat{
27958d4c6c35633437182289e3d226d156d31d3e801San Mehat	struct dirTodoNode *p, *np;
28058d4c6c35633437182289e3d226d156d31d3e801San Mehat	struct dosDirEntry *d, *nd;
28158d4c6c35633437182289e3d226d156d31d3e801San Mehat
28258d4c6c35633437182289e3d226d156d31d3e801San Mehat	for (p = pendingDirectories; p; p = np) {
28358d4c6c35633437182289e3d226d156d31d3e801San Mehat		np = p->next;
28458d4c6c35633437182289e3d226d156d31d3e801San Mehat		freeDirTodo(p);
28558d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
28658d4c6c35633437182289e3d226d156d31d3e801San Mehat	pendingDirectories = 0;
28758d4c6c35633437182289e3d226d156d31d3e801San Mehat	for (d = rootDir; d; d = nd) {
28858d4c6c35633437182289e3d226d156d31d3e801San Mehat		if ((nd = d->child) != NULL) {
28958d4c6c35633437182289e3d226d156d31d3e801San Mehat			d->child = 0;
29058d4c6c35633437182289e3d226d156d31d3e801San Mehat			continue;
29158d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
29258d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (!(nd = d->next))
29358d4c6c35633437182289e3d226d156d31d3e801San Mehat			nd = d->parent;
29458d4c6c35633437182289e3d226d156d31d3e801San Mehat		freeDosDirEntry(d);
29558d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
29658d4c6c35633437182289e3d226d156d31d3e801San Mehat	rootDir = lostDir = NULL;
29758d4c6c35633437182289e3d226d156d31d3e801San Mehat	free(buffer);
29858d4c6c35633437182289e3d226d156d31d3e801San Mehat	free(delbuf);
29958d4c6c35633437182289e3d226d156d31d3e801San Mehat	buffer = NULL;
30058d4c6c35633437182289e3d226d156d31d3e801San Mehat	delbuf = NULL;
30158d4c6c35633437182289e3d226d156d31d3e801San Mehat}
30258d4c6c35633437182289e3d226d156d31d3e801San Mehat
30358d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
30458d4c6c35633437182289e3d226d156d31d3e801San Mehat * Delete directory entries between startcl, startoff and endcl, endoff.
30558d4c6c35633437182289e3d226d156d31d3e801San Mehat */
30658d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic int
30758d4c6c35633437182289e3d226d156d31d3e801San Mehatdelete(int f, struct bootblock *boot, struct fatEntry *fat, cl_t startcl,
30858d4c6c35633437182289e3d226d156d31d3e801San Mehat    int startoff, cl_t endcl, int endoff, int notlast)
30958d4c6c35633437182289e3d226d156d31d3e801San Mehat{
31058d4c6c35633437182289e3d226d156d31d3e801San Mehat	u_char *s, *e;
31158d4c6c35633437182289e3d226d156d31d3e801San Mehat	loff_t off;
31258d4c6c35633437182289e3d226d156d31d3e801San Mehat	int clsz = boot->SecPerClust * boot->BytesPerSec;
31358d4c6c35633437182289e3d226d156d31d3e801San Mehat
31458d4c6c35633437182289e3d226d156d31d3e801San Mehat	s = delbuf + startoff;
31558d4c6c35633437182289e3d226d156d31d3e801San Mehat	e = delbuf + clsz;
31658d4c6c35633437182289e3d226d156d31d3e801San Mehat	while (startcl >= CLUST_FIRST && startcl < boot->NumClusters) {
31758d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (startcl == endcl) {
31858d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (notlast)
31958d4c6c35633437182289e3d226d156d31d3e801San Mehat				break;
32058d4c6c35633437182289e3d226d156d31d3e801San Mehat			e = delbuf + endoff;
32158d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
32258d4c6c35633437182289e3d226d156d31d3e801San Mehat		off = startcl * boot->SecPerClust + boot->ClusterOffset;
32358d4c6c35633437182289e3d226d156d31d3e801San Mehat		off *= boot->BytesPerSec;
324b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		if (lseek64(f, off, SEEK_SET) != off) {
325b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			printf("off = %llu\n", off);
326b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			perror("Unable to lseek64");
327b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			return FSFATAL;
328b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		}
329b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		if (read(f, delbuf, clsz) != clsz) {
33058d4c6c35633437182289e3d226d156d31d3e801San Mehat			perror("Unable to read directory");
33158d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSFATAL;
33258d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
33358d4c6c35633437182289e3d226d156d31d3e801San Mehat		while (s < e) {
33458d4c6c35633437182289e3d226d156d31d3e801San Mehat			*s = SLOT_DELETED;
33558d4c6c35633437182289e3d226d156d31d3e801San Mehat			s += 32;
33658d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
337b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		if (lseek64(f, off, SEEK_SET) != off) {
338b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			printf("off = %llu\n", off);
339b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			perror("Unable to lseek64");
340b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			return FSFATAL;
341b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		}
342b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		if (write(f, delbuf, clsz) != clsz) {
34358d4c6c35633437182289e3d226d156d31d3e801San Mehat			perror("Unable to write directory");
34458d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSFATAL;
34558d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
34658d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (startcl == endcl)
34758d4c6c35633437182289e3d226d156d31d3e801San Mehat			break;
34858d4c6c35633437182289e3d226d156d31d3e801San Mehat		startcl = fat[startcl].next;
34958d4c6c35633437182289e3d226d156d31d3e801San Mehat		s = delbuf;
35058d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
35158d4c6c35633437182289e3d226d156d31d3e801San Mehat	return FSOK;
35258d4c6c35633437182289e3d226d156d31d3e801San Mehat}
35358d4c6c35633437182289e3d226d156d31d3e801San Mehat
35458d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic int
35558d4c6c35633437182289e3d226d156d31d3e801San Mehatremovede(int f, struct bootblock *boot, struct fatEntry *fat, u_char *start,
35658d4c6c35633437182289e3d226d156d31d3e801San Mehat    u_char *end, cl_t startcl, cl_t endcl, cl_t curcl, char *path, int type)
35758d4c6c35633437182289e3d226d156d31d3e801San Mehat{
35858d4c6c35633437182289e3d226d156d31d3e801San Mehat	switch (type) {
35958d4c6c35633437182289e3d226d156d31d3e801San Mehat	case 0:
36058d4c6c35633437182289e3d226d156d31d3e801San Mehat		pwarn("Invalid long filename entry for %s\n", path);
36158d4c6c35633437182289e3d226d156d31d3e801San Mehat		break;
36258d4c6c35633437182289e3d226d156d31d3e801San Mehat	case 1:
36358d4c6c35633437182289e3d226d156d31d3e801San Mehat		pwarn("Invalid long filename entry at end of directory %s\n", path);
36458d4c6c35633437182289e3d226d156d31d3e801San Mehat		break;
36558d4c6c35633437182289e3d226d156d31d3e801San Mehat	case 2:
36658d4c6c35633437182289e3d226d156d31d3e801San Mehat		pwarn("Invalid long filename entry for volume label\n");
36758d4c6c35633437182289e3d226d156d31d3e801San Mehat		break;
36858d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
36958d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (ask(1, "Remove")) {
37058d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (startcl != curcl) {
37158d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (delete(f, boot, fat,
37258d4c6c35633437182289e3d226d156d31d3e801San Mehat				   startcl, start - buffer,
37358d4c6c35633437182289e3d226d156d31d3e801San Mehat				   endcl, end - buffer,
37458d4c6c35633437182289e3d226d156d31d3e801San Mehat				   endcl == curcl) == FSFATAL)
37558d4c6c35633437182289e3d226d156d31d3e801San Mehat				return FSFATAL;
37658d4c6c35633437182289e3d226d156d31d3e801San Mehat			start = buffer;
37758d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
37858d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (endcl == curcl)
37958d4c6c35633437182289e3d226d156d31d3e801San Mehat			for (; start < end; start += 32)
38058d4c6c35633437182289e3d226d156d31d3e801San Mehat				*start = SLOT_DELETED;
38158d4c6c35633437182289e3d226d156d31d3e801San Mehat		return FSDIRMOD;
38258d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
38358d4c6c35633437182289e3d226d156d31d3e801San Mehat	return FSERROR;
38458d4c6c35633437182289e3d226d156d31d3e801San Mehat}
38558d4c6c35633437182289e3d226d156d31d3e801San Mehat
38658d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
38758d4c6c35633437182289e3d226d156d31d3e801San Mehat * Check an in-memory file entry
38858d4c6c35633437182289e3d226d156d31d3e801San Mehat */
38958d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic int
39058d4c6c35633437182289e3d226d156d31d3e801San Mehatchecksize(struct bootblock *boot, struct fatEntry *fat, u_char *p,
39158d4c6c35633437182289e3d226d156d31d3e801San Mehat    struct dosDirEntry *dir)
39258d4c6c35633437182289e3d226d156d31d3e801San Mehat{
39358d4c6c35633437182289e3d226d156d31d3e801San Mehat	/*
39458d4c6c35633437182289e3d226d156d31d3e801San Mehat	 * Check size on ordinary files
39558d4c6c35633437182289e3d226d156d31d3e801San Mehat	 */
39658d4c6c35633437182289e3d226d156d31d3e801San Mehat	int32_t physicalSize;
39758d4c6c35633437182289e3d226d156d31d3e801San Mehat
39858d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (dir->head == CLUST_FREE)
39958d4c6c35633437182289e3d226d156d31d3e801San Mehat		physicalSize = 0;
40058d4c6c35633437182289e3d226d156d31d3e801San Mehat	else {
40158d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (dir->head < CLUST_FIRST || dir->head >= boot->NumClusters)
40258d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSERROR;
40358d4c6c35633437182289e3d226d156d31d3e801San Mehat		physicalSize = fat[dir->head].length * boot->ClusterSize;
40458d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
40558d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (physicalSize < dir->size) {
40658d4c6c35633437182289e3d226d156d31d3e801San Mehat		pwarn("size of %s is %u, should at most be %u\n",
40758d4c6c35633437182289e3d226d156d31d3e801San Mehat		      fullpath(dir), dir->size, physicalSize);
40858d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (ask(1, "Truncate")) {
40958d4c6c35633437182289e3d226d156d31d3e801San Mehat			dir->size = physicalSize;
41058d4c6c35633437182289e3d226d156d31d3e801San Mehat			p[28] = (u_char)physicalSize;
41158d4c6c35633437182289e3d226d156d31d3e801San Mehat			p[29] = (u_char)(physicalSize >> 8);
41258d4c6c35633437182289e3d226d156d31d3e801San Mehat			p[30] = (u_char)(physicalSize >> 16);
41358d4c6c35633437182289e3d226d156d31d3e801San Mehat			p[31] = (u_char)(physicalSize >> 24);
41458d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSDIRMOD;
41558d4c6c35633437182289e3d226d156d31d3e801San Mehat		} else
41658d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSERROR;
41758d4c6c35633437182289e3d226d156d31d3e801San Mehat	} else if (physicalSize - dir->size >= boot->ClusterSize) {
41858d4c6c35633437182289e3d226d156d31d3e801San Mehat		pwarn("%s has too many clusters allocated\n",
41958d4c6c35633437182289e3d226d156d31d3e801San Mehat		      fullpath(dir));
42058d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (ask(1, "Drop superfluous clusters")) {
42158d4c6c35633437182289e3d226d156d31d3e801San Mehat			cl_t cl;
42258d4c6c35633437182289e3d226d156d31d3e801San Mehat			u_int32_t sz = 0;
42358d4c6c35633437182289e3d226d156d31d3e801San Mehat
42458d4c6c35633437182289e3d226d156d31d3e801San Mehat			for (cl = dir->head; (sz += boot->ClusterSize) < dir->size;)
42558d4c6c35633437182289e3d226d156d31d3e801San Mehat				cl = fat[cl].next;
42658d4c6c35633437182289e3d226d156d31d3e801San Mehat			clearchain(boot, fat, fat[cl].next);
42758d4c6c35633437182289e3d226d156d31d3e801San Mehat			fat[cl].next = CLUST_EOF;
42858d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSFATMOD;
42958d4c6c35633437182289e3d226d156d31d3e801San Mehat		} else
43058d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSERROR;
43158d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
43258d4c6c35633437182289e3d226d156d31d3e801San Mehat	return FSOK;
43358d4c6c35633437182289e3d226d156d31d3e801San Mehat}
43458d4c6c35633437182289e3d226d156d31d3e801San Mehat
435b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com
436b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.comstatic u_char  dot_header[16]={0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00};
437b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.comstatic u_char  dot_dot_header[16]={0x2E, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00};
438b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com
439b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com/*
440b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com * Check for missing or broken '.' and '..' entries.
441b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com */
442b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.comstatic int
443b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.comcheck_dot_dot(int f, struct bootblock *boot, struct fatEntry *fat,struct dosDirEntry *dir)
444b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com{
445b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	u_char *p, *buf;
446b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	loff_t off;
447b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	int last;
448b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	cl_t cl;
449b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	int rc=0, n_count;
450b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com
451b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	int dot, dotdot;
452b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	dot = dotdot = 0;
453b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	cl = dir->head;
454b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com
455b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	if (dir->parent && (cl < CLUST_FIRST || cl >= boot->NumClusters)) {
456b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		return rc;
457b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	}
458b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com
459b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	do {
460b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		if (!(boot->flags & FAT32) && !dir->parent) {
461b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			last = boot->RootDirEnts * 32;
462b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			off = boot->ResSectors + boot->FATs * boot->FATsecs;
463b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		} else {
464b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			last = boot->SecPerClust * boot->BytesPerSec;
465b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			off = cl * boot->SecPerClust + boot->ClusterOffset;
466b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		}
467b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com
468b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		off *= boot->BytesPerSec;
469b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		buf = malloc(last);
470b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		if (!buf) {
471b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			perror("Unable to malloc");
472b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			return FSFATAL;
473b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		}
474b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		if (lseek64(f, off, SEEK_SET) != off) {
475b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			printf("off = %llu\n", off);
476b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			perror("Unable to lseek64");
477ef65d7304685707e0f59d9863d5d54992b123ebcrobert_ch_chou			free(buf);
478b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			return FSFATAL;
479b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		}
480b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		if (read(f, buf, last) != last) {
481b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			perror("Unable to read");
482ef65d7304685707e0f59d9863d5d54992b123ebcrobert_ch_chou			free(buf);
483b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			return FSFATAL;
484b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		}
485b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		last /= 32;
486b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		p = buf;
487b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		for (n_count=0, rc=0; n_count < 11; n_count++) {
488b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			if (dot_header[n_count] != p[n_count]) {
489b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com				rc=-1;
490b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com				break;
491b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			}
492b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		}
493b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		 if(!rc)
494b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			dot=1;
495b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com
496b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		for (n_count = 0, rc = 0; n_count < 11; n_count++) {
497b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			if (dot_dot_header[n_count] != p[n_count+32]) {
498b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com				rc=-1;
499b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com				break;
500b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			}
501b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		}
502b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		if(!rc)
503b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			dotdot=1;
504b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		free(buf);
505b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	} while ((cl = fat[cl].next) >= CLUST_FIRST && cl < boot->NumClusters);
506b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com
507b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	if (!dot || !dotdot) {
508b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		if (!dot)
509b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			pwarn("%s: '.' absent for %s.\n",__func__,dir->name);
510b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com
511b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		if (!dotdot)
512b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com			pwarn("%s: '..' absent for %s. \n",__func__,dir->name);
513b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		return -1;
514b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	}
515b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	return 0;
516b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com}
517b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com
51858d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
51958d4c6c35633437182289e3d226d156d31d3e801San Mehat * Read a directory and
52058d4c6c35633437182289e3d226d156d31d3e801San Mehat *   - resolve long name records
52158d4c6c35633437182289e3d226d156d31d3e801San Mehat *   - enter file and directory records into the parent's list
52258d4c6c35633437182289e3d226d156d31d3e801San Mehat *   - push directories onto the todo-stack
52358d4c6c35633437182289e3d226d156d31d3e801San Mehat */
52458d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic int
52558d4c6c35633437182289e3d226d156d31d3e801San MehatreadDosDirSection(int f, struct bootblock *boot, struct fatEntry *fat,
52658d4c6c35633437182289e3d226d156d31d3e801San Mehat    struct dosDirEntry *dir)
52758d4c6c35633437182289e3d226d156d31d3e801San Mehat{
52858d4c6c35633437182289e3d226d156d31d3e801San Mehat	struct dosDirEntry dirent, *d;
52958d4c6c35633437182289e3d226d156d31d3e801San Mehat	u_char *p, *vallfn, *invlfn, *empty;
53058d4c6c35633437182289e3d226d156d31d3e801San Mehat	loff_t off;
53158d4c6c35633437182289e3d226d156d31d3e801San Mehat	int i, j, k, last;
53258d4c6c35633437182289e3d226d156d31d3e801San Mehat	cl_t cl, valcl = ~0, invcl = ~0, empcl = ~0;
53358d4c6c35633437182289e3d226d156d31d3e801San Mehat	char *t;
53458d4c6c35633437182289e3d226d156d31d3e801San Mehat	u_int lidx = 0;
53558d4c6c35633437182289e3d226d156d31d3e801San Mehat	int shortSum;
53658d4c6c35633437182289e3d226d156d31d3e801San Mehat	int mod = FSOK;
537b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	int n_count=0;
538b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	int rc=0;
53958d4c6c35633437182289e3d226d156d31d3e801San Mehat#define	THISMOD	0x8000			/* Only used within this routine */
54058d4c6c35633437182289e3d226d156d31d3e801San Mehat
54158d4c6c35633437182289e3d226d156d31d3e801San Mehat	cl = dir->head;
54258d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (dir->parent && (cl < CLUST_FIRST || cl >= boot->NumClusters)) {
54358d4c6c35633437182289e3d226d156d31d3e801San Mehat		/*
54458d4c6c35633437182289e3d226d156d31d3e801San Mehat		 * Already handled somewhere else.
54558d4c6c35633437182289e3d226d156d31d3e801San Mehat		 */
54658d4c6c35633437182289e3d226d156d31d3e801San Mehat		return FSOK;
54758d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
54858d4c6c35633437182289e3d226d156d31d3e801San Mehat	shortSum = -1;
54958d4c6c35633437182289e3d226d156d31d3e801San Mehat	vallfn = invlfn = empty = NULL;
550b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	int dot,dotdot;
551b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com	dot = dotdot = 0;
552b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com
55358d4c6c35633437182289e3d226d156d31d3e801San Mehat	do {
55458d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (!(boot->flags & FAT32) && !dir->parent) {
55558d4c6c35633437182289e3d226d156d31d3e801San Mehat			last = boot->RootDirEnts * 32;
55658d4c6c35633437182289e3d226d156d31d3e801San Mehat			off = boot->ResSectors + boot->FATs * boot->FATsecs;
55758d4c6c35633437182289e3d226d156d31d3e801San Mehat		} else {
55858d4c6c35633437182289e3d226d156d31d3e801San Mehat			last = boot->SecPerClust * boot->BytesPerSec;
55958d4c6c35633437182289e3d226d156d31d3e801San Mehat			off = cl * boot->SecPerClust + boot->ClusterOffset;
56058d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
56158d4c6c35633437182289e3d226d156d31d3e801San Mehat
56258d4c6c35633437182289e3d226d156d31d3e801San Mehat		off *= boot->BytesPerSec;
563b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com		if (lseek64(f, off, SEEK_SET) != off) {
56458d4c6c35633437182289e3d226d156d31d3e801San Mehat                        printf("off = %llu\n", off);
56558d4c6c35633437182289e3d226d156d31d3e801San Mehat			perror("Unable to lseek64");
56658d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSFATAL;
56758d4c6c35633437182289e3d226d156d31d3e801San Mehat                }
56858d4c6c35633437182289e3d226d156d31d3e801San Mehat                if (read(f, buffer, last) != last) {
56958d4c6c35633437182289e3d226d156d31d3e801San Mehat			perror("Unable to read");
57058d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSFATAL;
57158d4c6c35633437182289e3d226d156d31d3e801San Mehat                }
57258d4c6c35633437182289e3d226d156d31d3e801San Mehat		last /= 32;
57358d4c6c35633437182289e3d226d156d31d3e801San Mehat		for (p = buffer, i = 0; i < last; i++, p += 32) {
57458d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (dir->fsckflags & DIREMPWARN) {
57558d4c6c35633437182289e3d226d156d31d3e801San Mehat				*p = SLOT_EMPTY;
57658d4c6c35633437182289e3d226d156d31d3e801San Mehat				continue;
57758d4c6c35633437182289e3d226d156d31d3e801San Mehat			}
57858d4c6c35633437182289e3d226d156d31d3e801San Mehat
57958d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (*p == SLOT_EMPTY || *p == SLOT_DELETED) {
58058d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (*p == SLOT_EMPTY) {
58158d4c6c35633437182289e3d226d156d31d3e801San Mehat					dir->fsckflags |= DIREMPTY;
58258d4c6c35633437182289e3d226d156d31d3e801San Mehat					empty = p;
58358d4c6c35633437182289e3d226d156d31d3e801San Mehat					empcl = cl;
58458d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
58558d4c6c35633437182289e3d226d156d31d3e801San Mehat				continue;
58658d4c6c35633437182289e3d226d156d31d3e801San Mehat			}
58758d4c6c35633437182289e3d226d156d31d3e801San Mehat
58858d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (dir->fsckflags & DIREMPTY) {
58958d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (!(dir->fsckflags & DIREMPWARN)) {
59058d4c6c35633437182289e3d226d156d31d3e801San Mehat					pwarn("%s has entries after end of directory\n",
59158d4c6c35633437182289e3d226d156d31d3e801San Mehat					      fullpath(dir));
59258d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (ask(1, "Extend")) {
59358d4c6c35633437182289e3d226d156d31d3e801San Mehat						u_char *q;
59458d4c6c35633437182289e3d226d156d31d3e801San Mehat
59558d4c6c35633437182289e3d226d156d31d3e801San Mehat						dir->fsckflags &= ~DIREMPTY;
59658d4c6c35633437182289e3d226d156d31d3e801San Mehat						if (delete(f, boot, fat,
59758d4c6c35633437182289e3d226d156d31d3e801San Mehat							   empcl, empty - buffer,
59858d4c6c35633437182289e3d226d156d31d3e801San Mehat							   cl, p - buffer, 1) == FSFATAL)
59958d4c6c35633437182289e3d226d156d31d3e801San Mehat							return FSFATAL;
60058d4c6c35633437182289e3d226d156d31d3e801San Mehat						q = empcl == cl ? empty : buffer;
60158d4c6c35633437182289e3d226d156d31d3e801San Mehat						for (; q < p; q += 32)
60258d4c6c35633437182289e3d226d156d31d3e801San Mehat							*q = SLOT_DELETED;
60358d4c6c35633437182289e3d226d156d31d3e801San Mehat						mod |= THISMOD|FSDIRMOD;
60458d4c6c35633437182289e3d226d156d31d3e801San Mehat					} else if (ask(1, "Truncate"))
60558d4c6c35633437182289e3d226d156d31d3e801San Mehat						dir->fsckflags |= DIREMPWARN;
60658d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
60758d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (dir->fsckflags & DIREMPWARN) {
60858d4c6c35633437182289e3d226d156d31d3e801San Mehat					*p = SLOT_DELETED;
60958d4c6c35633437182289e3d226d156d31d3e801San Mehat					mod |= THISMOD|FSDIRMOD;
61058d4c6c35633437182289e3d226d156d31d3e801San Mehat					continue;
61158d4c6c35633437182289e3d226d156d31d3e801San Mehat				} else if (dir->fsckflags & DIREMPTY)
61258d4c6c35633437182289e3d226d156d31d3e801San Mehat					mod |= FSERROR;
61358d4c6c35633437182289e3d226d156d31d3e801San Mehat				empty = NULL;
61458d4c6c35633437182289e3d226d156d31d3e801San Mehat			}
61558d4c6c35633437182289e3d226d156d31d3e801San Mehat
61658d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (p[11] == ATTR_WIN95) {
61758d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (*p & LRFIRST) {
61858d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (shortSum != -1) {
61958d4c6c35633437182289e3d226d156d31d3e801San Mehat						if (!invlfn) {
62058d4c6c35633437182289e3d226d156d31d3e801San Mehat							invlfn = vallfn;
62158d4c6c35633437182289e3d226d156d31d3e801San Mehat							invcl = valcl;
62258d4c6c35633437182289e3d226d156d31d3e801San Mehat						}
62358d4c6c35633437182289e3d226d156d31d3e801San Mehat					}
62458d4c6c35633437182289e3d226d156d31d3e801San Mehat					memset(longName, 0, sizeof longName);
62558d4c6c35633437182289e3d226d156d31d3e801San Mehat					shortSum = p[13];
62658d4c6c35633437182289e3d226d156d31d3e801San Mehat					vallfn = p;
62758d4c6c35633437182289e3d226d156d31d3e801San Mehat					valcl = cl;
62858d4c6c35633437182289e3d226d156d31d3e801San Mehat				} else if (shortSum != p[13]
62958d4c6c35633437182289e3d226d156d31d3e801San Mehat					   || lidx != (*p & LRNOMASK)) {
63058d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (!invlfn) {
63158d4c6c35633437182289e3d226d156d31d3e801San Mehat						invlfn = vallfn;
63258d4c6c35633437182289e3d226d156d31d3e801San Mehat						invcl = valcl;
63358d4c6c35633437182289e3d226d156d31d3e801San Mehat					}
63458d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (!invlfn) {
63558d4c6c35633437182289e3d226d156d31d3e801San Mehat						invlfn = p;
63658d4c6c35633437182289e3d226d156d31d3e801San Mehat						invcl = cl;
63758d4c6c35633437182289e3d226d156d31d3e801San Mehat					}
63858d4c6c35633437182289e3d226d156d31d3e801San Mehat					vallfn = NULL;
63958d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
64058d4c6c35633437182289e3d226d156d31d3e801San Mehat				lidx = *p & LRNOMASK;
64158d4c6c35633437182289e3d226d156d31d3e801San Mehat				t = longName + --lidx * 13;
64258d4c6c35633437182289e3d226d156d31d3e801San Mehat				for (k = 1; k < 11 && t < longName + sizeof(longName); k += 2) {
64358d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (!p[k] && !p[k + 1])
64458d4c6c35633437182289e3d226d156d31d3e801San Mehat						break;
64558d4c6c35633437182289e3d226d156d31d3e801San Mehat					*t++ = p[k];
64658d4c6c35633437182289e3d226d156d31d3e801San Mehat					/*
64758d4c6c35633437182289e3d226d156d31d3e801San Mehat					 * Warn about those unusable chars in msdosfs here?	XXX
64858d4c6c35633437182289e3d226d156d31d3e801San Mehat					 */
64958d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (p[k + 1])
65058d4c6c35633437182289e3d226d156d31d3e801San Mehat						t[-1] = '?';
65158d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
65258d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (k >= 11)
65358d4c6c35633437182289e3d226d156d31d3e801San Mehat					for (k = 14; k < 26 && t < longName + sizeof(longName); k += 2) {
65458d4c6c35633437182289e3d226d156d31d3e801San Mehat						if (!p[k] && !p[k + 1])
65558d4c6c35633437182289e3d226d156d31d3e801San Mehat							break;
65658d4c6c35633437182289e3d226d156d31d3e801San Mehat						*t++ = p[k];
65758d4c6c35633437182289e3d226d156d31d3e801San Mehat						if (p[k + 1])
65858d4c6c35633437182289e3d226d156d31d3e801San Mehat							t[-1] = '?';
65958d4c6c35633437182289e3d226d156d31d3e801San Mehat					}
66058d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (k >= 26)
66158d4c6c35633437182289e3d226d156d31d3e801San Mehat					for (k = 28; k < 32 && t < longName + sizeof(longName); k += 2) {
66258d4c6c35633437182289e3d226d156d31d3e801San Mehat						if (!p[k] && !p[k + 1])
66358d4c6c35633437182289e3d226d156d31d3e801San Mehat							break;
66458d4c6c35633437182289e3d226d156d31d3e801San Mehat						*t++ = p[k];
66558d4c6c35633437182289e3d226d156d31d3e801San Mehat						if (p[k + 1])
66658d4c6c35633437182289e3d226d156d31d3e801San Mehat							t[-1] = '?';
66758d4c6c35633437182289e3d226d156d31d3e801San Mehat					}
66858d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (t >= longName + sizeof(longName)) {
66958d4c6c35633437182289e3d226d156d31d3e801San Mehat					pwarn("long filename too long\n");
67058d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (!invlfn) {
67158d4c6c35633437182289e3d226d156d31d3e801San Mehat						invlfn = vallfn;
67258d4c6c35633437182289e3d226d156d31d3e801San Mehat						invcl = valcl;
67358d4c6c35633437182289e3d226d156d31d3e801San Mehat					}
67458d4c6c35633437182289e3d226d156d31d3e801San Mehat					vallfn = NULL;
67558d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
67658d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (p[26] | (p[27] << 8)) {
67758d4c6c35633437182289e3d226d156d31d3e801San Mehat					pwarn("long filename record cluster start != 0\n");
67858d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (!invlfn) {
67958d4c6c35633437182289e3d226d156d31d3e801San Mehat						invlfn = vallfn;
68058d4c6c35633437182289e3d226d156d31d3e801San Mehat						invcl = cl;
68158d4c6c35633437182289e3d226d156d31d3e801San Mehat					}
68258d4c6c35633437182289e3d226d156d31d3e801San Mehat					vallfn = NULL;
68358d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
68458d4c6c35633437182289e3d226d156d31d3e801San Mehat				continue;	/* long records don't carry further
68558d4c6c35633437182289e3d226d156d31d3e801San Mehat						 * information */
68658d4c6c35633437182289e3d226d156d31d3e801San Mehat			}
68758d4c6c35633437182289e3d226d156d31d3e801San Mehat
68858d4c6c35633437182289e3d226d156d31d3e801San Mehat			/*
68958d4c6c35633437182289e3d226d156d31d3e801San Mehat			 * This is a standard msdosfs directory entry.
69058d4c6c35633437182289e3d226d156d31d3e801San Mehat			 */
69158d4c6c35633437182289e3d226d156d31d3e801San Mehat			memset(&dirent, 0, sizeof dirent);
69258d4c6c35633437182289e3d226d156d31d3e801San Mehat
69358d4c6c35633437182289e3d226d156d31d3e801San Mehat			/*
69458d4c6c35633437182289e3d226d156d31d3e801San Mehat			 * it's a short name record, but we need to know
69558d4c6c35633437182289e3d226d156d31d3e801San Mehat			 * more, so get the flags first.
69658d4c6c35633437182289e3d226d156d31d3e801San Mehat			 */
69758d4c6c35633437182289e3d226d156d31d3e801San Mehat			dirent.flags = p[11];
69858d4c6c35633437182289e3d226d156d31d3e801San Mehat
69958d4c6c35633437182289e3d226d156d31d3e801San Mehat			/*
70058d4c6c35633437182289e3d226d156d31d3e801San Mehat			 * Translate from 850 to ISO here		XXX
70158d4c6c35633437182289e3d226d156d31d3e801San Mehat			 */
70258d4c6c35633437182289e3d226d156d31d3e801San Mehat			for (j = 0; j < 8; j++)
70358d4c6c35633437182289e3d226d156d31d3e801San Mehat				dirent.name[j] = p[j];
70458d4c6c35633437182289e3d226d156d31d3e801San Mehat			dirent.name[8] = '\0';
70558d4c6c35633437182289e3d226d156d31d3e801San Mehat			for (k = 7; k >= 0 && dirent.name[k] == ' '; k--)
70658d4c6c35633437182289e3d226d156d31d3e801San Mehat				dirent.name[k] = '\0';
70758d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (dirent.name[k] != '\0')
70858d4c6c35633437182289e3d226d156d31d3e801San Mehat				k++;
70958d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (dirent.name[0] == SLOT_E5)
71058d4c6c35633437182289e3d226d156d31d3e801San Mehat				dirent.name[0] = 0xe5;
71158d4c6c35633437182289e3d226d156d31d3e801San Mehat
71258d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (dirent.flags & ATTR_VOLUME) {
71358d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (vallfn || invlfn) {
71458d4c6c35633437182289e3d226d156d31d3e801San Mehat					mod |= removede(f, boot, fat,
71558d4c6c35633437182289e3d226d156d31d3e801San Mehat							invlfn ? invlfn : vallfn, p,
71658d4c6c35633437182289e3d226d156d31d3e801San Mehat							invlfn ? invcl : valcl, -1, 0,
71758d4c6c35633437182289e3d226d156d31d3e801San Mehat							fullpath(dir), 2);
71858d4c6c35633437182289e3d226d156d31d3e801San Mehat					vallfn = NULL;
71958d4c6c35633437182289e3d226d156d31d3e801San Mehat					invlfn = NULL;
72058d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
72158d4c6c35633437182289e3d226d156d31d3e801San Mehat				continue;
72258d4c6c35633437182289e3d226d156d31d3e801San Mehat			}
72358d4c6c35633437182289e3d226d156d31d3e801San Mehat
72458d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (p[8] != ' ')
72558d4c6c35633437182289e3d226d156d31d3e801San Mehat				dirent.name[k++] = '.';
72658d4c6c35633437182289e3d226d156d31d3e801San Mehat			for (j = 0; j < 3; j++)
72758d4c6c35633437182289e3d226d156d31d3e801San Mehat				dirent.name[k++] = p[j+8];
72858d4c6c35633437182289e3d226d156d31d3e801San Mehat			dirent.name[k] = '\0';
72958d4c6c35633437182289e3d226d156d31d3e801San Mehat			for (k--; k >= 0 && dirent.name[k] == ' '; k--)
73058d4c6c35633437182289e3d226d156d31d3e801San Mehat				dirent.name[k] = '\0';
73158d4c6c35633437182289e3d226d156d31d3e801San Mehat
73258d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (vallfn && shortSum != calcShortSum(p)) {
73358d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (!invlfn) {
73458d4c6c35633437182289e3d226d156d31d3e801San Mehat					invlfn = vallfn;
73558d4c6c35633437182289e3d226d156d31d3e801San Mehat					invcl = valcl;
73658d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
73758d4c6c35633437182289e3d226d156d31d3e801San Mehat				vallfn = NULL;
73858d4c6c35633437182289e3d226d156d31d3e801San Mehat			}
73958d4c6c35633437182289e3d226d156d31d3e801San Mehat			dirent.head = p[26] | (p[27] << 8);
74058d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (boot->ClustMask == CLUST32_MASK)
74158d4c6c35633437182289e3d226d156d31d3e801San Mehat				dirent.head |= (p[20] << 16) | (p[21] << 24);
74258d4c6c35633437182289e3d226d156d31d3e801San Mehat			dirent.size = p[28] | (p[29] << 8) | (p[30] << 16) | (p[31] << 24);
74358d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (vallfn) {
74458d4c6c35633437182289e3d226d156d31d3e801San Mehat				strcpy(dirent.lname, longName);
74558d4c6c35633437182289e3d226d156d31d3e801San Mehat				longName[0] = '\0';
74658d4c6c35633437182289e3d226d156d31d3e801San Mehat				shortSum = -1;
74758d4c6c35633437182289e3d226d156d31d3e801San Mehat			}
74858d4c6c35633437182289e3d226d156d31d3e801San Mehat
74958d4c6c35633437182289e3d226d156d31d3e801San Mehat			dirent.parent = dir;
75058d4c6c35633437182289e3d226d156d31d3e801San Mehat			dirent.next = dir->child;
75158d4c6c35633437182289e3d226d156d31d3e801San Mehat
75258d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (invlfn) {
75358d4c6c35633437182289e3d226d156d31d3e801San Mehat				mod |= k = removede(f, boot, fat,
75458d4c6c35633437182289e3d226d156d31d3e801San Mehat						    invlfn, vallfn ? vallfn : p,
75558d4c6c35633437182289e3d226d156d31d3e801San Mehat						    invcl, vallfn ? valcl : cl, cl,
75658d4c6c35633437182289e3d226d156d31d3e801San Mehat						    fullpath(&dirent), 0);
75758d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (mod & FSFATAL)
75858d4c6c35633437182289e3d226d156d31d3e801San Mehat					return FSFATAL;
75958d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (vallfn
76058d4c6c35633437182289e3d226d156d31d3e801San Mehat				    ? (valcl == cl && vallfn != buffer)
76158d4c6c35633437182289e3d226d156d31d3e801San Mehat				    : p != buffer)
76258d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (k & FSDIRMOD)
76358d4c6c35633437182289e3d226d156d31d3e801San Mehat						mod |= THISMOD;
76458d4c6c35633437182289e3d226d156d31d3e801San Mehat			}
76558d4c6c35633437182289e3d226d156d31d3e801San Mehat
76658d4c6c35633437182289e3d226d156d31d3e801San Mehat			vallfn = NULL; /* not used any longer */
76758d4c6c35633437182289e3d226d156d31d3e801San Mehat			invlfn = NULL;
76858d4c6c35633437182289e3d226d156d31d3e801San Mehat
76958d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (dirent.size == 0 && !(dirent.flags & ATTR_DIRECTORY)) {
77058d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (dirent.head != 0) {
77158d4c6c35633437182289e3d226d156d31d3e801San Mehat					pwarn("%s has clusters, but size 0\n",
77258d4c6c35633437182289e3d226d156d31d3e801San Mehat					      fullpath(&dirent));
77358d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (ask(1, "Drop allocated clusters")) {
77458d4c6c35633437182289e3d226d156d31d3e801San Mehat						p[26] = p[27] = 0;
77558d4c6c35633437182289e3d226d156d31d3e801San Mehat						if (boot->ClustMask == CLUST32_MASK)
77658d4c6c35633437182289e3d226d156d31d3e801San Mehat							p[20] = p[21] = 0;
77758d4c6c35633437182289e3d226d156d31d3e801San Mehat						clearchain(boot, fat, dirent.head);
77858d4c6c35633437182289e3d226d156d31d3e801San Mehat						dirent.head = 0;
77958d4c6c35633437182289e3d226d156d31d3e801San Mehat						mod |= THISMOD|FSDIRMOD|FSFATMOD;
78058d4c6c35633437182289e3d226d156d31d3e801San Mehat					} else
78158d4c6c35633437182289e3d226d156d31d3e801San Mehat						mod |= FSERROR;
78258d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
78358d4c6c35633437182289e3d226d156d31d3e801San Mehat			} else if (dirent.head == 0
78458d4c6c35633437182289e3d226d156d31d3e801San Mehat				   && !strcmp(dirent.name, "..")
78558d4c6c35633437182289e3d226d156d31d3e801San Mehat				   && dir->parent			/* XXX */
78658d4c6c35633437182289e3d226d156d31d3e801San Mehat				   && !dir->parent->parent) {
78758d4c6c35633437182289e3d226d156d31d3e801San Mehat				/*
78858d4c6c35633437182289e3d226d156d31d3e801San Mehat				 *  Do nothing, the parent is the root
78958d4c6c35633437182289e3d226d156d31d3e801San Mehat				 */
79058d4c6c35633437182289e3d226d156d31d3e801San Mehat			} else if (dirent.head < CLUST_FIRST
79158d4c6c35633437182289e3d226d156d31d3e801San Mehat				   || dirent.head >= boot->NumClusters
79258d4c6c35633437182289e3d226d156d31d3e801San Mehat				   || fat[dirent.head].next == CLUST_FREE
79358d4c6c35633437182289e3d226d156d31d3e801San Mehat				   || (fat[dirent.head].next >= CLUST_RSRVD
79458d4c6c35633437182289e3d226d156d31d3e801San Mehat				       && fat[dirent.head].next < CLUST_EOFS)
79558d4c6c35633437182289e3d226d156d31d3e801San Mehat				   || fat[dirent.head].head != dirent.head) {
79658d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (dirent.head == 0)
79758d4c6c35633437182289e3d226d156d31d3e801San Mehat					pwarn("%s has no clusters\n",
79858d4c6c35633437182289e3d226d156d31d3e801San Mehat					      fullpath(&dirent));
79958d4c6c35633437182289e3d226d156d31d3e801San Mehat				else if (dirent.head < CLUST_FIRST
80058d4c6c35633437182289e3d226d156d31d3e801San Mehat					 || dirent.head >= boot->NumClusters)
80158d4c6c35633437182289e3d226d156d31d3e801San Mehat					pwarn("%s starts with cluster out of range(%u)\n",
80258d4c6c35633437182289e3d226d156d31d3e801San Mehat					      fullpath(&dirent),
80358d4c6c35633437182289e3d226d156d31d3e801San Mehat					      dirent.head);
80458d4c6c35633437182289e3d226d156d31d3e801San Mehat				else if (fat[dirent.head].next == CLUST_FREE)
80558d4c6c35633437182289e3d226d156d31d3e801San Mehat					pwarn("%s starts with free cluster\n",
80658d4c6c35633437182289e3d226d156d31d3e801San Mehat					      fullpath(&dirent));
80758d4c6c35633437182289e3d226d156d31d3e801San Mehat				else if (fat[dirent.head].next >= CLUST_RSRVD)
80858d4c6c35633437182289e3d226d156d31d3e801San Mehat					pwarn("%s starts with cluster marked %s\n",
80958d4c6c35633437182289e3d226d156d31d3e801San Mehat					      fullpath(&dirent),
81058d4c6c35633437182289e3d226d156d31d3e801San Mehat					      rsrvdcltype(fat[dirent.head].next));
81158d4c6c35633437182289e3d226d156d31d3e801San Mehat				else
81258d4c6c35633437182289e3d226d156d31d3e801San Mehat					pwarn("%s doesn't start a cluster chain\n",
81358d4c6c35633437182289e3d226d156d31d3e801San Mehat					      fullpath(&dirent));
81458d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (dirent.flags & ATTR_DIRECTORY) {
815a3833718636c6bdcdf0bef2674e864e948e81d27San Mehat					if (ask(1, "Remove")) {
81658d4c6c35633437182289e3d226d156d31d3e801San Mehat						*p = SLOT_DELETED;
81758d4c6c35633437182289e3d226d156d31d3e801San Mehat						mod |= THISMOD|FSDIRMOD;
81858d4c6c35633437182289e3d226d156d31d3e801San Mehat					} else
81958d4c6c35633437182289e3d226d156d31d3e801San Mehat						mod |= FSERROR;
82058d4c6c35633437182289e3d226d156d31d3e801San Mehat					continue;
82158d4c6c35633437182289e3d226d156d31d3e801San Mehat				} else {
82258d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (ask(1, "Truncate")) {
82358d4c6c35633437182289e3d226d156d31d3e801San Mehat						p[28] = p[29] = p[30] = p[31] = 0;
82458d4c6c35633437182289e3d226d156d31d3e801San Mehat						p[26] = p[27] = 0;
82558d4c6c35633437182289e3d226d156d31d3e801San Mehat						if (boot->ClustMask == CLUST32_MASK)
82658d4c6c35633437182289e3d226d156d31d3e801San Mehat							p[20] = p[21] = 0;
82758d4c6c35633437182289e3d226d156d31d3e801San Mehat						dirent.size = 0;
82858d4c6c35633437182289e3d226d156d31d3e801San Mehat						mod |= THISMOD|FSDIRMOD;
82958d4c6c35633437182289e3d226d156d31d3e801San Mehat					} else
83058d4c6c35633437182289e3d226d156d31d3e801San Mehat						mod |= FSERROR;
83158d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
83258d4c6c35633437182289e3d226d156d31d3e801San Mehat			}
83358d4c6c35633437182289e3d226d156d31d3e801San Mehat
83458d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (dirent.head >= CLUST_FIRST && dirent.head < boot->NumClusters)
83558d4c6c35633437182289e3d226d156d31d3e801San Mehat				fat[dirent.head].flags |= FAT_USED;
83658d4c6c35633437182289e3d226d156d31d3e801San Mehat
83758d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (dirent.flags & ATTR_DIRECTORY) {
83858d4c6c35633437182289e3d226d156d31d3e801San Mehat				/*
83958d4c6c35633437182289e3d226d156d31d3e801San Mehat				 * gather more info for directories
84058d4c6c35633437182289e3d226d156d31d3e801San Mehat				 */
84158d4c6c35633437182289e3d226d156d31d3e801San Mehat				struct dirTodoNode *n;
84258d4c6c35633437182289e3d226d156d31d3e801San Mehat
84358d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (dirent.size) {
84458d4c6c35633437182289e3d226d156d31d3e801San Mehat					pwarn("Directory %s has size != 0\n",
84558d4c6c35633437182289e3d226d156d31d3e801San Mehat					      fullpath(&dirent));
84658d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (ask(1, "Correct")) {
84758d4c6c35633437182289e3d226d156d31d3e801San Mehat						p[28] = p[29] = p[30] = p[31] = 0;
84858d4c6c35633437182289e3d226d156d31d3e801San Mehat						dirent.size = 0;
84958d4c6c35633437182289e3d226d156d31d3e801San Mehat						mod |= THISMOD|FSDIRMOD;
85058d4c6c35633437182289e3d226d156d31d3e801San Mehat					} else
85158d4c6c35633437182289e3d226d156d31d3e801San Mehat						mod |= FSERROR;
85258d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
85358d4c6c35633437182289e3d226d156d31d3e801San Mehat				/*
854b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com				 * handle '.' and '..' specially
85558d4c6c35633437182289e3d226d156d31d3e801San Mehat				 */
85658d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (strcmp(dirent.name, ".") == 0) {
85758d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (dirent.head != dir->head) {
858b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com						pwarn("'.' entry in %s has incorrect start cluster\n",
85958d4c6c35633437182289e3d226d156d31d3e801San Mehat						      fullpath(dir));
86058d4c6c35633437182289e3d226d156d31d3e801San Mehat						if (ask(1, "Correct")) {
86158d4c6c35633437182289e3d226d156d31d3e801San Mehat							dirent.head = dir->head;
86258d4c6c35633437182289e3d226d156d31d3e801San Mehat							p[26] = (u_char)dirent.head;
86358d4c6c35633437182289e3d226d156d31d3e801San Mehat							p[27] = (u_char)(dirent.head >> 8);
86458d4c6c35633437182289e3d226d156d31d3e801San Mehat							if (boot->ClustMask == CLUST32_MASK) {
86558d4c6c35633437182289e3d226d156d31d3e801San Mehat								p[20] = (u_char)(dirent.head >> 16);
86658d4c6c35633437182289e3d226d156d31d3e801San Mehat								p[21] = (u_char)(dirent.head >> 24);
86758d4c6c35633437182289e3d226d156d31d3e801San Mehat							}
86858d4c6c35633437182289e3d226d156d31d3e801San Mehat							mod |= THISMOD|FSDIRMOD;
86958d4c6c35633437182289e3d226d156d31d3e801San Mehat						} else
87058d4c6c35633437182289e3d226d156d31d3e801San Mehat							mod |= FSERROR;
87158d4c6c35633437182289e3d226d156d31d3e801San Mehat					}
87258d4c6c35633437182289e3d226d156d31d3e801San Mehat					continue;
873b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com                } else if (strcmp(dirent.name, "..") == 0) {
87458d4c6c35633437182289e3d226d156d31d3e801San Mehat					if (dir->parent) {		/* XXX */
87558d4c6c35633437182289e3d226d156d31d3e801San Mehat						if (!dir->parent->parent) {
87658d4c6c35633437182289e3d226d156d31d3e801San Mehat							if (dirent.head) {
877b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com								pwarn("'..' entry in %s has non-zero start cluster\n",
87858d4c6c35633437182289e3d226d156d31d3e801San Mehat								      fullpath(dir));
87958d4c6c35633437182289e3d226d156d31d3e801San Mehat								if (ask(1, "Correct")) {
88058d4c6c35633437182289e3d226d156d31d3e801San Mehat									dirent.head = 0;
88158d4c6c35633437182289e3d226d156d31d3e801San Mehat									p[26] = p[27] = 0;
88258d4c6c35633437182289e3d226d156d31d3e801San Mehat									if (boot->ClustMask == CLUST32_MASK)
88358d4c6c35633437182289e3d226d156d31d3e801San Mehat										p[20] = p[21] = 0;
88458d4c6c35633437182289e3d226d156d31d3e801San Mehat									mod |= THISMOD|FSDIRMOD;
88558d4c6c35633437182289e3d226d156d31d3e801San Mehat								} else
88658d4c6c35633437182289e3d226d156d31d3e801San Mehat									mod |= FSERROR;
88758d4c6c35633437182289e3d226d156d31d3e801San Mehat							}
88858d4c6c35633437182289e3d226d156d31d3e801San Mehat						} else if (dirent.head != dir->parent->head) {
889b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com							pwarn("'..' entry in %s has incorrect start cluster\n",
89058d4c6c35633437182289e3d226d156d31d3e801San Mehat							      fullpath(dir));
89158d4c6c35633437182289e3d226d156d31d3e801San Mehat							if (ask(1, "Correct")) {
89258d4c6c35633437182289e3d226d156d31d3e801San Mehat								dirent.head = dir->parent->head;
89358d4c6c35633437182289e3d226d156d31d3e801San Mehat								p[26] = (u_char)dirent.head;
89458d4c6c35633437182289e3d226d156d31d3e801San Mehat								p[27] = (u_char)(dirent.head >> 8);
89558d4c6c35633437182289e3d226d156d31d3e801San Mehat								if (boot->ClustMask == CLUST32_MASK) {
89658d4c6c35633437182289e3d226d156d31d3e801San Mehat									p[20] = (u_char)(dirent.head >> 16);
89758d4c6c35633437182289e3d226d156d31d3e801San Mehat									p[21] = (u_char)(dirent.head >> 24);
89858d4c6c35633437182289e3d226d156d31d3e801San Mehat								}
89958d4c6c35633437182289e3d226d156d31d3e801San Mehat								mod |= THISMOD|FSDIRMOD;
90058d4c6c35633437182289e3d226d156d31d3e801San Mehat							} else
90158d4c6c35633437182289e3d226d156d31d3e801San Mehat								mod |= FSERROR;
90258d4c6c35633437182289e3d226d156d31d3e801San Mehat						}
90358d4c6c35633437182289e3d226d156d31d3e801San Mehat					}
90458d4c6c35633437182289e3d226d156d31d3e801San Mehat					continue;
905b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com				} else { //only one directory entry can point to dir->head, it's  '.'
906b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com					if (dirent.head == dir->head) {
907b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com						pwarn("%s entry in %s has incorrect start cluster.remove\n",
908b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com								dirent.name, fullpath(dir));
909b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com						//we have to remove this directory entry rigth now rigth here
910b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com						if (ask(1, "Remove")) {
911b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com							*p = SLOT_DELETED;
912b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com							mod |= THISMOD|FSDIRMOD;
913b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com						} else
914b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com							mod |= FSERROR;
915b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com						continue;
916b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com					}
917b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com					/* Consistency checking. a directory must have at least two entries:
918b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com					   a dot (.) entry that points to itself, and a dot-dot (..)
919b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com					   entry that points to its parent.
920b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com					 */
921b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com					if (check_dot_dot(f,boot,fat,&dirent)) {
922b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com						//mark directory entry as deleted.
923b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com						if (ask(1, "Remove")) {
924b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com							*p = SLOT_DELETED;
925b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com							mod |= THISMOD|FSDIRMOD;
926b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com						} else
927b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com							mod |= FSERROR;
928b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com						continue;
929b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com                    }
93058d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
93158d4c6c35633437182289e3d226d156d31d3e801San Mehat
93258d4c6c35633437182289e3d226d156d31d3e801San Mehat				/* create directory tree node */
93358d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (!(d = newDosDirEntry())) {
93458d4c6c35633437182289e3d226d156d31d3e801San Mehat					perror("No space for directory");
93558d4c6c35633437182289e3d226d156d31d3e801San Mehat					return FSFATAL;
93658d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
93758d4c6c35633437182289e3d226d156d31d3e801San Mehat				memcpy(d, &dirent, sizeof(struct dosDirEntry));
93858d4c6c35633437182289e3d226d156d31d3e801San Mehat				/* link it into the tree */
93958d4c6c35633437182289e3d226d156d31d3e801San Mehat				dir->child = d;
940b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com#if 0
941b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com				printf("%s: %s : 0x%02x:head %d, next 0x%0x parent 0x%0x child 0x%0x\n",
942b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com						__func__,d->name,d->flags,d->head,d->next,d->parent,d->child);
943b6ee08aadb580341a4d80943741b80de16a88b5dd.moskvitin@samsung.com#endif
94458d4c6c35633437182289e3d226d156d31d3e801San Mehat				/* Enter this directory into the todo list */
94558d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (!(n = newDirTodo())) {
94658d4c6c35633437182289e3d226d156d31d3e801San Mehat					perror("No space for todo list");
94758d4c6c35633437182289e3d226d156d31d3e801San Mehat					return FSFATAL;
94858d4c6c35633437182289e3d226d156d31d3e801San Mehat				}
94958d4c6c35633437182289e3d226d156d31d3e801San Mehat				n->next = pendingDirectories;
95058d4c6c35633437182289e3d226d156d31d3e801San Mehat				n->dir = d;
95158d4c6c35633437182289e3d226d156d31d3e801San Mehat				pendingDirectories = n;
95258d4c6c35633437182289e3d226d156d31d3e801San Mehat			} else {
95358d4c6c35633437182289e3d226d156d31d3e801San Mehat				mod |= k = checksize(boot, fat, p, &dirent);
95458d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (k & FSDIRMOD)
95558d4c6c35633437182289e3d226d156d31d3e801San Mehat					mod |= THISMOD;
95658d4c6c35633437182289e3d226d156d31d3e801San Mehat			}
95758d4c6c35633437182289e3d226d156d31d3e801San Mehat			boot->NumFiles++;
95858d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
95958d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (mod & THISMOD) {
96058d4c6c35633437182289e3d226d156d31d3e801San Mehat			last *= 32;
96158d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (lseek64(f, off, SEEK_SET) != off
96258d4c6c35633437182289e3d226d156d31d3e801San Mehat			    || write(f, buffer, last) != last) {
96358d4c6c35633437182289e3d226d156d31d3e801San Mehat				perror("Unable to write directory");
96458d4c6c35633437182289e3d226d156d31d3e801San Mehat				return FSFATAL;
96558d4c6c35633437182289e3d226d156d31d3e801San Mehat			}
96658d4c6c35633437182289e3d226d156d31d3e801San Mehat			mod &= ~THISMOD;
96758d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
96858d4c6c35633437182289e3d226d156d31d3e801San Mehat	} while ((cl = fat[cl].next) >= CLUST_FIRST && cl < boot->NumClusters);
96958d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (invlfn || vallfn)
97058d4c6c35633437182289e3d226d156d31d3e801San Mehat		mod |= removede(f, boot, fat,
97158d4c6c35633437182289e3d226d156d31d3e801San Mehat				invlfn ? invlfn : vallfn, p,
97258d4c6c35633437182289e3d226d156d31d3e801San Mehat				invlfn ? invcl : valcl, -1, 0,
97358d4c6c35633437182289e3d226d156d31d3e801San Mehat				fullpath(dir), 1);
97458d4c6c35633437182289e3d226d156d31d3e801San Mehat	return mod & ~THISMOD;
97558d4c6c35633437182289e3d226d156d31d3e801San Mehat}
97658d4c6c35633437182289e3d226d156d31d3e801San Mehat
97758d4c6c35633437182289e3d226d156d31d3e801San Mehatint
97858d4c6c35633437182289e3d226d156d31d3e801San MehathandleDirTree(int dosfs, struct bootblock *boot, struct fatEntry *fat)
97958d4c6c35633437182289e3d226d156d31d3e801San Mehat{
98058d4c6c35633437182289e3d226d156d31d3e801San Mehat	int mod;
98158d4c6c35633437182289e3d226d156d31d3e801San Mehat
98258d4c6c35633437182289e3d226d156d31d3e801San Mehat	mod = readDosDirSection(dosfs, boot, fat, rootDir);
98358d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (mod & FSFATAL)
98458d4c6c35633437182289e3d226d156d31d3e801San Mehat		return FSFATAL;
98558d4c6c35633437182289e3d226d156d31d3e801San Mehat
98658d4c6c35633437182289e3d226d156d31d3e801San Mehat	/*
98758d4c6c35633437182289e3d226d156d31d3e801San Mehat	 * process the directory todo list
98858d4c6c35633437182289e3d226d156d31d3e801San Mehat	 */
98958d4c6c35633437182289e3d226d156d31d3e801San Mehat	while (pendingDirectories) {
99058d4c6c35633437182289e3d226d156d31d3e801San Mehat		struct dosDirEntry *dir = pendingDirectories->dir;
99158d4c6c35633437182289e3d226d156d31d3e801San Mehat		struct dirTodoNode *n = pendingDirectories->next;
99258d4c6c35633437182289e3d226d156d31d3e801San Mehat
99358d4c6c35633437182289e3d226d156d31d3e801San Mehat		/*
99458d4c6c35633437182289e3d226d156d31d3e801San Mehat		 * remove TODO entry now, the list might change during
99558d4c6c35633437182289e3d226d156d31d3e801San Mehat		 * directory reads
99658d4c6c35633437182289e3d226d156d31d3e801San Mehat		 */
99758d4c6c35633437182289e3d226d156d31d3e801San Mehat		freeDirTodo(pendingDirectories);
99858d4c6c35633437182289e3d226d156d31d3e801San Mehat		pendingDirectories = n;
99958d4c6c35633437182289e3d226d156d31d3e801San Mehat
100058d4c6c35633437182289e3d226d156d31d3e801San Mehat		/*
100158d4c6c35633437182289e3d226d156d31d3e801San Mehat		 * handle subdirectory
100258d4c6c35633437182289e3d226d156d31d3e801San Mehat		 */
100358d4c6c35633437182289e3d226d156d31d3e801San Mehat		mod |= readDosDirSection(dosfs, boot, fat, dir);
100458d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (mod & FSFATAL)
100558d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSFATAL;
100658d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
100758d4c6c35633437182289e3d226d156d31d3e801San Mehat
100858d4c6c35633437182289e3d226d156d31d3e801San Mehat	return mod;
100958d4c6c35633437182289e3d226d156d31d3e801San Mehat}
101058d4c6c35633437182289e3d226d156d31d3e801San Mehat
101158d4c6c35633437182289e3d226d156d31d3e801San Mehat/*
101258d4c6c35633437182289e3d226d156d31d3e801San Mehat * Try to reconnect a FAT chain into dir
101358d4c6c35633437182289e3d226d156d31d3e801San Mehat */
101458d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic u_char *lfbuf;
101558d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic cl_t lfcl;
101658d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic loff_t lfoff;
101758d4c6c35633437182289e3d226d156d31d3e801San Mehat
101858d4c6c35633437182289e3d226d156d31d3e801San Mehatint
101958d4c6c35633437182289e3d226d156d31d3e801San Mehatreconnect(int dosfs, struct bootblock *boot, struct fatEntry *fat, cl_t head)
102058d4c6c35633437182289e3d226d156d31d3e801San Mehat{
102158d4c6c35633437182289e3d226d156d31d3e801San Mehat	struct dosDirEntry d;
102258d4c6c35633437182289e3d226d156d31d3e801San Mehat	u_char *p;
102358d4c6c35633437182289e3d226d156d31d3e801San Mehat
102458d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (!ask(1, "Reconnect"))
102558d4c6c35633437182289e3d226d156d31d3e801San Mehat		return FSERROR;
102658d4c6c35633437182289e3d226d156d31d3e801San Mehat
102758d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (!lostDir) {
102858d4c6c35633437182289e3d226d156d31d3e801San Mehat		for (lostDir = rootDir->child; lostDir; lostDir = lostDir->next) {
102958d4c6c35633437182289e3d226d156d31d3e801San Mehat			if (!strcmp(lostDir->name, LOSTDIR))
103058d4c6c35633437182289e3d226d156d31d3e801San Mehat				break;
103158d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
103258d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (!lostDir) {		/* Create LOSTDIR?		XXX */
103358d4c6c35633437182289e3d226d156d31d3e801San Mehat			pwarn("No %s directory\n", LOSTDIR);
103458d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSERROR;
103558d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
103658d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
103758d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (!lfbuf) {
103858d4c6c35633437182289e3d226d156d31d3e801San Mehat		lfbuf = malloc(boot->ClusterSize);
103958d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (!lfbuf) {
104058d4c6c35633437182289e3d226d156d31d3e801San Mehat			perror("No space for buffer");
104158d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSFATAL;
104258d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
104358d4c6c35633437182289e3d226d156d31d3e801San Mehat		p = NULL;
104458d4c6c35633437182289e3d226d156d31d3e801San Mehat	} else
104558d4c6c35633437182289e3d226d156d31d3e801San Mehat		p = lfbuf;
104658d4c6c35633437182289e3d226d156d31d3e801San Mehat	while (1) {
104758d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (p)
104858d4c6c35633437182289e3d226d156d31d3e801San Mehat			for (; p < lfbuf + boot->ClusterSize; p += 32)
104958d4c6c35633437182289e3d226d156d31d3e801San Mehat				if (*p == SLOT_EMPTY
105058d4c6c35633437182289e3d226d156d31d3e801San Mehat				    || *p == SLOT_DELETED)
105158d4c6c35633437182289e3d226d156d31d3e801San Mehat					break;
105258d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (p && p < lfbuf + boot->ClusterSize)
105358d4c6c35633437182289e3d226d156d31d3e801San Mehat			break;
105458d4c6c35633437182289e3d226d156d31d3e801San Mehat		lfcl = p ? fat[lfcl].next : lostDir->head;
105558d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (lfcl < CLUST_FIRST || lfcl >= boot->NumClusters) {
105658d4c6c35633437182289e3d226d156d31d3e801San Mehat			/* Extend LOSTDIR?				XXX */
105758d4c6c35633437182289e3d226d156d31d3e801San Mehat			pwarn("No space in %s\n", LOSTDIR);
1058ea128a499ca81c7ca92751b7a4e8f6405c4b6322Shengzhe Zhao			lfcl = (lostDir->head < boot->NumClusters) ? lostDir->head : 0;
105958d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSERROR;
106058d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
106158d4c6c35633437182289e3d226d156d31d3e801San Mehat		lfoff = lfcl * boot->ClusterSize
106258d4c6c35633437182289e3d226d156d31d3e801San Mehat		    + boot->ClusterOffset * boot->BytesPerSec;
106358d4c6c35633437182289e3d226d156d31d3e801San Mehat		if (lseek64(dosfs, lfoff, SEEK_SET) != lfoff
106458d4c6c35633437182289e3d226d156d31d3e801San Mehat		    || read(dosfs, lfbuf, boot->ClusterSize) != boot->ClusterSize) {
106558d4c6c35633437182289e3d226d156d31d3e801San Mehat			perror("could not read LOST.DIR");
106658d4c6c35633437182289e3d226d156d31d3e801San Mehat			return FSFATAL;
106758d4c6c35633437182289e3d226d156d31d3e801San Mehat		}
106858d4c6c35633437182289e3d226d156d31d3e801San Mehat		p = lfbuf;
106958d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
107058d4c6c35633437182289e3d226d156d31d3e801San Mehat
107158d4c6c35633437182289e3d226d156d31d3e801San Mehat	boot->NumFiles++;
107258d4c6c35633437182289e3d226d156d31d3e801San Mehat	/* Ensure uniqueness of entry here!				XXX */
107358d4c6c35633437182289e3d226d156d31d3e801San Mehat	memset(&d, 0, sizeof d);
107458d4c6c35633437182289e3d226d156d31d3e801San Mehat	(void)snprintf(d.name, sizeof(d.name), "%u", head);
107558d4c6c35633437182289e3d226d156d31d3e801San Mehat	d.flags = 0;
107658d4c6c35633437182289e3d226d156d31d3e801San Mehat	d.head = head;
107758d4c6c35633437182289e3d226d156d31d3e801San Mehat	d.size = fat[head].length * boot->ClusterSize;
107858d4c6c35633437182289e3d226d156d31d3e801San Mehat
107958d4c6c35633437182289e3d226d156d31d3e801San Mehat	memset(p, 0, 32);
108058d4c6c35633437182289e3d226d156d31d3e801San Mehat	memset(p, ' ', 11);
108158d4c6c35633437182289e3d226d156d31d3e801San Mehat	memcpy(p, d.name, strlen(d.name));
108258d4c6c35633437182289e3d226d156d31d3e801San Mehat	p[26] = (u_char)d.head;
108358d4c6c35633437182289e3d226d156d31d3e801San Mehat	p[27] = (u_char)(d.head >> 8);
108458d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (boot->ClustMask == CLUST32_MASK) {
108558d4c6c35633437182289e3d226d156d31d3e801San Mehat		p[20] = (u_char)(d.head >> 16);
108658d4c6c35633437182289e3d226d156d31d3e801San Mehat		p[21] = (u_char)(d.head >> 24);
108758d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
108858d4c6c35633437182289e3d226d156d31d3e801San Mehat	p[28] = (u_char)d.size;
108958d4c6c35633437182289e3d226d156d31d3e801San Mehat	p[29] = (u_char)(d.size >> 8);
109058d4c6c35633437182289e3d226d156d31d3e801San Mehat	p[30] = (u_char)(d.size >> 16);
109158d4c6c35633437182289e3d226d156d31d3e801San Mehat	p[31] = (u_char)(d.size >> 24);
109258d4c6c35633437182289e3d226d156d31d3e801San Mehat	fat[head].flags |= FAT_USED;
109358d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (lseek64(dosfs, lfoff, SEEK_SET) != lfoff
109458d4c6c35633437182289e3d226d156d31d3e801San Mehat	    || write(dosfs, lfbuf, boot->ClusterSize) != boot->ClusterSize) {
109558d4c6c35633437182289e3d226d156d31d3e801San Mehat		perror("could not write LOST.DIR");
109658d4c6c35633437182289e3d226d156d31d3e801San Mehat		return FSFATAL;
109758d4c6c35633437182289e3d226d156d31d3e801San Mehat	}
109858d4c6c35633437182289e3d226d156d31d3e801San Mehat	return FSDIRMOD;
109958d4c6c35633437182289e3d226d156d31d3e801San Mehat}
110058d4c6c35633437182289e3d226d156d31d3e801San Mehat
110158d4c6c35633437182289e3d226d156d31d3e801San Mehatvoid
110258d4c6c35633437182289e3d226d156d31d3e801San Mehatfinishlf(void)
110358d4c6c35633437182289e3d226d156d31d3e801San Mehat{
110458d4c6c35633437182289e3d226d156d31d3e801San Mehat	if (lfbuf)
110558d4c6c35633437182289e3d226d156d31d3e801San Mehat		free(lfbuf);
110658d4c6c35633437182289e3d226d156d31d3e801San Mehat	lfbuf = NULL;
110758d4c6c35633437182289e3d226d156d31d3e801San Mehat}
1108