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; }
/* * 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; } }