Пример #1
0
static int
removeall(const char *dir)
{
        int ret, fd = -1;
        dirent_t dirent;
        struct stat status;

        if (0 > chdir(dir)) {
                goto error;
        }

        ret = 1;
        while (ret != 0) {
                if (0 > (ret = getdent(".", &dirent))) {
                        goto error;
                }
                if (0 == ret) {
                        break;
                }

                if (0 > stat(dirent.d_name, &status)) {
                        goto error;
                }

                if (S_ISDIR(status.st_mode)) {
                        if (0 > removeall(dirent.d_name)) {
                                goto error;
                        }
                } else {
                        if (0 > unlink(dirent.d_name)) {
                                goto error;
                        }
                }
        }

        if (0 > chdir("..")) {
                return errno;
        }

        if (0 > rmdir(dir)) {
                return errno;
        }

        close(fd);
        return 0;

error:
        if (0 <= fd) {
                close(fd);
        }

        return errno;
}
Пример #2
0
/*
 *	Descend through the directories, starting at "name".
 *	Call dofile() for each directory entry.
 *	Save each directory name, and process at the end.
 */
static void
dodir(char *name)
{
	size_t dn_mark, dn_next;
	char *prev_base;
	int seg_stat_err;
	int num_segs;

	strcpy(base_name, name);

	/*
	 * Change to the new directory.
	 * Extend the full path.
	 */
	if ((dir_fd = open(name, O_RDONLY)) == -1) {
		error(0, errno,
		    catgets(catfd, SET, 3088, "Cannot open directory %s"),
		    fullpath);
		if (exit_status < ES_Path) exit_status = ES_Path;
		return;
	}
	getdent_s.offset = 0;
	dir_buf_count = 0;
	if (chdir(name) == -1 && chdir(fullpath) == -1) {
		error(0, errno,
		    catgets(catfd, SET, 3038, "cannot chdir to %s"),
		    fullpath);
		(void) close(dir_fd);
		if (exit_status < ES_Path) exit_status = ES_Path;
		return;
	}
	prev_base = base_name;
	base_name += strlen(name);
	if (base_name[-1] != '/') {
		*base_name++ = '/';
	}
	*base_name = '\0';

	/*
	 * Mark the directory name stack.
	 */
	dn_mark = dn_next = dn_size;

	while (getdent() > 0) {
		/* ignore dot and dot-dot */
		if (strcmp((const char *) dir->d_name, ".") == 0 ||
		    strcmp((const char *) dir->d_name, "..") == 0)
			continue;

		/*
		 * check to assure that construction of the full path name does
		 * not exceed the limit before doing the idstat call
		 */

		if ((int)(strlen(fullpath) + dir->d_namlen + 1) > MAXPATHLEN) {
			error(0, errno,
			    catgets(catfd, SET, 268,
			    "%s: Pathname too long"), fullpath);
			if (exit_status < ES_File) exit_status = ES_File;
			continue;
		}

		strcpy(base_name, (const char *) dir->d_name);
		idstat.id = dir->d_id;
		seg_num = 0;

		if (ioctl(fs_fd, F_IDSTAT, &idstat) < 0) {
			error(0, errno,
			    catgets(catfd, SET, 1090,
			    "Ioctl call to stat %s (%d, %d) failed."),
			    fullpath, (int)idstat.id.ino, idstat.id.gen);
			if (exit_status < ES_IDstat) exit_status = ES_IDstat;
			continue;
		}
		if (S_ISREQ(inode.di.mode)) {
			/*
			 * Try to eliminate removable media files which don't
			 * actually represent space on tape.  These are those
			 * for the archiver and stager, and those created by
			 * users for disaster recovery.
			 * For newly created filesystems, those for the
			 * archiver and stager will have parent inode
			 * SAM_ARCH_INO (5) and SAM_STAGE_INO (7) respectively.
			 * For legacy file systems we don't have a clue.
			 * Those created by users for reading
			 * (disaster recovery) which haven't been referenced
			 * will have size of MAXOFFSET_T, so throw these out too
			 * (in CheckRmStatus() ).
			 */
			if ((inode.di.parent_id.ino != SAM_ARCH_INO) &&
			    (inode.di.parent_id.ino != SAM_STAGE_INO)) {
				CheckRmStatus();
			}
		} else {
			CheckArchiveStatus();
		}

		if (S_ISSEGI(&inode.di)) {
			/*
			 * Inode is an index inode, perform archive_audit of
			 * any archive copies of the file's data segments.
			 */
			seg_stat_err = seg_stat_path(&num_segs);

			if (seg_stat_err) {
				continue;
			}

			for (seg_num = 1; seg_num <= num_segs; seg_num++) {
				idstat.id.ino =
				    (sam_ino_t)seg_stat_buf[seg_num - 1].st_ino;
				idstat.id.gen =
				    (int32_t)seg_stat_buf[seg_num - 1].gen;

				if (ioctl(fs_fd, F_IDSTAT, &idstat) < 0) {
					error(0, errno,
					    catgets(catfd, SET, 1091,
					    "Ioctl call to stat %s, "
					    "segment %d (%d, %d) failed."),
					    fullpath, seg_num,
					    (int)idstat.id.ino, idstat.id.gen);

					if (exit_status < ES_IDstat)
						exit_status = ES_IDstat;
					continue;
				}

				CheckArchiveStatus();
			}
		}

		if (S_ISDIR(inode.di.mode))  adddir((char *)dir->d_name);
	}

	if (close(dir_fd) < 0) {
		error(0, errno,
		    catgets(catfd, SET, 3040,
		    "cannot close directory %s"), fullpath);
		if (exit_status < ES_CloseFile) exit_status = ES_CloseFile;
	}

	/*
	 * Process all the directories found.
	 */
	while (dn_next < dn_size) {
		char *name;

		name = &dir_names[dn_next];
		dn_next += strlen(name) + 1;
		dodir(name);
	}
	dn_size = dn_mark;

	base_name = prev_base;
	*base_name = '\0';
	if (chdir("..") < 0 && chdir(fullpath) < 0) {
		error(0, errno,
		    catgets(catfd, SET, 572,
		    "cannot chdir to \"..\" %s"), fullpath);
		if (exit_status < ES_Path) exit_status = ES_Path;
	}
}