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