1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include <sys/inotify.h>
10 #include "alloc-util.h"
11 #include "cgroup-util.h"
12 #include "dirent-util.h"
15 #include "extract-word.h"
17 #include "format-util.h"
19 #include "hostname-util.h"
21 #include "login-util.h"
23 #include "parse-util.h"
24 #include "path-util.h"
25 #include "process-util.h"
26 #include "socket-util.h"
27 #include "stdio-util.h"
28 #include "string-util.h"
30 #include "user-util.h"
34 * invalid input parameters → -EINVAL
36 * process does not exist → -ESRCH
37 * cgroup does not exist → -ENOENT
38 * machine, session does not exist → -ENXIO
39 * requested metadata on object is missing → -ENODATA
42 _public_
int sd_pid_get_session(pid_t pid
, char **session
) {
45 assert_return(pid
>= 0, -EINVAL
);
46 assert_return(session
, -EINVAL
);
48 r
= cg_pid_get_session(pid
, session
);
49 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
52 _public_
int sd_pid_get_unit(pid_t pid
, char **unit
) {
55 assert_return(pid
>= 0, -EINVAL
);
56 assert_return(unit
, -EINVAL
);
58 r
= cg_pid_get_unit(pid
, unit
);
59 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
62 _public_
int sd_pid_get_user_unit(pid_t pid
, char **unit
) {
65 assert_return(pid
>= 0, -EINVAL
);
66 assert_return(unit
, -EINVAL
);
68 r
= cg_pid_get_user_unit(pid
, unit
);
69 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
72 _public_
int sd_pid_get_machine_name(pid_t pid
, char **name
) {
75 assert_return(pid
>= 0, -EINVAL
);
76 assert_return(name
, -EINVAL
);
78 r
= cg_pid_get_machine_name(pid
, name
);
79 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
82 _public_
int sd_pid_get_slice(pid_t pid
, char **slice
) {
85 assert_return(pid
>= 0, -EINVAL
);
86 assert_return(slice
, -EINVAL
);
88 r
= cg_pid_get_slice(pid
, slice
);
89 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
92 _public_
int sd_pid_get_user_slice(pid_t pid
, char **slice
) {
95 assert_return(pid
>= 0, -EINVAL
);
96 assert_return(slice
, -EINVAL
);
98 r
= cg_pid_get_user_slice(pid
, slice
);
99 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
102 _public_
int sd_pid_get_owner_uid(pid_t pid
, uid_t
*uid
) {
105 assert_return(pid
>= 0, -EINVAL
);
106 assert_return(uid
, -EINVAL
);
108 r
= cg_pid_get_owner_uid(pid
, uid
);
109 return IN_SET(r
, -ENXIO
, -ENOMEDIUM
) ? -ENODATA
: r
;
112 _public_
int sd_pid_get_cgroup(pid_t pid
, char **cgroup
) {
116 assert_return(pid
>= 0, -EINVAL
);
117 assert_return(cgroup
, -EINVAL
);
119 r
= cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER
, pid
, &c
);
123 /* The internal APIs return the empty string for the root
124 * cgroup, let's return the "/" in the public APIs instead, as
125 * that's easier and less ambiguous for people to grok. */
127 r
= free_and_strdup(&c
, "/");
137 _public_
int sd_pidfd_get_session(int pidfd
, char **ret_session
) {
138 _cleanup_free_
char *session
= NULL
;
142 assert_return(pidfd
>= 0, -EBADF
);
143 assert_return(ret_session
, -EINVAL
);
145 r
= pidfd_get_pid(pidfd
, &pid
);
149 r
= sd_pid_get_session(pid
, &session
);
153 r
= pidfd_verify_pid(pidfd
, pid
);
157 *ret_session
= TAKE_PTR(session
);
162 _public_
int sd_pidfd_get_unit(int pidfd
, char **ret_unit
) {
163 _cleanup_free_
char *unit
= NULL
;
167 assert_return(pidfd
>= 0, -EBADF
);
168 assert_return(ret_unit
, -EINVAL
);
170 r
= pidfd_get_pid(pidfd
, &pid
);
174 r
= sd_pid_get_unit(pid
, &unit
);
178 r
= pidfd_verify_pid(pidfd
, pid
);
182 *ret_unit
= TAKE_PTR(unit
);
187 _public_
int sd_pidfd_get_user_unit(int pidfd
, char **ret_unit
) {
188 _cleanup_free_
char *unit
= NULL
;
192 assert_return(pidfd
>= 0, -EBADF
);
193 assert_return(ret_unit
, -EINVAL
);
195 r
= pidfd_get_pid(pidfd
, &pid
);
199 r
= sd_pid_get_user_unit(pid
, &unit
);
203 r
= pidfd_verify_pid(pidfd
, pid
);
207 *ret_unit
= TAKE_PTR(unit
);
212 _public_
int sd_pidfd_get_machine_name(int pidfd
, char **ret_name
) {
213 _cleanup_free_
char *name
= NULL
;
217 assert_return(pidfd
>= 0, -EBADF
);
218 assert_return(ret_name
, -EINVAL
);
220 r
= pidfd_get_pid(pidfd
, &pid
);
224 r
= sd_pid_get_machine_name(pid
, &name
);
228 r
= pidfd_verify_pid(pidfd
, pid
);
232 *ret_name
= TAKE_PTR(name
);
237 _public_
int sd_pidfd_get_slice(int pidfd
, char **ret_slice
) {
238 _cleanup_free_
char *slice
= NULL
;
242 assert_return(pidfd
>= 0, -EBADF
);
243 assert_return(ret_slice
, -EINVAL
);
245 r
= pidfd_get_pid(pidfd
, &pid
);
249 r
= sd_pid_get_slice(pid
, &slice
);
253 r
= pidfd_verify_pid(pidfd
, pid
);
257 *ret_slice
= TAKE_PTR(slice
);
262 _public_
int sd_pidfd_get_user_slice(int pidfd
, char **ret_slice
) {
263 _cleanup_free_
char *slice
= NULL
;
267 assert_return(pidfd
>= 0, -EBADF
);
268 assert_return(ret_slice
, -EINVAL
);
270 r
= pidfd_get_pid(pidfd
, &pid
);
274 r
= sd_pid_get_user_slice(pid
, &slice
);
278 r
= pidfd_verify_pid(pidfd
, pid
);
282 *ret_slice
= TAKE_PTR(slice
);
287 _public_
int sd_pidfd_get_owner_uid(int pidfd
, uid_t
*ret_uid
) {
292 assert_return(pidfd
>= 0, -EINVAL
);
293 assert_return(ret_uid
, -EINVAL
);
295 r
= pidfd_get_pid(pidfd
, &pid
);
299 r
= sd_pid_get_owner_uid(pid
, &uid
);
303 r
= pidfd_verify_pid(pidfd
, pid
);
312 _public_
int sd_pidfd_get_cgroup(int pidfd
, char **ret_cgroup
) {
313 _cleanup_free_
char *cgroup
= NULL
;
317 assert_return(pidfd
>= 0, -EBADF
);
318 assert_return(ret_cgroup
, -EINVAL
);
320 r
= pidfd_get_pid(pidfd
, &pid
);
324 r
= sd_pid_get_cgroup(pid
, &cgroup
);
328 r
= pidfd_verify_pid(pidfd
, pid
);
332 *ret_cgroup
= TAKE_PTR(cgroup
);
337 _public_
int sd_peer_get_session(int fd
, char **session
) {
338 struct ucred ucred
= UCRED_INVALID
;
341 assert_return(fd
>= 0, -EBADF
);
342 assert_return(session
, -EINVAL
);
344 r
= getpeercred(fd
, &ucred
);
348 return cg_pid_get_session(ucred
.pid
, session
);
351 _public_
int sd_peer_get_owner_uid(int fd
, uid_t
*uid
) {
355 assert_return(fd
>= 0, -EBADF
);
356 assert_return(uid
, -EINVAL
);
358 r
= getpeercred(fd
, &ucred
);
362 return cg_pid_get_owner_uid(ucred
.pid
, uid
);
365 _public_
int sd_peer_get_unit(int fd
, char **unit
) {
369 assert_return(fd
>= 0, -EBADF
);
370 assert_return(unit
, -EINVAL
);
372 r
= getpeercred(fd
, &ucred
);
376 return cg_pid_get_unit(ucred
.pid
, unit
);
379 _public_
int sd_peer_get_user_unit(int fd
, char **unit
) {
383 assert_return(fd
>= 0, -EBADF
);
384 assert_return(unit
, -EINVAL
);
386 r
= getpeercred(fd
, &ucred
);
390 return cg_pid_get_user_unit(ucred
.pid
, unit
);
393 _public_
int sd_peer_get_machine_name(int fd
, char **machine
) {
397 assert_return(fd
>= 0, -EBADF
);
398 assert_return(machine
, -EINVAL
);
400 r
= getpeercred(fd
, &ucred
);
404 return cg_pid_get_machine_name(ucred
.pid
, machine
);
407 _public_
int sd_peer_get_slice(int fd
, char **slice
) {
411 assert_return(fd
>= 0, -EBADF
);
412 assert_return(slice
, -EINVAL
);
414 r
= getpeercred(fd
, &ucred
);
418 return cg_pid_get_slice(ucred
.pid
, slice
);
421 _public_
int sd_peer_get_user_slice(int fd
, char **slice
) {
425 assert_return(fd
>= 0, -EBADF
);
426 assert_return(slice
, -EINVAL
);
428 r
= getpeercred(fd
, &ucred
);
432 return cg_pid_get_user_slice(ucred
.pid
, slice
);
435 _public_
int sd_peer_get_cgroup(int fd
, char **cgroup
) {
439 assert_return(fd
>= 0, -EBADF
);
440 assert_return(cgroup
, -EINVAL
);
442 r
= getpeercred(fd
, &ucred
);
446 return sd_pid_get_cgroup(ucred
.pid
, cgroup
);
449 static int file_of_uid(uid_t uid
, char **p
) {
451 assert_return(uid_is_valid(uid
), -EINVAL
);
454 if (asprintf(p
, "/run/systemd/users/" UID_FMT
, uid
) < 0)
460 _public_
int sd_uid_get_state(uid_t uid
, char**state
) {
461 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
464 assert_return(state
, -EINVAL
);
466 r
= file_of_uid(uid
, &p
);
470 r
= parse_env_file(NULL
, p
, "STATE", &s
);
472 r
= free_and_strdup(&s
, "offline");
478 *state
= TAKE_PTR(s
);
482 _public_
int sd_uid_get_display(uid_t uid
, char **session
) {
483 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
486 assert_return(session
, -EINVAL
);
488 r
= file_of_uid(uid
, &p
);
492 r
= parse_env_file(NULL
, p
, "DISPLAY", &s
);
500 *session
= TAKE_PTR(s
);
505 _public_
int sd_uid_get_login_time(uid_t uid
, uint64_t *usec
) {
506 _cleanup_free_
char *p
= NULL
, *s
= NULL
, *rt
= NULL
;
510 assert_return(usec
, -EINVAL
);
512 r
= file_of_uid(uid
, &p
);
516 r
= parse_env_file(NULL
, p
, "STATE", &s
, "REALTIME", &rt
);
521 if (isempty(s
) || isempty(rt
))
524 if (!STR_IN_SET(s
, "active", "online"))
527 r
= safe_atou64(rt
, &t
);
535 static int file_of_seat(const char *seat
, char **_p
) {
542 if (!filename_is_valid(seat
))
545 p
= path_join("/run/systemd/seats", seat
);
547 _cleanup_free_
char *buf
= NULL
;
549 r
= sd_session_get_seat(NULL
, &buf
);
553 p
= path_join("/run/systemd/seats", buf
);
562 _public_
int sd_uid_is_on_seat(uid_t uid
, int require_active
, const char *seat
) {
563 _cleanup_free_
char *filename
= NULL
, *content
= NULL
;
566 assert_return(uid_is_valid(uid
), -EINVAL
);
568 r
= file_of_seat(seat
, &filename
);
572 r
= parse_env_file(NULL
, filename
,
573 require_active
? "ACTIVE_UID" : "UIDS",
579 if (isempty(content
))
582 char t
[DECIMAL_STR_MAX(uid_t
)];
583 xsprintf(t
, UID_FMT
, uid
);
585 return string_contains_word(content
, NULL
, t
);
588 static int uid_get_array(uid_t uid
, const char *variable
, char ***array
) {
589 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
595 r
= file_of_uid(uid
, &p
);
599 r
= parse_env_file(NULL
, p
, variable
, &s
);
600 if (r
== -ENOENT
|| (r
>= 0 && isempty(s
))) {
608 a
= strv_split(s
, NULL
);
613 r
= (int) strv_length(a
);
623 _public_
int sd_uid_get_sessions(uid_t uid
, int require_active
, char ***sessions
) {
624 return uid_get_array(
626 require_active
== 0 ? "ONLINE_SESSIONS" :
627 require_active
> 0 ? "ACTIVE_SESSIONS" :
632 _public_
int sd_uid_get_seats(uid_t uid
, int require_active
, char ***seats
) {
633 return uid_get_array(
635 require_active
== 0 ? "ONLINE_SEATS" :
636 require_active
> 0 ? "ACTIVE_SEATS" :
641 static int file_of_session(const char *session
, char **_p
) {
648 if (!session_id_valid(session
))
651 p
= path_join("/run/systemd/sessions", session
);
653 _cleanup_free_
char *buf
= NULL
;
655 r
= sd_pid_get_session(0, &buf
);
659 p
= path_join("/run/systemd/sessions", buf
);
669 _public_
int sd_session_is_active(const char *session
) {
670 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
673 r
= file_of_session(session
, &p
);
677 r
= parse_env_file(NULL
, p
, "ACTIVE", &s
);
685 return parse_boolean(s
);
688 _public_
int sd_session_is_remote(const char *session
) {
689 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
692 r
= file_of_session(session
, &p
);
696 r
= parse_env_file(NULL
, p
, "REMOTE", &s
);
704 return parse_boolean(s
);
707 _public_
int sd_session_get_state(const char *session
, char **state
) {
708 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
711 assert_return(state
, -EINVAL
);
713 r
= file_of_session(session
, &p
);
717 r
= parse_env_file(NULL
, p
, "STATE", &s
);
725 *state
= TAKE_PTR(s
);
730 _public_
int sd_session_get_uid(const char *session
, uid_t
*uid
) {
732 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
734 assert_return(uid
, -EINVAL
);
736 r
= file_of_session(session
, &p
);
740 r
= parse_env_file(NULL
, p
, "UID", &s
);
748 return parse_uid(s
, uid
);
751 static int session_get_string(const char *session
, const char *field
, char **value
) {
752 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
755 assert_return(value
, -EINVAL
);
758 r
= file_of_session(session
, &p
);
762 r
= parse_env_file(NULL
, p
, field
, &s
);
770 *value
= TAKE_PTR(s
);
774 _public_
int sd_session_get_username(const char *session
, char **username
) {
775 return session_get_string(session
, "USER", username
);
778 _public_
int sd_session_get_seat(const char *session
, char **seat
) {
779 return session_get_string(session
, "SEAT", seat
);
782 _public_
int sd_session_get_start_time(const char *session
, uint64_t *usec
) {
783 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
787 assert_return(usec
, -EINVAL
);
789 r
= file_of_session(session
, &p
);
793 r
= parse_env_file(NULL
, p
, "REALTIME", &s
);
801 r
= safe_atou64(s
, &t
);
809 _public_
int sd_session_get_tty(const char *session
, char **tty
) {
810 return session_get_string(session
, "TTY", tty
);
813 _public_
int sd_session_get_vt(const char *session
, unsigned *vtnr
) {
814 _cleanup_free_
char *vtnr_string
= NULL
;
818 assert_return(vtnr
, -EINVAL
);
820 r
= session_get_string(session
, "VTNR", &vtnr_string
);
824 r
= safe_atou(vtnr_string
, &u
);
832 _public_
int sd_session_get_service(const char *session
, char **service
) {
833 return session_get_string(session
, "SERVICE", service
);
836 _public_
int sd_session_get_type(const char *session
, char **type
) {
837 return session_get_string(session
, "TYPE", type
);
840 _public_
int sd_session_get_class(const char *session
, char **class) {
841 return session_get_string(session
, "CLASS", class);
844 _public_
int sd_session_get_desktop(const char *session
, char **desktop
) {
845 _cleanup_free_
char *escaped
= NULL
;
849 assert_return(desktop
, -EINVAL
);
851 r
= session_get_string(session
, "DESKTOP", &escaped
);
855 l
= cunescape(escaped
, 0, desktop
);
861 _public_
int sd_session_get_display(const char *session
, char **display
) {
862 return session_get_string(session
, "DISPLAY", display
);
865 _public_
int sd_session_get_remote_user(const char *session
, char **remote_user
) {
866 return session_get_string(session
, "REMOTE_USER", remote_user
);
869 _public_
int sd_session_get_remote_host(const char *session
, char **remote_host
) {
870 return session_get_string(session
, "REMOTE_HOST", remote_host
);
873 _public_
int sd_session_get_leader(const char *session
, pid_t
*leader
) {
874 _cleanup_free_
char *leader_string
= NULL
;
878 assert_return(leader
, -EINVAL
);
880 r
= session_get_string(session
, "LEADER", &leader_string
);
884 r
= parse_pid(leader_string
, &pid
);
892 _public_
int sd_seat_get_active(const char *seat
, char **session
, uid_t
*uid
) {
893 _cleanup_free_
char *p
= NULL
, *s
= NULL
, *t
= NULL
;
896 assert_return(session
|| uid
, -EINVAL
);
898 r
= file_of_seat(seat
, &p
);
902 r
= parse_env_file(NULL
, p
,
917 r
= parse_uid(t
, uid
);
923 *session
= TAKE_PTR(s
);
928 _public_
int sd_seat_get_sessions(
930 char ***ret_sessions
,
932 unsigned *ret_n_uids
) {
934 _cleanup_free_
char *fname
= NULL
, *session_line
= NULL
, *uid_line
= NULL
;
935 _cleanup_strv_free_
char **sessions
= NULL
;
936 _cleanup_free_ uid_t
*uids
= NULL
;
937 unsigned n_sessions
= 0;
940 r
= file_of_seat(seat
, &fname
);
944 r
= parse_env_file(NULL
, fname
,
945 "SESSIONS", &session_line
,
953 sessions
= strv_split(session_line
, NULL
);
957 n_sessions
= strv_length(sessions
);
960 if (ret_uids
&& uid_line
) {
961 uids
= new(uid_t
, n_sessions
);
966 for (const char *p
= uid_line
;;) {
967 _cleanup_free_
char *word
= NULL
;
969 r
= extract_first_word(&p
, &word
, NULL
, 0);
975 r
= parse_uid(word
, &uids
[n
++]);
985 *ret_sessions
= TAKE_PTR(sessions
);
987 *ret_uids
= TAKE_PTR(uids
);
989 *ret_n_uids
= n_sessions
;
994 static int seat_get_can(const char *seat
, const char *variable
) {
995 _cleanup_free_
char *p
= NULL
, *s
= NULL
;
1000 r
= file_of_seat(seat
, &p
);
1004 r
= parse_env_file(NULL
, p
,
1013 return parse_boolean(s
);
1016 _public_
int sd_seat_can_multi_session(const char *seat
) {
1020 _public_
int sd_seat_can_tty(const char *seat
) {
1021 return seat_get_can(seat
, "CAN_TTY");
1024 _public_
int sd_seat_can_graphical(const char *seat
) {
1025 return seat_get_can(seat
, "CAN_GRAPHICAL");
1028 _public_
int sd_get_seats(char ***seats
) {
1031 r
= get_files_in_directory("/run/systemd/seats/", seats
);
1040 _public_
int sd_get_sessions(char ***sessions
) {
1043 r
= get_files_in_directory("/run/systemd/sessions/", sessions
);
1052 _public_
int sd_get_uids(uid_t
**users
) {
1053 _cleanup_closedir_
DIR *d
= NULL
;
1056 _cleanup_free_ uid_t
*l
= NULL
;
1058 d
= opendir("/run/systemd/users/");
1060 if (errno
== ENOENT
) {
1068 FOREACH_DIRENT_ALL(de
, d
, return -errno
) {
1072 if (!dirent_is_file(de
))
1075 k
= parse_uid(de
->d_name
, &uid
);
1080 if ((unsigned) r
>= n
) {
1084 t
= reallocarray(l
, n
, sizeof(uid_t
));
1091 assert((unsigned) r
< n
);
1098 *users
= TAKE_PTR(l
);
1103 _public_
int sd_get_machine_names(char ***machines
) {
1104 _cleanup_strv_free_
char **l
= NULL
;
1108 r
= get_files_in_directory("/run/systemd/machines/", &l
);
1120 /* Filter out the unit: symlinks */
1121 for (a
= b
= l
; *a
; a
++) {
1122 if (startswith(*a
, "unit:") || !hostname_is_valid(*a
, 0))
1135 *machines
= TAKE_PTR(l
);
1140 _public_
int sd_machine_get_class(const char *machine
, char **class) {
1141 _cleanup_free_
char *c
= NULL
;
1145 assert_return(class, -EINVAL
);
1147 if (streq(machine
, ".host")) {
1152 if (!hostname_is_valid(machine
, 0))
1155 p
= strjoina("/run/systemd/machines/", machine
);
1156 r
= parse_env_file(NULL
, p
, "CLASS", &c
);
1165 *class = TAKE_PTR(c
);
1169 _public_
int sd_machine_get_ifindices(const char *machine
, int **ret_ifindices
) {
1170 _cleanup_free_
char *netif_line
= NULL
;
1174 assert_return(hostname_is_valid(machine
, 0), -EINVAL
);
1176 p
= strjoina("/run/systemd/machines/", machine
);
1177 r
= parse_env_file(NULL
, p
, "NETIF", &netif_line
);
1183 *ret_ifindices
= NULL
;
1187 _cleanup_strv_free_
char **tt
= strv_split(netif_line
, NULL
);
1191 _cleanup_free_
int *ifindices
= NULL
;
1192 if (ret_ifindices
) {
1193 ifindices
= new(int, strv_length(tt
));
1199 for (size_t i
= 0; tt
[i
]; i
++) {
1202 ind
= parse_ifindex(tt
[i
]);
1204 /* Return -EUCLEAN to distinguish from -EINVAL for invalid args */
1205 return ind
== -EINVAL
? -EUCLEAN
: ind
;
1213 *ret_ifindices
= TAKE_PTR(ifindices
);
1218 static int MONITOR_TO_FD(sd_login_monitor
*m
) {
1219 return (int) (unsigned long) m
- 1;
1222 static sd_login_monitor
* FD_TO_MONITOR(int fd
) {
1223 return (sd_login_monitor
*) (unsigned long) (fd
+ 1);
1226 _public_
int sd_login_monitor_new(const char *category
, sd_login_monitor
**m
) {
1227 _cleanup_close_
int fd
= -EBADF
;
1231 assert_return(m
, -EINVAL
);
1233 fd
= inotify_init1(IN_NONBLOCK
|IN_CLOEXEC
);
1237 if (!category
|| streq(category
, "seat")) {
1238 k
= inotify_add_watch(fd
, "/run/systemd/seats/", IN_MOVED_TO
|IN_DELETE
);
1245 if (!category
|| streq(category
, "session")) {
1246 k
= inotify_add_watch(fd
, "/run/systemd/sessions/", IN_MOVED_TO
|IN_DELETE
);
1253 if (!category
|| streq(category
, "uid")) {
1254 k
= inotify_add_watch(fd
, "/run/systemd/users/", IN_MOVED_TO
|IN_DELETE
);
1261 if (!category
|| streq(category
, "machine")) {
1262 k
= inotify_add_watch(fd
, "/run/systemd/machines/", IN_MOVED_TO
|IN_DELETE
);
1272 *m
= FD_TO_MONITOR(TAKE_FD(fd
));
1276 _public_ sd_login_monitor
* sd_login_monitor_unref(sd_login_monitor
*m
) {
1278 (void) close_nointr(MONITOR_TO_FD(m
));
1283 _public_
int sd_login_monitor_flush(sd_login_monitor
*m
) {
1286 assert_return(m
, -EINVAL
);
1288 r
= flush_fd(MONITOR_TO_FD(m
));
1295 _public_
int sd_login_monitor_get_fd(sd_login_monitor
*m
) {
1297 assert_return(m
, -EINVAL
);
1299 return MONITOR_TO_FD(m
);
1302 _public_
int sd_login_monitor_get_events(sd_login_monitor
*m
) {
1304 assert_return(m
, -EINVAL
);
1306 /* For now we will only return POLLIN here, since we don't
1307 * need anything else ever for inotify. However, let's have
1308 * this API to keep our options open should we later on need
1313 _public_
int sd_login_monitor_get_timeout(sd_login_monitor
*m
, uint64_t *timeout_usec
) {
1315 assert_return(m
, -EINVAL
);
1316 assert_return(timeout_usec
, -EINVAL
);
1318 /* For now we will only return UINT64_MAX, since we don't
1319 * need any timeout. However, let's have this API to keep our
1320 * options open should we later on need it. */
1321 *timeout_usec
= UINT64_MAX
;