예제 #1
0
/*
 * subordinate_parse:
 *
 * @line: a line to parse
 *
 * Returns a pointer to a subordinate_range struct representing the values
 * in @line, or NULL on failure.  Note that the returned value should not
 * be freed by the caller.
 */
static void *subordinate_parse (const char *line)
{
	static struct subordinate_range range;
	static char rangebuf[1024];
	int i;
	char *cp;
	char *fields[NFIELDS];

	/*
	 * Copy the string to a temporary buffer so the substrings can
	 * be modified to be NULL terminated.
	 */
	if (strlen (line) >= sizeof rangebuf)
		return NULL;	/* fail if too long */
	strcpy (rangebuf, line);

	/*
	 * Save a pointer to the start of each colon separated
	 * field.  The fields are converted into NUL terminated strings.
	 */

	for (cp = rangebuf, i = 0; (i < NFIELDS) && (NULL != cp); i++) {
		fields[i] = cp;
		while (('\0' != *cp) && (':' != *cp)) {
			cp++;
		}

		if ('\0' != *cp) {
			*cp = '\0';
			cp++;
		} else {
			cp = NULL;
		}
	}

	/*
	 * There must be exactly NFIELDS colon separated fields or
	 * the entry is invalid.  Also, fields must be non-blank.
	 */
	if (i != NFIELDS || *fields[0] == '\0' || *fields[1] == '\0' || *fields[2] == '\0')
		return NULL;
	range.owner = fields[0];
	if (getulong (fields[1], &range.start) == 0)
		return NULL;
	if (getulong (fields[2], &range.count) == 0)
		return NULL;

	return &range;
}
예제 #2
0
/** 
 * 
 * 
 * @param input 
 * @param filename 
 */
void do_ppt(FILE *input,char *filename) {
	int itemsread=1;
	int rectype;
	long reclen;
	unsigned char recbuf[8];

	while(itemsread) {
		itemsread = catdoc_read(recbuf, 1, 8, input);
/* 		fprintf(stderr,"itemsread=%d: ",itemsread); */
/* 		for(i=0; i<8; i++) */
/* 			fprintf(stderr,"%02x ",recbuf[i]); */
/* 		fprintf(stderr,"\n"); */
		
		if (catdoc_eof(input)) {
			process_item(DOCUMENT_END,0,input);
			return;
		}
		if(itemsread < 8)
			break;
		rectype=getshort(recbuf,2);
		reclen=getulong(recbuf,4);
		if (reclen < 0) {
			return;
		}	
		process_item(rectype,reclen,input);
	}
}
예제 #3
0
파일: main.c 프로젝트: bartman/wmii
int
main(int argc, char *argv[]) {
	char *s;

	ARGBEGIN{
	default:
		usage();
	}ARGEND;

	setlocale(LC_CTYPE, "");

	initdisplay();

	s = ARGF();
	if(s && !getulong(s, &win.w))
		usage();
	if (!s)
		win.w = getfocus();

	if(argc)
		usage();

	click(&win, Pt(1, 1));

	XCloseDisplay(display);
	return 0;
}
예제 #4
0
struct map_range *get_map_ranges(int ranges, int argc, char **argv)
{
	struct map_range *mappings, *mapping;
	int idx, argidx;

	if (ranges < 0 || argc < 0) {
		fprintf(stderr, "%s: error calculating number of arguments\n", Prog);
		return NULL;
	}

	if (ranges != ((argc + 2) / 3)) {
		fprintf(stderr, "%s: ranges: %u is wrong for argc: %d\n", Prog, ranges, argc);
		return NULL;
	}

	if ((ranges * 3) > argc) {
		fprintf(stderr, "ranges: %u argc: %d\n",
			ranges, argc);
		fprintf(stderr,
			_( "%s: Not enough arguments to form %u mappings\n"),
			Prog, ranges);
		return NULL;
	}

	mappings = calloc(ranges, sizeof(*mappings));
	if (!mappings) {
		fprintf(stderr, _( "%s: Memory allocation failure\n"),
			Prog);
		exit(EXIT_FAILURE);
	}

	/* Gather up the ranges from the command line */
	mapping = mappings;
	for (idx = 0; idx < ranges; idx++, argidx += 3, mapping++) {
		if (!getulong(argv[argidx + 0], &mapping->upper))
			return NULL;
		if (!getulong(argv[argidx + 1], &mapping->lower))
			return NULL;
		if (!getulong(argv[argidx + 2], &mapping->count))
			return NULL;
	}
	return mappings;
}
예제 #5
0
파일: message.c 프로젝트: aztrock/wmii
static Client *
strclient(View *v, char *s) {
	ulong id;

	if(!strcmp(s, "sel"))
		return view_selclient(v);
	if(getulong(s, &id))
		return win2client(id);

	return nil;
}
예제 #6
0
파일: setfocus.c 프로젝트: GregBowyer/wmii
int
main(int argc, char *argv[]) {
	XWindow w;

	ARGBEGIN{
	}ARGEND;

	initdisplay();

	if(!getulong(EARGF(exit(1)), &w))
		exit(1);

	XSetInputFocus(display, w, RevertToParent, CurrentTime);
	XCloseDisplay(display);
}
예제 #7
0
파일: message.c 프로젝트: aztrock/wmii
static char*
select_frame(Frame *f, IxpMsg *m, int sym) {
	Frame *fp;
	Client *c;
	Area *a;
	char *s;
	ulong i;

	if(!f)
		return Ebadvalue;
	a = f->area;

	SET(fp);
	switch(sym) {
	case LUP:
		for(fp = a->frame; fp->anext; fp = fp->anext)
			if(fp->anext == f) break;
		break;
	case LDOWN:
		fp = f->anext;
		if(fp == nil)
			fp = a->frame;
		break;
	case LCLIENT:
		s = getword(m);
		if(s == nil || !getulong(s, &i))
			return "usage: select client <client>";
		c = win2client(i);
		if(c == nil)
			return "unknown client";
		fp = view_clientframe(f->view, c);
		break;
	default:
		assert(!"can't get here");
	}

	if(fp == nil)
		return "invalid selection";

	focus_frame(fp, False);
	frame_to_top(fp);
	if(f->view == screen->sel)
		restack_view(f->view);
	return nil;
}
예제 #8
0
파일: scandisk.c 프로젝트: mchav/ScanDisk
/*
 * worker function that checks and repairs incosistency errors
 */
void chkerr(struct direntry* dirent, char* filename, 
                   uint8_t *image_buf, struct bpb33* bpb) {
    int num_clusters = count_clusters(dirent, image_buf, bpb);
    uint32_t entry_size = getulong(dirent->deFileSize);

    // remove empty files
    if (entry_size == 0) {
        if (dirent->deAttributes == ATTR_NORMAL && dirent->deName[0] != 
            SLOT_EMPTY && dirent->deName[0] != SLOT_DELETED) {
            printf("Empty file found... removing. \n\n");
            dirent->deName[0] = SLOT_DELETED;
        }
    }
    
    // fix size inconsistencies
    if (num_clusters != 0 && entry_size < num_clusters - 512 ) { // take entry to be right
        printf("OUT OF BOUNDS: \n\tFilename: %s \n\t\tsize in directory entry: %d, size in FAT chain: %d.) \n\n", filename, entry_size, num_clusters);
        repair(dirent, image_buf, bpb, entry_size);
    } else if (entry_size > num_clusters) { // take FAT to be right
        printf("OUT OF BOUNDS: \n\tFilename: %s \n\t\tsize in directory entry: %d, size in FAT chain: %d \n\n", filename, entry_size, num_clusters);
        putulong(dirent->deFileSize, num_clusters);
    }
}
예제 #9
0
unsigned long getdef_ulong (const char *item, unsigned long dflt)
{
	struct itemdef *d;
	unsigned long val;

	if (!def_loaded) {
		def_load ();
	}

	d = def_find (item);
	if ((NULL == d) || (NULL == d->value)) {
		return dflt;
	}

	if (getulong (d->value, &val) == 0) {
		/* FIXME: we should have a getulong */
		fprintf (stderr,
		         _("configuration error - cannot parse %s value: '%s'"),
		         item, d->value);
		return dflt;
	}

	return val;
}
예제 #10
0
파일: main.c 프로젝트: heilage-nsk/configs
int
main(int argc, char *argv[]) {
	char *s;

	fmtinstall('r', errfmt);
extern int fmtevent(Fmt*);
	fmtinstall('E', fmtevent);

	ARGBEGIN{
	default:
		usage();
	}ARGEND;

	s = EARGF(usage());
	if(!getulong(s, &win.xid))
		usage();

	if(argc)
		usage();

	setlocale(LC_CTYPE, "");

	initdisplay();

	frame = findframe(&win);
	getwinsize(&frame);
	restrut();
	sethandler(&frame, &handlers);
	selectinput(&frame, StructureNotifyMask);

	running = true;
	xevent_loop();

	XCloseDisplay(display);
	return 0;
}
예제 #11
0
/** 
 * Reads next directory entry from file
 * 
 * @param name buffer for name converted to us-ascii should be at least 33 chars long
 * @param size size of file 
 * 
 * @return 0 if everything is ok -1 on error
 */
FILE *ole_readdir(FILE *f) {
	int i, nLen;
	unsigned char *oleBuf;
	oleEntry *e=NULL;
	long int chainMaxLen, chainCurrent;
	
	if ( properties == NULL || propCurNumber >= propNumber || f == NULL )
		return NULL;
	oleBuf=properties + propCurNumber*PROP_BLOCK_SIZE;
	if( !rightOleType(oleBuf))
		return NULL;
	if ((e = (oleEntry*)malloc(sizeof(oleEntry))) == NULL) {
		perror("Can\'t allocate memory");
		return NULL;
	}
	e->dirPos=oleBuf;
	e->type=getOleType(oleBuf);
	e->file=f;
	e->startBlock=getlong(oleBuf,0x74);
	e->blocks=NULL;
	
	nLen=getshort(oleBuf,0x40);
	for (i=0 ; i < nLen /2; i++)
		e->name[i]=(char)oleBuf[i*2];
	e->name[i]='\0';
	propCurNumber++;
	e->length=getulong(oleBuf,0x78);
/* Read sector chain for object */
	chainMaxLen = 25;
	e->numOfBlocks = 0;
	chainCurrent = e->startBlock;
	e->isBigBlock = (e->length >= 0x1000) || !strcmp(e->name, "Root Entry");
/* 	fprintf(stderr, "e->name=%s e->length=%ld\n", e->name, e->length); */
/* 	fprintf(stderr, "e->startBlock=%ld BBD=%p\n", e->startBlock, BBD); */
	if (e->startBlock >= 0 &&
		e->length >= 0 &&
		(e->startBlock <=
		 fileLength/(e->isBigBlock ? sectorSize : shortSectorSize))) {
		if((e->blocks=malloc(chainMaxLen*sizeof(long int))) == NULL ) {
			return NULL;
		}
		while(1) {
/* 			fprintf(stderr, "chainCurrent=%ld\n", chainCurrent); */
			e->blocks[e->numOfBlocks++] = chainCurrent;
			if (e->numOfBlocks >= chainMaxLen) {
				long int *newChain;
				chainMaxLen+=25;
				if ((newChain=realloc(e->blocks,
									  chainMaxLen*sizeof(long int))) != NULL)
					e->blocks=newChain;
				else {
					perror("Properties realloc error");
					free(e->blocks);
					e->blocks=NULL;
					return NULL;
				}
			}
			if ( e->isBigBlock ) {
				chainCurrent = getlong(BBD, chainCurrent*4);
			} else if ( SBD != NULL ) {
				chainCurrent = getlong(SBD, chainCurrent*4);
			} else {
				chainCurrent=-1;
			}
			if(chainCurrent <= 0 ||
			   chainCurrent >= ( e->isBigBlock ?
								 ((bbdNumBlocks*sectorSize)/4)
								 : ((sbdNumber*shortSectorSize)/4) ) ||
			   (e->numOfBlocks >
				e->length/(e->isBigBlock ? sectorSize : shortSectorSize))) {
/*   				fprintf(stderr, "chain End=%ld\n", chainCurrent);   */
				break;
			}
		}
	}
	
	if(e->length > (e->isBigBlock ? sectorSize : shortSectorSize)*e->numOfBlocks)
		e->length = (e->isBigBlock ? sectorSize : shortSectorSize)*e->numOfBlocks;
/* 	fprintf(stderr, "READDIR: e->name=%s e->numOfBlocks=%ld length=%ld\n", */
/* 					e->name, e->numOfBlocks, e->length); */
	
	return (FILE*)e;
}
예제 #12
0
void check_file_length(uint16_t cluster, uint8_t *image_buf, struct bpb33* bpb)
{
    struct direntry *dirent;
    int d, i;
    dirent = (struct direntry*) cluster_to_addr(cluster, image_buf, bpb);
    int clust_size = bpb->bpbBytesPerSec * bpb->bpbSecPerClust;

    while (1) {
        for (d = 0; d < clust_size; d += sizeof(struct direntry)) {
            char name[9];
            char extension[4];
            uint32_t size;
            uint16_t file_cluster;
            name[8] = ' ';
            extension[3] = ' ';
            memcpy(name, &(dirent->deName[0]), 8);
            memcpy(extension, dirent->deExtension, 3);

            if (name[0] == SLOT_EMPTY)
                return;

            /* skip over deleted entries */
            if (((uint8_t)name[0]) == SLOT_DELETED)
                continue;

            /* names are space padded - remove the spaces */
            for (i = 8; i > 0; i--) {
                if (name[i] == ' ')
                    name[i] = '\0';
                else
                    break;
            }

            /* remove the spaces from extensions */
            for (i = 3; i > 0; i--) {
                if (extension[i] == ' ')
                    extension[i] = '\0';
                else
                    break;
            }

            /* don't print "." or ".." directories */
            if (strcmp(name, ".") == 0) {
                dirent++;
                continue;
            }
            if (strcmp(name, "..") == 0) {
                dirent++;
                continue;
            }

            if ((dirent->deAttributes & ATTR_VOLUME) != 0) {
                continue;
            } else if ((dirent->deAttributes & ATTR_DIRECTORY) != 0) {
                file_cluster = getushort(dirent->deStartCluster);
                check_file_length(file_cluster, image_buf, bpb);
            } else {
                size = getulong(dirent->deFileSize);
                file_cluster = getushort(dirent->deStartCluster);
                uint16_t fat_size_clusters = get_file_length(file_cluster, image_buf, bpb);

                uint32_t size_clusters = (size + (clust_size - 1)) / clust_size;
                uint32_t fat_size = fat_size_clusters * clust_size;
                if (size_clusters != fat_size_clusters) {
                    printf("%s.%s %u %u\n", name, extension, size, fat_size);

                    uint16_t begin_cluster = file_cluster + size_clusters - 1;
                    uint16_t end_cluster = file_cluster + fat_size_clusters;
                    free_clusters(begin_cluster, end_cluster, image_buf, bpb);
                }
            }

            dirent++;
        }

        /* We've reached the end of the cluster for this directory. Where's the next cluster? */
        if (cluster == 0) {
            // root dir is special
            dirent++;
        } else {
            cluster = get_fat_entry(cluster, image_buf, bpb);
            dirent = (struct direntry*) cluster_to_addr(cluster, image_buf, bpb);
        }
    }
}
예제 #13
0
static int
mountmsdosfs(struct vnode *devvp, struct mount *mp)
{
	struct msdosfsmount *pmp;
	struct buf *bp;
	struct cdev *dev;
	union bootsector *bsp;
	struct byte_bpb33 *b33;
	struct byte_bpb50 *b50;
	struct byte_bpb710 *b710;
	u_int8_t SecPerClust;
	u_long clusters;
	int ronly, error;
	struct g_consumer *cp;
	struct bufobj *bo;

	bp = NULL;		/* This and pmp both used in error_exit. */
	pmp = NULL;
	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;

	dev = devvp->v_rdev;
	dev_ref(dev);
	DROP_GIANT();
	g_topology_lock();
	error = g_vfs_open(devvp, &cp, "msdosfs", ronly ? 0 : 1);
	g_topology_unlock();
	PICKUP_GIANT();
	VOP_UNLOCK(devvp, 0);
	if (error)
		goto error_exit;

	bo = &devvp->v_bufobj;

	/*
	 * Read the boot sector of the filesystem, and then check the
	 * boot signature.  If not a dos boot sector then error out.
	 *
	 * NOTE: 8192 is a magic size that works for ffs.
	 */
	error = bread(devvp, 0, 8192, NOCRED, &bp);
	if (error)
		goto error_exit;
	bp->b_flags |= B_AGE;
	bsp = (union bootsector *)bp->b_data;
	b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB;
	b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB;
	b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB;

#ifndef MSDOSFS_NOCHECKSIG
	if (bsp->bs50.bsBootSectSig0 != BOOTSIG0
	    || bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
		error = EINVAL;
		goto error_exit;
	}
#endif

	pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK | M_ZERO);
	pmp->pm_mountp = mp;
	pmp->pm_cp = cp;
	pmp->pm_bo = bo;

	lockinit(&pmp->pm_fatlock, 0, msdosfs_lock_msg, 0, 0);

	/*
	 * Initialize ownerships and permissions, since nothing else will
	 * initialize them iff we are mounting root.
	 */
	pmp->pm_uid = UID_ROOT;
	pmp->pm_gid = GID_WHEEL;
	pmp->pm_mask = pmp->pm_dirmask = S_IXUSR | S_IXGRP | S_IXOTH |
	    S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR;

	/*
	 * Experimental support for large MS-DOS filesystems.
	 * WARNING: This uses at least 32 bytes of kernel memory (which is not
	 * reclaimed until the FS is unmounted) for each file on disk to map
	 * between the 32-bit inode numbers used by VFS and the 64-bit
	 * pseudo-inode numbers used internally by msdosfs. This is only
	 * safe to use in certain controlled situations (e.g. read-only FS
	 * with less than 1 million files).
	 * Since the mappings do not persist across unmounts (or reboots), these
	 * filesystems are not suitable for exporting through NFS, or any other
	 * application that requires fixed inode numbers.
	 */
	vfs_flagopt(mp->mnt_optnew, "large", &pmp->pm_flags, MSDOSFS_LARGEFS);

	/*
	 * Compute several useful quantities from the bpb in the
	 * bootsector.  Copy in the dos 5 variant of the bpb then fix up
	 * the fields that are different between dos 5 and dos 3.3.
	 */
	SecPerClust = b50->bpbSecPerClust;
	pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec);
	if (pmp->pm_BytesPerSec < DEV_BSIZE) {
		error = EINVAL;
		goto error_exit;
	}
	pmp->pm_ResSectors = getushort(b50->bpbResSectors);
	pmp->pm_FATs = b50->bpbFATs;
	pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts);
	pmp->pm_Sectors = getushort(b50->bpbSectors);
	pmp->pm_FATsecs = getushort(b50->bpbFATsecs);
	pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack);
	pmp->pm_Heads = getushort(b50->bpbHeads);
	pmp->pm_Media = b50->bpbMedia;

	/* calculate the ratio of sector size to DEV_BSIZE */
	pmp->pm_BlkPerSec = pmp->pm_BytesPerSec / DEV_BSIZE;

	/*
	 * We don't check pm_Heads nor pm_SecPerTrack, because
	 * these may not be set for EFI file systems. We don't
	 * use these anyway, so we're unaffected if they are
	 * invalid.
	 */
	if (!pmp->pm_BytesPerSec || !SecPerClust) {
		error = EINVAL;
		goto error_exit;
	}

	if (pmp->pm_Sectors == 0) {
		pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
		pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
	} else {
		pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);
		pmp->pm_HugeSectors = pmp->pm_Sectors;
	}
	if (!(pmp->pm_flags & MSDOSFS_LARGEFS)) {
		if (pmp->pm_HugeSectors > 0xffffffff /
		    (pmp->pm_BytesPerSec / sizeof(struct direntry)) + 1) {
			/*
			 * We cannot deal currently with this size of disk
			 * due to fileid limitations (see msdosfs_getattr and
			 * msdosfs_readdir)
			 */
			error = EINVAL;
			vfs_mount_error(mp,
			    "Disk too big, try '-o large' mount option");
			goto error_exit;
		}
	}

	if (pmp->pm_RootDirEnts == 0) {
		if (pmp->pm_FATsecs
		    || getushort(b710->bpbFSVers)) {
			error = EINVAL;
#ifdef MSDOSFS_DEBUG
			printf("mountmsdosfs(): bad FAT32 filesystem\n");
#endif
			goto error_exit;
		}
		pmp->pm_fatmask = FAT32_MASK;
		pmp->pm_fatmult = 4;
		pmp->pm_fatdiv = 1;
		pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);
		if (getushort(b710->bpbExtFlags) & FATMIRROR)
			pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
		else
			pmp->pm_flags |= MSDOSFS_FATMIRROR;
	} else
		pmp->pm_flags |= MSDOSFS_FATMIRROR;

	/*
	 * Check a few values (could do some more):
	 * - logical sector size: power of 2, >= block size
	 * - sectors per cluster: power of 2, >= 1
	 * - number of sectors:   >= 1, <= size of partition
	 * - number of FAT sectors: >= 1
	 */
	if ( (SecPerClust == 0)
	  || (SecPerClust & (SecPerClust - 1))
	  || (pmp->pm_BytesPerSec < DEV_BSIZE)
	  || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1))
	  || (pmp->pm_HugeSectors == 0)
	  || (pmp->pm_FATsecs == 0)
	  || (SecPerClust * pmp->pm_BlkPerSec > MAXBSIZE / DEV_BSIZE)
	) {
		error = EINVAL;
		goto error_exit;
	}

	pmp->pm_HugeSectors *= pmp->pm_BlkPerSec;
	pmp->pm_HiddenSects *= pmp->pm_BlkPerSec;	/* XXX not used? */
	pmp->pm_FATsecs     *= pmp->pm_BlkPerSec;
	SecPerClust         *= pmp->pm_BlkPerSec;

	pmp->pm_fatblk = pmp->pm_ResSectors * pmp->pm_BlkPerSec;

	if (FAT32(pmp)) {
		pmp->pm_rootdirblk = getulong(b710->bpbRootClust);
		pmp->pm_firstcluster = pmp->pm_fatblk
			+ (pmp->pm_FATs * pmp->pm_FATsecs);
		pmp->pm_fsinfo = getushort(b710->bpbFSInfo) * pmp->pm_BlkPerSec;
	} else {
		pmp->pm_rootdirblk = pmp->pm_fatblk +
			(pmp->pm_FATs * pmp->pm_FATsecs);
		pmp->pm_rootdirsize = howmany(pmp->pm_RootDirEnts *
			sizeof(struct direntry), DEV_BSIZE); /* in blocks */
		pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
	}

	pmp->pm_maxcluster = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
	    SecPerClust + 1;
	pmp->pm_fatsize = pmp->pm_FATsecs * DEV_BSIZE;	/* XXX not used? */

	if (pmp->pm_fatmask == 0) {
		if (pmp->pm_maxcluster
		    <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) {
			/*
			 * This will usually be a floppy disk. This size makes
			 * sure that one fat entry will not be split across
			 * multiple blocks.
			 */
			pmp->pm_fatmask = FAT12_MASK;
			pmp->pm_fatmult = 3;
			pmp->pm_fatdiv = 2;
		} else {
			pmp->pm_fatmask = FAT16_MASK;
			pmp->pm_fatmult = 2;
			pmp->pm_fatdiv = 1;
		}
	}

	clusters = (pmp->pm_fatsize / pmp->pm_fatmult) * pmp->pm_fatdiv;
	if (pmp->pm_maxcluster >= clusters) {
#ifdef MSDOSFS_DEBUG
		printf("Warning: number of clusters (%ld) exceeds FAT "
		    "capacity (%ld)\n", pmp->pm_maxcluster + 1, clusters);
#endif
		pmp->pm_maxcluster = clusters - 1;
	}

	if (FAT12(pmp))
		pmp->pm_fatblocksize = 3 * 512;
	else
		pmp->pm_fatblocksize = PAGE_SIZE;
	pmp->pm_fatblocksize = roundup(pmp->pm_fatblocksize,
	    pmp->pm_BytesPerSec);
	pmp->pm_fatblocksec = pmp->pm_fatblocksize / DEV_BSIZE;
	pmp->pm_bnshift = ffs(DEV_BSIZE) - 1;

	/*
	 * Compute mask and shift value for isolating cluster relative byte
	 * offsets and cluster numbers from a file offset.
	 */
	pmp->pm_bpcluster = SecPerClust * DEV_BSIZE;
	pmp->pm_crbomask = pmp->pm_bpcluster - 1;
	pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1;

	/*
	 * Check for valid cluster size
	 * must be a power of 2
	 */
	if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) {
		error = EINVAL;
		goto error_exit;
	}

	/*
	 * Release the bootsector buffer.
	 */
	brelse(bp);
	bp = NULL;

	/*
	 * Check the fsinfo sector if we have one.  Silently fix up our
	 * in-core copy of fp->fsinxtfree if it is unknown (0xffffffff)
	 * or too large.  Ignore fp->fsinfree for now, since we need to
	 * read the entire FAT anyway to fill the inuse map.
	 */
	if (pmp->pm_fsinfo) {
		struct fsinfo *fp;

		if ((error = bread(devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec,
		    NOCRED, &bp)) != 0)
			goto error_exit;
		fp = (struct fsinfo *)bp->b_data;
		if (!bcmp(fp->fsisig1, "RRaA", 4)
		    && !bcmp(fp->fsisig2, "rrAa", 4)
		    && !bcmp(fp->fsisig3, "\0\0\125\252", 4)) {
			pmp->pm_nxtfree = getulong(fp->fsinxtfree);
			if (pmp->pm_nxtfree > pmp->pm_maxcluster)
				pmp->pm_nxtfree = CLUST_FIRST;
		} else
			pmp->pm_fsinfo = 0;
		brelse(bp);
		bp = NULL;
	}

	/*
	 * Finish initializing pmp->pm_nxtfree (just in case the first few
	 * sectors aren't properly reserved in the FAT).  This completes
	 * the fixup for fp->fsinxtfree, and fixes up the zero-initialized
	 * value if there is no fsinfo.  We will use pmp->pm_nxtfree
	 * internally even if there is no fsinfo.
	 */
	if (pmp->pm_nxtfree < CLUST_FIRST)
		pmp->pm_nxtfree = CLUST_FIRST;

	/*
	 * Allocate memory for the bitmap of allocated clusters, and then
	 * fill it in.
	 */
	pmp->pm_inusemap = malloc(howmany(pmp->pm_maxcluster + 1, N_INUSEBITS)
				  * sizeof(*pmp->pm_inusemap),
				  M_MSDOSFSFAT, M_WAITOK);

	/*
	 * fillinusemap() needs pm_devvp.
	 */
	pmp->pm_devvp = devvp;
	pmp->pm_dev = dev;

	/*
	 * Have the inuse map filled in.
	 */
	MSDOSFS_LOCK_MP(pmp);
	error = fillinusemap(pmp);
	MSDOSFS_UNLOCK_MP(pmp);
	if (error != 0)
		goto error_exit;

	/*
	 * If they want fat updates to be synchronous then let them suffer
	 * the performance degradation in exchange for the on disk copy of
	 * the fat being correct just about all the time.  I suppose this
	 * would be a good thing to turn on if the kernel is still flakey.
	 */
	if (mp->mnt_flag & MNT_SYNCHRONOUS)
		pmp->pm_flags |= MSDOSFSMNT_WAITONFAT;

	/*
	 * Finish up.
	 */
	if (ronly)
		pmp->pm_flags |= MSDOSFSMNT_RONLY;
	else {
		if ((error = markvoldirty(pmp, 1)) != 0) {
			(void)markvoldirty(pmp, 0);
			goto error_exit;
		}
		pmp->pm_fmod = 1;
	}
	mp->mnt_data =  pmp;
	mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
	mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
	MNT_ILOCK(mp);
	mp->mnt_flag |= MNT_LOCAL;
	mp->mnt_kern_flag |= MNTK_USES_BCACHE;
	MNT_IUNLOCK(mp);

	if (pmp->pm_flags & MSDOSFS_LARGEFS)
		msdosfs_fileno_init(mp);

	return 0;

error_exit:
	if (bp)
		brelse(bp);
	if (cp != NULL) {
		DROP_GIANT();
		g_topology_lock();
		g_vfs_close(cp);
		g_topology_unlock();
		PICKUP_GIANT();
	}
	if (pmp) {
		lockdestroy(&pmp->pm_fatlock);
		if (pmp->pm_inusemap)
			free(pmp->pm_inusemap, M_MSDOSFSFAT);
		free(pmp, M_MSDOSFSMNT);
		mp->mnt_data = NULL;
	}
	dev_rel(dev);
	return (error);
}
예제 #14
0
uint16_t print_dirent(struct direntry *dirent, int indent)
{
    uint16_t followclust = 0;

    int i;
    char name[9];
    char extension[4];
    uint32_t size;
    uint16_t file_cluster;
    name[8] = ' ';
    extension[3] = ' ';
    memcpy(name, &(dirent->deName[0]), 8);
    memcpy(extension, dirent->deExtension, 3);
    if (name[0] == SLOT_EMPTY)
    {
	return followclust;
    }

    /* skip over deleted entries */
    if (((uint8_t)name[0]) == SLOT_DELETED)
    {
	return followclust;
    }

    if (((uint8_t)name[0]) == 0x2E)
    {
	// dot entry ("." or "..")
	// skip it
        return followclust;
    }

    /* names are space padded - remove the spaces */
    for (i = 8; i > 0; i--) 
    {
	if (name[i] == ' ') 
	    name[i] = '\0';
	else 
	    break;
    }

    /* remove the spaces from extensions */
    for (i = 3; i > 0; i--) 
    {
	if (extension[i] == ' ') 
	    extension[i] = '\0';
	else 
	    break;
    }

    if ((dirent->deAttributes & ATTR_WIN95LFN) == ATTR_WIN95LFN)
    {
	// ignore any long file name extension entries
	//
	// printf("Win95 long-filename entry seq 0x%0x\n", dirent->deName[0]);
    }
    else if ((dirent->deAttributes & ATTR_VOLUME) != 0) 
    {
	printf("Volume: %s\n", name);
    } 
    else if ((dirent->deAttributes & ATTR_DIRECTORY) != 0) 
    {
        // don't deal with hidden directories; MacOS makes these
        // for trash directories and such; just ignore them.
	if ((dirent->deAttributes & ATTR_HIDDEN) != ATTR_HIDDEN)
        {
	    print_indent(indent);
    	    printf("%s/ (directory)\n", name);
            file_cluster = getushort(dirent->deStartCluster);
            followclust = file_cluster;
        }
    }
    else 
    {
        /*
         * a "regular" file entry
         * print attributes, size, starting cluster, etc.
         */
	int ro = (dirent->deAttributes & ATTR_READONLY) == ATTR_READONLY;
	int hidden = (dirent->deAttributes & ATTR_HIDDEN) == ATTR_HIDDEN;
	int sys = (dirent->deAttributes & ATTR_SYSTEM) == ATTR_SYSTEM;
	int arch = (dirent->deAttributes & ATTR_ARCHIVE) == ATTR_ARCHIVE;

	size = getulong(dirent->deFileSize);
	print_indent(indent);
	printf("%s.%s (%u bytes) (starting cluster %d) %c%c%c%c\n", 
	       name, extension, size, getushort(dirent->deStartCluster),
	       ro?'r':' ', 
               hidden?'h':' ', 
               sys?'s':' ', 
               arch?'a':' ');
    }

    return followclust;
}
예제 #15
0
void check_lost_files(int usedClusters[], uint16_t cluster, uint8_t *image_buf, struct bpb33* bpb)
{
    // A value of 1 means that the cluster is used somewhere.
    usedClusters[cluster] = 1;

    struct direntry *dirent;
    int d, i;
    dirent = (struct direntry*) cluster_to_addr(cluster, image_buf, bpb);
    int clust_size = bpb->bpbBytesPerSec * bpb->bpbSecPerClust;

    while (1) {
        for (d = 0; d < clust_size; d += sizeof(struct direntry)) {
            char name[9];
            char extension[4];
            uint32_t size;
            uint16_t file_cluster;
            name[8] = ' ';
            extension[3] = ' ';
            memcpy(name, &(dirent->deName[0]), 8);
            memcpy(extension, dirent->deExtension, 3);

            if (name[0] == SLOT_EMPTY)
                return;

            /* skip over deleted entries */
            if (((uint8_t)name[0]) == SLOT_DELETED)
                continue;

            /* names are space padded - remove the spaces */
            for (i = 8; i > 0; i--) {
                if (name[i] == ' ')
                    name[i] = '\0';
                else
                    break;
            }

            /* remove the spaces from extensions */
            for (i = 3; i > 0; i--) {
                if (extension[i] == ' ')
                    extension[i] = '\0';
                else
                    break;
            }

            /* don't print "." or ".." directories */
            if (strcmp(name, ".") == 0) {
                dirent++;
                continue;
            }
            if (strcmp(name, "..") == 0) {
                dirent++;
                continue;
            }

            if ((dirent->deAttributes & ATTR_VOLUME) != 0) {
            } else if ((dirent->deAttributes & ATTR_DIRECTORY) != 0) {
                file_cluster = getushort(dirent->deStartCluster);
                check_lost_files(usedClusters, file_cluster, image_buf, bpb);
            } else {
                /* We have a file. We should follow the file and remove all the used clusters from our collection! */
                size = getulong(dirent->deFileSize);
                uint16_t file_cluster_begin = getushort(dirent->deStartCluster);
                //uint16_t cluster, uint32_t bytes_remaining, uint8_t *image_buf, struct bpb33* bpb
                mark_file_clusters_used(usedClusters, file_cluster_begin, size, image_buf, bpb);
            }

            dirent++;
        }

        /* We've reached the end of the cluster for this directory. Where's the next cluster? */
        if (cluster == 0) {
            // root dir is special
            dirent++;
        } else {
            cluster = get_fat_entry(cluster, image_buf, bpb);
            dirent = (struct direntry*) cluster_to_addr(cluster, image_buf, bpb);
        }
    }
}
예제 #16
0
파일: message.c 프로젝트: aztrock/wmii
char*
select_area(Area *a, IxpMsg *m) {
	Frame *f;
	Area *ap;
	View *v;
	char *s;
	ulong i;
	int sym;

	v = a->view;
	s = getword(m);
	sym = getsym(s);
	
	switch(sym) {
	case LTOGGLE:
		if(!a->floating)
			ap = v->area;
		else if(v->revert && v->revert != a)
			ap = v->revert;
		else
			ap = v->area->next;
		break;
	case LUP:
	case LDOWN:
	case LCLIENT:
		return select_frame(a->sel, m, sym);
	case LLEFT:
		if(a->floating)
			return Ebadvalue;
		for(ap=v->area->next; ap->next; ap=ap->next)
			if(ap->next == a) break;
		break;
	case LRIGHT:
		if(a->floating)
			return Ebadvalue;
		ap = a->next;
		if(ap == nil)
			ap = v->area->next;
		break;
	case LTILDE:
		ap = v->area;
		break;
	default:
		if(!strcmp(s, "sel"))
			ap = v->sel;
		else {
			if(!getulong(s, &i) || i == 0)
				return Ebadvalue;
			for(ap=v->area->next; ap; ap=ap->next)
				if(--i == 0) break;
			if(i != 0)
				return Ebadvalue;
		}
		if((s = getword(m))) {
			if(!getulong(s, &i))
				return Ebadvalue;
			for(f = ap->frame; f; f = f->anext)
				if(--i == 0) break;
			if(i != 0)
				return Ebadvalue;
			focus_frame(f, True);
			return nil;
		}
	}

	focus_area(ap);
	return nil;
}
예제 #17
0
파일: fat.c 프로젝트: MaxRzv/VP2motion
int
fatfindfile(char *fname)
{
	int		rc, i, j;

	putstr("--MBR--\n");
	rc = readblock(DOSBBSECTOR, buf);

	if (dos_partition(0)->dp_typ != 6) {
		putstr("bad partition type\n");
		return -1;
	};

	start = getulong(dos_partition(0)->dp_start);
	dump_long("start ", start);

	putstr("--BOOT--\n");
	rc = readblock(start, buf);
	if (getushort(bootsector->bpbBytesPerSec) != 512) {
		putstr("bad sector size\n");
		return -1;
	};

	cluster_size = bootsector->bpbSecPerClust;
	dump_long("cluster_size ", cluster_size);

	start_fat = start + getushort(bootsector->bpbResSectors);
	dump_long("start_fat ", start_fat);

	root_size = getushort(bootsector->bpbRootDirEnts);
	root_size = (root_size * 32+511)/512;
	dump_long("root_size ", root_size);

	dump_long("FATsecs ", getushort(bootsector->bpbFATsecs));
	dump_long("FATs ", bootsector->bpbFATs);
	start_root = start_fat + bootsector->bpbFATs * getushort(bootsector->bpbFATsecs);
	start = start_root + root_size - 2 * cluster_size; /* first data sector for 0-based clusters */
	dump_long("start_root ", start_root);

	current_cluster = 0;

	putstr("--ROOT--\n");
	for(j = 0; j<root_size; j++) {
		rc = readblock(start_root + j, buf);
		for(i = 0; i<16; i++) {
			rc = (direntry(i)->deName)[0];
			if (rc == SLOT_EMPTY || rc == SLOT_DELETED) continue;

			rc = direntry(i)->deAttributes & (ATTR_VOLUME|ATTR_DIRECTORY);
			if (rc) continue;

			current_cluster = getushort(direntry(i)->deStartCluster);
			bytes_left = getulong(direntry(i)->deFileSize);

			putstr(direntry(i)->deName);
			putnl();
			/* printf("%12s %02x %ld %ld\n", 
					direntry(i)->deName, 
					direntry(i)->deAttributes & 0x18, 
					current_cluster,
					bytes_left
					); */

			if (!strncmp(direntry(i)->deName, fname, 11)) {
				break;
			};
			current_cluster = 0;
		};
		if (current_cluster) break;
	};

	if (!current_cluster) {
		putstr("file not found\n");
		return -1;
	};
	current_sector = 0;
	putstr("File ok\n");
	return 0;
}
예제 #18
0
main(int argc, char *argv[])
#endif
{
	char *fmt, *start;
	int fieldwidth, precision;
	char convch, nextch;
	char *format;

#if !defined(SHELL) && !defined(BUILTIN)
	setlocale (LC_ALL, "");
#endif

	/* Need to accept/ignore "--" option. */
	if (argc > 1 && strcmp(argv[1], "--") == 0) {
		argc--;
		argv++;
	}

	if (argc < 2) {
		usage();
		return (1);
	}

	format = *++argv;
	gargv = ++argv;

#define SKIP1	"#-+ 0"
#define SKIP2	"*0123456789"
	do {
		/*
		 * Basic algorithm is to scan the format string for conversion
		 * specifications -- once one is found, find out if the field
		 * width or precision is a '*'; if it is, gather up value. 
		 * Note, format strings are reused as necessary to use up the
		 * provided arguments, arguments of zero/null string are 
		 * provided to use up the format string.
		 */

		/* find next format specification */
		for (fmt = format; *fmt; fmt++) {
			switch (*fmt) {
			case '%':
				start = fmt++;

				if (*fmt == '%') {
					putchar ('%');
					break;
				} else if (*fmt == 'b') {
					char *p = getstr();
					if (print_escape_str(p)) {
						return (rval);
					}
					break;
				}

				/* skip to field width */
				for (; strchr(SKIP1, *fmt); ++fmt) ;
				fieldwidth = *fmt == '*' ? getint() : 0;

				/* skip to possible '.', get following precision */
				for (; strchr(SKIP2, *fmt); ++fmt) ;
				if (*fmt == '.')
					++fmt;
				precision = *fmt == '*' ? getint() : 0;

				for (; strchr(SKIP2, *fmt); ++fmt) ;
				if (!*fmt) {
					warnx ("missing format character");
					return(1);
				}

				convch = *fmt;
				nextch = *(fmt + 1);
				*(fmt + 1) = '\0';
				switch(convch) {
				case 'c': {
					char p = getchr();
					PF(start, p);
					break;
				}
				case 's': {
					char *p = getstr();
					PF(start, p);
					break;
				}
				case 'd':
				case 'i': {
					long p;
					char *f = mklong(start, convch);
					if (!f) {
						warnx("out of memory");
						return (1);
					}
					p = getlong();
					PF(f, p);
					break;
				}
				case 'o':
				case 'u':
				case 'x':
				case 'X': {
					unsigned long p;
					char *f = mklong(start, convch);
					if (!f) {
						warnx("out of memory");
						return (1);
					}
					p = getulong();
					PF(f, p);
					break;
				}
				case 'e':
				case 'E':
				case 'f':
				case 'g':
				case 'G': {
					double p = getdouble();
					PF(start, p);
					break;
				}
				default:
					warnx ("%s: invalid directive", start);
					return(1);
				}
				*(fmt + 1) = nextch;
				break;

			case '\\':
				fmt += print_escape(fmt);
				break;

			default:
				putchar (*fmt);
				break;
			}
		}
	} while (gargv > argv && *gargv);

	return (rval);
}
예제 #19
0
int
msdosfs_readdir(void *v)
{
	struct vop_readdir_args *ap = v;
	int error = 0;
	int diff;
	long n;
	int blsize;
	long on;
	long lost;
	long count;
	uint32_t dirsperblk;
	uint32_t cn, lbn;
	uint32_t fileno;
	long bias = 0;
	daddr64_t bn;
	struct buf *bp;
	struct denode *dep = VTODE(ap->a_vp);
	struct msdosfsmount *pmp = dep->de_pmp;
	struct direntry *dentp;
	struct dirent dirbuf;
	struct uio *uio = ap->a_uio;
	u_long *cookies = NULL;
	int ncookies = 0;
	off_t offset, wlast = -1;
	int chksum = -1;

#ifdef MSDOSFS_DEBUG
	printf("msdosfs_readdir(): vp %08x, uio %08x, cred %08x, eofflagp %08x\n",
	    ap->a_vp, uio, ap->a_cred, ap->a_eofflag);
#endif

	/*
	 * msdosfs_readdir() won't operate properly on regular files since
	 * it does i/o only with the filesystem vnode, and hence can
	 * retrieve the wrong block from the buffer cache for a plain file.
	 * So, fail attempts to readdir() on a plain file.
	 */
	if ((dep->de_Attributes & ATTR_DIRECTORY) == 0)
		return (ENOTDIR);

	/*
	 * To be safe, initialize dirbuf
	 */
	bzero(dirbuf.d_name, sizeof(dirbuf.d_name));

	/*
	 * If the user buffer is smaller than the size of one dos directory
	 * entry or the file offset is not a multiple of the size of a
	 * directory entry, then we fail the read.
	 */
	count = uio->uio_resid & ~(sizeof(struct direntry) - 1);
	offset = uio->uio_offset;
	if (count < sizeof(struct direntry) ||
	    (offset & (sizeof(struct direntry) - 1)))
		return (EINVAL);
	lost = uio->uio_resid - count;
	uio->uio_resid = count;

	if (ap->a_ncookies) {
		ncookies = uio->uio_resid / sizeof(struct direntry) + 3;
		cookies = malloc(ncookies * sizeof(u_long), M_TEMP, M_WAITOK);
		*ap->a_cookies = cookies;
		*ap->a_ncookies = ncookies;
	}

	dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry);

	/*
	 * If they are reading from the root directory then, we simulate
	 * the . and .. entries since these don't exist in the root
	 * directory.  We also set the offset bias to make up for having to
	 * simulate these entries. By this I mean that at file offset 64 we
	 * read the first entry in the root directory that lives on disk.
	 */
	if (dep->de_StartCluster == MSDOSFSROOT
	    || (FAT32(pmp) && dep->de_StartCluster == pmp->pm_rootdirblk)) {
#if 0
		printf("msdosfs_readdir(): going after . or .. in root dir, offset %d\n",
		    offset);
#endif
		bias = 2 * sizeof(struct direntry);
		if (offset < bias) {
			for (n = (int)offset / sizeof(struct direntry);
			     n < 2; n++) {
			        if (FAT32(pmp))
				        dirbuf.d_fileno = pmp->pm_rootdirblk;
				else
				        dirbuf.d_fileno = 1;
				dirbuf.d_type = DT_DIR;
				switch (n) {
				case 0:
					dirbuf.d_namlen = 1;
					strlcpy(dirbuf.d_name, ".",
					    sizeof dirbuf.d_name);
					break;
				case 1:
					dirbuf.d_namlen = 2;
					strlcpy(dirbuf.d_name, "..",
					    sizeof dirbuf.d_name);
					break;
				}
				dirbuf.d_reclen = DIRENT_SIZE(&dirbuf);
				if (uio->uio_resid < dirbuf.d_reclen)
					goto out;
				error = uiomove((caddr_t) &dirbuf,
						dirbuf.d_reclen, uio);
				if (error)
					goto out;
				offset += sizeof(struct direntry);
				if (cookies) {
					*cookies++ = offset;
					if (--ncookies <= 0)
						goto out;
				}
			}
		}
	}

	while (uio->uio_resid > 0) {
		lbn = de_cluster(pmp, offset - bias);
		on = (offset - bias) & pmp->pm_crbomask;
		n = min(pmp->pm_bpcluster - on, uio->uio_resid);
		diff = dep->de_FileSize - (offset - bias);
		if (diff <= 0)
			break;
		n = min(n, diff);
		if ((error = pcbmap(dep, lbn, &bn, &cn, &blsize)) != 0)
			break;
		error = bread(pmp->pm_devvp, bn, blsize, NOCRED, &bp);
		if (error) {
			brelse(bp);
			return (error);
		}
		n = min(n, blsize - bp->b_resid);

		/*
		 * Convert from dos directory entries to fs-independent
		 * directory entries.
		 */
		for (dentp = (struct direntry *)(bp->b_data + on);
		     (char *)dentp < bp->b_data + on + n;
		     dentp++, offset += sizeof(struct direntry)) {
#if 0
			printf("rd: dentp %08x prev %08x crnt %08x deName %02x attr %02x\n",
			    dentp, prev, crnt, dentp->deName[0], dentp->deAttributes);
#endif
			/*
			 * If this is an unused entry, we can stop.
			 */
			if (dentp->deName[0] == SLOT_EMPTY) {
				brelse(bp);
				goto out;
			}
			/*
			 * Skip deleted entries.
			 */
			if (dentp->deName[0] == SLOT_DELETED) {
				chksum = -1;
				wlast = -1;
				continue;
			}

			/*
			 * Handle Win95 long directory entries
			 */
			if (dentp->deAttributes == ATTR_WIN95) {
				struct winentry *wep;
				if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
					continue;
				wep = (struct winentry *)dentp;
				chksum = win2unixfn(wep, &dirbuf, chksum);
				if (wep->weCnt & WIN_LAST)
					wlast = offset;
				continue;
			}

			/*
			 * Skip volume labels
			 */
			if (dentp->deAttributes & ATTR_VOLUME) {
				chksum = -1;
				wlast = -1;
				continue;
			}

			/*
			 * This computation of d_fileno must match
			 * the computation of va_fileid in
			 * msdosfs_getattr.
			 */
			fileno = getushort(dentp->deStartCluster);
			if (FAT32(pmp))
			    fileno |= getushort(dentp->deHighClust) << 16;

			if (dentp->deAttributes & ATTR_DIRECTORY) {
				/* Special-case root */
				if (fileno == MSDOSFSROOT)  {
					fileno = FAT32(pmp) ?
					    pmp->pm_rootdirblk : 1;
				}

				dirbuf.d_fileno = fileno;
				dirbuf.d_type = DT_DIR;
			} else {
				if (getulong(dentp->deFileSize) == 0) {
					uint64_t fileno64;

					fileno64 = (cn == MSDOSFSROOT) ?
					    roottobn(pmp, 0) : cntobn(pmp, cn);

					fileno64 *= dirsperblk;
					fileno64 += dentp -
					    (struct direntry *)bp->b_data;

					fileno = fileidhash(fileno64);
				}

				dirbuf.d_fileno = fileno;
				dirbuf.d_type = DT_REG;
			}

			if (chksum != winChksum(dentp->deName))
				dirbuf.d_namlen = dos2unixfn(dentp->deName,
				    (u_char *)dirbuf.d_name,
				    pmp->pm_flags & MSDOSFSMNT_SHORTNAME);
			else
				dirbuf.d_name[dirbuf.d_namlen] = 0;
			chksum = -1;
			dirbuf.d_reclen = DIRENT_SIZE(&dirbuf);
			if (uio->uio_resid < dirbuf.d_reclen) {
				brelse(bp);
				/* Remember long-name offset. */
				if (wlast != -1)
					offset = wlast;
				goto out;
			}
			wlast = -1;
			error = uiomove((caddr_t) &dirbuf,
					dirbuf.d_reclen, uio);
			if (error) {
				brelse(bp);
				goto out;
			}
			if (cookies) {
				*cookies++ = offset + sizeof(struct direntry);
				if (--ncookies <= 0) {
					brelse(bp);
					goto out;
				}
			}
		}
		brelse(bp);
	}

out:
	/* Subtract unused cookies */
	if (ap->a_ncookies)
		*ap->a_ncookies -= ncookies;

	uio->uio_offset = offset;
	uio->uio_resid += lost;
	if (dep->de_FileSize - (offset - bias) <= 0)
		*ap->a_eofflag = 1;
	else
		*ap->a_eofflag = 0;
	return (error);
}
예제 #20
0
파일: message.c 프로젝트: aztrock/wmii
char *
message_root(void *p, IxpMsg *m) {
	Font *fn;
	char *s, *ret;
	ulong n;

	USED(p);
	ret = nil;
	s = getword(m);

	switch(getsym(s)) {
	case LQUIT:
		srv.running = 0;
		break;
	case LEXEC:
		execstr = smprint("exec %s", (char*)m->pos);
		srv.running = 0;
		break;
	case LVIEW:
		select_view((char*)m->pos);
		break;
	case LSELCOLORS:
		fprint(2, "%s: warning: selcolors have been removed\n", argv0);
		return Ebadcmd;
	case LFOCUSCOLORS:
		ret = parse_colors(m, &def.focuscolor);
		focus_view(screen, screen->sel);
		break;
	case LNORMCOLORS:
		ret = parse_colors(m, &def.normcolor);
		focus_view(screen, screen->sel);
		break;
	case LFONT:
		fn = loadfont((char*)m->pos);
		if(fn) {
			freefont(def.font);
			def.font = fn;
			resize_bar(screen);
		}else
			ret = "can't load font";
		focus_view(screen, screen->sel);
		break;
	case LBORDER:
		if(!getulong(getword(m), &n))
			return Ebadvalue;
		def.border = n;
		focus_view(screen, screen->sel);
		break;
	case LGRABMOD:
		s = getword(m);
		n = str2modmask(s);

		if((n & (Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) == 0)
			return Ebadvalue;

		utflcpy(def.grabmod, s, sizeof(def.grabmod));
		def.mod = n;
		break;
	default:
		return Ebadcmd;
	}
	return ret;
}
예제 #21
0
int
msdosfs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l, struct msdosfs_args *argp)
{
	struct msdosfsmount *pmp;
	struct buf *bp;
	dev_t dev = devvp->v_rdev;
	union bootsector *bsp;
	struct byte_bpb33 *b33;
	struct byte_bpb50 *b50;
	struct byte_bpb710 *b710;
	uint8_t SecPerClust;
	int	ronly, error, tmp;
	int	bsize;
	uint64_t psize;
	unsigned secsize;

	/* Flush out any old buffers remaining from a previous use. */
	if ((error = vinvalbuf(devvp, V_SAVE, l->l_cred, l, 0, 0)) != 0)
		return (error);

	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;

	bp  = NULL; /* both used in error_exit */
	pmp = NULL;

	error = fstrans_mount(mp);
	if (error)
		goto error_exit;

	error = getdisksize(devvp, &psize, &secsize);
	if (error) {
		if (argp->flags & MSDOSFSMNT_GEMDOSFS)
			goto error_exit;

		/* ok, so it failed.  we most likely don't need the info */
		secsize = DEV_BSIZE;
		psize = 0;
		error = 0;
	}

	if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
		bsize = secsize;
		if (bsize != 512) {
			DPRINTF(("Invalid block bsize %d for GEMDOS\n", bsize));
			error = EINVAL;
			goto error_exit;
		}
	} else
		bsize = 0;

	/*
	 * Read the boot sector of the filesystem, and then check the
	 * boot signature.  If not a dos boot sector then error out.
	 */
	if ((error = bread(devvp, 0, secsize, NOCRED, 0, &bp)) != 0)
		goto error_exit;
	bsp = (union bootsector *)bp->b_data;
	b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB;
	b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB;
	b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB;

	if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
		if (bsp->bs50.bsBootSectSig0 != BOOTSIG0
		    || bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
			DPRINTF(("bootsig0 %d bootsig1 %d\n", 
			    bsp->bs50.bsBootSectSig0,
			    bsp->bs50.bsBootSectSig1));
			error = EINVAL;
			goto error_exit;
		}
	}

	pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK);
	memset(pmp, 0, sizeof *pmp);
	pmp->pm_mountp = mp;

	/*
	 * Compute several useful quantities from the bpb in the
	 * bootsector.  Copy in the dos 5 variant of the bpb then fix up
	 * the fields that are different between dos 5 and dos 3.3.
	 */
	SecPerClust = b50->bpbSecPerClust;
	pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec);
	pmp->pm_ResSectors = getushort(b50->bpbResSectors);
	pmp->pm_FATs = b50->bpbFATs;
	pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts);
	pmp->pm_Sectors = getushort(b50->bpbSectors);
	pmp->pm_FATsecs = getushort(b50->bpbFATsecs);
	pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack);
	pmp->pm_Heads = getushort(b50->bpbHeads);
	pmp->pm_Media = b50->bpbMedia;

	if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
		/* XXX - We should probably check more values here */
    		if (!pmp->pm_BytesPerSec || !SecPerClust
	    		|| pmp->pm_SecPerTrack > 63) {
			DPRINTF(("bytespersec %d secperclust %d "
			    "secpertrack %d\n", 
			    pmp->pm_BytesPerSec, SecPerClust,
			    pmp->pm_SecPerTrack));
			error = EINVAL;
			goto error_exit;
		}
	}

	if (pmp->pm_Sectors == 0) {
		pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
		pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
	} else {
		pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);
		pmp->pm_HugeSectors = pmp->pm_Sectors;
	}

	if (pmp->pm_RootDirEnts == 0) {
		unsigned short vers = getushort(b710->bpbFSVers);
		/*
		 * Some say that bsBootSectSig[23] must be zero, but
		 * Windows does not require this and some digital cameras
		 * do not set these to zero.  Therefore, do not insist.
		 */
		if (pmp->pm_Sectors || pmp->pm_FATsecs || vers) {
			DPRINTF(("sectors %d fatsecs %lu vers %d\n",
			    pmp->pm_Sectors, pmp->pm_FATsecs, vers));
			error = EINVAL;
			goto error_exit;
		}
		pmp->pm_fatmask = FAT32_MASK;
		pmp->pm_fatmult = 4;
		pmp->pm_fatdiv = 1;
		pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);

		/* mirrorring is enabled if the FATMIRROR bit is not set */
		if ((getushort(b710->bpbExtFlags) & FATMIRROR) == 0)
			pmp->pm_flags |= MSDOSFS_FATMIRROR;
		else
			pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
	} else
		pmp->pm_flags |= MSDOSFS_FATMIRROR;

	if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
		if (FAT32(pmp)) {
			DPRINTF(("FAT32 for GEMDOS\n"));
			/*
			 * GEMDOS doesn't know FAT32.
			 */
			error = EINVAL;
			goto error_exit;
		}

		/*
		 * Check a few values (could do some more):
		 * - logical sector size: power of 2, >= block size
		 * - sectors per cluster: power of 2, >= 1
		 * - number of sectors:   >= 1, <= size of partition
		 */
		if ( (SecPerClust == 0)
		  || (SecPerClust & (SecPerClust - 1))
		  || (pmp->pm_BytesPerSec < bsize)
		  || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1))
		  || (pmp->pm_HugeSectors == 0)
		  || (pmp->pm_HugeSectors * (pmp->pm_BytesPerSec / bsize)
		      > psize)) {
			DPRINTF(("consistency checks for GEMDOS\n"));
			error = EINVAL;
			goto error_exit;
		}
		/*
		 * XXX - Many parts of the msdosfs driver seem to assume that
		 * the number of bytes per logical sector (BytesPerSec) will
		 * always be the same as the number of bytes per disk block
		 * Let's pretend it is.
		 */
		tmp = pmp->pm_BytesPerSec / bsize;
		pmp->pm_BytesPerSec  = bsize;
		pmp->pm_HugeSectors *= tmp;
		pmp->pm_HiddenSects *= tmp;
		pmp->pm_ResSectors  *= tmp;
		pmp->pm_Sectors     *= tmp;
		pmp->pm_FATsecs     *= tmp;
		SecPerClust         *= tmp;
	}

	/* Check that fs has nonzero FAT size */
	if (pmp->pm_FATsecs == 0) {
		DPRINTF(("FATsecs is 0\n"));
		error = EINVAL;
		goto error_exit;
	}

	pmp->pm_fatblk = pmp->pm_ResSectors;
	if (FAT32(pmp)) {
		pmp->pm_rootdirblk = getulong(b710->bpbRootClust);
		pmp->pm_firstcluster = pmp->pm_fatblk
			+ (pmp->pm_FATs * pmp->pm_FATsecs);
		pmp->pm_fsinfo = getushort(b710->bpbFSInfo);
	} else {
		pmp->pm_rootdirblk = pmp->pm_fatblk +
			(pmp->pm_FATs * pmp->pm_FATsecs);
		pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry)
				       + pmp->pm_BytesPerSec - 1)
			/ pmp->pm_BytesPerSec;/* in sectors */
		pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
	}

	pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
	    SecPerClust;
	pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1;
	pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec;

	if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
		if (pmp->pm_nmbrofclusters <= (0xff0 - 2)) {
			pmp->pm_fatmask = FAT12_MASK;
			pmp->pm_fatmult = 3;
			pmp->pm_fatdiv = 2;
		} else {
			pmp->pm_fatmask = FAT16_MASK;
			pmp->pm_fatmult = 2;
			pmp->pm_fatdiv = 1;
		}
	} else if (pmp->pm_fatmask == 0) {
		if (pmp->pm_maxcluster
		    <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) {
			/*
			 * This will usually be a floppy disk. This size makes
			 * sure that one FAT entry will not be split across
			 * multiple blocks.
			 */
			pmp->pm_fatmask = FAT12_MASK;
			pmp->pm_fatmult = 3;
			pmp->pm_fatdiv = 2;
		} else {
			pmp->pm_fatmask = FAT16_MASK;
			pmp->pm_fatmult = 2;
			pmp->pm_fatdiv = 1;
		}
	}
	if (FAT12(pmp))
		pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec;
	else
		pmp->pm_fatblocksize = MAXBSIZE;

	pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec;
	pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1;

	/*
	 * Compute mask and shift value for isolating cluster relative byte
	 * offsets and cluster numbers from a file offset.
	 */
	pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSec;
	pmp->pm_crbomask = pmp->pm_bpcluster - 1;
	pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1;

	/*
	 * Check for valid cluster size
	 * must be a power of 2
	 */
	if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) {
		DPRINTF(("bpcluster %lu cnshift %lu\n", 
		    pmp->pm_bpcluster, pmp->pm_cnshift));
		error = EINVAL;
		goto error_exit;
	}

	/*
	 * Cluster size must be within limit of MAXBSIZE.
	 * Many FAT filesystems will not have clusters larger than
	 * 32KiB due to limits in Windows versions before Vista.
	 */
	if (pmp->pm_bpcluster > MAXBSIZE) {
		DPRINTF(("bpcluster %lu > MAXBSIZE %d\n",
		    pmp->pm_bpcluster, MAXBSIZE));
		error = EINVAL;
		goto error_exit;
	}

	/*
	 * Release the bootsector buffer.
	 */
	brelse(bp, BC_AGE);
	bp = NULL;

	/*
	 * Check FSInfo.
	 */
	if (pmp->pm_fsinfo) {
		struct fsinfo *fp;

		/*
		 * XXX	If the fsinfo block is stored on media with
		 *	2KB or larger sectors, is the fsinfo structure
		 *	padded at the end or in the middle?
		 */
		if ((error = bread(devvp, de_bn2kb(pmp, pmp->pm_fsinfo),
		    pmp->pm_BytesPerSec, NOCRED, 0, &bp)) != 0)
			goto error_exit;
		fp = (struct fsinfo *)bp->b_data;
		if (!memcmp(fp->fsisig1, "RRaA", 4)
		    && !memcmp(fp->fsisig2, "rrAa", 4)
		    && !memcmp(fp->fsisig3, "\0\0\125\252", 4)
		    && !memcmp(fp->fsisig4, "\0\0\125\252", 4))
			pmp->pm_nxtfree = getulong(fp->fsinxtfree);
		else
			pmp->pm_fsinfo = 0;
		brelse(bp, 0);
		bp = NULL;
	}

	/*
	 * Check and validate (or perhaps invalidate?) the fsinfo structure?
	 * XXX
	 */
	if (pmp->pm_fsinfo) {
		if ((pmp->pm_nxtfree == 0xffffffffUL) ||
		    (pmp->pm_nxtfree > pmp->pm_maxcluster))
			pmp->pm_fsinfo = 0;
	}

	/*
	 * Allocate memory for the bitmap of allocated clusters, and then
	 * fill it in.
	 */
	pmp->pm_inusemap = malloc(((pmp->pm_maxcluster + N_INUSEBITS)
				   / N_INUSEBITS)
				  * sizeof(*pmp->pm_inusemap),
				  M_MSDOSFSFAT, M_WAITOK);

	/*
	 * fillinusemap() needs pm_devvp.
	 */
	pmp->pm_dev = dev;
	pmp->pm_devvp = devvp;

	/*
	 * Have the inuse map filled in.
	 */
	if ((error = fillinusemap(pmp)) != 0) {
		DPRINTF(("fillinusemap %d\n", error));
		goto error_exit;
	}

	/*
	 * If they want FAT updates to be synchronous then let them suffer
	 * the performance degradation in exchange for the on disk copy of
	 * the FAT being correct just about all the time.  I suppose this
	 * would be a good thing to turn on if the kernel is still flakey.
	 */
	if (mp->mnt_flag & MNT_SYNCHRONOUS)
		pmp->pm_flags |= MSDOSFSMNT_WAITONFAT;

	/*
	 * Finish up.
	 */
	if (ronly)
		pmp->pm_flags |= MSDOSFSMNT_RONLY;
	else
		pmp->pm_fmod = 1;
	mp->mnt_data = pmp;
	mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev;
	mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_MSDOS);
	mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
	mp->mnt_stat.f_namemax = MSDOSFS_NAMEMAX(pmp);
	mp->mnt_flag |= MNT_LOCAL;
	mp->mnt_dev_bshift = pmp->pm_bnshift;
	mp->mnt_fs_bshift = pmp->pm_cnshift;

	/*
	 * If we ever do quotas for DOS filesystems this would be a place
	 * to fill in the info in the msdosfsmount structure. You dolt,
	 * quotas on dos filesystems make no sense because files have no
	 * owners on dos filesystems. of course there is some empty space
	 * in the directory entry where we could put uid's and gid's.
	 */

	spec_node_setmountedfs(devvp, mp);

	return (0);

error_exit:
	fstrans_unmount(mp);
	if (bp)
		brelse(bp, BC_AGE);
	if (pmp) {
		if (pmp->pm_inusemap)
			free(pmp->pm_inusemap, M_MSDOSFSFAT);
		free(pmp, M_MSDOSFSMNT);
		mp->mnt_data = NULL;
	}
	return (error);
}
예제 #22
0
int
msdosfs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p,
    struct msdosfs_args *argp)
{
	struct msdosfsmount *pmp;
	struct buf *bp;
	dev_t dev = devvp->v_rdev;
	union bootsector *bsp;
	struct byte_bpb33 *b33;
	struct byte_bpb50 *b50;
	struct byte_bpb710 *b710;
	extern struct vnode *rootvp;
	u_int8_t SecPerClust;
	int	ronly, error, bmapsiz;
	uint32_t fat_max_clusters;

	/*
	 * Disallow multiple mounts of the same device.
	 * Disallow mounting of a device that is currently in use
	 * (except for root, which might share swap device for miniroot).
	 * Flush out any old buffers remaining from a previous use.
	 */
	if ((error = vfs_mountedon(devvp)) != 0)
		return (error);
	if (vcount(devvp) > 1 && devvp != rootvp)
		return (EBUSY);
	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
	error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
	VOP_UNLOCK(devvp, 0, p);
	if (error)
		return (error);

	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
	error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
	if (error)
		return (error);

	bp  = NULL; /* both used in error_exit */
	pmp = NULL;

	/*
	 * Read the boot sector of the filesystem, and then check the
	 * boot signature.  If not a dos boot sector then error out.
	 */
	if ((error = bread(devvp, 0, 4096, NOCRED, &bp)) != 0)
		goto error_exit;
	bp->b_flags |= B_AGE;
	bsp = (union bootsector *)bp->b_data;
	b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB;
	b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB;
	b710 = (struct byte_bpb710 *)bsp->bs710.bsPBP;

	pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK | M_ZERO);
	pmp->pm_mountp = mp;

	/*
	 * Compute several useful quantities from the bpb in the
	 * bootsector.  Copy in the dos 5 variant of the bpb then fix up
	 * the fields that are different between dos 5 and dos 3.3.
	 */
	SecPerClust = b50->bpbSecPerClust;
	pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec);
	pmp->pm_ResSectors = getushort(b50->bpbResSectors);
	pmp->pm_FATs = b50->bpbFATs;
	pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts);
	pmp->pm_Sectors = getushort(b50->bpbSectors);
	pmp->pm_FATsecs = getushort(b50->bpbFATsecs);
	pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack);
	pmp->pm_Heads = getushort(b50->bpbHeads);
	pmp->pm_Media = b50->bpbMedia;

	/* Determine the number of DEV_BSIZE blocks in a MSDOSFS sector */
	pmp->pm_BlkPerSec = pmp->pm_BytesPerSec / DEV_BSIZE;

    	if (!pmp->pm_BytesPerSec || !SecPerClust || pmp->pm_SecPerTrack > 64) {
		error = EFTYPE;
		goto error_exit;
	}

	if (pmp->pm_Sectors == 0) {
		pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
		pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
	} else {
		pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);
		pmp->pm_HugeSectors = pmp->pm_Sectors;
	}

	if (pmp->pm_RootDirEnts == 0) {
		if (pmp->pm_Sectors || pmp->pm_FATsecs ||
		    getushort(b710->bpbFSVers)) {
		        error = EINVAL;
			goto error_exit;
		}
		pmp->pm_fatmask = FAT32_MASK;
		pmp->pm_fatmult = 4;
		pmp->pm_fatdiv = 1;
		pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);
		if (getushort(b710->bpbExtFlags) & FATMIRROR)
		        pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
		else
		        pmp->pm_flags |= MSDOSFS_FATMIRROR;
	} else
	        pmp->pm_flags |= MSDOSFS_FATMIRROR;

	/*
	 * More sanity checks:
	 *	MSDOSFS sectors per cluster: >0 && power of 2
	 *	MSDOSFS sector size: >= DEV_BSIZE && power of 2
	 *	HUGE sector count: >0
	 * 	FAT sectors: >0
	 */
	if ((SecPerClust == 0) || (SecPerClust & (SecPerClust - 1)) ||
	    (pmp->pm_BytesPerSec < DEV_BSIZE) ||
	    (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1)) ||
	    (pmp->pm_HugeSectors == 0) || (pmp->pm_FATsecs == 0)) {
		error = EINVAL;
		goto error_exit;
	}		
	
	pmp->pm_HugeSectors *= pmp->pm_BlkPerSec;
	pmp->pm_HiddenSects *= pmp->pm_BlkPerSec;
	pmp->pm_FATsecs *= pmp->pm_BlkPerSec;
	pmp->pm_fatblk = pmp->pm_ResSectors * pmp->pm_BlkPerSec;
	SecPerClust *= pmp->pm_BlkPerSec;

	if (FAT32(pmp)) {
	        pmp->pm_rootdirblk = getulong(b710->bpbRootClust);
		pmp->pm_firstcluster = pmp->pm_fatblk
		        + (pmp->pm_FATs * pmp->pm_FATsecs);
		pmp->pm_fsinfo = getushort(b710->bpbFSInfo) * pmp->pm_BlkPerSec;
	} else {
	        pmp->pm_rootdirblk = pmp->pm_fatblk +
		        (pmp->pm_FATs * pmp->pm_FATsecs);
		pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry)
				       + DEV_BSIZE - 1) / DEV_BSIZE;
		pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
	}

	pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
	    SecPerClust;
	pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1;
	pmp->pm_fatsize = pmp->pm_FATsecs * DEV_BSIZE;

	if (pmp->pm_fatmask == 0) {
		if (pmp->pm_maxcluster
		    <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) {
			/*
			 * This will usually be a floppy disk. This size makes
			 * sure that one fat entry will not be split across
			 * multiple blocks.
			 */
			pmp->pm_fatmask = FAT12_MASK;
			pmp->pm_fatmult = 3;
			pmp->pm_fatdiv = 2;
		} else {
			pmp->pm_fatmask = FAT16_MASK;
			pmp->pm_fatmult = 2;
			pmp->pm_fatdiv = 1;
		}
	}
	if (FAT12(pmp))
		pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec;
	else
		pmp->pm_fatblocksize = MAXBSIZE;

	/*
	 * We now have the number of sectors in each FAT, so can work
	 * out how many clusters can be represented in a FAT.  Let's
	 * make sure the file system doesn't claim to have more clusters
	 * than this.
	 *
	 * We perform the calculation like we do to avoid integer overflow.
	 *
	 * This will give us a count of clusters.  They are numbered
	 * from 0, so the max cluster value is one less than the value
	 * we end up with.
	 */
	fat_max_clusters = pmp->pm_fatsize / pmp->pm_fatmult;
	fat_max_clusters *= pmp->pm_fatdiv;
	if (pmp->pm_maxcluster >= fat_max_clusters) {
#ifndef SMALL_KERNEL
		printf("msdosfs: reducing max cluster to %d from %d "
		    "due to FAT size\n", fat_max_clusters - 1,
		    pmp->pm_maxcluster);
#endif
		pmp->pm_maxcluster = fat_max_clusters - 1;
	}

	pmp->pm_fatblocksec = pmp->pm_fatblocksize / DEV_BSIZE;
	pmp->pm_bnshift = ffs(DEV_BSIZE) - 1;

	/*
	 * Compute mask and shift value for isolating cluster relative byte
	 * offsets and cluster numbers from a file offset.
	 */
	pmp->pm_bpcluster = SecPerClust * DEV_BSIZE;
	pmp->pm_crbomask = pmp->pm_bpcluster - 1;
	pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1;

	/*
	 * Check for valid cluster size
	 * must be a power of 2
	 */
	if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) {
		error = EFTYPE;
		goto error_exit;
	}

	/*
	 * Release the bootsector buffer.
	 */
	brelse(bp);
	bp = NULL;

	/*
	 * Check FSInfo
	 */
	if (pmp->pm_fsinfo) {
	        struct fsinfo *fp;

		if ((error = bread(devvp, pmp->pm_fsinfo, fsi_size(pmp),
		    NOCRED, &bp)) != 0)
		        goto error_exit;
		fp = (struct fsinfo *)bp->b_data;
		if (!bcmp(fp->fsisig1, "RRaA", 4)
		    && !bcmp(fp->fsisig2, "rrAa", 4)
		    && !bcmp(fp->fsisig3, "\0\0\125\252", 4)
		    && !bcmp(fp->fsisig4, "\0\0\125\252", 4))
		        /* Valid FSInfo. */
			;
		else
		        pmp->pm_fsinfo = 0;
		/* XXX make sure this tiny buf doesn't come back in fillinusemap! */
		SET(bp->b_flags, B_INVAL);
		brelse(bp);
		bp = NULL;
	}

	/*
	 * Check and validate (or perhaps invalidate?) the fsinfo structure? XXX
	 */

	/*
	 * Allocate memory for the bitmap of allocated clusters, and then
	 * fill it in.
	 */
	bmapsiz = (pmp->pm_maxcluster + N_INUSEBITS - 1) / N_INUSEBITS;
	if (bmapsiz == 0 || SIZE_MAX / bmapsiz < sizeof(*pmp->pm_inusemap)) {
		/* detect multiplicative integer overflow */
		error = EINVAL;
		goto error_exit;
	}
	pmp->pm_inusemap = malloc(bmapsiz * sizeof(*pmp->pm_inusemap),
	    M_MSDOSFSFAT, M_WAITOK | M_CANFAIL);
	if (pmp->pm_inusemap == NULL) {
		error = EINVAL;
		goto error_exit;
	}

	/*
	 * fillinusemap() needs pm_devvp.
	 */
	pmp->pm_dev = dev;
	pmp->pm_devvp = devvp;

	/*
	 * Have the inuse map filled in.
	 */
	if ((error = fillinusemap(pmp)) != 0)
		goto error_exit;

	/*
	 * If they want fat updates to be synchronous then let them suffer
	 * the performance degradation in exchange for the on disk copy of
	 * the fat being correct just about all the time.  I suppose this
	 * would be a good thing to turn on if the kernel is still flakey.
	 */
	if (mp->mnt_flag & MNT_SYNCHRONOUS)
		pmp->pm_flags |= MSDOSFSMNT_WAITONFAT;

	/*
	 * Finish up.
	 */
	if (ronly)
		pmp->pm_flags |= MSDOSFSMNT_RONLY;
	else
		pmp->pm_fmod = 1;
	mp->mnt_data = (qaddr_t)pmp;
        mp->mnt_stat.f_fsid.val[0] = (long)dev;
        mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
#ifdef QUOTA
	/*
	 * If we ever do quotas for DOS filesystems this would be a place
	 * to fill in the info in the msdosfsmount structure. You dolt,
	 * quotas on dos filesystems make no sense because files have no
	 * owners on dos filesystems. of course there is some empty space
	 * in the directory entry where we could put uid's and gid's.
	 */
#endif
	devvp->v_specmountpoint = mp;

	return (0);

error_exit:
	devvp->v_specmountpoint = NULL;
	if (bp)
		brelse(bp);

	vn_lock(devvp, LK_EXCLUSIVE|LK_RETRY, p);
	(void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
	VOP_UNLOCK(devvp, 0, p);

	if (pmp) {
		if (pmp->pm_inusemap)
			free(pmp->pm_inusemap, M_MSDOSFSFAT);
		free(pmp, M_MSDOSFSMNT);
		mp->mnt_data = (qaddr_t)0;
	}
	return (error);
}
예제 #23
0
/************PRINT_DIRENT***************/
uint16_t print_dirent(struct direntry *dirent, int indent, uint8_t *image_buf, struct bpb33* bpb, int *refcount )
{
    uint16_t followclust = 0;

    int i;
    char name[9];
    char extension[4];
    uint32_t size;
    uint16_t file_cluster;
    name[8] = ' ';
    extension[3] = ' ';
    memcpy(name, &(dirent->deName[0]), 8);
    memcpy(extension, dirent->deExtension, 3);
    if (name[0] == SLOT_EMPTY)
    {
	return followclust;
    }

    /* skip over deleted entries */
    if (((uint8_t)name[0]) == SLOT_DELETED)
    {
	return followclust;
    }

    if (((uint8_t)name[0]) == 0x2E)
    {
	// dot entry ("." or "..")
	// skip it
        return followclust;
    }

    /* names are space padded - remove the spaces */
    for (i = 8; i > 0; i--) 
    {
	if (name[i] == ' ') 
	    name[i] = '\0';
	else 
	    break;
    }

    /* remove the spaces from extensions */
    for (i = 3; i > 0; i--) 
    {
	if (extension[i] == ' ') 
	    extension[i] = '\0';
	else 
	    break;
    }

    if ((dirent->deAttributes & ATTR_WIN95LFN) == ATTR_WIN95LFN)
    {
	// ignore any long file name extension entries
	//
	// printf("Win95 long-filename entry seq 0x%0x\n", dirent->deName[0]);
    }
    else if ((dirent->deAttributes & ATTR_VOLUME) != 0) 
    {
	printf("Volume: %s\n", name);
    } 
    else if ((dirent->deAttributes & ATTR_DIRECTORY) != 0) 
    {
        // don't deal with hidden directories; MacOS makes these
        // for trash directories and such; just ignore them.
	if ((dirent->deAttributes & ATTR_HIDDEN) != ATTR_HIDDEN)
        {
	    print_indent(indent);
    	    printf("%s/ (directory)\n", name);
            file_cluster = getushort(dirent->deStartCluster);
            followclust = file_cluster;
        }
    }
    else 
    {
        /*
         * a "regular" file entry
         * print attributes, size, starting cluster, etc.
         */
	int ro = (dirent->deAttributes & ATTR_READONLY) == ATTR_READONLY;
	int hidden = (dirent->deAttributes & ATTR_HIDDEN) == ATTR_HIDDEN;
	int sys = (dirent->deAttributes & ATTR_SYSTEM) == ATTR_SYSTEM;
	int arch = (dirent->deAttributes & ATTR_ARCHIVE) == ATTR_ARCHIVE;

	size = getulong(dirent->deFileSize);
	print_indent(indent);
	printf("%s.%s (%u bytes) (starting cluster %d) %c%c%c%c\n", 
	       name, extension, size, getushort(dirent->deStartCluster),
	       ro?'r':' ', 
               hidden?'h':' ', 
               sys?'s':' ', 
               arch?'a':' ');

		
		int cluster_count = 0;
        
		uint16_t curr_cluster = getushort(dirent->deStartCluster);
		uint16_t original_cluster = curr_cluster;
        
        uint16_t previous;

        while(is_valid_cluster(curr_cluster,bpb))
		{
            refcount[curr_cluster]++;
			if(refcount[curr_cluster] > 1) //problem
			{
				printf("ERROR REFCOUNT > 1 FOR:  %d, refcount = %d\n", curr_cluster, refcount[curr_cluster]);  
				dirent->deName[0] = SLOT_DELETED;
				refcount[curr_cluster]--;
			}

			previous = curr_cluster;
			curr_cluster = get_fat_entry(curr_cluster, image_buf, bpb);
			if(previous == curr_cluster) //points to itself
			{
				printf("ERROR POINTS TO SELF\n");
				set_fat_entry(curr_cluster, FAT12_MASK & CLUST_EOFS, image_buf, bpb);
				cluster_count++;
				break;
			}
			if(curr_cluster == (FAT12_MASK & CLUST_BAD))
			{
				printf("BAD CLUSTER\n");
				set_fat_entry(curr_cluster, FAT12_MASK & CLUST_FREE, image_buf, bpb);
				set_fat_entry(previous, FAT12_MASK & CLUST_EOFS, image_buf, bpb);
				break;
			}
			cluster_count++;
		}
		
		int clusters = 0;
		if(size%512 == 0)
		{
			clusters = size/512;
		}
		else
		{
			clusters = (size/512)+1;
		}
		if(clusters < cluster_count)
		{
			printf("ERROR: FILE SIZE TOO SMALL FOR NUM CLUSTERS\n");
			curr_cluster = get_fat_entry(original_cluster+clusters - 1, image_buf, bpb);
			printf("FIXED \n");
			while(is_valid_cluster(curr_cluster, bpb))
			{
				previous = curr_cluster;
				set_fat_entry(previous, FAT12_MASK & CLUST_FREE, image_buf, bpb);
				curr_cluster = get_fat_entry(curr_cluster, image_buf, bpb);
			}
			set_fat_entry(original_cluster +clusters -1, FAT12_MASK &CLUST_EOFS, image_buf, bpb);
			}
		else if(clusters > cluster_count)
		{
			printf("ERROR: FILE SIZE TOO LARGE FOR NUM CLUSTERS\n");
			uint32_t correct_size = cluster_count * bpb->bpbBytesPerSec;
			putulong(dirent->deFileSize, correct_size);
			printf("FIXED \n");
		}
		

    }

    return followclust;
}
예제 #24
0
파일: message.c 프로젝트: aztrock/wmii
char *
send_client(View *v, IxpMsg *m, Bool swap) {
	Area *to, *a;
	Frame *f;
	Client *c;
	char *s;
	ulong i;
	int sym;

	s = getword(m);

	c = strclient(v, s);
	if(c == nil)
		return Ebadvalue;

	f = view_clientframe(v, c);
	if(f == nil)
		return Ebadvalue;

	a = f->area;
	to = nil;

	s = getword(m);
	sym = getsym(s);

	switch(sym) {
	case LUP:
	case LDOWN:
		return send_frame(f, sym, swap);
	case LLEFT:
		if(a->floating)
			return Ebadvalue;

		if(a->prev != v->area)
			to = a->prev;
		a = v->area;
		break;
	case LRIGHT:
		if(a->floating)
			return Ebadvalue;

		to = a->next;
		break;
	case LTOGGLE:
		if(!a->floating)
			to = v->area;
		else if(c->revert && !c->revert->floating)
			to = c->revert;
		else
			to = v->area->next;
		break;
	default:
		if(!getulong(s, &i) || i == 0)
			return Ebadvalue;

		for(to=v->area; to; to=to->next)
			if(!i--) break;
		break;
	}

	if(!to && !swap && (f->anext || f != f->area->frame))
		to = new_column(v, a, 0);

	if(!to)
		return Ebadvalue;

	if(!swap)
		send_to_area(to, f);
	else if(to->sel)
		swap_frames(f, to->sel);
	else
		return Ebadvalue;

	flushevents(EnterWindowMask, False);
	focus_frame(f, True);
	arrange_view(v);
	update_views();
	return nil;
}
예제 #25
0
/** 
 * Initializes ole structure
 * 
 * @param f (FILE *) compound document file, positioned at bufSize
 *           byte. Might be pipe or socket 
 * @param buffer (void *) bytes already read from f
 * @param bufSize number of bytes already read from f should be less
 *                than 512 
 * 
 * @return 
 */
FILE* ole_init(FILE *f, void *buffer, size_t bufSize)  {
	unsigned char oleBuf[BBD_BLOCK_SIZE];
	unsigned char *tmpBuf;
	FILE *newfile;
	int ret=0, i;
	long int sbdMaxLen, sbdCurrent, propMaxLen, propCurrent, mblock, msat_size;
	oleEntry *tEntry;

	/* deleting old data (if it was allocated) */
	ole_finish();
	
	if (fseek(f,0,SEEK_SET) == -1) {
		if ( errno == ESPIPE ) {
			/* We got non-seekable file, create temp file */
			if((newfile=tmpfile()) == NULL) {
				perror("Can't create tmp file");
				return NULL;
			}
			if (bufSize > 0) {
				ret=fwrite(buffer, 1, bufSize, newfile);
				if(ret != bufSize) {
					perror("Can't write to tmp file");
					return NULL;
				}
			}
			
			while(!feof(f)){
				ret=fread(oleBuf,1,BBD_BLOCK_SIZE,f);
				fwrite(oleBuf, 1, ret, newfile);
			}
			fseek(newfile,0,SEEK_SET);
		} else {
			perror("Can't seek in file");
			return NULL;
		}
	} else {
		newfile=f;
	}	
	fseek(newfile,0,SEEK_END);
	fileLength=ftell(newfile);
/* 	fprintf(stderr, "fileLength=%ld\n", fileLength); */
	fseek(newfile,0,SEEK_SET);
	ret=fread(oleBuf,1,BBD_BLOCK_SIZE,newfile);
	if ( ret != BBD_BLOCK_SIZE ) {
		return NULL;
	}
	if (strncmp(oleBuf,ole_sign,8) != 0) {
		return NULL;
	}
 	sectorSize = 1<<getshort(oleBuf,0x1e);
	shortSectorSize=1<<getshort(oleBuf,0x20);
	
/* Read BBD into memory */
	bbdNumBlocks = getulong(oleBuf,0x2c);
	if((BBD=malloc(bbdNumBlocks*sectorSize)) == NULL ) {
		return NULL;
	}
	
	if((tmpBuf=malloc(MSAT_ORIG_SIZE)) == NULL ) {
		return NULL;
	}
	memcpy(tmpBuf,oleBuf+0x4c,MSAT_ORIG_SIZE);
	mblock=getlong(oleBuf,0x44);
	msat_size=getlong(oleBuf,0x48);

/* 	fprintf(stderr, "msat_size=%ld\n", msat_size); */

	i=0;
	while((mblock >= 0) && (i < msat_size)) {
		unsigned char *newbuf;
/* 		fprintf(stderr, "i=%d mblock=%ld\n", i, mblock); */
		if ((newbuf=realloc(tmpBuf, sectorSize*(i+1)+MSAT_ORIG_SIZE)) != NULL) {
			tmpBuf=newbuf;
		} else {
			perror("MSAT realloc error");
			free(tmpBuf);
			ole_finish();
			return NULL;
		}
		
		fseek(newfile, 512+mblock*sectorSize, SEEK_SET);
		if(fread(tmpBuf+MSAT_ORIG_SIZE+(sectorSize-4)*i,
						 1, sectorSize, newfile) != sectorSize) {
			fprintf(stderr, "Error read MSAT!\n");
			ole_finish();
			return NULL;
		}

		i++;
		mblock=getlong(tmpBuf, MSAT_ORIG_SIZE+(sectorSize-4)*i);
	}
	
/* 	fprintf(stderr, "bbdNumBlocks=%ld\n", bbdNumBlocks); */
	for(i=0; i< bbdNumBlocks; i++) {
		long int bbdSector=getlong(tmpBuf,4*i);
		
		if (bbdSector >= fileLength/sectorSize || bbdSector < 0) {
			fprintf(stderr, "Bad BBD entry!\n");
			ole_finish();
			return NULL;
		}
		fseek(newfile, 512+bbdSector*sectorSize, SEEK_SET);
		if ( fread(BBD+i*sectorSize, 1, sectorSize, newfile) != sectorSize ) {
			fprintf(stderr, "Can't read BBD!\n");
			free(tmpBuf);
			ole_finish();
			return NULL;
		}
	}
	free(tmpBuf);
	
/* Read SBD into memory */
	sbdLen=0;
	sbdMaxLen=10;
	sbdCurrent = sbdStart = getlong(oleBuf,0x3c);
	if (sbdStart > 0) {
		if((SBD=malloc(sectorSize*sbdMaxLen)) == NULL ) {
			ole_finish();
			return NULL;
		}
		while(1) {
			fseek(newfile, 512+sbdCurrent*sectorSize, SEEK_SET);
			fread(SBD+sbdLen*sectorSize, 1, sectorSize, newfile);
			sbdLen++;
			if (sbdLen >= sbdMaxLen) {
				unsigned char *newSBD;
				
				sbdMaxLen+=5;
				if ((newSBD=realloc(SBD, sectorSize*sbdMaxLen)) != NULL) {
					SBD=newSBD;
				} else {
					perror("SBD realloc error");
					ole_finish();
					return NULL;
				}
			}
			sbdCurrent = getlong(BBD, sbdCurrent*4);
			if(sbdCurrent < 0 ||
				sbdCurrent >= fileLength/sectorSize)
				break;
		}
		sbdNumber = (sbdLen*sectorSize)/shortSectorSize;
/*   		fprintf(stderr, "sbdLen=%ld sbdNumber=%ld\n",sbdLen, sbdNumber); */
	} else {
		SBD=NULL;
	}
/* Read property catalog into memory */
	propLen = 0;
	propMaxLen = 5;
	propCurrent = propStart = getlong(oleBuf,0x30);
	if (propStart >= 0) {
		if((properties=malloc(propMaxLen*sectorSize)) == NULL ) {
			ole_finish();
			return NULL;
		}
		while(1) {
/*  			fprintf(stderr, "propCurrent=%ld\n",propCurrent); */
			fseek(newfile, 512+propCurrent*sectorSize, SEEK_SET);
			fread(properties+propLen*sectorSize,
				  1, sectorSize, newfile);
			propLen++;
			if (propLen >= propMaxLen) {
				unsigned char *newProp;
				
				propMaxLen+=5;
				if ((newProp=realloc(properties, propMaxLen*sectorSize)) != NULL)
					properties=newProp;
				else {
					perror("Properties realloc error");
					ole_finish();
					return NULL;
				}
			}
			
			propCurrent = getlong(BBD, propCurrent*4);
			if(propCurrent < 0 ||
			   propCurrent >= fileLength/sectorSize ) {
				break;
			}
		}
/*  		fprintf(stderr, "propLen=%ld\n",propLen); */
		propNumber = (propLen*sectorSize)/PROP_BLOCK_SIZE;
		propCurNumber = 0;
	} else {
		ole_finish();
		properties = NULL;
		return NULL;
	}
	
	
/* Find Root Entry */
	while((tEntry=(oleEntry*)ole_readdir(newfile)) != NULL) {
		if (tEntry->type == oleRootDir ) {
			rootEntry=tEntry;
			break;
		}
		ole_close((FILE*)tEntry);
	}
	propCurNumber = 0;
	fseek(newfile, 0, SEEK_SET);
	if (!rootEntry) {
		fprintf(stderr,"Broken OLE structure. Cannot find root entry in this file!\n");		ole_finish();
		return NULL;
	}	
	return newfile;
}
예제 #26
0
파일: FSFormatName.c 프로젝트: aosm/libfs
/* Check if the disk is MSDOS disk and return its subtypes */
bool is_msdos(char *devnode, int *fssubtype)
{
	union bootsector *bsp;
	struct byte_bpb710 *b710;
	u_int32_t FATSectors;
	u_int32_t TotalSectors;
	u_int32_t countOfClusters;
	u_int32_t DataSectors;
	u_int32_t RootDirSectors;
    u_int16_t BytesPerSector;
    u_int8_t SectorsPerCluster;
	char *buffer = NULL;
	int fd = 0;
	bool retval = false;

	/* default fssubtype to non-existing value */
	*fssubtype = -1;
	
	buffer = (char *)malloc(MAX_DOS_BLOCKSIZE);
	if (!buffer) {
		goto out;
	}
	
	/* open the device */	
	fd = open(devnode, O_RDONLY | O_NDELAY, 0);
	if (fd <= 0) {
		goto out;
	}
	
	/* read the block */
	if (getblk(fd, 0, MAX_DOS_BLOCKSIZE, buffer) < MAX_DOS_BLOCKSIZE) {
		goto out;
	}
	
	bsp = (union bootsector *)buffer;
    b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB;
   
	/* The first three bytes are an Intel x86 jump instruction.  It should be one
     * of the following forms:
     *    0xE9 0x?? 0x??
     *    0xEC 0x?? 0x90
     * where 0x?? means any byte value is OK.
     */
    if (bsp->bs50.bsJump[0] != 0xE9
        && (bsp->bs50.bsJump[0] != 0xEB || bsp->bs50.bsJump[2] != 0x90)) {
		goto out;
    }

    /* We only work with 512, 1024, and 2048 byte sectors */
	BytesPerSector = getushort(b710->bpbBytesPerSec);
	if ((BytesPerSector < 0x200) || (BytesPerSector & (BytesPerSector - 1)) || (BytesPerSector > 0x800)) {
		goto out;
	}
	
	/* Check to make sure valid sectors per cluster */
    SectorsPerCluster = b710->bpbSecPerClust;
    if ((SectorsPerCluster == 0 ) || (SectorsPerCluster & (SectorsPerCluster - 1))) {
		goto out;
	}

	RootDirSectors = ((getushort(b710->bpbRootDirEnts) * 32) + (BytesPerSector - 1)) / BytesPerSector;

	if (getushort(b710->bpbFATsecs)) {
		FATSectors = getushort(b710->bpbFATsecs);
	} else {
		FATSectors = getulong(b710->bpbBigFATsecs);
	}

	if (getushort(b710->bpbSectors)) {
		TotalSectors = getushort(b710->bpbSectors);
	} else {
		TotalSectors = getulong(b710->bpbHugeSectors);
	}

	DataSectors = TotalSectors - (getushort(b710->bpbResSectors) + (b710->bpbFATs * FATSectors) + RootDirSectors); 
	
	countOfClusters = DataSectors/(b710->bpbSecPerClust);

	if (countOfClusters < 4085) {
		/* FAT12 */
		*fssubtype = 0;
	} else if (countOfClusters < 65525) {
		/* FAT16 */
		*fssubtype = 1;
	} else {
		/* FAT32 */
		*fssubtype = 2;
	}

	retval = true;
	
out:
	if (buffer) {
		free(buffer);
	}
	if (fd > 0) {
		close(fd);
	}
	return retval;
}
예제 #27
0
파일: lastlog.c 프로젝트: brauner/shadow
int main (int argc, char **argv)
{
	/*
	 * Get the program name. The program name is used as a prefix to
	 * most error messages.
	 */
	Prog = Basename (argv[0]);

	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	process_root_flag ("-R", argc, argv);

#ifdef WITH_AUDIT
	audit_help_open ();
#endif

	{
		int c;
		static struct option const longopts[] = {
			{"before", required_argument, NULL, 'b'},
			{"clear",  no_argument,       NULL, 'C'},
			{"help",   no_argument,       NULL, 'h'},
			{"root",   required_argument, NULL, 'R'},
			{"set",    no_argument,       NULL, 'S'},
			{"time",   required_argument, NULL, 't'},
			{"user",   required_argument, NULL, 'u'},
			{NULL, 0, NULL, '\0'}
		};

		while ((c = getopt_long (argc, argv, "b:ChR:St:u:", longopts,
		                         NULL)) != -1) {
			switch (c) {
			case 'b':
			{
				unsigned long inverse_days;
				if (getulong (optarg, &inverse_days) == 0) {
					fprintf (stderr,
					         _("%s: invalid numeric argument '%s'\n"),
					         Prog, optarg);
					exit (EXIT_FAILURE);
				}
				inverse_seconds = (time_t) inverse_days * DAY;
				bflg = true;
				break;
			}
			case 'C':
			{
				Cflg = true;
				break;
			}
			case 'h':
				usage (EXIT_SUCCESS);
				/*@notreached@*/break;
			case 'R': /* no-op, handled in process_root_flag () */
				break;
			case 'S':
			{
				Sflg = true;
				break;
			}
			case 't':
			{
				unsigned long days;
				if (getulong (optarg, &days) == 0) {
					fprintf (stderr,
					         _("%s: invalid numeric argument '%s'\n"),
					         Prog, optarg);
					exit (EXIT_FAILURE);
				}
				seconds = (time_t) days * DAY;
				tflg = true;
				break;
			}
			case 'u':
			{
				const struct passwd *pwent;
				/*
				 * The user can be:
				 *  - a login name
				 *  - numerical
				 *  - a numerical login ID
				 *  - a range (-x, x-, x-y)
				 */
				uflg = true;
				/* local, no need for xgetpwnam */
				pwent = getpwnam (optarg);
				if (NULL != pwent) {
					umin = (unsigned long) pwent->pw_uid;
					has_umin = true;
					umax = umin;
					has_umax = true;
				} else {
					if (getrange (optarg,
					              &umin, &has_umin,
					              &umax, &has_umax) == 0) {
						fprintf (stderr,
						         _("%s: Unknown user or range: %s\n"),
						         Prog, optarg);
						exit (EXIT_FAILURE);
					}
				}
				break;
			}
			default:
				usage (EXIT_FAILURE);
				/*@notreached@*/break;
			}
		}
		if (argc > optind) {
			fprintf (stderr,
			         _("%s: unexpected argument: %s\n"),
			         Prog, argv[optind]);
			usage (EXIT_FAILURE);
		}
		if (Cflg && Sflg) {
			fprintf (stderr,
			         _("%s: Option -C cannot be used together with option -S\n"),
			         Prog);
			usage (EXIT_FAILURE);
		}
		if ((Cflg || Sflg) && !uflg) {
			fprintf (stderr,
			         _("%s: Options -C and -S require option -u to specify the user\n"),
			         Prog);
			usage (EXIT_FAILURE);
		}
	}

	lastlogfile = fopen (LASTLOG_FILE, (Cflg || Sflg)?"r+":"r");
	if (NULL == lastlogfile) {
		perror (LASTLOG_FILE);
		exit (EXIT_FAILURE);
	}

	/* Get the lastlog size */
	if (fstat (fileno (lastlogfile), &statbuf) != 0) {
		fprintf (stderr,
		         _("%s: Cannot get the size of %s: %s\n"),
		         Prog, LASTLOG_FILE, strerror (errno));
		exit (EXIT_FAILURE);
	}

	if (Cflg || Sflg)
		update ();
	else
		print ();

	(void) fclose (lastlogfile);

	return EXIT_SUCCESS;
}
예제 #28
0
int compare(char *filename, uint16_t followclust, struct direntry *dirent, uint8_t *image_buf, struct bpb33* bpb){
	//will loop through fat until eof marking the good/bad/free clusters and freeing them
	uint32_t realsize = getulong(dirent->deFileSize);
	uint32_t clustersize = bpb->bpbSecPerClust*bpb->bpbBytesPerSec;
	int expected_num_clust = (realsize+511)/clustersize;  // finds num clusters according to the meta data
	
	//find actual num clusters in fat
	uint16_t fatent = get_fat_entry(followclust, image_buf, bpb);
	uint16_t prev_fatent = fatent;
	int count = 1;
	
	while(!is_end_of_file(fatent)) {  //loops through checking if eof
		uint16_t temp =get_fat_entry(fatent, image_buf, bpb);
		if (fatent == (FAT12_MASK & CLUST_BAD)){ //if the fatent is bad it will mark it in the array
			printf("Bad cluster");
			desperation[followclust+count]=-1;
			printf("File is inconsistant: name is: %s\n",filename);
			}
		
		

		if(count>=expected_num_clust)	//if we have more clusters than expected
			{	
			
			if (count==expected_num_clust) {  //will only happen once
				printf("count is greater\n");
				//will set the previous entry to be eof and fee the current cluster
				//will also set desperation =2 at the eof and 3 at the free cluster
				// this is becasue we want a record in desperation of free normal or not looked at clusters
				set_fat_entry(prev_fatent,FAT12_MASK&CLUST_EOFS, image_buf, bpb);
				desperation[followclust+count-1]=2;
				set_fat_entry(fatent, FAT12_MASK&CLUST_FREE, image_buf, bpb);
				desperation[followclust+count]=3;
				printf("file is inconsistant!!! name is: %s\n",filename);
			
				}
		
			else {
				// if we are over the size just free current cluster
				set_fat_entry(fatent, FAT12_MASK&CLUST_FREE, image_buf, bpb);
			
				}
			//when count is over expected we will put 3 in every cluster over size eof
			desperation[followclust+count]=3;
			fatent=temp;
			count++;
			}
		
		else {

			//if we are still running through the clusters then if we find a free set it as 3 or if it is just normal then set it as 1
			if (fatent == (FAT12_MASK&CLUST_FREE)) {
				printf("FREE CLUSTER BEFORE EOF WEEWOOWEEWOO");
				desperation[followclust+count]=3;
				
				}
			else {
				desperation[followclust+count]=1;
				}
			prev_fatent=fatent;
			fatent=get_fat_entry(fatent,image_buf, bpb);
			count++;
			}
			
		
		}
	desperation[followclust+count]=2;//set this block as an eof in desperation
	if (expected_num_clust>count){
		//if at the end cluster is greater than expected change the size in the meta data to be what the fat size is
		uint32_t clustersize = bpb->bpbSecPerClust*bpb->bpbBytesPerSec;
		putulong(dirent->deFileSize, (count*clustersize));
		printf("File is inconsistant!!! name is: %s \n", filename);
	}
	//loop through the current files clusters on desperation and until you hit the eof
	int i= followclust;
	int countgucci=0;
	while (desperation[i]!=2)
		{
		if (desperation[i]==1) {
			countgucci++;
			}
		}
	//put the newsize into the metadata
	putulong(dirent->deFileSize, (countgucci*clustersize));
	return count;
}
예제 #29
0
struct map_range *get_map_ranges(int ranges, int argc, char **argv)
{
	struct map_range *mappings, *mapping;
	int idx, argidx;

	if (ranges < 0 || argc < 0) {
		fprintf(stderr, "%s: error calculating number of arguments\n", Prog);
		return NULL;
	}

	if (ranges != ((argc + 2) / 3)) {
		fprintf(stderr, "%s: ranges: %u is wrong for argc: %d\n", Prog, ranges, argc);
		return NULL;
	}

	if ((ranges * 3) > argc) {
		fprintf(stderr, "ranges: %u argc: %d\n",
			ranges, argc);
		fprintf(stderr,
			_( "%s: Not enough arguments to form %u mappings\n"),
			Prog, ranges);
		return NULL;
	}

	mappings = calloc(ranges, sizeof(*mappings));
	if (!mappings) {
		fprintf(stderr, _( "%s: Memory allocation failure\n"),
			Prog);
		exit(EXIT_FAILURE);
	}

	/* Gather up the ranges from the command line */
	mapping = mappings;
	for (idx = 0, argidx = 0; idx < ranges; idx++, argidx += 3, mapping++) {
		if (!getulong(argv[argidx + 0], &mapping->upper)) {
			free(mappings);
			return NULL;
		}
		if (!getulong(argv[argidx + 1], &mapping->lower)) {
			free(mappings);
			return NULL;
		}
		if (!getulong(argv[argidx + 2], &mapping->count)) {
			free(mappings);
			return NULL;
		}
		if (ULONG_MAX - mapping->upper <= mapping->count || ULONG_MAX - mapping->lower <= mapping->count) {
			fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog);
			exit(EXIT_FAILURE);
		}
		if (mapping->upper > UINT_MAX ||
			mapping->lower > UINT_MAX ||
			mapping->count > UINT_MAX)  {
			fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog);
			exit(EXIT_FAILURE);
		}
		if (mapping->lower + mapping->count > UINT_MAX ||
				mapping->upper + mapping->count > UINT_MAX) {
			fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog);
			exit(EXIT_FAILURE);
		}
		if (mapping->lower + mapping->count < mapping->lower ||
				mapping->upper + mapping->count < mapping->upper) {
			/* this one really shouldn't be possible given previous checks */
			fprintf(stderr, _( "%s: subuid overflow detected.\n"), Prog);
			exit(EXIT_FAILURE);
		}
	}
	return mappings;
}
예제 #30
0
struct msdosfsmount *
msdosfs_mount(struct vnode *devvp, int flags)
{
	struct msdosfsmount *pmp = NULL;
	struct buf *bp;
	union bootsector *bsp;
	struct byte_bpb33 *b33;
	struct byte_bpb50 *b50;
	struct byte_bpb710 *b710;
	uint8_t SecPerClust;
	int	ronly = 0, error, tmp;
	int	bsize;
	struct msdos_options *m = devvp->fs->fs_specific;
	uint64_t psize = m->create_size;
	unsigned secsize = 512;

	DPRINTF(("%s(bread 0)\n", __func__));
	if ((error = bread(devvp, 0, secsize, NULL, 0, &bp)) != 0)
		goto error_exit;

	bsp = (union bootsector *)bp->b_data;
	b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB;
	b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB;
	b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB;

	if (!(flags & MSDOSFSMNT_GEMDOSFS)) {
		if (bsp->bs50.bsBootSectSig0 != BOOTSIG0
		    || bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
			DPRINTF(("bootsig0 %d bootsig1 %d\n", 
			    bsp->bs50.bsBootSectSig0,
			    bsp->bs50.bsBootSectSig1));
			error = EINVAL;
			goto error_exit;
		}
		bsize = 0;
	} else
		bsize = 512;

	pmp = ecalloc(1, sizeof *pmp);
	/*
	 * Compute several useful quantities from the bpb in the
	 * bootsector.  Copy in the dos 5 variant of the bpb then fix up
	 * the fields that are different between dos 5 and dos 3.3.
	 */
	SecPerClust = b50->bpbSecPerClust;
	pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec);
	pmp->pm_ResSectors = getushort(b50->bpbResSectors);
	pmp->pm_FATs = b50->bpbFATs;
	pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts);
	pmp->pm_Sectors = getushort(b50->bpbSectors);
	pmp->pm_FATsecs = getushort(b50->bpbFATsecs);
	pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack);
	pmp->pm_Heads = getushort(b50->bpbHeads);
	pmp->pm_Media = b50->bpbMedia;

	DPRINTF(("%s(BytesPerSec=%u, ResSectors=%u, FATs=%d, RootDirEnts=%u, "
	    "Sectors=%u, FATsecs=%lu, SecPerTrack=%u, Heads=%u, Media=%u)\n",
	    __func__, pmp->pm_BytesPerSec, pmp->pm_ResSectors, pmp->pm_FATs,
	    pmp->pm_RootDirEnts, pmp->pm_Sectors, pmp->pm_FATsecs,
	    pmp->pm_SecPerTrack, pmp->pm_Heads, pmp->pm_Media));
	if (!(flags & MSDOSFSMNT_GEMDOSFS)) {
		/* XXX - We should probably check more values here */
    		if (!pmp->pm_BytesPerSec || !SecPerClust
	    		|| pmp->pm_SecPerTrack > 63) {
			DPRINTF(("bytespersec %d secperclust %d "
			    "secpertrack %d\n", 
			    pmp->pm_BytesPerSec, SecPerClust,
			    pmp->pm_SecPerTrack));
			error = EINVAL;
			goto error_exit;
		}
	}

	if (pmp->pm_Sectors == 0) {
		pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
		pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
	} else {
		pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);
		pmp->pm_HugeSectors = pmp->pm_Sectors;
	}

	if (pmp->pm_RootDirEnts == 0) {
		unsigned short vers = getushort(b710->bpbFSVers);
		/*
		 * Some say that bsBootSectSig[23] must be zero, but
		 * Windows does not require this and some digital cameras
		 * do not set these to zero.  Therefore, do not insist.
		 */
		if (pmp->pm_Sectors || pmp->pm_FATsecs || vers) {
			DPRINTF(("sectors %d fatsecs %lu vers %d\n",
			    pmp->pm_Sectors, pmp->pm_FATsecs, vers));
			error = EINVAL;
			goto error_exit;
		}
		pmp->pm_fatmask = FAT32_MASK;
		pmp->pm_fatmult = 4;
		pmp->pm_fatdiv = 1;
		pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);

		/* mirrorring is enabled if the FATMIRROR bit is not set */
		if ((getushort(b710->bpbExtFlags) & FATMIRROR) == 0)
			pmp->pm_flags |= MSDOSFS_FATMIRROR;
		else
			pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
	} else
		pmp->pm_flags |= MSDOSFS_FATMIRROR;

	if (flags & MSDOSFSMNT_GEMDOSFS) {
		if (FAT32(pmp)) {
			DPRINTF(("FAT32 for GEMDOS\n"));
			/*
			 * GEMDOS doesn't know FAT32.
			 */
			error = EINVAL;
			goto error_exit;
		}

		/*
		 * Check a few values (could do some more):
		 * - logical sector size: power of 2, >= block size
		 * - sectors per cluster: power of 2, >= 1
		 * - number of sectors:   >= 1, <= size of partition
		 */
		if ( (SecPerClust == 0)
		  || (SecPerClust & (SecPerClust - 1))
		  || (pmp->pm_BytesPerSec < bsize)
		  || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1))
		  || (pmp->pm_HugeSectors == 0)
		  || (pmp->pm_HugeSectors * (pmp->pm_BytesPerSec / bsize)
		      > psize)) {
			DPRINTF(("consistency checks for GEMDOS\n"));
			error = EINVAL;
			goto error_exit;
		}
		/*
		 * XXX - Many parts of the msdosfs driver seem to assume that
		 * the number of bytes per logical sector (BytesPerSec) will
		 * always be the same as the number of bytes per disk block
		 * Let's pretend it is.
		 */
		tmp = pmp->pm_BytesPerSec / bsize;
		pmp->pm_BytesPerSec  = bsize;
		pmp->pm_HugeSectors *= tmp;
		pmp->pm_HiddenSects *= tmp;
		pmp->pm_ResSectors  *= tmp;
		pmp->pm_Sectors     *= tmp;
		pmp->pm_FATsecs     *= tmp;
		SecPerClust         *= tmp;
	}

	/* Check that fs has nonzero FAT size */
	if (pmp->pm_FATsecs == 0) {
		DPRINTF(("FATsecs is 0\n"));
		error = EINVAL;
		goto error_exit;
	}

	pmp->pm_fatblk = pmp->pm_ResSectors;
	if (FAT32(pmp)) {
		pmp->pm_rootdirblk = getulong(b710->bpbRootClust);
		pmp->pm_firstcluster = pmp->pm_fatblk
			+ (pmp->pm_FATs * pmp->pm_FATsecs);
		pmp->pm_fsinfo = getushort(b710->bpbFSInfo);
	} else {
		pmp->pm_rootdirblk = pmp->pm_fatblk +
			(pmp->pm_FATs * pmp->pm_FATsecs);
		pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry)
				       + pmp->pm_BytesPerSec - 1)
			/ pmp->pm_BytesPerSec;/* in sectors */
		pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
	}

	pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
	    SecPerClust;
	pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1;
	pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec;

	if (flags & MSDOSFSMNT_GEMDOSFS) {
		if (pmp->pm_nmbrofclusters <= (0xff0 - 2)) {
			pmp->pm_fatmask = FAT12_MASK;
			pmp->pm_fatmult = 3;
			pmp->pm_fatdiv = 2;
		} else {
			pmp->pm_fatmask = FAT16_MASK;
			pmp->pm_fatmult = 2;
			pmp->pm_fatdiv = 1;
		}
	} else if (pmp->pm_fatmask == 0) {
		if (pmp->pm_maxcluster
		    <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) {
			/*
			 * This will usually be a floppy disk. This size makes
			 * sure that one FAT entry will not be split across
			 * multiple blocks.
			 */
			pmp->pm_fatmask = FAT12_MASK;
			pmp->pm_fatmult = 3;
			pmp->pm_fatdiv = 2;
		} else {
			pmp->pm_fatmask = FAT16_MASK;
			pmp->pm_fatmult = 2;
			pmp->pm_fatdiv = 1;
		}
	}
	if (FAT12(pmp))
		pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec;
	else
		pmp->pm_fatblocksize = MAXBSIZE;

	pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec;
	pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1;

	/*
	 * Compute mask and shift value for isolating cluster relative byte
	 * offsets and cluster numbers from a file offset.
	 */
	pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSec;
	pmp->pm_crbomask = pmp->pm_bpcluster - 1;
	pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1;

	DPRINTF(("%s(fatmask=%lu, fatmult=%u, fatdiv=%u, fatblocksize=%lu, "
	    "fatblocksec=%lu, bnshift=%lu, pbcluster=%lu, crbomask=%lu, "
	    "cnshift=%lu)\n",
	    __func__, pmp->pm_fatmask, pmp->pm_fatmult, pmp->pm_fatdiv,
	    pmp->pm_fatblocksize, pmp->pm_fatblocksec, pmp->pm_bnshift,
	    pmp->pm_bpcluster, pmp->pm_crbomask, pmp->pm_cnshift));
	/*
	 * Check for valid cluster size
	 * must be a power of 2
	 */
	if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) {
		DPRINTF(("bpcluster %lu cnshift %lu\n", 
		    pmp->pm_bpcluster, pmp->pm_cnshift));
		error = EINVAL;
		goto error_exit;
	}

	/*
	 * Release the bootsector buffer.
	 */
	brelse(bp, BC_AGE);
	bp = NULL;

	/*
	 * Check FSInfo.
	 */
	if (pmp->pm_fsinfo) {
		struct fsinfo *fp;

		/*
		 * XXX	If the fsinfo block is stored on media with
		 *	2KB or larger sectors, is the fsinfo structure
		 *	padded at the end or in the middle?
		 */
		DPRINTF(("%s(bread %lu)\n", __func__,
		    (unsigned long)de_bn2kb(pmp, pmp->pm_fsinfo)));
		if ((error = bread(devvp, de_bn2kb(pmp, pmp->pm_fsinfo),
		    pmp->pm_BytesPerSec, NULL, 0, &bp)) != 0)
			goto error_exit;
		fp = (struct fsinfo *)bp->b_data;
		if (!memcmp(fp->fsisig1, "RRaA", 4)
		    && !memcmp(fp->fsisig2, "rrAa", 4)
		    && !memcmp(fp->fsisig3, "\0\0\125\252", 4)
		    && !memcmp(fp->fsisig4, "\0\0\125\252", 4))
			pmp->pm_nxtfree = getulong(fp->fsinxtfree);
		else
			pmp->pm_fsinfo = 0;
		brelse(bp, 0);
		bp = NULL;
	}

	/*
	 * Check and validate (or perhaps invalidate?) the fsinfo structure?
	 * XXX
	 */
	if (pmp->pm_fsinfo) {
		if ((pmp->pm_nxtfree == 0xffffffffUL) ||
		    (pmp->pm_nxtfree > pmp->pm_maxcluster))
			pmp->pm_fsinfo = 0;
	}

	/*
	 * Allocate memory for the bitmap of allocated clusters, and then
	 * fill it in.
	 */
	pmp->pm_inusemap = ecalloc(sizeof(*pmp->pm_inusemap),
	    ((pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS));
	/*
	 * fillinusemap() needs pm_devvp.
	 */
	pmp->pm_dev = 0;
	pmp->pm_devvp = devvp;

	/*
	 * Have the inuse map filled in.
	 */
	if ((error = fillinusemap(pmp)) != 0) {
		DPRINTF(("fillinusemap %d\n", error));
		goto error_exit;
	}

	/*
	 * Finish up.
	 */
	if (ronly)
		pmp->pm_flags |= MSDOSFSMNT_RONLY;
	else
		pmp->pm_fmod = 1;

	/*
	 * If we ever do quotas for DOS filesystems this would be a place
	 * to fill in the info in the msdosfsmount structure. You dolt,
	 * quotas on dos filesystems make no sense because files have no
	 * owners on dos filesystems. of course there is some empty space
	 * in the directory entry where we could put uid's and gid's.
	 */

	return pmp;

error_exit:
	if (bp)
		brelse(bp, BC_AGE);
	if (pmp) {
		if (pmp->pm_inusemap)
			free(pmp->pm_inusemap);
		free(pmp);
	}
	errno = error;
	return pmp;
}