Bug 203435 - sysrc(8) does not insert newline if missing at EOF
Summary: sysrc(8) does not insert newline if missing at EOF
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 11.0-RELEASE
Hardware: Any Any
: --- Affects Many People
Assignee: Devin Teske
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-09-29 11:47 UTC by Andreas Sommer
Modified: 2018-06-21 14:45 UTC (History)
1 user (show)

See Also:


Attachments
Patch to ensure LF at end of each line before calling "tail -r" to avoid squashing last two lines (753 bytes, patch)
2018-04-22 09:08 UTC, Andreas Sommer
no flags Details | Diff
Terminal session to showcase that the fix works (569 bytes, text/plain)
2018-04-22 09:09 UTC, Andreas Sommer
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Andreas Sommer 2015-09-29 11:47:50 UTC
To reproduce:

# echo -n 'a=b' >> /etc/rc.conf
# sysrc c=d
c:  -> 
# cat /etc/rc.conf
[...]
a=bc="d"

It may happen that someone changes rc.conf without adding a newline at the end of file. In that case, sysrc will also not behave correctly anymore. It should ensure the newline exists when adding a new entry. Also, the output "c:  -> " is incorrect, should be "c:  -> d".

Else the system may not come up correctly anymore because the syntax is incorrect.
Comment 1 Michael Gmelin freebsd_committer freebsd_triage 2015-10-05 12:39:37 UTC
@dteske: Could you look into this?
Comment 2 Andreas Sommer 2018-04-22 09:08:57 UTC
Created attachment 192720 [details]
Patch to ensure LF at end of each line before calling "tail -r" to avoid squashing last two lines
Comment 3 Andreas Sommer 2018-04-22 09:09:28 UTC
Created attachment 192721 [details]
Terminal session to showcase that the fix works
Comment 4 Devin Teske freebsd_committer freebsd_triage 2018-04-22 20:25:05 UTC
Thank you for the patch.

A couple of notes:

    awk "{print}"

Is better written in short-hand as:

    awk 1

Where the particular awk-syntax in-use is:

    awk "test [{action}]"

When "test" evaluates to true and no action is present, the default action is "{print}". Thus, a test of "1" without an action will do the default and print the line.

When sysrc reports:

    c:  -> 

That will be solved by fixing the missing newline issue, but it is in-fact reporting the correct value given the erroneous conflation of new data with the previous last-line of the file. That is to explain that sysrc reports what the boot system will see and that since the effective last-line of the file was:

    a=bc="d"

In shell, this will cause the variable a to be equal to "bc=d" and thus the variable c has no value (the report of "c: (null before) -> (null after)" is technically correct. This does not mean that the problem of incorrectly munging the last two lines in the case of a no-EOL file won't be fixed, on the contrary -- when that problem is fixed, the before/after report will no longer appear incorrect.
Comment 5 Devin Teske freebsd_committer freebsd_triage 2018-04-22 20:29:41 UTC
After some quick testing, it seems tail is the problem.

While pairing awk with tail solves the problem, I wonder if it wouldn't just be better to drop tail for an all-awk solllution (below):

awk '{L[NR]=$0}END{for(n=NR;n;n--)print L[n]}'
Comment 6 Andreas Sommer 2018-04-22 20:40:00 UTC
(In reply to Devin Teske from comment #5)
Thanks for your awk mastery hints. I'm fine with replacing tail with your awk script. Either way solves the problem.

Regarding my initial `old -> new` problem description, I came to the same conclusions as you after finding out where the issues comes from: behavior is as expected.
Comment 7 Devin Teske freebsd_committer freebsd_triage 2018-04-22 20:44:31 UTC
Alternatively, we could just use a sub-shell with cat piped to "tail -r":

    new_contents=$( echo "$( cat "$file" )" 2> /dev/null | tail -r )

Will think about which one is best (above echo-cat-tail vs awk-only vs awk-tail). I think I might just go with:

    new_contents=$( awk 1 "$file" 2> /dev/null | tail -r )

Because echo-cat-tail requires an extra sub-shell which is undesirable and I suspect awk-only to be less optimized than awk-tail (above)
Comment 8 commit-hook freebsd_committer freebsd_triage 2018-06-17 06:04:42 UTC
A commit references this bug:

Author: dteske
Date: Sun Jun 17 06:03:48 UTC 2018
New revision: 335280
URL: https://svnweb.freebsd.org/changeset/base/335280

Log:
  sysrc.subr: Fix handling of files with missing newline at EOF

  PR:		bin/203435
  Reported by:	Andreas Sommer <andreas.sommer87@googlemail.com>
  MFC after:	1 week
  X-MFC-to:	stable/11
  Sponsored by:	Smule, Inc.

Changes:
  head/usr.sbin/bsdconfig/share/sysrc.subr
Comment 9 Devin Teske freebsd_committer freebsd_triage 2018-06-17 06:06:12 UTC
Can you test to see if the updated code fixes your issue?
Comment 10 Andreas Sommer 2018-06-17 07:51:41 UTC
Yes, the fix works fine (tested on 11.1-RELEASE-p9). Thanks for also catching the case of inserting a new configuration key when the file doesn't end with newline.

Please close as FIXED as you see fit (like, after merging).
Comment 11 Andreas Sommer 2018-06-17 12:56:46 UTC
Just wondering: shouldn't the comment "If not found, append new value to last file and return" read "first file" (first of $rc_conf_files)?
Comment 12 commit-hook freebsd_committer freebsd_triage 2018-06-17 20:33:08 UTC
A commit references this bug:

Author: dteske
Date: Sun Jun 17 20:32:44 UTC 2018
New revision: 335302
URL: https://svnweb.freebsd.org/changeset/base/335302

Log:
  sysrc.subr: Fix a comment for accuracy

  PR:		bin/203435
  Reported by:	Andreas Sommer <andreas.sommer87@googlemail.com>
  MFC after:	6 days
  X-MFC-to:	stable/11
  X-MFC-with:	r335280
  Sponsored by:	Smule, Inc.

Changes:
  head/usr.sbin/bsdconfig/share/sysrc.subr
Comment 13 commit-hook freebsd_committer freebsd_triage 2018-06-21 14:42:32 UTC
A commit references this bug:

Author: dteske
Date: Thu Jun 21 14:41:58 UTC 2018
New revision: 335484
URL: https://svnweb.freebsd.org/changeset/base/335484

Log:
  MFC r335280-r335281, r335302: sysrc.subr updates

  r335280: Fix handling of files with missing newline at EOF
  r335302: Fix a comment for accuracy

  PR:		bin/203435
  Reported by:	Andreas Sommer <andreas.sommer87@googlemail.com>

  r335281: Fix display when value is "-n"

  PR:		bin/226406
  Reported by:	Marius Halden <marius.halden@modirum.com>

  Sponsored by:	Smule, Inc.

Changes:
_U  stable/11/
  stable/11/usr.sbin/bsdconfig/share/sysrc.subr
Comment 14 Devin Teske freebsd_committer freebsd_triage 2018-06-21 14:45:05 UTC
Thank you very much for your extended patience in awaiting resolution. Cheers.