static int deep_remove_dir (const char *path) { DIR *dirp; struct dirent *dp; if (rmdir (path) != 0) { if (errno == ENOTEMPTY || errno == EEXIST /* Ugly workaround for ugly AIX 4.1 (and 3.2) header bug (it defines ENOTEMPTY and EEXIST to 17 but actually returns 87). */ || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87)) { if ((dirp = CVS_OPENDIR (path)) == NULL) /* If unable to open the directory return * an error */ return -1; errno = 0; while ((dp = CVS_READDIR (dirp)) != NULL) { char *buf; if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0) continue; buf = Xasprintf ("%s/%s", path, dp->d_name); /* See comment in unlink_file_dir explanation of why we use isdir instead of just calling unlink and checking the status. */ if (isdir (buf)) { if (deep_remove_dir (buf)) { CVS_CLOSEDIR (dirp); free (buf); return -1; } } else { if (CVS_UNLINK (buf) != 0) { CVS_CLOSEDIR (dirp); free (buf); return -1; } } free (buf); errno = 0; } if (errno != 0) { int save_errno = errno; CVS_CLOSEDIR (dirp); errno = save_errno; return -1; } CVS_CLOSEDIR (dirp); return rmdir (path); } else return -1; } /* Was able to remove the directory return 0 */ return 0; }
/* * Process the current directory, looking for files not in ILIST and * not on the global ignore list for this directory. If we find one, * call PROC passing it the name of the file and the update dir. * ENTRIES is the entries list, which is used to identify known * directories. ENTRIES may be NULL, in which case we assume that any * directory with a CVS administration directory is known. */ void ignore_files (List *ilist, List *entries, const char *update_dir, Ignore_proc proc) { int subdirs; DIR *dirp; struct dirent *dp; struct stat sb; char *file; const char *xdir; List *files; Node *p; /* Set SUBDIRS if we have subdirectory information in ENTRIES. */ if (entries == NULL) subdirs = 0; else { struct stickydirtag *sdtp = entries->list->data; subdirs = sdtp == NULL || sdtp->subdirs; } /* we get called with update_dir set to "." sometimes... strip it */ if (strcmp (update_dir, ".") == 0) xdir = ""; else xdir = update_dir; dirp = CVS_OPENDIR ("."); if (dirp == NULL) { error (0, errno, "cannot open current directory"); return; } ign_add_file (CVSDOTIGNORE, 1); wrap_add_file (CVSDOTWRAPPER, 1); /* Make a list for the files. */ files = getlist (); while (errno = 0, (dp = CVS_READDIR (dirp)) != NULL) { file = dp->d_name; if (strcmp (file, ".") == 0 || strcmp (file, "..") == 0) continue; if (findnode_fn (ilist, file) != NULL) continue; if (subdirs) { Node *node; node = findnode_fn (entries, file); if (node != NULL && ((Entnode *) node->data)->type == ENT_SUBDIR) { char *p; int dir; /* For consistency with past behaviour, we only ignore this directory if there is a CVS subdirectory. This will normally be the case, but the user may have messed up the working directory somehow. */ p = Xasprintf ("%s/%s", file, CVSADM); dir = isdir (p); free (p); if (dir) continue; } } /* We could be ignoring FIFOs and other files which are neither regular files nor directories here. */ if (ign_name (file)) continue; if ( #ifdef DT_DIR dp->d_type != DT_UNKNOWN || #endif lstat (file, &sb) != -1) { if ( #ifdef DT_DIR dp->d_type == DT_DIR || (dp->d_type == DT_UNKNOWN && S_ISDIR (sb.st_mode)) #else S_ISDIR (sb.st_mode) #endif ) { if (!subdirs) { char *temp = Xasprintf ("%s/%s", file, CVSADM); if (isdir (temp)) { free (temp); continue; } free (temp); } } #ifdef S_ISLNK else if ( #ifdef DT_DIR dp->d_type == DT_LNK || (dp->d_type == DT_UNKNOWN && S_ISLNK (sb.st_mode)) #else S_ISLNK (sb.st_mode) #endif ) { continue; } #endif } p = getnode (); p->type = FILES; p->key = xstrdup (file); (void) addnode (files, p); } if (errno != 0) error (0, errno, "error reading current directory"); (void) CVS_CLOSEDIR (dirp); sortlist (files, fsortcmp); for (p = files->list->next; p != files->list; p = p->next) (*proc) (p->key, xdir); dellist (&files); }