+int systemd_unit_list(int isuser, int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure)
+{
+ DIR *dir;
+ char path[PATH_MAX + 1];
+ struct dirent *dent;
+ int rc, isfile;
+ size_t offset, len;
+ struct stat st;
+
+ /* get the path */
+ rc = systemd_get_units_dir(path, sizeof path - 1, isuser);
+ if (rc < 0)
+ return rc;
+ offset = (size_t)rc;
+
+ /* open the directory */
+ dir = opendir(path);
+ if (!dir)
+ return -1;
+
+ /* prepare path */
+ path[offset++] = '/';
+
+ /* read the directory */
+ for(;;) {
+ /* get next entry */
+ errno = 0;
+ dent = readdir(dir);
+ if (dent == NULL) {
+ /* end or error */
+ rc = (!errno) - 1;
+ break;
+ }
+
+ /* is a file? */
+ if (dent->d_type == DT_REG)
+ isfile = 1;
+ else if (dent->d_type != DT_UNKNOWN)
+ isfile = 0;
+ else {
+ rc = fstatat(dirfd(dir), dent->d_name, &st, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT);
+ if (rc < 0)
+ break;
+ isfile = S_ISREG(st.st_mode);
+ }
+
+ /* calls the callback if is a file */
+ if (isfile) {
+ len = strlen(dent->d_name);
+ if (offset + len >= sizeof path) {
+ rc = seterrno(ENAMETOOLONG);
+ break;
+ }
+ memcpy(&path[offset], dent->d_name, 1 + len);
+ rc = callback(closure, &path[offset], path, isuser);
+ if (rc)
+ break;
+ }
+ }
+ closedir(dir);
+ return rc;
+}
+
+int systemd_unit_list_all(int (*callback)(void *closure, const char *name, const char *path, int isuser), void *closure)
+{
+ return systemd_unit_list(1, callback, closure) ? : systemd_unit_list(0, callback, closure);
+}
+