[systemd-devel] [PATCH 2/2] systemctl: add "systemctl cat"
--- TODO | 2 -- src/shared/fileio.c | 73 - src/shared/fileio.h | 1 + src/systemctl/systemctl.c | 91 +++ 4 files changed, 149 insertions(+), 18 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 +#include #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/systemctl/systemctl.c b/src/systemctl/systemctl.c index 576396f..18d5e45 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3665,16 +3665,25 @@ static int show_all( return 0; } -static int get_unit_from_arg(sd_bus *bus, char *arg, char **unitp, bool interpret_as_job_id) { -uint32_t id; +static int cat(sd_bus *bus, char **args) { int r = 0; +char **name; -if (safe_atou32(arg, &id) < 0) { -_cleanup_free_ char *n = NULL; -char *unit; -/* Interpret as unit name */ +_cleanup_free_ char *unit = NULL, *n = NULL; + +assert(bus); +assert(args); -n = unit_name_mangle(arg); +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); if (!n) r
[systemd-devel] [PATCH 2/2] systemctl: add "systemctl cat"
--- TODO | 2 -- src/shared/fileio.c | 73 - src/shared/fileio.h | 1 + src/systemctl/systemctl.c | 91 +++ 4 files changed, 164 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 +#include #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/systemctl/systemctl.c b/src/systemctl/systemctl.c index 6cb7a82..18d5e45 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3665,6 +3665,95 @@ 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); +if (!n) +return log_oom(); + +unit = unit_dbus_path_from_name(n); +if (!unit) +return log_oom(); + +if (need_daemon_reload(bus, n)) { +log_error("Unit file of %s changed on disk. Run 'systemctl%s daemon-reload'.", +
Re: [systemd-devel] [PATCH 2/2] systemctl: add "systemctl cat"
On Sat, Nov 23, 2013 at 07:52:53PM -0800, Shawn Landden wrote: > --- > TODO | 2 -- > src/shared/fileio.c | 73 - > src/shared/fileio.h | 1 + > src/systemctl/systemctl.c | 91 > +++ > 4 files changed, 164 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 > +#include > #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; Can you convert this to GREEDY_REALLOC? It should be a bit simpler then. > + > +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/systemctl/systemctl.c b/src/systemctl/systemctl.c > index 6cb7a82..18d5e45 100644 > --- a/src/systemctl/systemctl.c > +++ b/src/systemctl/systemctl.c > @@ -3665,6 +3665,95 @@ 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 *stdou
Re: [systemd-devel] [PATCH 2/2] systemctl: add "systemctl cat"
On Wed, Nov 27, 2013 at 11:59 PM, Zbigniew Jędrzejewski-Szmek wrote: > On Sat, Nov 23, 2013 at 07:52:53PM -0800, Shawn Landden wrote: >> --- >> TODO | 2 -- >> src/shared/fileio.c | 73 - >> src/shared/fileio.h | 1 + >> src/systemctl/systemctl.c | 91 >> +++ >> 4 files changed, 164 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 >> +#include >> #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; > Can you convert this to GREEDY_REALLOC? It should be a bit simpler then. GREEDY_REALLOC isn't appropriate here, (or read_full_file() which this code is from), as in general stat is going to succeed and we are going to read the whole file in one run. > >> + >> +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/systemctl/systemctl.c b/src/systemctl/systemctl.c >> index 6cb7a82..18d5e45 100644 >> --- a/src/systemctl/systemctl.c >> +++ b/src/systemctl/systemctl.c >> @@ -3665,6 +3665,95 @@ static int show_all( >> return 0; >> } >> >> +static int cat(sd_bus *bus, char **args) { >> +int r = 0; >> +char **name; >> + >> +