Example #1
0
static int
fn_match(const char *fname, const char *pattern)
{
	char fc, pc;

	do {
		fc = *fname++;
		pc = *pattern++;
		if (!fc && !pc)
			return 1;
		if (pc == '?' && fc)
			pc = fc;
	} while (fc == pc);

	if (pc != '*')
		return 0;
	/*
	 * Too hard (and unnecessary really) too check for "*?name" etc....
	 * "**" will look for a '*' and "*?" a '?'
	 */
	pc = *pattern++;
	if (!pc)
		return 1;
	while ((fname = strchr(fname, pc)))
		if (fn_match(++fname, pattern))
			return 1;
	return 0;
}
Example #2
0
static int
fn_match(char *pattern, char *string, char **pend)
{
	char c;
	char test;

	*pend = NULL;
	for (;;) {
		switch (c = *pattern++) {
		case '\0':
			/*
			 * Ok we found an exact match
			 */
			if (*string == '\0')
				return(0);

			/*
			 * Check if it is a prefix match
			 */
			if ((dflag == 1) || (*string != '/'))
				return(-1);

			/*
			 * It is a prefix match, remember where the trailing
			 * / is located
			 */
			*pend = string;
			return(0);
		case '?':
			if ((test = *string++) == '\0')
				return (-1);
			break;
		case '*':
			c = *pattern;
			/*
			 * Collapse multiple *'s.
			 */
			while (c == '*')
				c = *++pattern;

			/*
			 * Optimized hack for pattern with a * at the end
			 */
			if (c == '\0')
				return (0);

			/*
			 * General case, use recursion.
			 */
			while ((test = *string) != '\0') {
				if (!fn_match(pattern, string, pend))
					return (0);
				++string;
			}
			return (-1);
		case '[':
			/*
			 * range match
			 */
			if (((test = *string++) == '\0') ||
			    ((pattern = range_match(pattern, test)) == NULL))
				return (-1);
			break;
		case '\\':
		default:
			if (c != *string++)
				return (-1);
			break;
		}
	}
	/* NOTREACHED */
}
Example #3
0
int
pat_match(ARCHD *arcn)
{
	PATTERN *pt;

	arcn->pat = NULL;

	/*
	 * if there are no more patterns and we have -n (and not -c) we are
	 * done. otherwise with no patterns to match, matches all
	 */
	if (pathead == NULL) {
		if (nflag && !cflag)
			return(-1);
		return(0);
	}

	/*
	 * have to search down the list one at a time looking for a match.
	 */
	pt = pathead;
	while (pt != NULL) {
		/*
		 * check for a file name match unless we have DIR_MTCH set in
		 * this pattern then we want a prefix match
		 */
		if (pt->flgs & DIR_MTCH) {
			/*
			 * this pattern was matched before to a directory
			 * as we must have -n set for this (but not -d). We can
			 * only match CHILDREN of that directory so we must use
			 * an exact prefix match (no wildcards).
			 */
			if ((arcn->name[pt->plen] == '/') &&
			    (strncmp(pt->pstr, arcn->name, pt->plen) == 0))
				break;
		} else if (fn_match(pt->pstr, arcn->name, &pt->pend) == 0)
			break;
		pt = pt->fow;
	}

	/*
	 * return the result, remember that cflag (-c) inverts the sense of a
	 * match
	 */
	if (pt == NULL)
		return(cflag ? 0 : 1);

	/*
	 * We had a match, now when we invert the sense (-c) we reject this
	 * member. However we have to tag the pattern a being successful, (in a
	 * match, not in selecting an archive member) so we call pat_sel() here.
	 */
	arcn->pat = pt;
	if (!cflag)
		return(0);

	if (pat_sel(arcn) < 0)
		return(-1);
	arcn->pat = NULL;
	return(1);
}
Example #4
0
__compactcall void
ufs_ls(struct open_file *f, const char *pattern,
	void (*funcp)(char* arg), char* path)
{
	struct file *fp = (struct file *)f->f_fsdata;
	char *buf;
	size_t buf_size;
	entry_t	*names = 0, *n, **np;

	fp->f_seekp = 0;
	while (fp->f_seekp < (off_t)fp->f_di.di_size) {
		struct direct  *dp, *edp;
		int rc = buf_read_file(f, &buf, &buf_size);
		if (rc)
			goto out;
		/* some firmware might use block size larger than DEV_BSIZE */
		if (buf_size < DIRBLKSIZ)
			goto out;

		dp = (struct direct *)buf;
		edp = (struct direct *)(buf + buf_size);

		for (; dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
			const char *t;
			if (dp->d_ino ==  0)
				continue;

			if (dp->d_type >= NELEM(typestr) ||
			    !(t = typestr[dp->d_type])) {
				/*
				 * This does not handle "old"
				 * filesystems properly. On little
				 * endian machines, we get a bogus
				 * type name if the namlen matches a
				 * valid type identifier. We could
				 * check if we read namlen "0" and
				 * handle this case specially, if
				 * there were a pressing need...
				 */
				printf("bad dir entry\n");
				goto out;
			}
			if (pattern && !fn_match(dp->d_name, pattern))
				continue;
			n = alloc(sizeof *n + strlen(dp->d_name));
			if (!n) {
				printf("%d: %s (%s)\n",
					dp->d_ino, dp->d_name, t);
				continue;
			}
			n->e_ino = dp->d_ino;
			n->e_type = dp->d_type;
			strcpy(n->e_name, dp->d_name);
			for (np = &names; *np; np = &(*np)->e_next) {
				if (strcmp(n->e_name, (*np)->e_name) < 0)
					break;
			}
			n->e_next = *np;
			*np = n;
		}
		fp->f_seekp += buf_size;
	}

	if (names) {
		entry_t *p_names = names;
		do {
			n = p_names;
			printf("%d: %s (%s)\n",
				n->e_ino, n->e_name, typestr[n->e_type]);
			p_names = n->e_next;
		} while (p_names);
	} else {
		printf("not found\n");
	}
out:
	if (names) {
		do {
			n = names;
			names = n->e_next;
			dealloc(n, 0);
		} while (names);
	}
}
void
efifs_ls(const char *path)
{
	int             fd;
	struct stat     sb;
	size_t          size;
	char            dirbuf[DIRBLKSIZ];
	const char	*fname = 0;
	char		*p;
	entry_t		*names = 0, *n, **np;

	if ((fd = open(path, 0)) < 0
	    || fstat(fd, &sb) < 0
	    || (sb.st_mode & S_IFMT) != S_IFDIR) {
		/* Path supplied isn't a directory, open parent
		   directory and list matching files. */
		if (fd >= 0)
			close(fd);
		fname = strrchr(path, '/');
		if (fname) {
			size = fname - path;
			p = alloc(size + 1);
			if (!p)
				goto out;
			memcpy(p, path, size);
			p[size] = 0;
			fd = open(p, 0);
			free(p, size + 1);
		} else {
			fd = open("", 0);
			fname = path;
		}

		if (fd < 0) {
			printf("ls: %s\n", strerror(errno));
			return;
		}
		if (fstat(fd, &sb) < 0) {
			printf("stat: %s\n", strerror(errno));
			goto out;
		}
		if ((sb.st_mode & S_IFMT) != S_IFDIR) {
			printf("%s: %s\n", path, strerror(ENOTDIR));
			goto out;
		}
	}

	while ((size = read(fd, dirbuf, DIRBLKSIZ)) == DIRBLKSIZ) {
		struct dirent  *dp, *edp;

		dp = (struct dirent *) dirbuf;
		edp = (struct dirent *) (dirbuf + size);

		for (; dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
			const char *t;
			if (dp->d_ino ==  0)
				continue;

			if (dp->d_type >= NELEM(typestr) ||
			    !(t = typestr[dp->d_type])) {
				/*
				 * This does not handle "old"
				 * filesystems properly. On little
				 * endian machines, we get a bogus
				 * type name if the namlen matches a
				 * valid type identifier. We could
				 * check if we read namlen "0" and
				 * handle this case specially, if
				 * there were a pressing need...
				 */
				printf("bad dir entry\n");
				goto out;
			}
			if (fname && !fn_match(dp->d_name, fname))
				continue;
			n = alloc(sizeof *n + strlen(dp->d_name));
			if (!n) {
				printf("%d: %s (%s)\n",
					dp->d_ino, dp->d_name, t);
				continue;
			}
			n->e_ino = dp->d_ino;
			n->e_type = dp->d_type;
			strcpy(n->e_name, dp->d_name);
			for (np = &names; *np; np = &(*np)->e_next) {
				if (strcmp(n->e_name, (*np)->e_name) < 0)
					break;
			}
			n->e_next = *np;
			*np = n;
		}
	}

	if (names) {
		do {
			n = names;
			printf("%d: %s (%s)\n",
				n->e_ino, n->e_name, typestr[n->e_type]);
			names = n->e_next;
			free(n, 0);
		} while (names);
	} else {
		printf( "%s not found\n", path );
	}
out:
	close(fd);
}