+
+
+int
+rm_r(const char *path)
+{
+ int ret = 0;
+ DIR *dir;
+ struct dirent *dent;
+
+ if (path == NULL) {
+ opkg_perror(ERROR, "Missing directory parameter");
+ return -1;
+ }
+
+ dir = opendir(path);
+ if (dir == NULL) {
+ opkg_perror(ERROR, "Failed to open dir %s", path);
+ return -1;
+ }
+
+ if (fchdir(dirfd(dir)) == -1) {
+ opkg_perror(ERROR, "Failed to change to dir %s", path);
+ closedir(dir);
+ return -1;
+ }
+
+ while (1) {
+ errno = 0;
+ if ((dent = readdir(dir)) == NULL) {
+ if (errno) {
+ opkg_perror(ERROR, "Failed to read dir %s",
+ path);
+ ret = -1;
+ }
+ break;
+ }
+
+ if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
+ continue;
+
+#ifdef _BSD_SOURCE
+ if (dent->d_type == DT_DIR) {
+ if ((ret = rm_r(dent->d_name)) == -1)
+ break;
+ continue;
+ } else if (dent->d_type == DT_UNKNOWN)
+#endif
+ {
+ struct stat st;
+ if ((ret = lstat(dent->d_name, &st)) == -1) {
+ opkg_perror(ERROR, "Failed to lstat %s",
+ dent->d_name);
+ break;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ if ((ret = rm_r(dent->d_name)) == -1)
+ break;
+ continue;
+ }
+ }
+
+ if ((ret = unlink(dent->d_name)) == -1) {
+ opkg_perror(ERROR, "Failed to unlink %s", dent->d_name);
+ break;
+ }
+ }
+
+ if (chdir("..") == -1) {
+ ret = -1;
+ opkg_perror(ERROR, "Failed to change to dir %s/..", path);
+ }
+
+ if (rmdir(path) == -1 ) {
+ ret = -1;
+ opkg_perror(ERROR, "Failed to remove dir %s", path);
+ }
+
+ if (closedir(dir) == -1) {
+ ret = -1;
+ opkg_perror(ERROR, "Failed to close dir %s", path);
+ }
+
+ return ret;
+}