@@ -43,6 +43,9 @@ static void on_interrupt(void);
4343static void on_cleanup (void );
4444static pqsigfunc oldhandler = NULL ;
4545
46+ static char * * pgut_pgfnames (const char * path , bool strict );
47+ static void pgut_pgfnames_cleanup (char * * filenames );
48+
4649void discard_response (PGconn * conn );
4750
4851void
@@ -1062,3 +1065,140 @@ discard_response(PGconn *conn)
10621065 PQclear (res );
10631066 } while (res );
10641067}
1068+
1069+ /*
1070+ * pgfnames
1071+ *
1072+ * return a list of the names of objects in the argument directory. Caller
1073+ * must call pgfnames_cleanup later to free the memory allocated by this
1074+ * function.
1075+ */
1076+ char * *
1077+ pgut_pgfnames (const char * path , bool strict )
1078+ {
1079+ DIR * dir ;
1080+ struct dirent * file ;
1081+ char * * filenames ;
1082+ int numnames = 0 ;
1083+ int fnsize = 200 ; /* enough for many small dbs */
1084+
1085+ dir = opendir (path );
1086+ if (dir == NULL )
1087+ {
1088+ elog (strict ? ERROR : WARNING , "could not open directory \"%s\": %m" , path );
1089+ return NULL ;
1090+ }
1091+
1092+ filenames = (char * * ) palloc (fnsize * sizeof (char * ));
1093+
1094+ while (errno = 0 , (file = readdir (dir )) != NULL )
1095+ {
1096+ if (strcmp (file -> d_name , "." ) != 0 && strcmp (file -> d_name , ".." ) != 0 )
1097+ {
1098+ if (numnames + 1 >= fnsize )
1099+ {
1100+ fnsize *= 2 ;
1101+ filenames = (char * * ) repalloc (filenames ,
1102+ fnsize * sizeof (char * ));
1103+ }
1104+ filenames [numnames ++ ] = pstrdup (file -> d_name );
1105+ }
1106+ }
1107+
1108+ if (errno )
1109+ {
1110+ elog (strict ? ERROR : WARNING , "could not read directory \"%s\": %m" , path );
1111+ return NULL ;
1112+ }
1113+
1114+ filenames [numnames ] = NULL ;
1115+
1116+ if (closedir (dir ))
1117+ {
1118+ elog (strict ? ERROR : WARNING , "could not close directory \"%s\": %m" , path );
1119+ return NULL ;
1120+ }
1121+
1122+ return filenames ;
1123+ }
1124+
1125+ /*
1126+ * pgfnames_cleanup
1127+ *
1128+ * deallocate memory used for filenames
1129+ */
1130+ void
1131+ pgut_pgfnames_cleanup (char * * filenames )
1132+ {
1133+ char * * fn ;
1134+
1135+ for (fn = filenames ; * fn ; fn ++ )
1136+ pfree (* fn );
1137+
1138+ pfree (filenames );
1139+ }
1140+
1141+ /* Shamelessly stolen from commom/rmtree.c */
1142+ bool
1143+ pgut_rmtree (const char * path , bool rmtopdir , bool strict )
1144+ {
1145+ bool result = true;
1146+ char pathbuf [MAXPGPATH ];
1147+ char * * filenames ;
1148+ char * * filename ;
1149+ struct stat statbuf ;
1150+
1151+ /*
1152+ * we copy all the names out of the directory before we start modifying
1153+ * it.
1154+ */
1155+ filenames = pgut_pgfnames (path , strict );
1156+
1157+ if (filenames == NULL )
1158+ return false;
1159+
1160+ /* now we have the names we can start removing things */
1161+ for (filename = filenames ; * filename ; filename ++ )
1162+ {
1163+ snprintf (pathbuf , MAXPGPATH , "%s/%s" , path , * filename );
1164+
1165+ if (lstat (pathbuf , & statbuf ) != 0 )
1166+ {
1167+ elog (strict ? ERROR : WARNING , "could not stat file or directory \"%s\": %m" , pathbuf );
1168+ result = false;
1169+ break ;
1170+ }
1171+
1172+ if (S_ISDIR (statbuf .st_mode ))
1173+ {
1174+ /* call ourselves recursively for a directory */
1175+ if (!pgut_rmtree (pathbuf , true, strict ))
1176+ {
1177+ result = false;
1178+ break ;
1179+ }
1180+ }
1181+ else
1182+ {
1183+ if (unlink (pathbuf ) != 0 )
1184+ {
1185+ elog (strict ? ERROR : WARNING , "could not remove file or directory \"%s\": %m" , pathbuf );
1186+ result = false;
1187+ break ;
1188+ }
1189+ }
1190+ }
1191+
1192+ if (rmtopdir )
1193+ {
1194+ if (rmdir (path ) != 0 )
1195+ {
1196+ elog (strict ? ERROR : WARNING , "could not remove file or directory \"%s\": %m" , path );
1197+ result = false;
1198+ }
1199+ }
1200+
1201+ pgut_pgfnames_cleanup (filenames );
1202+
1203+ return result ;
1204+ }
0 commit comments