[systemd-devel] [PATCH] systemctl: add systemctl cat
--- TODO | 2 - man/systemctl.xml | 9 src/shared/fileio.c | 73 ++- src/shared/fileio.h | 1 + src/shared/util.c | 2 + src/systemctl/systemctl.c | 107 ++ 6 files changed, 191 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 6ba4b31..7c6003b 100644 --- a/TODO +++ b/TODO @@ -125,8 +125,6 @@ Features: * optimize the cgroup propagation bits, especially unit_get_members_mask(), cgroup_context_get_mask() -* systemctl cat or systemctl view command or or so, that cats the backing unit file of a service, plus its drop-ins and shows them in a pager - * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it diff --git a/man/systemctl.xml b/man/systemctl.xml index 33a2935..8a66130 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -727,7 +727,16 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service human-readable output./para /listitem /varlistentry +varlistentry + termcommandcat replaceableNAME/replaceable.../command/term + listitem +paraShow backing files of one or more units. +Prints the fragment, drop-ins, and source (sysvinit compat) +of units. Each file is preceded by a comment which includes the +file name./para + /listitem +/varlistentry varlistentry termcommandset-property replaceableNAME/replaceable replaceableASSIGNMENT/replaceable.../command/term diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 733b320..ac1b409 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -20,6 +20,7 @@ ***/ #include unistd.h +#include sys/sendfile.h #include fileio.h #include util.h #include strv.h @@ -117,6 +118,77 @@ int read_one_line_file(const char *fn, char **line) { return 0; } +ssize_t sendfile_full(int out_fd, const char *fn) { +_cleanup_fclose_ FILE *f; +struct stat st; +int r; +ssize_t s; + +size_t n, l; +_cleanup_free_ char *buf = NULL; + +assert(out_fd 0); +assert(fn); + +f = fopen(fn, r); +if (!f) +return -errno; + +r = fstat(fileno(f), st); +if (r 0) +return -errno; + +s = sendfile(out_fd, fileno(f), NULL, st.st_size); +if (s 0) +if (errno == EINVAL || errno == ENOSYS) { +/* continue below */ +} else +return -errno; +else +return s; + +/* sendfile() failed, fall back to read/write */ + +/* Safety check */ +if (st.st_size 4*1024*1024) +return -E2BIG; + +n = st.st_size 0 ? st.st_size : LINE_MAX; +l = 0; + +while (true) { +char *t; +size_t k; + +t = realloc(buf, n); +if (!t) +return -ENOMEM; + +buf = t; +k = fread(buf + l, 1, n - l, f); + +if (k = 0) { +if (ferror(f)) +return -errno; + +break; +} + +l += k; +n *= 2; + +/* Safety check */ +if (n 4*1024*1024) +return -E2BIG; +} + +r = write(out_fd, buf, l); +if (r 0) +return -errno; + +return (ssize_t) l; +} + int read_full_file(const char *fn, char **contents, size_t *size) { _cleanup_fclose_ FILE *f = NULL; size_t n, l; @@ -168,7 +240,6 @@ int read_full_file(const char *fn, char **contents, size_t *size) { buf[l] = 0; *contents = buf; -buf = NULL; if (size) *size = l; diff --git a/src/shared/fileio.h b/src/shared/fileio.h index 59e4150..06c2887 100644 --- a/src/shared/fileio.h +++ b/src/shared/fileio.h @@ -31,6 +31,7 @@ int write_string_file_atomic(const char *fn, const char *line); int read_one_line_file(const char *fn, char **line); int read_full_file(const char *fn, char **contents, size_t *size); +ssize_t sendfile_full(int out_fd, const char *fn); int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; int load_env_file(const char *fname, const char *separator, char ***l); diff --git a/src/shared/util.c b/src/shared/util.c index deb74c4..e6a32b9 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -5904,6 +5904,8 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need) { size_t a;
Re: [systemd-devel] [PATCH] systemctl: add systemctl cat
On Sat, Nov 30, 2013 at 04:09:26PM -0800, Shawn Landden wrote: --- TODO | 2 - man/systemctl.xml | 9 src/shared/fileio.c | 73 ++- src/shared/fileio.h | 1 + src/shared/util.c | 2 + src/systemctl/systemctl.c | 107 ++ 6 files changed, 191 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 6ba4b31..7c6003b 100644 --- a/TODO +++ b/TODO @@ -125,8 +125,6 @@ Features: * optimize the cgroup propagation bits, especially unit_get_members_mask(), cgroup_context_get_mask() -* systemctl cat or systemctl view command or or so, that cats the backing unit file of a service, plus its drop-ins and shows them in a pager - Hi Shawn, applied, I think this willl prove to be useful tool. I removed the part that shows the SourcePath. E.g. with mount units generated from /proc/self/mountinfo most of the lines shown are irrelevant. I think it would be nice to teach systemd about the line/lines in SourcePath that the unit comes from, and then say that this unit was generated based on Nevertheless, I don't think it ever makes sense to show the contents of SourcePath, since it doesn't mix with the rest of the output, since it is in a different format. Also, when the unit doesn't exist, nothing is printed, and no error is shown, and return value is 0. This doesn't seem to be correct, I think that a check if the unit is actually known to systemd should be added. Since we can have units without any source whatsoever, the lack of fragment path/drop-ins cannot be considered a good enough indication. I'm not sure what's the best way to implement this check. Zbyszek ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel
[systemd-devel] [PATCH] systemctl: add systemctl cat
--- TODO | 2 - src/shared/fileio.c | 73 ++- src/shared/fileio.h | 1 + src/shared/util.c | 2 + src/systemctl/systemctl.c | 97 +++ 5 files changed, 172 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 6ba4b31..7c6003b 100644 --- a/TODO +++ b/TODO @@ -125,8 +125,6 @@ Features: * optimize the cgroup propagation bits, especially unit_get_members_mask(), cgroup_context_get_mask() -* systemctl cat or systemctl view command or or so, that cats the backing unit file of a service, plus its drop-ins and shows them in a pager - * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 733b320..ac1b409 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -20,6 +20,7 @@ ***/ #include unistd.h +#include sys/sendfile.h #include fileio.h #include util.h #include strv.h @@ -117,6 +118,77 @@ int read_one_line_file(const char *fn, char **line) { return 0; } +ssize_t sendfile_full(int out_fd, const char *fn) { +_cleanup_fclose_ FILE *f; +struct stat st; +int r; +ssize_t s; + +size_t n, l; +_cleanup_free_ char *buf = NULL; + +assert(out_fd 0); +assert(fn); + +f = fopen(fn, r); +if (!f) +return -errno; + +r = fstat(fileno(f), st); +if (r 0) +return -errno; + +s = sendfile(out_fd, fileno(f), NULL, st.st_size); +if (s 0) +if (errno == EINVAL || errno == ENOSYS) { +/* continue below */ +} else +return -errno; +else +return s; + +/* sendfile() failed, fall back to read/write */ + +/* Safety check */ +if (st.st_size 4*1024*1024) +return -E2BIG; + +n = st.st_size 0 ? st.st_size : LINE_MAX; +l = 0; + +while (true) { +char *t; +size_t k; + +t = realloc(buf, n); +if (!t) +return -ENOMEM; + +buf = t; +k = fread(buf + l, 1, n - l, f); + +if (k = 0) { +if (ferror(f)) +return -errno; + +break; +} + +l += k; +n *= 2; + +/* Safety check */ +if (n 4*1024*1024) +return -E2BIG; +} + +r = write(out_fd, buf, l); +if (r 0) +return -errno; + +return (ssize_t) l; +} + int read_full_file(const char *fn, char **contents, size_t *size) { _cleanup_fclose_ FILE *f = NULL; size_t n, l; @@ -168,7 +240,6 @@ int read_full_file(const char *fn, char **contents, size_t *size) { buf[l] = 0; *contents = buf; -buf = NULL; if (size) *size = l; diff --git a/src/shared/fileio.h b/src/shared/fileio.h index 59e4150..06c2887 100644 --- a/src/shared/fileio.h +++ b/src/shared/fileio.h @@ -31,6 +31,7 @@ int write_string_file_atomic(const char *fn, const char *line); int read_one_line_file(const char *fn, char **line); int read_full_file(const char *fn, char **contents, size_t *size); +ssize_t sendfile_full(int out_fd, const char *fn); int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; int load_env_file(const char *fname, const char *separator, char ***l); diff --git a/src/shared/util.c b/src/shared/util.c index deb74c4..e6a32b9 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -5904,6 +5904,8 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need) { size_t a; void *q; +assert(allocated); + if (*allocated = need) return *p; diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 6cb7a82..633c07d 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3665,6 +3665,101 @@ static int show_all( return 0; } +static int cat(sd_bus *bus, char **args) { +int r = 0; +char **name; + +_cleanup_free_ char *unit = NULL, *n = NULL; + +assert(bus); +assert(args); + +pager_open_if_enabled(); + +STRV_FOREACH(name, args+1) { +_cleanup_free_ char *fragment_path = NULL; +_cleanup_strv_free_ char **dropin_paths = NULL; +sd_bus_error error; +FILE *stdout; +char **path; + +n = unit_name_mangle(*name);
[systemd-devel] [PATCH] systemctl: add systemctl cat
v3: log_warning() inserts a trailing newline --- TODO | 2 - src/shared/fileio.c | 73 ++- src/shared/fileio.h | 1 + src/shared/util.c | 2 + src/systemctl/systemctl.c | 97 +++ 5 files changed, 172 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 6ba4b31..7c6003b 100644 --- a/TODO +++ b/TODO @@ -125,8 +125,6 @@ Features: * optimize the cgroup propagation bits, especially unit_get_members_mask(), cgroup_context_get_mask() -* systemctl cat or systemctl view command or or so, that cats the backing unit file of a service, plus its drop-ins and shows them in a pager - * rfkill,backlight: we probably should run the load tools inside of the udev rules so that the state is properly initialized by the time other software sees it * tmpfiles: when applying ownership to /run/log/journal, also do this for the journal fails contained in it diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 733b320..ac1b409 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -20,6 +20,7 @@ ***/ #include unistd.h +#include sys/sendfile.h #include fileio.h #include util.h #include strv.h @@ -117,6 +118,77 @@ int read_one_line_file(const char *fn, char **line) { return 0; } +ssize_t sendfile_full(int out_fd, const char *fn) { +_cleanup_fclose_ FILE *f; +struct stat st; +int r; +ssize_t s; + +size_t n, l; +_cleanup_free_ char *buf = NULL; + +assert(out_fd 0); +assert(fn); + +f = fopen(fn, r); +if (!f) +return -errno; + +r = fstat(fileno(f), st); +if (r 0) +return -errno; + +s = sendfile(out_fd, fileno(f), NULL, st.st_size); +if (s 0) +if (errno == EINVAL || errno == ENOSYS) { +/* continue below */ +} else +return -errno; +else +return s; + +/* sendfile() failed, fall back to read/write */ + +/* Safety check */ +if (st.st_size 4*1024*1024) +return -E2BIG; + +n = st.st_size 0 ? st.st_size : LINE_MAX; +l = 0; + +while (true) { +char *t; +size_t k; + +t = realloc(buf, n); +if (!t) +return -ENOMEM; + +buf = t; +k = fread(buf + l, 1, n - l, f); + +if (k = 0) { +if (ferror(f)) +return -errno; + +break; +} + +l += k; +n *= 2; + +/* Safety check */ +if (n 4*1024*1024) +return -E2BIG; +} + +r = write(out_fd, buf, l); +if (r 0) +return -errno; + +return (ssize_t) l; +} + int read_full_file(const char *fn, char **contents, size_t *size) { _cleanup_fclose_ FILE *f = NULL; size_t n, l; @@ -168,7 +240,6 @@ int read_full_file(const char *fn, char **contents, size_t *size) { buf[l] = 0; *contents = buf; -buf = NULL; if (size) *size = l; diff --git a/src/shared/fileio.h b/src/shared/fileio.h index 59e4150..06c2887 100644 --- a/src/shared/fileio.h +++ b/src/shared/fileio.h @@ -31,6 +31,7 @@ int write_string_file_atomic(const char *fn, const char *line); int read_one_line_file(const char *fn, char **line); int read_full_file(const char *fn, char **contents, size_t *size); +ssize_t sendfile_full(int out_fd, const char *fn); int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; int load_env_file(const char *fname, const char *separator, char ***l); diff --git a/src/shared/util.c b/src/shared/util.c index deb74c4..e6a32b9 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -5904,6 +5904,8 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need) { size_t a; void *q; +assert(allocated); + if (*allocated = need) return *p; diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 6cb7a82..284020c 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3665,6 +3665,101 @@ static int show_all( return 0; } +static int cat(sd_bus *bus, char **args) { +int r = 0; +char **name; + +_cleanup_free_ char *unit = NULL, *n = NULL; + +assert(bus); +assert(args); + +pager_open_if_enabled(); + +STRV_FOREACH(name, args+1) { +_cleanup_free_ char *fragment_path = NULL; +_cleanup_strv_free_ char **dropin_paths = NULL; +sd_bus_error error; +FILE *stdout; +char **path; +
Re: [systemd-devel] [PATCH] systemctl: add systemctl cat
On Thu, Nov 28, 2013 at 10:34:10AM -0800, Shawn Landden wrote: v3: log_warning() inserts a trailing newline --- TODO | 2 - src/shared/fileio.c | 73 ++- src/shared/fileio.h | 1 + src/shared/util.c | 2 + src/systemctl/systemctl.c | 97 +++ 5 files changed, 172 insertions(+), 3 deletions(-) Hm, this seems to still need some more work: % build/systemctl cat session-1.scope Failed to cat : No such file or directory # session-1.scope has no fragment path, just an override: % build/systemctl show session-1.scope|grep -E 'Frag|Drop' DropInPaths=/run/systemd/system/session-1.scope.d/90-After-systemd-user-sessions\x2eservice.conf /run/systemd/system/session-1.scope.d/90-Description.conf /run/systemd/system/session-1.scope.d/90-KillMode.conf /run/systemd/system/session-1.scope.d/90-SendSIGHUP.conf /run/systemd/system/session-1.scope.d/90-Slice.conf /run/systemd/system/session-1.scope.d/90-TimeoutStopUSec.conf Also, manpage should be updated and shell completion scripts would be nice to update too. Zbyszek ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel