コード例 #1
0
ファイル: pkg_repo.c プロジェクト: yerenkow/pkg
int
pkg_create_repo(char *path, bool force, bool filelist,
		void (progress)(struct pkg *pkg, void *data), void *data)
{
	FTS *fts = NULL;
	struct thd_data thd_data;
	int num_workers;
	size_t len;
	pthread_t *tids = NULL;
	struct digest_list_entry *dlist = NULL, *cur_dig, *dtmp;
	sqlite3 *sqlite = NULL;

	char *errmsg = NULL;
	int retcode = EPKG_OK;

	char *repopath[2];
	char repodb[MAXPATHLEN + 1];
	char repopack[MAXPATHLEN + 1];
	char *manifest_digest;
	FILE *psyml, *fsyml, *mandigests;

	psyml = fsyml = mandigests = NULL;

	if (!is_dir(path)) {
		pkg_emit_error("%s is not a directory", path);
		return (EPKG_FATAL);
	}

	repopath[0] = path;
	repopath[1] = NULL;

	len = sizeof(num_workers);
	if (sysctlbyname("hw.ncpu", &num_workers, &len, NULL, 0) == -1)
		num_workers = 6;

	if ((fts = fts_open(repopath, FTS_PHYSICAL|FTS_NOCHDIR, NULL)) == NULL) {
		pkg_emit_errno("fts_open", path);
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	snprintf(repodb, sizeof(repodb), "%s/%s", path, repo_packagesite_file);
	if ((psyml = fopen(repodb, "w")) == NULL) {
		retcode = EPKG_FATAL;
		goto cleanup;
	}
	if (filelist) {
		snprintf(repodb, sizeof(repodb), "%s/%s", path, repo_filesite_file);
		if ((fsyml = fopen(repodb, "w")) == NULL) {
			retcode = EPKG_FATAL;
			goto cleanup;
		}
	}
	snprintf(repodb, sizeof(repodb), "%s/%s", path, repo_digests_file);
	if ((mandigests = fopen(repodb, "w")) == NULL) {
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	snprintf(repodb, sizeof(repodb), "%s/%s", path, repo_db_file);
	snprintf(repopack, sizeof(repopack), "%s/repo.txz", path);

	pack_extract(repopack, repo_db_file, repodb);

	if ((retcode = pkgdb_repo_open(repodb, force, &sqlite, true)) != EPKG_OK)
		goto cleanup;

	if ((retcode = pkgdb_repo_init(sqlite, true)) != EPKG_OK)
		goto cleanup;

	thd_data.root_path = path;
	thd_data.max_results = num_workers;
	thd_data.num_results = 0;
	thd_data.stop = false;
	thd_data.fts = fts;
	thd_data.read_files = filelist;
	pthread_mutex_init(&thd_data.fts_m, NULL);
	thd_data.results = NULL;
	thd_data.thd_finished = 0;
	pthread_mutex_init(&thd_data.results_m, NULL);
	pthread_cond_init(&thd_data.has_result, NULL);
	pthread_cond_init(&thd_data.has_room, NULL);

	/* Launch workers */
	tids = calloc(num_workers, sizeof(pthread_t));
	for (int i = 0; i < num_workers; i++) {
		pthread_create(&tids[i], NULL, (void *)&read_pkg_file, &thd_data);
	}

	for (;;) {
		struct pkg_result *r;
		const char *origin;

		long manifest_pos, files_pos;

		pthread_mutex_lock(&thd_data.results_m);
		while ((r = thd_data.results) == NULL) {
			if (thd_data.thd_finished == num_workers) {
				break;
			}
			pthread_cond_wait(&thd_data.has_result, &thd_data.results_m);
		}
		if (r != NULL) {
			LL_DELETE(thd_data.results, thd_data.results);
			thd_data.num_results--;
			pthread_cond_signal(&thd_data.has_room);
		}
		pthread_mutex_unlock(&thd_data.results_m);
		if (r == NULL) {
			break;
		}

		if (r->retcode != EPKG_OK) {
			continue;
		}

		/* do not add if package if already in repodb
		   (possibly at a different pkg_path) */

		retcode = pkgdb_repo_cksum_exists(sqlite, r->cksum);
		if (retcode == EPKG_FATAL) {
			goto cleanup;
		}
		else if (retcode == EPKG_OK) {
			continue;
		}

		if (progress != NULL)
			progress(r->pkg, data);

		manifest_pos = ftell(psyml);
		pkg_emit_manifest_file(r->pkg, psyml, PKG_MANIFEST_EMIT_COMPACT, &manifest_digest);
		if (filelist) {
			files_pos = ftell(fsyml);
			pkg_emit_filelist(r->pkg, fsyml);
		} else {
			files_pos = 0;
		}

		pkg_get(r->pkg, PKG_ORIGIN, &origin);

		cur_dig = malloc(sizeof (struct digest_list_entry));
		cur_dig->origin = strdup(origin);
		cur_dig->digest = manifest_digest;
		cur_dig->manifest_pos = manifest_pos;
		cur_dig->files_pos = files_pos;
		LL_PREPEND(dlist, cur_dig);

		retcode = pkgdb_repo_add_package(r->pkg, r->path, sqlite,
				manifest_digest, false, true);
		if (retcode == EPKG_END) {
			continue;
		}
		else if (retcode != EPKG_OK) {
			goto cleanup;
		}

		pkg_free(r->pkg);
		free(r);
	}

	/* Now sort all digests */
	LL_SORT(dlist, digest_sort_compare_func);
cleanup:
	if (pkgdb_repo_close(sqlite, retcode == EPKG_OK) != EPKG_OK) {
		retcode = EPKG_FATAL;
	}
	LL_FOREACH_SAFE(dlist, cur_dig, dtmp) {
		if (retcode == EPKG_OK) {
			fprintf(mandigests, "%s:%s:%ld:%ld\n", cur_dig->origin,
				cur_dig->digest, cur_dig->manifest_pos, cur_dig->files_pos);
		}
		free(cur_dig->digest);
		free(cur_dig->origin);
		free(cur_dig);
	}
	if (tids != NULL) {
		// Cancel running threads
		if (retcode != EPKG_OK) {
			pthread_mutex_lock(&thd_data.fts_m);
			thd_data.stop = true;
			pthread_mutex_unlock(&thd_data.fts_m);
		}
		// Join on threads to release thread IDs
		for (int i = 0; i < num_workers; i++) {
			pthread_join(tids[i], NULL);
		}
		free(tids);
	}

	if (fts != NULL)
		fts_close(fts);

	if (fsyml != NULL)
		fclose(fsyml);

	if (psyml != NULL)
		fclose(psyml);

	if (mandigests != NULL)
		fclose(mandigests);

	if (sqlite != NULL)
		sqlite3_close(sqlite);

	if (errmsg != NULL)
		sqlite3_free(errmsg);

	sqlite3_shutdown();

	return (retcode);
}
コード例 #2
0
ファイル: nftw.c プロジェクト: BwRy/fuzzer-android
int
nftw(const char *path, int (*fn)(const char *, const struct stat *, int,
				 struct FTW *), int nfds, int ftwflags)
{
  /* LINTED */
  char * const paths[2] = { __UNCONST(path), NULL };
  struct FTW f;
  FTSENT *cur;
  FTS *ftsp;
  int ftsflags, fnflag, error, postorder, sverrno;

  /* XXX - nfds is currently unused */
  if (nfds < 1 || nfds > OPEN_MAX) {
    errno = EINVAL;
    return (-1);
  }

  ftsflags = FTS_COMFOLLOW;
  if (!(ftwflags & FTW_CHDIR))
    ftsflags |= FTS_NOCHDIR;
  if (ftwflags & FTW_MOUNT)
    ftsflags |= FTS_XDEV;
  if (ftwflags & FTW_PHYS)
    ftsflags |= FTS_PHYSICAL;
  postorder = (ftwflags & FTW_DEPTH) != 0;
  ftsp = fts_open(paths, ftsflags, NULL);
  if (ftsp == NULL)
    return (-1);
  error = 0;
  while ((cur = fts_read(ftsp)) != NULL) {
    switch (cur->fts_info) {
    case FTS_D:
      if (postorder)
	continue;
      fnflag = FTW_D;
      break;
    case FTS_DNR:
      fnflag = FTW_DNR;
      break;
    case FTS_DP:
      if (!postorder)
	continue;
      fnflag = FTW_DP;
      break;
    case FTS_F:
    case FTS_DEFAULT:
      fnflag = FTW_F;
      break;
    case FTS_NS:
    case FTS_NSOK:
      fnflag = FTW_NS;
      break;
    case FTS_SL:
      fnflag = FTW_SL;
      break;
    case FTS_SLNONE:
      fnflag = FTW_SLN;
      break;
    case FTS_DC:
      errno = ELOOP;
      /* FALLTHROUGH */
    default:
      error = -1;
      goto done;
    }
    f.base = cur->fts_pathlen - cur->fts_namelen;
    f.level = cur->fts_level;
    error = fn(cur->fts_path, cur->fts_statp, fnflag, &f);
    if (error != 0)
      break;
  }
 done:
  sverrno = errno;
  (void) fts_close(ftsp);
  errno = sverrno;
  return (error);
}
コード例 #3
0
ファイル: forbidden.c プロジェクト: CeKMTL/polipo
void
parseDomainFile(AtomPtr file,
                DomainPtr **domains_return, regex_t **regex_return)
{
    struct stat ss;
    regex_t *regex;
    int rc;

    if(*domains_return) {
        DomainPtr *domain = *domains_return;
        while(*domain) {
            free(*domain);
            domain++;
        }
        free(*domains_return);
        *domains_return = NULL;
    }

    if(*regex_return) {
        regfree(*regex_return);
        *regex_return = NULL;
    }

    if(!file || file->length == 0)
        return;

    domains = malloc(64 * sizeof(DomainPtr));
    if(domains == NULL) {
        do_log(L_ERROR, "Couldn't allocate domain list.\n");
        return;
    }
    dlen = 0;
    dsize = 64;

    regexbuf = malloc(512);
    if(regexbuf == NULL) {
        do_log(L_ERROR, "Couldn't allocate regex.\n");
        free(domains);
        return;
    }
    rlen = 0;
    rsize = 512;

    rc = stat(file->string, &ss);
    if(rc < 0) {
        if(errno != ENOENT)
            do_log_error(L_WARN, errno, "Couldn't stat file %s", file->string);
    } else {
        if(!S_ISDIR(ss.st_mode))
            readDomainFile(file->string);
        else {
            char *fts_argv[2];
            FTS *fts;
            FTSENT *fe;
            fts_argv[0] = file->string;
            fts_argv[1] = NULL;
            fts = fts_open(fts_argv, FTS_LOGICAL, NULL);
            if(fts) {
                while(1) {
                    fe = fts_read(fts);
                    if(!fe) break;
                    if(fe->fts_info != FTS_D && fe->fts_info != FTS_DP &&
                       fe->fts_info != FTS_DC && fe->fts_info != FTS_DNR)
                        readDomainFile(fe->fts_accpath);
                }
                fts_close(fts);
            } else {
                do_log_error(L_ERROR, errno,
                             "Couldn't scan directory %s", file->string);
            }
        }
    }

    if(dlen > 0) {
        domains[dlen] = NULL;
    } else {
        free(domains);
        domains = NULL;
    }

    if(rlen > 0) {
        regex = malloc(sizeof(regex_t));
        rc = regcomp(regex, regexbuf, REG_EXTENDED | REG_NOSUB);
        if(rc != 0) {
            char errbuf[100];
            regerror(rc, regex, errbuf, 100);
            do_log(L_ERROR, "Couldn't compile regex: %s.\n", errbuf);
            free(regex);
            regex = NULL;
        }
    } else {
        regex = NULL;
    }
    free(regexbuf);

    *domains_return = domains;
    *regex_return = regex;

    return;
}
コード例 #4
0
ファイル: ctm_dequeue.c プロジェクト: edgar-pek/PerspicuOS
int
main(int argc, char **argv)
{
    char *log_file = NULL;
    char *queue_dir = NULL;
    char *list[2];
    int num_to_send = DEFAULT_NUM, chunk;
    int fd;
    FTS *fts;
    FTSENT *ftsent;
    int piece, npieces;
    char filename[PATH_MAX];

    err_prog_name(argv[0]);

    OPTIONS("[-l log] [-n num] queuedir")
	NUMBER('n', num_to_send)
	STRING('l', log_file)
    ENDOPTS

    if (argc != 2)
	usage();

    if (log_file)
	err_set_log(log_file);

    queue_dir = argv[1];
    list[0] = queue_dir;
    list[1] = NULL;

    fts = fts_open(list, FTS_PHYSICAL|FTS_COMFOLLOW, fts_sort);
    if (fts == NULL)
    {
	err("fts failed on `%s'", queue_dir);
	exit(1);
    }

    ftsent = fts_read(fts);
    if (ftsent == NULL || ftsent->fts_info != FTS_D)
    {
	err("not a directory: %s", queue_dir);
	exit(1);
    }

    ftsent = fts_children(fts, 0);
    if (ftsent == NULL && errno)
    {
	err("*ftschildren failed");
	exit(1);
    }

    for (chunk = 1; ftsent != NULL; ftsent = ftsent->fts_link)
    {
	/*
	 * Skip non-files and ctm_smail tmp files (ones starting with `.')
	 */
	if (ftsent->fts_info != FTS_F || ftsent->fts_name[0] == '.')
	    continue;

	sprintf(filename, "%s/%s", queue_dir, ftsent->fts_name);
	fd = open(filename, O_RDONLY);
	if (fd < 0)
	{
	    err("*open: %s", filename);
	    exit(1);
	}

	if (run_sendmail(fd))
	    exit(1);

	close(fd);
	
	if (unlink(filename) < 0)
	{
	    err("*unlink: %s", filename);
	    exit(1);
	}
	
	/*
	 * Deduce the delta, piece number, and number of pieces from
	 * the name of the file in the queue.  Ideally, we should be
	 * able to get the mail alias name too.
	 *
	 * NOTE: This depends intimately on the queue name used in ctm_smail.
	 */
	npieces = atoi(&ftsent->fts_name[ftsent->fts_namelen-3]);
	piece = atoi(&ftsent->fts_name[ftsent->fts_namelen-7]);
	err("%.*s %d/%d sent", ftsent->fts_namelen-8, ftsent->fts_name,
		piece, npieces);

	if (chunk++ == num_to_send)
	    break;
    }

    fts_close(fts);

    return(0);
}
コード例 #5
0
ファイル: chown.c プロジェクト: FreeBSDFoundation/freebsd
int
main(int argc, char **argv)
{
	FTS *ftsp;
	FTSENT *p;
	int Hflag, Lflag, Rflag, fflag, hflag, vflag, xflag;
	int ch, fts_options, rval;
	char *cp;

	ischown = (strcmp(basename(argv[0]), "chown") == 0);

	Hflag = Lflag = Rflag = fflag = hflag = vflag = xflag = 0;
	while ((ch = getopt(argc, argv, "HLPRfhvx")) != -1)
		switch (ch) {
		case 'H':
			Hflag = 1;
			Lflag = 0;
			break;
		case 'L':
			Lflag = 1;
			Hflag = 0;
			break;
		case 'P':
			Hflag = Lflag = 0;
			break;
		case 'R':
			Rflag = 1;
			break;
		case 'f':
			fflag = 1;
			break;
		case 'h':
			hflag = 1;
			break;
		case 'v':
			vflag++;
			break;
		case 'x':
			xflag = 1;
			break;
		case '?':
		default:
			usage();
		}
	argv += optind;
	argc -= optind;

	if (argc < 2)
		usage();

	(void)signal(SIGINFO, siginfo_handler);

	if (Rflag) {
		if (hflag && (Hflag || Lflag))
			errx(1, "the -R%c and -h options may not be "
			    "specified together", Hflag ? 'H' : 'L');
		if (Lflag) {
			fts_options = FTS_LOGICAL;
		} else {
			fts_options = FTS_PHYSICAL;

			if (Hflag) {
				fts_options |= FTS_COMFOLLOW;
			}
		}
	} else if (hflag) {
		fts_options = FTS_PHYSICAL;
	} else {
		fts_options = FTS_LOGICAL;
	}

	if (xflag)
		fts_options |= FTS_XDEV;

	uid = (uid_t)-1;
	gid = (gid_t)-1;
	if (ischown) {
		if ((cp = strchr(*argv, ':')) != NULL) {
			*cp++ = '\0';
			a_gid(cp);
		}
#ifdef SUPPORT_DOT
		else if ((cp = strchr(*argv, '.')) != NULL) {
			warnx("separation of user and group with a period is deprecated");
			*cp++ = '\0';
			a_gid(cp);
		}
#endif
		a_uid(*argv);
	} else
		a_gid(*argv);

	if ((ftsp = fts_open(++argv, fts_options, NULL)) == NULL)
		err(1, NULL);

	for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
		int atflag;

		if ((fts_options & FTS_LOGICAL) ||
		    ((fts_options & FTS_COMFOLLOW) &&
		    p->fts_level == FTS_ROOTLEVEL))
			atflag = 0;
		else
			atflag = AT_SYMLINK_NOFOLLOW;

		switch (p->fts_info) {
		case FTS_D:			/* Change it at FTS_DP. */
			if (!Rflag)
				fts_set(ftsp, p, FTS_SKIP);
			continue;
		case FTS_DNR:			/* Warn, chown. */
			warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
			rval = 1;
			break;
		case FTS_ERR:			/* Warn, continue. */
		case FTS_NS:
			warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
			rval = 1;
			continue;
		default:
			break;
		}
		if (siginfo) {
			print_info(p, 2);
			siginfo = 0;
		}
		if ((uid == (uid_t)-1 || uid == p->fts_statp->st_uid) &&
		    (gid == (gid_t)-1 || gid == p->fts_statp->st_gid))
			continue;
		if (fchownat(AT_FDCWD, p->fts_accpath, uid, gid, atflag)
		    == -1 && !fflag) {
			chownerr(p->fts_path);
			rval = 1;
		} else if (vflag)
			print_info(p, vflag);
	}
	if (errno)
		err(1, "fts_read");
	exit(rval);
}
コード例 #6
0
ファイル: xar.c プロジェクト: Merturbation/xar
static int archive(const char *filename, int arglen, char *args[]) {
	xar_t x;
	FTS *fts;
	FTSENT *ent;
	int flags;
	struct lnode *i;
	const char *default_compression;

	x = xar_open(filename, WRITE);
	if( !x ) {
		fprintf(stderr, "Error creating archive %s\n", filename);
		exit(1);
	}

	if( Toccksum )
		xar_opt_set(x, XAR_OPT_TOCCKSUM, Toccksum);

	if( Compression )
		xar_opt_set(x, XAR_OPT_COMPRESSION, Compression);

	if( CompressionArg )
		xar_opt_set(x, XAR_OPT_COMPRESSIONARG, CompressionArg);

	if( Coalesce )
		xar_opt_set(x, XAR_OPT_COALESCE, "true");

	if( LinkSame )
		xar_opt_set(x, XAR_OPT_LINKSAME, "true");

	if ( Rsize != NULL )
		xar_opt_set(x, XAR_OPT_RSIZE, Rsize);

	xar_register_errhandler(x, err_callback, NULL);

	for( i = PropInclude; i; i=i->next ) {
		xar_opt_set(x, XAR_OPT_PROPINCLUDE, i->str);
	}
	for( i = PropExclude; i; i=i->next ) {
		xar_opt_set(x, XAR_OPT_PROPEXCLUDE, i->str);
	}

	if( Subdoc )
		add_subdoc(x);

	if( Perms == SYMBOLIC ) {
		xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_SYMBOLIC);
	}
	if( Perms == NUMERIC ) {
		xar_opt_set(x, XAR_OPT_OWNERSHIP, XAR_OPT_VAL_NUMERIC);
	}

	default_compression = strdup(xar_opt_get(x, XAR_OPT_COMPRESSION));
	if( !default_compression )
		default_compression = strdup(XAR_OPT_VAL_GZIP);

	flags = FTS_PHYSICAL|FTS_NOSTAT|FTS_NOCHDIR;
	if( Local )
		flags |= FTS_XDEV;
	fts = fts_open(args, flags, NULL);
	if( !fts ) {
		fprintf(stderr, "Error traversing file tree\n");
		exit(1);
	}

	while( (ent = fts_read(fts)) ) {
		xar_file_t f;
		int exclude_match = 1;
		int nocompress_match = 1;
		if( ent->fts_info == FTS_DP )
			continue;

		if( strcmp(ent->fts_path, "/") == 0 )
			continue;
		if( strcmp(ent->fts_path, ".") == 0 )
			continue;
		
		for( i = Exclude; i; i=i->next ) {
			exclude_match = regexec(&i->reg, ent->fts_path, 0, NULL, 0);
			if( !exclude_match )
				break;
		}
		if( !exclude_match ) {
			if( Verbose )
				printf("Excluding %s\n", ent->fts_path);
			continue;
		}

		for( i = NoCompress; i; i=i->next ) {
			nocompress_match = regexec(&i->reg, ent->fts_path, 0, NULL, 0);
			if( !nocompress_match ) {
				xar_opt_set(x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE);
				break;
			}
		}
		f = xar_add(x, ent->fts_path);
		if( !f ) {
			fprintf(stderr, "Error adding file %s\n", ent->fts_path);
		} else {
			print_file(x, f);
		}
		if( !nocompress_match )
			xar_opt_set(x, XAR_OPT_COMPRESSION, default_compression);
	}
	fts_close(fts);
	if( xar_close(x) != 0 ) {
		fprintf(stderr, "Error creating the archive\n");
		if( !Err )
			Err = 42;
	}

	free((char *)default_compression);
	for( i = Exclude; i; ) {
		struct lnode *tmp;
		regfree(&i->reg);
		tmp = i;
		i = i->next;
		free(tmp);
	}
	for( i = NoCompress; i; ) {
		struct lnode *tmp;
		regfree(&i->reg);
		tmp = i;
		i = i->next;
		free(tmp);
	}

	return Err;
}
コード例 #7
0
ファイル: rm.c プロジェクト: dezelin/kBuild
static int
rm_tree(char **argv)
{
	FTS *fts;
	FTSENT *p;
	int needstat;
	int flags;
	int rval;

	/*
	 * Check up front before anything is deleted. This will not catch
	 * everything, but we'll check the individual items later.
	 */
	int i;
	for (i = 0; argv[i]; i++) {
		if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, argv[i])) {
			return 1;
		}
	}

	/*
	 * Remove a file hierarchy.  If forcing removal (-f), or interactive
	 * (-i) or can't ask anyway (stdin_ok), don't stat the file.
	 */
	needstat = !uid || (!fflag && !iflag && stdin_ok);

	/*
	 * If the -i option is specified, the user can skip on the pre-order
	 * visit.  The fts_number field flags skipped directories.
	 */
#define	SKIPPED	1

	flags = FTS_PHYSICAL;
	if (!needstat)
		flags |= FTS_NOSTAT;
#ifdef FTS_WHITEOUT
	if (Wflag)
		flags |= FTS_WHITEOUT;
#endif
	if (!(fts = fts_open(argv, flags, NULL))) {
		return err(1, "fts_open");
	}
	while ((p = fts_read(fts)) != NULL) {
		const char *operation = "chflags";
		switch (p->fts_info) {
		case FTS_DNR:
			if (!fflag || p->fts_errno != ENOENT) {
				fprintf(stderr, "fts: %s: %s: %s" CUR_LINE() "\n",
				        argv0, p->fts_path, strerror(p->fts_errno));
				eval = 1;
			}
			continue;
		case FTS_ERR:
			fts_close(fts);
			return errx(1, "fts: %s: %s " CUR_LINE(), p->fts_path, strerror(p->fts_errno));
		case FTS_NS:
			/*
			 * Assume that since fts_read() couldn't stat the
			 * file, it can't be unlinked.
			 */
			if (!needstat)
				break;
			if (!fflag || p->fts_errno != ENOENT) {
				fprintf(stderr, "fts: %s: %s: %s " CUR_LINE() "\n",
				        argv0, p->fts_path, strerror(p->fts_errno));
				eval = 1;
			}
			continue;
		case FTS_D:
			/* Pre-order: give user chance to skip. */
			if (!fflag && !check(p->fts_path, p->fts_accpath,
			    p->fts_statp)) {
				(void)fts_set(fts, p, FTS_SKIP);
				p->fts_number = SKIPPED;
			}
#ifdef UF_APPEND
			else if (!uid &&
				 (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
				 !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
				 chflags(p->fts_accpath,
					 p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
				goto err;
#endif
			continue;
		case FTS_DP:
			/* Post-order: see if user skipped. */
			if (p->fts_number == SKIPPED)
				continue;
			break;
		default:
			if (!fflag &&
			    !check(p->fts_path, p->fts_accpath, p->fts_statp))
				continue;
		}

		/*
		 * Protect against deleting root files and directories.
		 */
		if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, p->fts_accpath)) {
			fts_close(fts);
			return 1;
		}

		rval = 0;
#ifdef UF_APPEND
		if (!uid &&
		    (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
		    !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
			rval = chflags(p->fts_accpath,
				       p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
#endif
		if (rval == 0) {
			/*
			 * If we can't read or search the directory, may still be
			 * able to remove it.  Don't print out the un{read,search}able
			 * message unless the remove fails.
			 */
			switch (p->fts_info) {
			case FTS_DP:
			case FTS_DNR:
				rval = rmdir(p->fts_accpath);
				if (rval == 0 || (fflag && errno == ENOENT)) {
					if (rval == 0 && vflag)
						(void)printf("%s\n",
						    p->fts_path);
					continue;
				}
				operation = "mkdir";
				break;

#ifdef FTS_W
			case FTS_W:
				rval = undelete(p->fts_accpath);
				if (rval == 0 && (fflag && errno == ENOENT)) {
					if (vflag)
						(void)printf("%s\n",
						    p->fts_path);
					continue;
				}
				operation = "undelete";
				break;
#endif

			case FTS_NS:
				/*
				 * Assume that since fts_read() couldn't stat
				 * the file, it can't be unlinked.
				 */
				if (fflag)
					continue;
				/* FALLTHROUGH */
			default:
				if (Pflag)
					if (!rm_overwrite(p->fts_accpath, NULL))
						continue;
				rval = unlink(p->fts_accpath);
#ifdef _MSC_VER
				if (rval != 0) {
    					chmod(p->fts_accpath, 0777);
					rval = unlink(p->fts_accpath);
				}
#endif

				if (rval == 0 || (fflag && errno == ENOENT)) {
					if (rval == 0 && vflag)
						(void)printf("%s\n",
						    p->fts_path);
					continue;
				}
				operation = "unlink";
				break;
			}
		}
#ifdef UF_APPEND
err:
#endif
		fprintf(stderr, "%s: %s: %s: %s " CUR_LINE() "\n", operation, argv0, p->fts_path, strerror(errno));
		eval = 1;
	}
	if (errno) {
		fprintf(stderr, "%s: fts_read: %s " CUR_LINE() "\n", argv0, strerror(errno));
		eval = 1;
	}
	fts_close(fts);
	return eval;
}
コード例 #8
0
ファイル: cp.c プロジェクト: 2014-class/freerouter
static int
copy(char *argv[], enum op type, int fts_options)
{
	struct stat to_stat;
	FTS *ftsp;
	FTSENT *curr;
	int base = 0, dne, badcp, rval;
	size_t nlen;
	char *p, *target_mid;
	mode_t mask, mode;

	/*
	 * Keep an inverted copy of the umask, for use in correcting
	 * permissions on created directories when not using -p.
	 */
	mask = ~umask(0777);
	umask(~mask);

	if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL)
		err(1, "fts_open");
	for (badcp = rval = 0; (curr = fts_read(ftsp)) != NULL; badcp = 0) {
		switch (curr->fts_info) {
		case FTS_NS:
		case FTS_DNR:
		case FTS_ERR:
			warnx("%s: %s",
			    curr->fts_path, strerror(curr->fts_errno));
			badcp = rval = 1;
			continue;
		case FTS_DC:			/* Warn, continue. */
			warnx("%s: directory causes a cycle", curr->fts_path);
			badcp = rval = 1;
			continue;
		default:
			;
		}

		/*
		 * If we are in case (2) or (3) above, we need to append the
                 * source name to the target name.
                 */
		if (type != FILE_TO_FILE) {
			/*
			 * Need to remember the roots of traversals to create
			 * correct pathnames.  If there's a directory being
			 * copied to a non-existent directory, e.g.
			 *	cp -R a/dir noexist
			 * the resulting path name should be noexist/foo, not
			 * noexist/dir/foo (where foo is a file in dir), which
			 * is the case where the target exists.
			 *
			 * Also, check for "..".  This is for correct path
			 * concatenation for paths ending in "..", e.g.
			 *	cp -R .. /tmp
			 * Paths ending in ".." are changed to ".".  This is
			 * tricky, but seems the easiest way to fix the problem.
			 *
			 * XXX
			 * Since the first level MUST be FTS_ROOTLEVEL, base
			 * is always initialized.
			 */
			if (curr->fts_level == FTS_ROOTLEVEL) {
				if (type != DIR_TO_DNE) {
					p = strrchr(curr->fts_path, '/');
					base = (p == NULL) ? 0 :
					    (int)(p - curr->fts_path + 1);

					if (!strcmp(&curr->fts_path[base],
					    ".."))
						base += 1;
				} else
					base = curr->fts_pathlen;
			}

			p = &curr->fts_path[base];
			nlen = curr->fts_pathlen - base;
			target_mid = to.target_end;
			if (*p != '/' && target_mid[-1] != '/')
				*target_mid++ = '/';
			*target_mid = 0;
			if (target_mid - to.p_path + nlen >= PATH_MAX) {
				warnx("%s%s: name too long (not copied)",
				    to.p_path, p);
				badcp = rval = 1;
				continue;
			}
			(void)strncat(target_mid, p, nlen);
			to.p_end = target_mid + nlen;
			*to.p_end = 0;
			STRIP_TRAILING_SLASH(to);
		}

		if (curr->fts_info == FTS_DP) {
			/*
			 * We are nearly finished with this directory.  If we
			 * didn't actually copy it, or otherwise don't need to
			 * change its attributes, then we are done.
			 */
			if (!curr->fts_number)
				continue;
			/*
			 * If -p is in effect, set all the attributes.
			 * Otherwise, set the correct permissions, limited
			 * by the umask.  Optimise by avoiding a chmod()
			 * if possible (which is usually the case if we
			 * made the directory).  Note that mkdir() does not
			 * honour setuid, setgid and sticky bits, but we
			 * normally want to preserve them on directories.
			 */
			if (pflag) {
				if (setfile(curr->fts_statp, -1))
					rval = 1;
				if (preserve_dir_acls(curr->fts_statp,
				    curr->fts_accpath, to.p_path) != 0)
					rval = 1;
			} else {
				mode = curr->fts_statp->st_mode;
				if ((mode & (S_ISUID | S_ISGID | S_ISTXT)) ||
				    ((mode | S_IRWXU) & mask) != (mode & mask))
					if (chmod(to.p_path, mode & mask) != 0){
						warn("chmod: %s", to.p_path);
						rval = 1;
					}
			}
			continue;
		}

		/* Not an error but need to remember it happened */
		if (stat(to.p_path, &to_stat) == -1)
			dne = 1;
		else {
			if (to_stat.st_dev == curr->fts_statp->st_dev &&
			    to_stat.st_ino == curr->fts_statp->st_ino) {
				warnx("%s and %s are identical (not copied).",
				    to.p_path, curr->fts_path);
				badcp = rval = 1;
				if (S_ISDIR(curr->fts_statp->st_mode))
					(void)fts_set(ftsp, curr, FTS_SKIP);
				continue;
			}
			if (!S_ISDIR(curr->fts_statp->st_mode) &&
			    S_ISDIR(to_stat.st_mode)) {
				warnx("cannot overwrite directory %s with "
				    "non-directory %s",
				    to.p_path, curr->fts_path);
				badcp = rval = 1;
				continue;
			}
			dne = 0;
		}

		switch (curr->fts_statp->st_mode & S_IFMT) {
		case S_IFLNK:
			/* Catch special case of a non-dangling symlink */
			if ((fts_options & FTS_LOGICAL) ||
			    ((fts_options & FTS_COMFOLLOW) &&
			    curr->fts_level == 0)) {
				if (copy_file(curr, dne))
					badcp = rval = 1;
			} else {	
				if (copy_link(curr, !dne))
					badcp = rval = 1;
			}
			break;
		case S_IFDIR:
			if (!Rflag) {
				warnx("%s is a directory (not copied).",
				    curr->fts_path);
				(void)fts_set(ftsp, curr, FTS_SKIP);
				badcp = rval = 1;
				break;
			}
			/*
			 * If the directory doesn't exist, create the new
			 * one with the from file mode plus owner RWX bits,
			 * modified by the umask.  Trade-off between being
			 * able to write the directory (if from directory is
			 * 555) and not causing a permissions race.  If the
			 * umask blocks owner writes, we fail..
			 */
			if (dne) {
				if (mkdir(to.p_path,
				    curr->fts_statp->st_mode | S_IRWXU) < 0)
					err(1, "%s", to.p_path);
			} else if (!S_ISDIR(to_stat.st_mode)) {
				errno = ENOTDIR;
				err(1, "%s", to.p_path);
			}
			/*
			 * Arrange to correct directory attributes later
			 * (in the post-order phase) if this is a new
			 * directory, or if the -p flag is in effect.
			 */
			curr->fts_number = pflag || dne;
			break;
		case S_IFBLK:
		case S_IFCHR:
			if (Rflag) {
				if (copy_special(curr->fts_statp, !dne))
					badcp = rval = 1;
			} else {
				if (copy_file(curr, dne))
					badcp = rval = 1;
			}
			break;
		case S_IFSOCK:
			warnx("%s is a socket (not copied).",
				    curr->fts_path);
			break;
		case S_IFIFO:
			if (Rflag) {
				if (copy_fifo(curr->fts_statp, !dne))
					badcp = rval = 1;
			} else {
				if (copy_file(curr, dne))
					badcp = rval = 1;
			}
			break;
		default:
			if (copy_file(curr, dne))
				badcp = rval = 1;
			break;
		}
		if (vflag && !badcp)
			(void)printf("%s -> %s\n", curr->fts_path, to.p_path);
	}
	if (errno)
		err(1, "fts_read");
	fts_close(ftsp);
	return (rval);
}
コード例 #9
0
ファイル: du.c プロジェクト: AhmadTux/freebsd
int
main(int argc, char *argv[])
{
	FTS		*fts;
	FTSENT		*p;
	off_t		savednumber, curblocks;
	off_t		threshold, threshold_sign;
	int		ftsoptions;
	int		depth;
	int		Hflag, Lflag, aflag, sflag, dflag, cflag;
	int		hflag, lflag, ch, notused, rval;
	char 		**save;
	static char	dot[] = ".";

	setlocale(LC_ALL, "");

	Hflag = Lflag = aflag = sflag = dflag = cflag = hflag =
	    lflag = Aflag = 0;

	save = argv;
	ftsoptions = FTS_PHYSICAL;
	savednumber = 0;
	threshold = 0;
	threshold_sign = 1;
	cblocksize = DEV_BSIZE;
	blocksize = 0;
	depth = INT_MAX;
	SLIST_INIT(&ignores);

	while ((ch = getopt(argc, argv, "AB:HI:LPasd:chklmnrt:x")) != -1)
		switch (ch) {
		case 'A':
			Aflag = 1;
			break;
		case 'B':
			errno = 0;
			cblocksize = atoi(optarg);
			if (errno == ERANGE || cblocksize <= 0) {
				warnx("invalid argument to option B: %s",
				    optarg);
				usage();
			}
			break;
		case 'H':
			Hflag = 1;
			Lflag = 0;
			break;
		case 'I':
			ignoreadd(optarg);
			break;
		case 'L':
			Lflag = 1;
			Hflag = 0;
			break;
		case 'P':
			Hflag = Lflag = 0;
			break;
		case 'a':
			aflag = 1;
			break;
		case 's':
			sflag = 1;
			break;
		case 'd':
			dflag = 1;
			errno = 0;
			depth = atoi(optarg);
			if (errno == ERANGE || depth < 0) {
				warnx("invalid argument to option d: %s",
				    optarg);
				usage();
			}
			break;
		case 'c':
			cflag = 1;
			break;
		case 'h':
			hflag = 1;
			break;
		case 'k':
			hflag = 0;
			blocksize = 1024;
			break;
		case 'l':
			lflag = 1;
			break;
		case 'm':
			hflag = 0;
			blocksize = 1048576;
			break;
		case 'n':
			nodumpflag = 1;
			break;
		case 'r':		 /* Compatibility. */
			break;
		case 't' :
			if (expand_number(optarg, &threshold) != 0 ||
			    threshold == 0) {
				warnx("invalid threshold: %s", optarg);
				usage();
			} else if (threshold < 0)
				threshold_sign = -1;
			break;
		case 'x':
			ftsoptions |= FTS_XDEV;
			break;
		case '?':
		default:
			usage();
			/* NOTREACHED */
		}

	argc -= optind;
	argv += optind;

	/*
	 * XXX
	 * Because of the way that fts(3) works, logical walks will not count
	 * the blocks actually used by symbolic links.  We rationalize this by
	 * noting that users computing logical sizes are likely to do logical
	 * copies, so not counting the links is correct.  The real reason is
	 * that we'd have to re-implement the kernel's symbolic link traversing
	 * algorithm to get this right.  If, for example, you have relative
	 * symbolic links referencing other relative symbolic links, it gets
	 * very nasty, very fast.  The bottom line is that it's documented in
	 * the man page, so it's a feature.
	 */

	if (Hflag)
		ftsoptions |= FTS_COMFOLLOW;
	if (Lflag) {
		ftsoptions &= ~FTS_PHYSICAL;
		ftsoptions |= FTS_LOGICAL;
	}

	if (!Aflag && (cblocksize % DEV_BSIZE) != 0)
		cblocksize = howmany(cblocksize, DEV_BSIZE) * DEV_BSIZE;

	if (aflag + dflag + sflag > 1)
		usage();
	if (sflag)
		depth = 0;

	if (!*argv) {
		argv = save;
		argv[0] = dot;
		argv[1] = NULL;
	}

	if (blocksize == 0)
		(void)getbsize(&notused, &blocksize);

	if (!Aflag) {
		cblocksize /= DEV_BSIZE;
		blocksize /= DEV_BSIZE;
	}

	if (threshold != 0)
		threshold = howmany(threshold / DEV_BSIZE * cblocksize,
		    blocksize);

	rval = 0;

	(void)signal(SIGINFO, siginfo);

	if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
		err(1, "fts_open");

	while ((p = fts_read(fts)) != NULL) {
		switch (p->fts_info) {
		case FTS_D:			/* Ignore. */
			if (ignorep(p))
				fts_set(fts, p, FTS_SKIP);
			break;
		case FTS_DP:
			if (ignorep(p))
				break;

			curblocks = Aflag ?
			    howmany(p->fts_statp->st_size, cblocksize) :
			    howmany(p->fts_statp->st_blocks, cblocksize);
			p->fts_parent->fts_bignum += p->fts_bignum +=
			    curblocks;

			if (p->fts_level <= depth && threshold <=
			    threshold_sign * howmany(p->fts_bignum *
			    cblocksize, blocksize)) {
				if (hflag) {
					prthumanval(p->fts_bignum);
					(void)printf("\t%s\n", p->fts_path);
				} else {
					(void)printf("%jd\t%s\n",
					    (intmax_t)howmany(p->fts_bignum *
					    cblocksize, blocksize),
					    p->fts_path);
				}
			}
			if (info) {
				info = 0;
				(void)printf("\t%s\n", p->fts_path);
			}
			break;
		case FTS_DC:			/* Ignore. */
			break;
		case FTS_DNR:			/* Warn, continue. */
		case FTS_ERR:
		case FTS_NS:
			warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
			rval = 1;
			break;
		default:
			if (ignorep(p))
				break;

			if (lflag == 0 && p->fts_statp->st_nlink > 1 &&
			    linkchk(p))
				break;

			curblocks = Aflag ?
			    howmany(p->fts_statp->st_size, cblocksize) :
			    howmany(p->fts_statp->st_blocks, cblocksize);

			if (aflag || p->fts_level == 0) {
				if (hflag) {
					prthumanval(curblocks);
					(void)printf("\t%s\n", p->fts_path);
				} else {
					(void)printf("%jd\t%s\n",
					    (intmax_t)howmany(curblocks *
					    cblocksize, blocksize),
					    p->fts_path);
				}
			}

			p->fts_parent->fts_bignum += curblocks;
		}
		savednumber = p->fts_parent->fts_bignum;
	}

	if (errno)
		err(1, "fts_read");

	if (cflag) {
		if (hflag) {
			prthumanval(savednumber);
			(void)printf("\ttotal\n");
		} else {
			(void)printf("%jd\ttotal\n", (intmax_t)howmany(
			    savednumber * cblocksize, blocksize));
		}
	}

	ignoreclean();
	exit(rval);
}
コード例 #10
0
ファイル: ls.c プロジェクト: a565109863/src
/*
 * Traverse() walks the logical directory structure specified by the argv list
 * in the order specified by the mastercmp() comparison function.  During the
 * traversal it passes linked lists of structures to display() which represent
 * a superset (may be exact set) of the files to be displayed.
 */
static void
traverse(int argc, char *argv[], int options)
{
	FTS *ftsp;
	FTSENT *p, *chp;
	int ch_options, saved_errno;

	if ((ftsp =
	    fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL)
		err(1, NULL);

	display(NULL, fts_children(ftsp, 0));
	if (f_listdir)
		return;

	/*
	 * If not recursing down this tree and don't need stat info, just get
	 * the names.
	 */
	ch_options = !f_recursive && options & FTS_NOSTAT ? FTS_NAMEONLY : 0;

	while ((p = fts_read(ftsp)) != NULL)
		switch (p->fts_info) {
		case FTS_D:
			if (p->fts_name[0] == '.' &&
			    p->fts_level != FTS_ROOTLEVEL && !f_listdot)
				break;

			/*
			 * If already output something, put out a newline as
			 * a separator.  If multiple arguments, precede each
			 * directory with its name.
			 */
			if (output)
				(void)printf("\n%s:\n", p->fts_path);
			else if (argc > 1) {
				(void)printf("%s:\n", p->fts_path);
				output = 1;
			}

			chp = fts_children(ftsp, ch_options);
			saved_errno = errno;
			display(p, chp);

			/*
			 * On fts_children() returning error do recurse to see
			 * the error.
			 */
			if (!f_recursive && !(chp == NULL && saved_errno != 0))
				(void)fts_set(ftsp, p, FTS_SKIP);
			break;
		case FTS_DC:
			warnx("%s: directory causes a cycle", p->fts_name);
			break;
		case FTS_DNR:
		case FTS_ERR:
			warnx("%s: %s", p->fts_name[0] == '\0' ? p->fts_path :
			    p->fts_name, strerror(p->fts_errno));
			rval = 1;
			break;
		}
	if (errno)
		err(1, "fts_read");

	fts_close(ftsp);
}
コード例 #11
0
void __do_dremove(IN tt_io_ev_t *io_ev)
{
    __dremove_t *dremove = (__dremove_t *)io_ev;

    tt_char_t *path[2] = {(tt_char_t *)dremove->path, NULL};
    FTS *fts;
    FTSENT *ftse;

retry1:
    fts = fts_open(path, FTS_NOCHDIR | FTS_NOSTAT | FTS_PHYSICAL, NULL);
    if (fts == NULL) {
        if (errno == EINTR) {
            goto retry1;
        } else {
            TT_ERROR_NTV("fail to open fts: %s", path);
            dremove->result = TT_FAIL;
            return;
        }
    }

    while (1) {
    retry2:
        ftse = fts_read(fts);
        if (ftse == NULL) {
            if (errno == 0) {
                break;
            } else if (errno == EINTR) {
                goto retry2;
            } else {
                TT_ERROR_NTV("fail to read fts");
                __RETRY_IF_EINTR(fts_close(fts) != 0);
                dremove->result = TT_FAIL;
                return;
            }
        }

        switch (ftse->fts_info) {
            case FTS_DEFAULT:
            case FTS_F:
            case FTS_NSOK:
            case FTS_SL:
            case FTS_SLNONE: {
                // remove file
                if (unlink(ftse->fts_accpath) != 0) {
                    TT_ERROR_NTV("fail to remove file[%s]", ftse->fts_accpath);
                    __RETRY_IF_EINTR(fts_close(fts) != 0);
                    dremove->result = TT_FAIL;
                    return;
                }
            } break;
            case FTS_DP: {
                // can remove directory now
                if (rmdir(ftse->fts_accpath) != 0) {
                    TT_ERROR_NTV("fail to remove directory[%s]",
                                 ftse->fts_accpath);
                    __RETRY_IF_EINTR(fts_close(fts) != 0);
                    dremove->result = TT_FAIL;
                    return;
                }
            } break;
            case FTS_D: {
                // something to ignore
            } break;
            default: {
                // something unexpected
                TT_ERROR("expected fts info: %d", ftse->fts_info);
                __RETRY_IF_EINTR(fts_close(fts) != 0);
                dremove->result = TT_FAIL;
                return;
            } break;
        }
    }

    __RETRY_IF_EINTR(fts_close(fts) != 0);
    dremove->result = TT_SUCCESS;
}
コード例 #12
0
ファイル: ftree.c プロジェクト: daniloegea/freebsd
static int
ftree_arg(void)
{
	char *pt;

	/*
	 * close off the current file tree
	 */
	if (ftsp != NULL) {
		(void)fts_close(ftsp);
		ftsp = NULL;
	}

	/*
	 * keep looping until we get a valid file tree to process. Stop when we
	 * reach the end of the list (or get an eof on stdin)
	 */
	for(;;) {
		if (fthead == NULL) {
			/*
			 * the user didn't supply any args, get the file trees
			 * to process from stdin;
			 */
			if (fgets(farray[0], PAXPATHLEN+1, stdin) == NULL)
				return(-1);
			if ((pt = strchr(farray[0], '\n')) != NULL)
				*pt = '\0';
		} else {
			/*
			 * the user supplied the file args as arguments to pax
			 */
			if (ftcur == NULL)
				ftcur = fthead;
			else if ((ftcur = ftcur->fow) == NULL)
				return(-1);
			if (ftcur->chflg) {
				/* First fchdir() back... */
				if (fchdir(cwdfd) < 0) {
					syswarn(1, errno,
					  "Can't fchdir to starting directory");
					return(-1);
				}
				if (chdir(ftcur->fname) < 0) {
					syswarn(1, errno, "Can't chdir to %s",
					    ftcur->fname);
					return(-1);
				}
				continue;
			} else
				farray[0] = ftcur->fname;
		}

		/*
		 * Watch it, fts wants the file arg stored in an array of char
		 * ptrs, with the last one a null. We use a two element array
		 * and set farray[0] to point at the buffer with the file name
		 * in it. We cannot pass all the file args to fts at one shot
		 * as we need to keep a handle on which file arg generates what
		 * files (the -n and -d flags need this). If the open is
		 * successful, return a 0.
		 */
		if ((ftsp = fts_open(farray, ftsopts, NULL)) != NULL)
			break;
	}
	return(0);
}
コード例 #13
0
ファイル: chown.c プロジェクト: Leon555/Mac-src-essentials
int
main(int argc, char **argv)
{
	FTS *ftsp;
	FTSENT *p;
	int Hflag, Lflag, Pflag, Rflag, fflag, hflag, vflag;
	int ch, fts_options, rval;
	char *cp;
	int unix2003_compat = 0;
	int symlink_found = 0;

	if (argc < 1)
		usage();
	cp = strrchr(argv[0], '/');
	cp = (cp != NULL) ? cp + 1 : argv[0];
	ischown = (strcmp(cp, "chown") == 0);

	Hflag = Lflag = Pflag = Rflag = fflag = hflag = vflag = 0;
	while ((ch = getopt(argc, argv, "HLPRfhv")) != -1)
		switch (ch) {
		case 'H':
			Hflag = 1;
			Lflag = Pflag = 0;
			break;
		case 'L':
			Lflag = 1;
			Hflag = Pflag = 0;
			break;
		case 'P':
			Pflag = 1;
			Hflag = Lflag = 0;
			break;
		case 'R':
			Rflag = 1;
			break;
		case 'f':
			fflag = 1;
			break;
		case 'h':
			hflag = 1;
	 		break;
		case 'v':
			vflag = 1;
			break;
		case '?':
		default:
			usage();
		}
	argv += optind;
	argc -= optind;

	if (argc < 2)
		usage();
	if (!Rflag && (Hflag || Lflag || Pflag))
		warnx("options -H, -L, -P only useful with -R");

	if (Rflag) {
		fts_options = FTS_PHYSICAL;
		if (hflag && (Hflag || Lflag))
			errx(1, "the -R%c and -h options may not be "
			    "specified together", Hflag ? 'H' : 'L');
		if (Hflag)
			fts_options |= FTS_COMFOLLOW;
		else if (Lflag) {
			fts_options &= ~FTS_PHYSICAL;
			fts_options |= FTS_LOGICAL;
		}
	} else
		fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;

	uid = (uid_t)-1;
	gid = (gid_t)-1;
	if (ischown) {
		unix2003_compat = COMPAT_MODE("bin/chown", "Unix2003");
		if ((cp = strchr(*argv, ':')) != NULL) {
			*cp++ = '\0';
			a_gid(cp);
		}
#ifdef SUPPORT_DOT
		else if ((cp = strchr(*argv, '.')) != NULL) {
			warnx("separation of user and group with a period is deprecated");
			*cp++ = '\0';
			a_gid(cp);
		}
#endif
		a_uid(*argv);
	} else {
		unix2003_compat = COMPAT_MODE("bin/chgrp", "Unix2003");
		a_gid(*argv);
	}

	if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
		err(1, NULL);

	for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
		symlink_found = 0;
		switch (p->fts_info) {
		case FTS_D:			/* Change it at FTS_DP. */
			if (!Rflag)
				fts_set(ftsp, p, FTS_SKIP);
			continue;
		case FTS_DNR:			/* Warn, chown. */
			warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
			rval = 1;
			break;
		case FTS_ERR:			/* Warn, continue. */
		case FTS_NS:
			warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
			rval = 1;
			continue;
		case FTS_SL:
		case FTS_SLNONE:
			/*
			 * The only symlinks that end up here are ones that
			 * don't point to anything and ones that we found
			 * doing a physical walk.
			 */
			if (hflag)
				break;
			else {
				symlink_found = 1;
				if (unix2003_compat) {
					if (Hflag || Lflag) {       /* -H or -L was specified */
						if (p->fts_errno) {
							warnx("%s: %s", p->fts_name, strerror(p->fts_errno));
							rval = 1;
							continue;
						}
					}
					break; /* Otherwise symlinks keep going */
				}
				continue;
			}
		default:
			break;
		}
		if (unix2003_compat) {
			/* Can only avoid updating times if both uid and gid are -1 */
			if ((uid == (uid_t)-1) && (gid == (gid_t)-1))
				continue;
		} else {
			if ((uid == (uid_t)-1 || uid == p->fts_statp->st_uid) &&
			    (gid == (gid_t)-1 || gid == p->fts_statp->st_gid))
				continue;
		}
		if (((hflag || symlink_found) ? lchown : chown)(p->fts_accpath, uid, gid) == -1) {
			if (!fflag) {
				chownerr(p->fts_path);
				rval = 1;
			}
		} else {
			if (vflag)
				printf("%s\n", p->fts_path);
		}
	}
	if (errno)
		err(1, "fts_read");
	exit(rval);
}
コード例 #14
0
ファイル: fscrawl.c プロジェクト: fiktivkod/archived
static FTS* _fts_open(char *path, int opts) {

    char *npath[2] = { path, NULL };

    return fts_open(npath, opts, NULL);
}
コード例 #15
0
ファイル: ckdist.c プロジェクト: AhmadTux/DragonFlyBSD
int
main(int argc, char *argv[])
{
    static char *arg[2];
    struct stat sb;
    FTS *ftsp;
    FTSENT *f;
    int rval, c, type;

    while ((c = getopt(argc, argv, "ad:in:rst:x")) != -1)
	switch (c) {
	case 'a':
	    opt_all = 1;
	    break;
	case 'd':
	    opt_dir = optarg;
	    break;
	case 'i':
	    opt_ignore = 1;
	    break;
	case 'n':
	    opt_name = optarg;
	    break;
	case 'r':
	    opt_recurse = 1;
	    break;
	case 's':
	    opt_silent = 1;
	    break;
	case 't':
	    if ((opt_type = disttype(optarg)) == 0) {
		warnx("illegal argument to -t option");
		usage();
	    }
	    break;
	case 'x':
	    opt_exist = 1;
	    break;
	default:
	    usage();
	}
    argc -= optind;
    argv += optind;
    if (argc < 1)
	usage();
    if (opt_dir) {
	if (stat(opt_dir, &sb))
	    err(2, "%s", opt_dir);
	if (!S_ISDIR(sb.st_mode))
	    errx(2, "%s: not a directory", opt_dir);
    }
    rval = 0;
    do {
	if (isstdin(*argv))
	    rval |= ckdist(*argv, opt_type);
	else if (stat(*argv, &sb))
	    rval |= fail(*argv, NULL);
	else if (S_ISREG(sb.st_mode))
	    rval |= ckdist(*argv, opt_type);
	else {
	    arg[0] = *argv;
	    if ((ftsp = fts_open(arg, FTS_LOGICAL, NULL)) == NULL)
		err(2, "fts_open");
	    while ((f = fts_read(ftsp)) != NULL)
		switch (f->fts_info) {
		case FTS_DC:
		    rval = fail(f->fts_path, "Directory causes a cycle");
		    break;
		case FTS_DNR:
		case FTS_ERR:
		case FTS_NS:
		    rval = fail(f->fts_path, sys_errlist[f->fts_errno]);
		    break;
		case FTS_D:
		    if (!opt_recurse && f->fts_level > FTS_ROOTLEVEL &&
			fts_set(ftsp, f, FTS_SKIP))
			err(2, "fts_set");
		    break;
		case FTS_F:
		    if ((type = distfile(f->fts_name)) != 0 &&
			(!opt_type || type == opt_type))
			rval |= ckdist(f->fts_path, type);
		    break;
                default: ;
		}
	    if (errno)
		err(2, "fts_read");
	    if (fts_close(ftsp))
		err(2, "fts_close");
	}
    } while (*++argv);
    return rval;
}
コード例 #16
0
ファイル: rm.c プロジェクト: 0xffffffRabbit/NextBSD-1
static void
rm_tree(char **argv)
{
	FTS *fts;
	FTSENT *p;
	int needstat;
	int flags;
	int rval;

	/*
	 * Remove a file hierarchy.  If forcing removal (-f), or interactive
	 * (-i) or can't ask anyway (stdin_ok), don't stat the file.
	 */
	needstat = !uid || (!fflag && !iflag && stdin_ok);

	/*
	 * If the -i option is specified, the user can skip on the pre-order
	 * visit.  The fts_number field flags skipped directories.
	 */
#define	SKIPPED	1

	flags = FTS_PHYSICAL;
	if (!needstat)
		flags |= FTS_NOSTAT;
	if (Wflag)
		flags |= FTS_WHITEOUT;
	if (xflag)
		flags |= FTS_XDEV;
	if (!(fts = fts_open(argv, flags, NULL))) {
		if (fflag && errno == ENOENT)
			return;
		err(1, "fts_open");
	}
	while ((p = fts_read(fts)) != NULL) {
		switch (p->fts_info) {
		case FTS_DNR:
			if (!fflag || p->fts_errno != ENOENT) {
				warnx("%s: %s",
				    p->fts_path, strerror(p->fts_errno));
				eval = 1;
			}
			continue;
		case FTS_ERR:
			errx(1, "%s: %s", p->fts_path, strerror(p->fts_errno));
		case FTS_NS:
			/*
			 * Assume that since fts_read() couldn't stat the
			 * file, it can't be unlinked.
			 */
			if (!needstat)
				break;
			if (!fflag || p->fts_errno != ENOENT) {
				warnx("%s: %s",
				    p->fts_path, strerror(p->fts_errno));
				eval = 1;
			}
			continue;
		case FTS_D:
			/* Pre-order: give user chance to skip. */
			if (!fflag && !check(p->fts_path, p->fts_accpath,
			    p->fts_statp)) {
				(void)fts_set(fts, p, FTS_SKIP);
				p->fts_number = SKIPPED;
			}
			else if (!uid &&
				 (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
				 !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
				 lchflags(p->fts_accpath,
					 p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
				goto err;
			continue;
		case FTS_DP:
			/* Post-order: see if user skipped. */
			if (p->fts_number == SKIPPED)
				continue;
			break;
		default:
			if (!fflag &&
			    !check(p->fts_path, p->fts_accpath, p->fts_statp))
				continue;
		}

		rval = 0;
		if (!uid &&
		    (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
		    !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
			rval = lchflags(p->fts_accpath,
				       p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
		if (rval == 0) {
			/*
			 * If we can't read or search the directory, may still be
			 * able to remove it.  Don't print out the un{read,search}able
			 * message unless the remove fails.
			 */
			switch (p->fts_info) {
			case FTS_DP:
			case FTS_DNR:
				rval = rmdir(p->fts_accpath);
				if (rval == 0 || (fflag && errno == ENOENT)) {
					if (rval == 0 && vflag)
						(void)printf("%s\n",
						    p->fts_path);
					if (rval == 0 && info) {
						info = 0;
						(void)printf("%s\n",
						    p->fts_path);
					}
					continue;
				}
				break;

			case FTS_W:
				rval = undelete(p->fts_accpath);
				if (rval == 0 && (fflag && errno == ENOENT)) {
					if (vflag)
						(void)printf("%s\n",
						    p->fts_path);
					if (info) {
						info = 0;
						(void)printf("%s\n",
						    p->fts_path);
					}
					continue;
				}
				break;

			case FTS_NS:
				/*
				 * Assume that since fts_read() couldn't stat
				 * the file, it can't be unlinked.
				 */
				if (fflag)
					continue;
				/* FALLTHROUGH */

			case FTS_F:
			case FTS_NSOK:
				if (Pflag)
					if (!rm_overwrite(p->fts_accpath, p->fts_info ==
					    FTS_NSOK ? NULL : p->fts_statp))
						continue;
				/* FALLTHROUGH */

			default:
				rval = unlink(p->fts_accpath);
				if (rval == 0 || (fflag && errno == ENOENT)) {
					if (rval == 0 && vflag)
						(void)printf("%s\n",
						    p->fts_path);
					if (rval == 0 && info) {
						info = 0;
						(void)printf("%s\n",
						    p->fts_path);
					}
					continue;
				}
			}
		}
err:
		warn("%s", p->fts_path);
		eval = 1;
	}
	if (!fflag && errno)
		err(1, "fts_read");
	fts_close(fts);
}
コード例 #17
0
int restorecon_main(int argc, char **argv)
{
    int ch, recurse = 0, ftsflags = FTS_PHYSICAL;
    int i = 0;

    progname = argv[0];

    do {
        ch = getopt(argc, argv, "nrRv");
        if (ch == EOF)
            break;
        switch (ch) {
        case 'n':
            nochange = 1;
            break;
        case 'r':
        case 'R':
            recurse = 1;
            break;
        case 'v':
            verbose = 1;
            break;
        default:
            usage();
        }
    } while (1);

    argc -= optind;
    argv += optind;
    if (!argc)
        usage();

    sehandle = selinux_android_file_context_handle();

    if (!sehandle) {
        fprintf(stderr, "Could not load file_contexts:  %s\n",
                strerror(errno));
        return -1;
    }

    if (recurse) {
        FTS *fts;
        FTSENT *ftsent;
        fts = fts_open(argv, ftsflags, NULL);
        if (!fts) {
            fprintf(stderr, "Could not traverse filesystems (first was %s):  %s\n",
                    argv[0], strerror(errno));
            return -1;
        }
        while ((ftsent = fts_read(fts))) {
            switch (ftsent->fts_info) {
            case FTS_DP:
                break;
            case FTS_DNR:
            case FTS_ERR:
            case FTS_NS:
                fprintf(stderr, "Could not access %s:  %s\n", ftsent->fts_path,
                        strerror(errno));
                fts_set(fts, ftsent, FTS_SKIP);
                break;
            default:
                if (restore(ftsent->fts_path, ftsent->fts_statp) < 0)
                    fts_set(fts, ftsent, FTS_SKIP);
                break;
            }
        }
    } else {
        int i, rc;
        struct stat sb;

        for (i = 0; i < argc; i++) {
            rc = lstat(argv[i], &sb);
            if (rc < 0) {
                fprintf(stderr, "Could not stat %s:  %s\n", argv[i],
                        strerror(errno));
                continue;
            }
            restore(argv[i], &sb);
        }
    }

    return 0;
}
コード例 #18
0
static int
vwalk(void)
{
	FTS *t;
	FTSENT *p;
	NODE *ep, *level;
	int specdepth, rval;
	char *argv[2];
	char dot[] = ".";

	argv[0] = dot;
	argv[1] = NULL;
	if ((t = fts_open(argv, ftsoptions, nsort)) == NULL)
		err(1, "line %d: fts_open", lineno);
	level = root;
	specdepth = rval = 0;
	while ((p = fts_read(t))) {
		if (check_excludes(p->fts_name, p->fts_path)) {
			fts_set(t, p, FTS_SKIP);
			continue;
		}
		switch(p->fts_info) {
		case FTS_D:
		case FTS_SL:
			break;
		case FTS_DP:
			if (specdepth > p->fts_level) {
				for (level = level->parent; level->prev;
				      level = level->prev);
				--specdepth;
			}
			continue;
		case FTS_DNR:
		case FTS_ERR:
		case FTS_NS:
			warnx("%s: %s", RP(p), strerror(p->fts_errno));
			continue;
		default:
			if (dflag)
				continue;
		}

		if (specdepth != p->fts_level)
			goto extra;
		for (ep = level; ep; ep = ep->next)
			if ((ep->flags & F_MAGIC &&
			    !fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) ||
			    !strcmp(ep->name, p->fts_name)) {
				ep->flags |= F_VISIT;
				if ((ep->flags & F_NOCHANGE) == 0 &&
				    compare(ep->name, ep, p))
					rval = MISMATCHEXIT;
				if (ep->flags & F_IGN)
					(void)fts_set(t, p, FTS_SKIP);
				else if (ep->child && ep->type == F_DIR &&
				    p->fts_info == FTS_D) {
					level = ep->child;
					++specdepth;
				}
				break;
			}

		if (ep)
			continue;
extra:
		if (!eflag) {
			(void)printf("%s extra", RP(p));
			if (rflag) {
				if ((S_ISDIR(p->fts_statp->st_mode)
				    ? rmdir : unlink)(p->fts_accpath)) {
					(void)printf(", not removed: %s",
					    strerror(errno));
				} else
					(void)printf(", removed");
			}
			(void)putchar('\n');
		}
		(void)fts_set(t, p, FTS_SKIP);
	}
	(void)fts_close(t);
	if (sflag)
		warnx("%s checksum: %lu", fullpath, (unsigned long)crc_total);
	return (rval);
}
コード例 #19
0
ファイル: ftree.c プロジェクト: janpaulus/brocre
static int
ftree_arg(void)
{
    /*
     * close off the current file tree
     */
    if (ftsp != NULL) {
        (void)fts_close(ftsp);
        ftsp = NULL;
    }

    /*
     * keep looping until we get a valid file tree to process. Stop when we
     * reach the end of the list (or get an eof on stdin)
     */
    for(;;) {
        if (fthead == NULL) {
            int i, c = EOF;
            /*
             * the user didn't supply any args, get the file trees
             * to process from stdin;
             */
            for (i = 0; i < PAXPATHLEN + 2; i++) {
                c = getchar();
                if (c == EOF)
                    break;
                else if (c == sep) {
                    if (i != 0)
                        break;
                } else
                    farray[0][i] = c;
            }
            if (i == 0)
                return -1;
            farray[0][i] = '\0';
        } else {
            /*
             * the user supplied the file args as arguements to pax
             */
            if (ftcur == NULL)
                ftcur = fthead;
            else if ((ftcur = ftcur->fow) == NULL)
                return -1;

            if (ftcur->refcnt < 0) {
                /*
                 * chdir entry.
                 * Change directory and retry loop.
                 */
                if (ar_dochdir(ftcur->fname))
                    return (-1);
                continue;
            }
            farray[0] = ftcur->fname;
        }

        /*
         * watch it, fts wants the file arg stored in a array of char
         * ptrs, with the last one a null. we use a two element array
         * and set farray[0] to point at the buffer with the file name
         * in it. We cannot pass all the file args to fts at one shot
         * as we need to keep a handle on which file arg generates what
         * files (the -n and -d flags need this). If the open is
         * successful, return a 0.
         */
        if ((ftsp = fts_open(farray, ftsopts, NULL)) != NULL)
            break;
    }
    return 0;
}
コード例 #20
0
ファイル: cp.c プロジェクト: Bluerise/bitrig
int
copy(char *argv[], enum op type, int fts_options)
{
	struct stat to_stat;
	FTS *ftsp;
	FTSENT *curr;
	int base, nlen, rval;
	char *p, *target_mid;
	base = 0;

	if ((ftsp = fts_open(argv, fts_options, NULL)) == NULL)
		err(1, NULL);
	for (rval = 0; (curr = fts_read(ftsp)) != NULL;) {
		switch (curr->fts_info) {
		case FTS_NS:
		case FTS_DNR:
		case FTS_ERR:
			warnx("%s: %s",
			    curr->fts_path, strerror(curr->fts_errno));
			rval = 1;
			continue;
		case FTS_DC:
			warnx("%s: directory causes a cycle", curr->fts_path);
			rval = 1;
			continue;
		}

		/*
		 * If we are in case (2) or (3) above, we need to append the
		 * source name to the target name.
		 */
		if (type != FILE_TO_FILE) {
			/*
			 * Need to remember the roots of traversals to create
			 * correct pathnames.  If there's a directory being
			 * copied to a non-existent directory, e.g.
			 *	cp -R a/dir noexist
			 * the resulting path name should be noexist/foo, not
			 * noexist/dir/foo (where foo is a file in dir), which
			 * is the case where the target exists.
			 *
			 * Also, check for "..".  This is for correct path
			 * concatenation for paths ending in "..", e.g.
			 *	cp -R .. /tmp
			 * Paths ending in ".." are changed to ".".  This is
			 * tricky, but seems the easiest way to fix the problem.
			 *
			 * XXX
			 * Since the first level MUST be FTS_ROOTLEVEL, base
			 * is always initialized.
			 */
			if (curr->fts_level == FTS_ROOTLEVEL) {
				if (type != DIR_TO_DNE) {
					p = find_last_component(curr->fts_path);
					base = p - curr->fts_path;
					
					if (!strcmp(&curr->fts_path[base],
					    ".."))
						base += 1;
				} else
					base = curr->fts_pathlen;
			}

			p = &curr->fts_path[base];
			nlen = curr->fts_pathlen - base;
			target_mid = to.target_end;
			if (*p != '/' && target_mid[-1] != '/')
				*target_mid++ = '/';
			*target_mid = '\0';
			if (target_mid - to.p_path + nlen >= PATH_MAX) {
				warnx("%s%s: name too long (not copied)",
				    to.p_path, p);
				rval = 1;
				continue;
			}
			(void)strncat(target_mid, p, nlen);
			to.p_end = target_mid + nlen;
			*to.p_end = '\0';
		}

		/* Not an error but need to remember it happened */
		if (stat(to.p_path, &to_stat) == -1) {
			if (curr->fts_info == FTS_DP)
				continue;
			/*
			 * We use fts_pointer as a boolean to indicate that
			 * we created this directory ourselves.  We'll use
			 * this later on via the fts_dne macro to decide
			 * whether or not to set the directory mode during
			 * the post-order pass.
			 */
			curr->fts_pointer = (void *)1;
		} else {
			/*
			 * Set directory mode/user/times on the post-order
			 * pass.  We can't do this earlier because the mode
			 * may not allow us write permission.  Furthermore,
			 * if we set the times during the pre-order pass,
			 * they will get changed later when the directory
			 * is populated.
			 */
			if (curr->fts_info == FTS_DP) {
				if (!S_ISDIR(to_stat.st_mode))
					continue;
				/*
				 * If not -p and directory didn't exist, set
				 * it to be the same as the from directory,
				 * unmodified by the umask; arguably wrong,
				 * but it's been that way forever.
				 */
				if (pflag && setfile(curr->fts_statp, -1))
					rval = 1;
				else if (fts_dne(curr))
					(void)chmod(to.p_path,
					    curr->fts_statp->st_mode);
				continue;
			}
			if (to_stat.st_dev == curr->fts_statp->st_dev &&
			    to_stat.st_ino == curr->fts_statp->st_ino) {
				warnx("%s and %s are identical (not copied).",
				    to.p_path, curr->fts_path);
				rval = 1;
				if (S_ISDIR(curr->fts_statp->st_mode))
					(void)fts_set(ftsp, curr, FTS_SKIP);
				continue;
			}
			if (!S_ISDIR(curr->fts_statp->st_mode) &&
			    S_ISDIR(to_stat.st_mode)) {
		warnx("cannot overwrite directory %s with non-directory %s",
				    to.p_path, curr->fts_path);
				rval = 1;
				continue;
			}
		}

		switch (curr->fts_statp->st_mode & S_IFMT) {
		case S_IFLNK:
			if (copy_link(curr, !fts_dne(curr))) {
				rval = 1;
				continue;
			}
			break;
		case S_IFDIR:
			if (!Rflag && !rflag) {
				warnx("%s is a directory (not copied).",
				    curr->fts_path);
				(void)fts_set(ftsp, curr, FTS_SKIP);
				rval = 1;
				continue;
			}
			/*
			 * If the directory doesn't exist, create the new
			 * one with the from file mode plus owner RWX bits,
			 * modified by the umask.  Trade-off between being
			 * able to write the directory (if from directory is
			 * 555) and not causing a permissions race.  If the
			 * umask blocks owner writes, we fail..
			 */
			if (fts_dne(curr)) {
				if (mkdir(to.p_path,
				    curr->fts_statp->st_mode | S_IRWXU) < 0)
					err(1, "%s", to.p_path);
			} else if (!S_ISDIR(to_stat.st_mode))
				errc(1, ENOTDIR, "%s", to.p_path);
			break;
		case S_IFBLK:
		case S_IFCHR:
			if (Rflag ?
			    copy_special(curr->fts_statp, !fts_dne(curr)) :
			    copy_file(curr, fts_dne(curr))) {
				rval = 1;
				continue;
			}
			break;
		case S_IFIFO:
			if (Rflag ?
			    copy_fifo(curr->fts_statp, !fts_dne(curr)) :
			    copy_file(curr, fts_dne(curr))) {
				rval = 1;
				continue;
			}
			break;
		case S_IFSOCK:
			warnc(EOPNOTSUPP, "%s", curr->fts_path);
			break;
		default:
			if (copy_file(curr, fts_dne(curr))) {
				rval = 1;
				continue;
			}
			break;
		}
		if (vflag)
			(void)printf("%s -> %s\n", curr->fts_path, to.p_path);
	}
	if (errno)
		err(1, "fts_read");
	(void)fts_close(ftsp);
	return (rval);
}
コード例 #21
0
ファイル: chflags.c プロジェクト: 0xbda2d2f8/freebsd
int
main(int argc, char *argv[])
{
	FTS *ftsp;
	FTSENT *p;
	u_long clear, newflags, set;
	long val;
	int Hflag, Lflag, Rflag, fflag, hflag, vflag;
	int ch, fts_options, oct, rval;
	char *flags, *ep;
	int (*change_flags)(const char *, unsigned long);

	Hflag = Lflag = Rflag = fflag = hflag = vflag = 0;
	while ((ch = getopt(argc, argv, "HLPRfhv")) != -1)
		switch (ch) {
		case 'H':
			Hflag = 1;
			Lflag = 0;
			break;
		case 'L':
			Lflag = 1;
			Hflag = 0;
			break;
		case 'P':
			Hflag = Lflag = 0;
			break;
		case 'R':
			Rflag = 1;
			break;
		case 'f':
			fflag = 1;
			break;
		case 'h':
			hflag = 1;
			break;
		case 'v':
			vflag++;
			break;
		case '?':
		default:
			usage();
		}
	argv += optind;
	argc -= optind;

	if (argc < 2)
		usage();

	if (Rflag) {
		fts_options = FTS_PHYSICAL;
		if (hflag)
			errx(1, "the -R and -h options "
			        "may not be specified together");
		if (Hflag)
			fts_options |= FTS_COMFOLLOW;
		if (Lflag) {
			fts_options &= ~FTS_PHYSICAL;
			fts_options |= FTS_LOGICAL;
		}
	} else
		fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;

	change_flags = hflag ? lchflags : chflags;

	flags = *argv;
	if (*flags >= '0' && *flags <= '7') {
		errno = 0;
		val = strtol(flags, &ep, 8);
		if (val < 0)
			errno = ERANGE;
		if (errno)
                        err(1, "invalid flags: %s", flags);
                if (*ep)
                        errx(1, "invalid flags: %s", flags);
		set = val;
                oct = 1;
	} else {
		if (strtofflags(&flags, &set, &clear))
                        errx(1, "invalid flag: %s", flags);
		clear = ~clear;
		oct = 0;
	}

	if ((ftsp = fts_open(++argv, fts_options , 0)) == NULL)
		err(1, NULL);

	for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
		switch (p->fts_info) {
		case FTS_D:	/* Change it at FTS_DP if we're recursive. */
			if (!Rflag)
				fts_set(ftsp, p, FTS_SKIP);
			continue;
		case FTS_DNR:			/* Warn, chflag, continue. */
			warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
			rval = 1;
			break;
		case FTS_ERR:			/* Warn, continue. */
		case FTS_NS:
			warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
			rval = 1;
			continue;
		case FTS_SL:			/* Ignore. */
		case FTS_SLNONE:
			/*
			 * The only symlinks that end up here are ones that
			 * don't point to anything and ones that we found
			 * doing a physical walk.
			 */
			if (!hflag)
				continue;
			/* FALLTHROUGH */
		default:
			break;
		}
		if (oct)
			newflags = set;
		else
			newflags = (p->fts_statp->st_flags | set) & clear;
		if (newflags == p->fts_statp->st_flags)
			continue;
		if ((*change_flags)(p->fts_accpath, newflags) && !fflag) {
			warn("%s", p->fts_path);
			rval = 1;
		} else if (vflag) {
			(void)printf("%s", p->fts_path);
			if (vflag > 1)
				(void)printf(": 0%lo -> 0%lo",
				    (u_long)p->fts_statp->st_flags,
				    newflags);
			(void)printf("\n");
		}
	}
	if (errno)
		err(1, "fts_read");
	exit(rval);
}
コード例 #22
0
ファイル: nftw.c プロジェクト: ARMtools/newlib-cygwin
int
nftw(const char *path, int (*fn)(const char *, const struct stat *, int,
     struct FTW *), int nfds __attribute__ ((unused)), int ftwflags)
{
	char * const paths[2] = { (char *)path, NULL };
	struct FTW ftw;
	FTSENT *cur;
	FTS *ftsp;
	int error = 0, ftsflags, fnflag, postorder, sverrno;

#if 0
	/* GLibc allows nfds < 1 and treats it as nfds == 1.  Since nfds is
	   not used in this OpenBSD version anyway, just ignore it for
	   Linux compatibility. */
	/* XXX - nfds is currently unused */
	if (nfds < 1 || nfds > OPEN_MAX) {
		errno = EINVAL;
		return (-1);
	}
#endif

	ftsflags = FTS_COMFOLLOW;
	if (!(ftwflags & FTW_CHDIR))
		ftsflags |= FTS_NOCHDIR;
	if (ftwflags & FTW_MOUNT)
		ftsflags |= FTS_XDEV;
	if (ftwflags & FTW_PHYS)
		ftsflags |= FTS_PHYSICAL;
	else
		ftsflags |= FTS_LOGICAL;
	postorder = (ftwflags & FTW_DEPTH) != 0;
	ftsp = fts_open(paths, ftsflags, NULL);
	if (ftsp == NULL)
		return (-1);
	while ((cur = fts_read(ftsp)) != NULL) {
		switch (cur->fts_info) {
		case FTS_D:
			if (postorder)
				continue;
			fnflag = FTW_D;
			break;
		case FTS_DNR:
			fnflag = FTW_DNR;
			break;
		case FTS_DP:
			if (!postorder)
				continue;
			fnflag = FTW_DP;
			break;
		case FTS_F:
		case FTS_DEFAULT:
			fnflag = FTW_F;
			break;
		case FTS_NS:
		case FTS_NSOK:
			fnflag = FTW_NS;
			break;
		case FTS_SL:
			fnflag = FTW_SL;
			break;
		case FTS_SLNONE:
			fnflag = FTW_SLN;
			break;
		case FTS_DC:
			errno = ELOOP;
			/* FALLTHROUGH */
		default:
			error = -1;
			goto done;
		}
		ftw.base = cur->fts_pathlen - cur->fts_namelen;
		ftw.level = cur->fts_level;
		error = fn(cur->fts_path, cur->fts_statp, fnflag, &ftw);
		if (error != 0)
			break;
	}
done:
	sverrno = errno;
	if (fts_close(ftsp) != 0 && error == 0)
		error = -1;
	else
		errno = sverrno;
	return (error);
}
コード例 #23
0
ファイル: mklka.c プロジェクト: chutzimir/coda
int WalkTree(char *troot, char *prefix, struct rwcdb *dbh)
{
  /* Traverse tree at troot and insert a record into database
     dbhandle for each (plain) file.  The key of the record is the
     SHA value of the file; the data part of the record is
     the pathname of the file (absolute or relative to troot,
     depending on RelativePathFlag.
     Returns 0 on success, -1 on error of any kind.
     On exit, NumEntries has number of records inserted.
  */

  int rc;
  FTSENT *nextf; /* next element in tree */
  FTS *fth; /* open handle for fts() routines */
  char *path_argv[2];
  unsigned char shabuf[SHA_DIGEST_LENGTH];
  int troot_strlen = 0, prefix_strlen = 0; /* save length of troot in this */
  int myfd, dlen;
  char *path;

  if (RelativePathFlag) {
      /* find the length of the prefix */
      prefix_strlen = strlen(prefix);
      if (prefix[prefix_strlen] == '/')
	  prefix_strlen--;

      /* find length of the treeroot */
      troot_strlen = strlen(troot);
      if (troot[troot_strlen] == '/')
	  troot_strlen--;
  }

  path_argv[0] = troot;
  path_argv[1] = NULL;
  fth = fts_open(path_argv, FTS_PHYSICAL, NULL);
  if (!fth) {
    printf("%s: %s\n", troot, strerror(errno));
    return(-1);
  }

  while ((nextf = fts_read(fth)) != NULL) {
    if (nextf->fts_info != FTS_F) continue; /* skip all but plain files */

    /* compute the SHA of this file */
    myfd = open(nextf->fts_name, O_RDONLY, 0);
    if (myfd < 0) {
      printf("Skipping %s: %s\n", nextf->fts_path, strerror(errno));
      continue;
    }

    ComputeViceSHA(myfd, shabuf);
    close(myfd);

    /* Construct record to be inserted */
    if (RelativePathFlag) {
	dlen = prefix_strlen + nextf->fts_pathlen - troot_strlen + 1;
	strcpy(prefix + prefix_strlen, nextf->fts_path + troot_strlen);
	path = prefix;
    } else {
	dlen = nextf->fts_pathlen + 1;
	path = nextf->fts_path;
    }

    /* Insert record into db */
    rc = rwcdb_insert(dbh, (char *)shabuf, SHA_DIGEST_LENGTH, path, dlen);
    if (rc != 1) {
      printf("%s: insert into database failed\n", nextf->fts_path);
      rc = -1; goto WalkDone;
    }
    
    /* Successfully added one more entry! */
    NumEntries++;
    if (VerboseFlag) {
      char temp[2*SHA_DIGEST_LENGTH+1];
      ViceSHAtoHex(shabuf, temp, sizeof(temp));
      printf("Entry %05d:  %s  %s\n", NumEntries, temp, path);
    }
    else {
      if ((NumEntries > 99) && (!(NumEntries % 100))) {
	printf("#"); /* indicate progress */
	fflush(stdout);
      }
    }
  }

  /* loop exited on fts_read() error or when done */
  if (errno) {
    printf("fts_read(): %s\n", strerror(errno));
    rc = -1; goto WalkDone;
  }
  else {
    rc = 0; 
    if (!VerboseFlag && (NumEntries > 99)) printf("\n"); /* terminate line of hashes */
  }

 WalkDone: /* rc has return code on entry */
  fts_close(fth);
  return(rc);
}
コード例 #24
0
ファイル: register.c プロジェクト: calyx/darwinbuild
int register_files(char* build, char* project, char* path) {
	ssize_t res = 0;
	int loaded = 0;
	
	create_tables();

	if (SQL("BEGIN")) { return -1; }

	prune_old_entries(build, project);
	
	

	//
	// Enumerate the files in the path (DSTROOT) and associate them
	// with the project name and version in the sqlite database.
	// Uses ent->fts_number to mark which files we have and have
	// not seen before.
	//
	// Skip the first result, since that is . of the DSTROOT itself.
	char* path_argv[] = { path, NULL };
	FTS* fts = fts_open(path_argv, FTS_PHYSICAL | FTS_COMFOLLOW | FTS_XDEV, compare);
	FTSENT* ent = fts_read(fts); // throw away the entry for the DSTROOT itself
	while ((ent = fts_read(fts)) != NULL) {
		char filename[MAXPATHLEN+1];
		char symlink[MAXPATHLEN+1];
		ssize_t len;
		
		// Filename
		filename[0] = 0;
		ent_filename(ent, filename, MAXPATHLEN);

		// Symlinks
		symlink[0] = 0;
		if (ent->fts_info == FTS_SL || ent->fts_info == FTS_SLNONE) {
			len = readlink(ent->fts_accpath, symlink, MAXPATHLEN);
			if (len >= 0) symlink[len] = 0;
		}
		
		// Default to empty SHA-1 checksum
		char* checksum = strdup("                                        ");
		
		// Checksum regular files
		if (ent->fts_info == FTS_F) {
			int fd = open(ent->fts_accpath, O_RDONLY);
			if (fd == -1) {
				perror(filename);
				return -1;
			}
			int isMachO;
			res = register_libraries(fd, build, project, filename, &isMachO);
			lseek(fd, (off_t)0, SEEK_SET);
			if (isMachO && have_undo_prebinding() == 0) {
				checksum = calculate_unprebound_digest(ent->fts_accpath);
			} else {
				checksum = calculate_digest(fd);
			}
			close(fd);
		}

		// register regular files and symlinks in the DB
		if (ent->fts_info == FTS_F || ent->fts_info == FTS_SL || ent->fts_info == FTS_SLNONE) {
			res = SQL("INSERT INTO files (build, project, path) VALUES (%Q,%Q,%Q)",
				build, project, filename);
			++loaded;
		}
		
		// add all regular files, directories, and symlinks to the manifest
		if (ent->fts_info == FTS_F || ent->fts_info == FTS_D ||
			ent->fts_info == FTS_SL || ent->fts_info == FTS_SLNONE) {
			fprintf(stdout, "%s %o %d %d %lld .%s%s%s\n",
				checksum,
				ent->fts_statp->st_mode,
				ent->fts_statp->st_uid,
				ent->fts_statp->st_gid,
				(ent->fts_info != FTS_D) ? ent->fts_statp->st_size : (off_t)0,
				filename,
				symlink[0] ? " -> " : "",
				symlink[0] ? symlink : "");
		}
		free(checksum);
	}
	fts_close(fts);
	
	if (SQL("COMMIT")) { return -1; }

	fprintf(stderr, "%s - %d files registered.\n", project, loaded);
	
	return (int)res;
}