Re: [PATCH] grub: add grub variable update functionality
On 1/14/19 10:49 AM, Daniel Kiper wrote: > On Fri, Jan 04, 2019 at 07:53:42AM -0500, Prarit Bhargava wrote: >> Please be aware I am NOT subscribed to grub-devel. >> >> P. >> >> ---8<--- >> >> Customers and users of the kernel are commenting that there is no way to >> update >> a grub variable without copy and pasting the existing data. >> >> For example, >> >> [10:57 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list >> saved_entry=0 >> next_entry= >> kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro >> crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap >> rd.lvm.lv=rhel_intel-wildcatpass-07/root >> rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 >> ignore_loglevel >> [10:57 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv - set >> kernelopts="root=/dev/mapper/rhel_intel--wildcatpass--07-root ro >> crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap >> rd.lvm.lv=rhel_intel-wildcatpass-07/root >> rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 >> ignore_loglevel newarg" >> [10:57 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list >> saved_entry=0 >> next_entry= >> kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro >> crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap >> rd.lvm.lv=rhel_intel-wildcatpass-07/root >> rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 >> ignore_loglevel newarg >> >> which is cumbersome. >> >> Add functionality to add to an existing variable. For example, >> >> [10:58 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list >> saved_entry=0 >> next_entry= >> kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro >> crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap >> rd.lvm.lv=rhel_intel-wildcatpass-07/root >> rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 >> ignore_loglevel >> [10:58 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv - set >> kernelopts+="newarg" >> [10:59 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list >> saved_entry=0 >> next_entry= >> kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro >> crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap >> rd.lvm.lv=rhel_intel-wildcatpass-07/root >> rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 >> ignore_loglevel newarg >> >> Signed-off-by: Prarit Bhargava >> Cc: mleit...@redhat.com >> Cc: pjo...@redhat.com >> Cc: javi...@redhat.com >> Cc: ar...@redhat.com >> --- >> grub-core/lib/envblk.c| 61 +++ >> include/grub/lib/envblk.h | 1 + >> util/grub-editenv.c | 25 +++- >> 3 files changed, 86 insertions(+), 1 deletion(-) >> >> diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c >> index 230e0e9d9abe..8ddbe2e8267e 100644 >> --- a/grub-core/lib/envblk.c >> +++ b/grub-core/lib/envblk.c >> @@ -295,3 +295,64 @@ grub_envblk_iterate (grub_envblk_t envblk, >>p = find_next_line (p, pend); >> } >> } >> + >> +int >> +grub_envblk_add (grub_envblk_t envblk, const char *name, const char *add) > > s/grub_envblk_add/grub_envblk_extend/? Hi Daniel, thanks for the valuable feedback. After reading your comments I saw that using grub_envblk_iterate() to modify the entry was easier than attempting to parse everything myself. I've added that to my v2. Unfortunately this means I'm skipping over some of your comments which are no longer applicable to v2. > >> +{ >> + char *current, *new, *ostart, *pstart, *pend; >> + int newsize, ret = 1; >> + >> + /* get a copy of the existing entry */ >> + pstart = envblk->buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1; >> + pstart = grub_strstr (pstart, name); > > grub_strcmp() instead of grub_strstr()? > > Even if not what will happen if e.g. env file contains this line among others: > > xyx=kernelopts > >> + if (!pstart) >> + { >> + ret = -1; /* existing entry not found */ >> + goto out; > > s/out/err/ Applied to v2. > >> + } >> + pend = grub_strchr (pstart, '\n'); > > If grub_strcmp() then you do not need this... > >> + if (!pend || pend > (envblk->buf + envblk->size)) >> + { >> + ret = -1; /* existing entry not found */ >> + goto out; >> + } >> + >> + current = grub_zalloc (pend - pstart + 1); >> + if (!current) >> + { >> + ret = -2; /* out of memory */ >> + goto out; >> + } >> + grub_strncpy (current, pstart, (int)(pend - pstart)); > > Do we need (int) cast here? > >> + ostart = grub_strchr (current, '='); >> + ostart++; >> + >> + /* create a buffer for the updated entry. */ > > Please start all comments with capital letter. Applied to v2. > >> + newsize = grub_strlen (ostart) + grub_strlen (add) + 2; >> + new = grub_zalloc (newsize); > > You do not need newsize here. Please drop it. Applied to v2. > >> + if (!new) >> +{ >> + return -2; /* out of memory
Re: [PATCH] grub: add grub variable update functionality
On Fri, Jan 04, 2019 at 07:53:42AM -0500, Prarit Bhargava wrote: > Please be aware I am NOT subscribed to grub-devel. > > P. > > ---8<--- > > Customers and users of the kernel are commenting that there is no way to > update > a grub variable without copy and pasting the existing data. > > For example, > > [10:57 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list > saved_entry=0 > next_entry= > kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro > crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap > rd.lvm.lv=rhel_intel-wildcatpass-07/root > rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 > ignore_loglevel > [10:57 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv - set > kernelopts="root=/dev/mapper/rhel_intel--wildcatpass--07-root ro > crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap > rd.lvm.lv=rhel_intel-wildcatpass-07/root > rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 > ignore_loglevel newarg" > [10:57 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list > saved_entry=0 > next_entry= > kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro > crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap > rd.lvm.lv=rhel_intel-wildcatpass-07/root > rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 > ignore_loglevel newarg > > which is cumbersome. > > Add functionality to add to an existing variable. For example, > > [10:58 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list > saved_entry=0 > next_entry= > kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro > crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap > rd.lvm.lv=rhel_intel-wildcatpass-07/root > rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 > ignore_loglevel > [10:58 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv - set > kernelopts+="newarg" > [10:59 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list > saved_entry=0 > next_entry= > kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro > crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap > rd.lvm.lv=rhel_intel-wildcatpass-07/root > rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 > ignore_loglevel newarg > > Signed-off-by: Prarit Bhargava > Cc: mleit...@redhat.com > Cc: pjo...@redhat.com > Cc: javi...@redhat.com > Cc: ar...@redhat.com > --- > grub-core/lib/envblk.c| 61 +++ > include/grub/lib/envblk.h | 1 + > util/grub-editenv.c | 25 +++- > 3 files changed, 86 insertions(+), 1 deletion(-) > > diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c > index 230e0e9d9abe..8ddbe2e8267e 100644 > --- a/grub-core/lib/envblk.c > +++ b/grub-core/lib/envblk.c > @@ -295,3 +295,64 @@ grub_envblk_iterate (grub_envblk_t envblk, >p = find_next_line (p, pend); > } > } > + > +int > +grub_envblk_add (grub_envblk_t envblk, const char *name, const char *add) s/grub_envblk_add/grub_envblk_extend/? > +{ > + char *current, *new, *ostart, *pstart, *pend; > + int newsize, ret = 1; > + > + /* get a copy of the existing entry */ > + pstart = envblk->buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1; > + pstart = grub_strstr (pstart, name); grub_strcmp() instead of grub_strstr()? Even if not what will happen if e.g. env file contains this line among others: xyx=kernelopts > + if (!pstart) > + { > + ret = -1; /* existing entry not found */ > + goto out; s/out/err/ > + } > + pend = grub_strchr (pstart, '\n'); If grub_strcmp() then you do not need this... > + if (!pend || pend > (envblk->buf + envblk->size)) > + { > + ret = -1; /* existing entry not found */ > + goto out; > + } > + > + current = grub_zalloc (pend - pstart + 1); > + if (!current) > + { > + ret = -2; /* out of memory */ > + goto out; > + } > + grub_strncpy (current, pstart, (int)(pend - pstart)); Do we need (int) cast here? > + ostart = grub_strchr (current, '='); > + ostart++; > + > + /* create a buffer for the updated entry. */ Please start all comments with capital letter. > + newsize = grub_strlen (ostart) + grub_strlen (add) + 2; > + new = grub_zalloc (newsize); You do not need newsize here. Please drop it. > + if (!new) > +{ > + return -2; /* out of memory */ May I ask you to use proper GRUB errors, e.g. GRUB_ERR_OUT_OF_MEMORY here. Please take a look at include/grub/err.h for more details. > + goto out; > +} > + > + grub_strcpy (new, ostart); > + grub_memcpy (new + grub_strlen (new), " ", 1); > + grub_strcpy (new + grub_strlen (new), add); grub_snprintf() is your friend. > + /* erase the current entry */ > + grub_envblk_delete (envblk, name); > + /* add the updated entry */ > + if (!grub_envblk_set (envblk, name, new)) > +{ > + /* restore the original entry. This should always work */ > +
Re: [PATCH] grub: add grub variable update functionality
Just re-pinging on this ... P. On 1/4/19 7:53 AM, Prarit Bhargava wrote: > Please be aware I am NOT subscribed to grub-devel. > > P. > > ---8<--- > > Customers and users of the kernel are commenting that there is no way to > update > a grub variable without copy and pasting the existing data. > > For example, > > [10:57 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list > saved_entry=0 > next_entry= > kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro > crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap > rd.lvm.lv=rhel_intel-wildcatpass-07/root > rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 > ignore_loglevel > [10:57 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv - set > kernelopts="root=/dev/mapper/rhel_intel--wildcatpass--07-root ro > crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap > rd.lvm.lv=rhel_intel-wildcatpass-07/root > rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 > ignore_loglevel newarg" > [10:57 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list > saved_entry=0 > next_entry= > kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro > crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap > rd.lvm.lv=rhel_intel-wildcatpass-07/root > rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 > ignore_loglevel newarg > > which is cumbersome. > > Add functionality to add to an existing variable. For example, > > [10:58 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list > saved_entry=0 > next_entry= > kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro > crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap > rd.lvm.lv=rhel_intel-wildcatpass-07/root > rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 > ignore_loglevel > [10:58 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv - set > kernelopts+="newarg" > [10:59 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list > saved_entry=0 > next_entry= > kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro > crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap > rd.lvm.lv=rhel_intel-wildcatpass-07/root > rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 > ignore_loglevel newarg > > Signed-off-by: Prarit Bhargava > Cc: mleit...@redhat.com > Cc: pjo...@redhat.com > Cc: javi...@redhat.com > Cc: ar...@redhat.com > --- > grub-core/lib/envblk.c| 61 +++ > include/grub/lib/envblk.h | 1 + > util/grub-editenv.c | 25 +++- > 3 files changed, 86 insertions(+), 1 deletion(-) > > diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c > index 230e0e9d9abe..8ddbe2e8267e 100644 > --- a/grub-core/lib/envblk.c > +++ b/grub-core/lib/envblk.c > @@ -295,3 +295,64 @@ grub_envblk_iterate (grub_envblk_t envblk, >p = find_next_line (p, pend); > } > } > + > +int > +grub_envblk_add (grub_envblk_t envblk, const char *name, const char *add) > +{ > + char *current, *new, *ostart, *pstart, *pend; > + int newsize, ret = 1; > + > + /* get a copy of the existing entry */ > + pstart = envblk->buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1; > + pstart = grub_strstr (pstart, name); > + if (!pstart) > + { > + ret = -1; /* existing entry not found */ > + goto out; > + } > + pend = grub_strchr (pstart, '\n'); > + if (!pend || pend > (envblk->buf + envblk->size)) > + { > + ret = -1; /* existing entry not found */ > + goto out; > + } > + > + current = grub_zalloc (pend - pstart + 1); > + if (!current) > + { > + ret = -2; /* out of memory */ > + goto out; > + } > + grub_strncpy (current, pstart, (int)(pend - pstart)); > + > + ostart = grub_strchr (current, '='); > + ostart++; > + > + /* create a buffer for the updated entry. */ > + newsize = grub_strlen (ostart) + grub_strlen (add) + 2; > + new = grub_zalloc (newsize); > + if (!new) > +{ > + return -2; /* out of memory */ > + goto out; > +} > + > + grub_strcpy (new, ostart); > + grub_memcpy (new + grub_strlen (new), " ", 1); > + grub_strcpy (new + grub_strlen (new), add); > + > + /* erase the current entry */ > + grub_envblk_delete (envblk, name); > + /* add the updated entry */ > + if (!grub_envblk_set (envblk, name, new)) > +{ > + /* restore the original entry. This should always work */ > + grub_envblk_set (envblk, name, ostart); > + ret = 0; > +} > + > +out: > + grub_free(new); > + grub_free(current); > + return ret; > +} > diff --git a/include/grub/lib/envblk.h b/include/grub/lib/envblk.h > index c3e655921709..2a0f09e3435b 100644 > --- a/include/grub/lib/envblk.h > +++ b/include/grub/lib/envblk.h > @@ -37,6 +37,7 @@ void grub_envblk_delete (grub_envblk_t envblk, const char > *name); > void grub_envblk_iterate (grub_envblk_t envblk, >void
[PATCH] grub: add grub variable update functionality
Please be aware I am NOT subscribed to grub-devel. P. ---8<--- Customers and users of the kernel are commenting that there is no way to update a grub variable without copy and pasting the existing data. For example, [10:57 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list saved_entry=0 next_entry= kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap rd.lvm.lv=rhel_intel-wildcatpass-07/root rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 ignore_loglevel [10:57 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv - set kernelopts="root=/dev/mapper/rhel_intel--wildcatpass--07-root ro crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap rd.lvm.lv=rhel_intel-wildcatpass-07/root rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 ignore_loglevel newarg" [10:57 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list saved_entry=0 next_entry= kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap rd.lvm.lv=rhel_intel-wildcatpass-07/root rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 ignore_loglevel newarg which is cumbersome. Add functionality to add to an existing variable. For example, [10:58 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list saved_entry=0 next_entry= kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap rd.lvm.lv=rhel_intel-wildcatpass-07/root rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 ignore_loglevel [10:58 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv - set kernelopts+="newarg" [10:59 AM root@intel-wildcatpass-07 grub-2.02]# ./grub-editenv list saved_entry=0 next_entry= kernelopts=root=/dev/mapper/rhel_intel--wildcatpass--07-root ro crashkernel=auto resume=/dev/mapper/rhel_intel--wildcatpass--07-swap rd.lvm.lv=rhel_intel-wildcatpass-07/root rd.lvm.lv=rhel_intel-wildcatpass-07/swap console=ttyS0,115200n81 ignore_loglevel newarg Signed-off-by: Prarit Bhargava Cc: mleit...@redhat.com Cc: pjo...@redhat.com Cc: javi...@redhat.com Cc: ar...@redhat.com --- grub-core/lib/envblk.c| 61 +++ include/grub/lib/envblk.h | 1 + util/grub-editenv.c | 25 +++- 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c index 230e0e9d9abe..8ddbe2e8267e 100644 --- a/grub-core/lib/envblk.c +++ b/grub-core/lib/envblk.c @@ -295,3 +295,64 @@ grub_envblk_iterate (grub_envblk_t envblk, p = find_next_line (p, pend); } } + +int +grub_envblk_add (grub_envblk_t envblk, const char *name, const char *add) +{ + char *current, *new, *ostart, *pstart, *pend; + int newsize, ret = 1; + + /* get a copy of the existing entry */ + pstart = envblk->buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1; + pstart = grub_strstr (pstart, name); + if (!pstart) + { + ret = -1; /* existing entry not found */ + goto out; + } + pend = grub_strchr (pstart, '\n'); + if (!pend || pend > (envblk->buf + envblk->size)) + { + ret = -1; /* existing entry not found */ + goto out; + } + + current = grub_zalloc (pend - pstart + 1); + if (!current) + { + ret = -2; /* out of memory */ + goto out; + } + grub_strncpy (current, pstart, (int)(pend - pstart)); + + ostart = grub_strchr (current, '='); + ostart++; + + /* create a buffer for the updated entry. */ + newsize = grub_strlen (ostart) + grub_strlen (add) + 2; + new = grub_zalloc (newsize); + if (!new) +{ + return -2; /* out of memory */ + goto out; +} + + grub_strcpy (new, ostart); + grub_memcpy (new + grub_strlen (new), " ", 1); + grub_strcpy (new + grub_strlen (new), add); + + /* erase the current entry */ + grub_envblk_delete (envblk, name); + /* add the updated entry */ + if (!grub_envblk_set (envblk, name, new)) +{ + /* restore the original entry. This should always work */ + grub_envblk_set (envblk, name, ostart); + ret = 0; +} + +out: + grub_free(new); + grub_free(current); + return ret; +} diff --git a/include/grub/lib/envblk.h b/include/grub/lib/envblk.h index c3e655921709..2a0f09e3435b 100644 --- a/include/grub/lib/envblk.h +++ b/include/grub/lib/envblk.h @@ -37,6 +37,7 @@ void grub_envblk_delete (grub_envblk_t envblk, const char *name); void grub_envblk_iterate (grub_envblk_t envblk, void *hook_data, int hook (const char *name, const char *value, void *hook_data)); +int grub_envblk_add(grub_envblk_t envblk, const char *name, const char *add); void grub_envblk_close (grub_envblk_t envblk); static inline char * diff --git a/util/grub-editenv.c b/util/grub-editenv.c index 118e89fe57fe..2df81a20b6bc 100644 --- a/util/grub-editenv.c