Merge lp:~chipaca/snappy/atomic-follow-symlinks into lp:~snappy-dev/snappy/snappy-moved-to-github

Proposed by John Lenton
Status: Merged
Approved by: Michael Vogt
Approved revision: 799
Merged at revision: 796
Proposed branch: lp:~chipaca/snappy/atomic-follow-symlinks
Merge into: lp:~snappy-dev/snappy/snappy-moved-to-github
Diff against target: 377 lines (+140/-27)
10 files modified
coreconfig/config.go (+11/-11)
helpers/helpers.go (+18/-1)
helpers/helpers_test.go (+99/-3)
partition/bootloader_uboot.go (+1/-1)
partition/bootloader_uboot_test.go (+4/-4)
partition/migrate_grub.go (+1/-1)
snappy/auth.go (+1/-1)
snappy/click.go (+1/-1)
snappy/firstboot.go (+1/-1)
snappy/hwaccess.go (+3/-3)
To merge this branch: bzr merge lp:~chipaca/snappy/atomic-follow-symlinks
Reviewer Review Type Date Requested Status
Michael Vogt (community) Approve
Review via email: mp+275310@code.launchpad.net

Commit message

Make atomic follow symlinks (so you don't have to write to /etc/writable).

To post a comment you must log in.
Revision history for this message
Michael Vogt (mvo) wrote :

Thanks!

review: Approve
Revision history for this message
Snappy Tarmac (snappydevtarmac) wrote :
Download full text (8.7 KiB)

The attempt to merge lp:~chipaca/snappy/atomic-follow-symlinks into lp:snappy failed. Below is the output from the failed tests.

Checking docs
Checking formatting
Installing godeps
Install golint
Obtaining dependencies
update github.com/gorilla/mux failed; trying to fetch newer version
update github.com/mvo5/goconfigparser failed; trying to fetch newer version
github.com/gorilla/mux now at ee1815431e497d3850809578c93ab6705f1a19f7
update github.com/cheggaaa/pb failed; trying to fetch newer version
github.com/mvo5/goconfigparser now at 26426272dda20cc76aa1fa44286dc743d2972fe8
update github.com/mvo5/uboot-go failed; trying to fetch newer version
github.com/cheggaaa/pb now at e8c7cc515bfde3e267957a3b110080ceed51354e
update gopkg.in/check.v1 failed; trying to fetch newer version
github.com/mvo5/uboot-go now at 361f6ebcbb54f389d15dc9faefa000e996ba3e37
update github.com/gosexy/gettext failed; trying to fetch newer version
gopkg.in/check.v1 now at 64131543e7896d5bcc6bd5a76287eb75ea96c673
update github.com/peterh/liner failed; trying to fetch newer version
github.com/gosexy/gettext now at 98b7b91596d20b96909e6b60d57411547dd9959c
update gopkg.in/tomb.v2 failed; trying to fetch newer version
github.com/peterh/liner now at 1bb0d1c1a25ed393d8feb09bab039b2b1b1fbced
update code.google.com/p/go.crypto failed; trying to fetch newer version
gopkg.in/tomb.v2 now at 14b3d72120e8d10ea6e6b7f87f7175734b1faab8
update github.com/blakesmith/ar failed; trying to fetch newer version
code.google.com/p/go.crypto now at 69e2a90ed92d03812364aeb947b7068dc42e561e
update github.com/coreos/go-systemd failed; trying to fetch newer version
github.com/blakesmith/ar now at c9a977dd0cc1392b023382c7bfa5a22af8d3b730
update github.com/gorilla/context failed; trying to fetch newer version
github.com/coreos/go-systemd now at f743bc15d6bddd23662280b4ad20f7c874cdd5ad
update github.com/jessevdk/go-flags failed; trying to fetch newer version
github.com/gorilla/context now at 1c83b3eabd45b6d76072b66b746c20815fb2872d
update golang.org/x/crypto failed; trying to fetch newer version
github.com/jessevdk/go-flags now at 1acbbaff2f347c412a0c7884873bd72cc9c1f5b4
update gopkg.in/yaml.v2 failed; trying to fetch newer version
golang.org/x/crypto now at 60052bd85f2d91293457e8811b0cf26b773de469
gopkg.in/yaml.v2 now at 49c95bdc21843256fb6c4e0d370a05f24a0bf213
Building
Running tests from /tmp/tmp.YRgRWPKpsg/src/launchpad.net/snappy
? launchpad.net/snappy/cmd/snapd [no test files]
=== RUN Test
OK: 12 passed
--- PASS: Test (0.04 seconds)
PASS
coverage: 21.2% of statements
ok launchpad.net/snappy/cmd/snappy 0.051s coverage: 21.2% of statements
=== RUN Test
OK: 53 passed
--- PASS: Test (0.35 seconds)
PASS
coverage: 91.7% of statements
ok launchpad.net/snappy/coreconfig 0.352s coverage: 91.7% of statements
=== RUN Test
OK: 39 passed
--- PASS: Test (0.16 seconds)
PASS
coverage: 69.8% of statements
ok launchpad.net/snappy/daemon 0.172s coverage: 69.8% of statements
? launchpad.net/snappy/dirs [no test files]
=== RUN Test
OK: 64 passed
--- PASS: Test (0.36 seconds)
PASS
coverage: 79.2% of statements
ok launchpad.net/snappy/helpers 0.371s coverage: 79.2% of statements
=== RUN Test
OK: 0 passed, 2 ski...

Read more...

799. By John Lenton

make the follow symlink behaviour depend on a flag. Oh, add a flag.

Revision history for this message
Michael Vogt (mvo) wrote :

Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'coreconfig/config.go'
--- coreconfig/config.go 2015-10-22 10:44:15 +0000
+++ coreconfig/config.go 2015-10-22 12:45:46 +0000
@@ -39,12 +39,12 @@
3939
40const (40const (
41 tzPathEnvironment string = "UBUNTU_CORE_CONFIG_TZ_FILE"41 tzPathEnvironment string = "UBUNTU_CORE_CONFIG_TZ_FILE"
42 tzPathDefault string = "/etc/writable/timezone"42 tzPathDefault string = "/etc/timezone"
43)43)
4444
45var (45var (
46 tzZoneInfoPath = "/usr/share/zoneinfo"46 tzZoneInfoPath = "/usr/share/zoneinfo"
47 tzZoneInfoTarget = "/etc/writable/localtime"47 tzZoneInfoTarget = "/etc/localtime"
48)48)
4949
50const (50const (
@@ -58,8 +58,8 @@
58 modulesPath = "/etc/modules-load.d/ubuntu-core.conf"58 modulesPath = "/etc/modules-load.d/ubuntu-core.conf"
59 interfacesRoot = "/etc/network/interfaces.d/"59 interfacesRoot = "/etc/network/interfaces.d/"
60 pppRoot = "/etc/ppp/"60 pppRoot = "/etc/ppp/"
61 watchdogConfigPath = "/etc/writable/watchdog.conf"61 watchdogConfigPath = "/etc/watchdog.conf"
62 watchdogStartupPath = "/etc/writable/default/watchdog"62 watchdogStartupPath = "/etc/default/watchdog"
63)63)
6464
65var (65var (
@@ -311,7 +311,7 @@
311 return err311 return err
312 }312 }
313313
314 return helpers.AtomicWriteFile(tzFile(), []byte(timezone), 0644)314 return helpers.AtomicWriteFile(tzFile(), []byte(timezone), 0644, helpers.AtomicWriteFollow)
315}315}
316316
317func getPassthrough(rootDir string) (pc []passthroughConfig, err error) {317func getPassthrough(rootDir string) (pc []passthroughConfig, err error) {
@@ -340,7 +340,7 @@
340 os.Remove(path)340 os.Remove(path)
341 continue341 continue
342 }342 }
343 if err := helpers.AtomicWriteFile(path, []byte(c.Content), 0644); err != nil {343 if err := helpers.AtomicWriteFile(path, []byte(c.Content), 0644, helpers.AtomicWriteFollow); err != nil {
344 return err344 return err
345 }345 }
346 }346 }
@@ -376,7 +376,7 @@
376376
377// setModprobe sets the specified modprobe config377// setModprobe sets the specified modprobe config
378var setModprobe = func(modprobe string) error {378var setModprobe = func(modprobe string) error {
379 return helpers.AtomicWriteFile(modprobePath, []byte(modprobe), 0644)379 return helpers.AtomicWriteFile(modprobePath, []byte(modprobe), 0644, helpers.AtomicWriteFollow)
380}380}
381381
382func getModules() ([]string, error) {382func getModules() ([]string, error) {
@@ -463,7 +463,7 @@
463 buf.WriteByte('\n')463 buf.WriteByte('\n')
464 }464 }
465465
466 return helpers.AtomicWriteFile(modulesPath, buf.Bytes(), 0644)466 return helpers.AtomicWriteFile(modulesPath, buf.Bytes(), 0644, helpers.AtomicWriteFollow)
467}467}
468468
469// getWatchdog returns the current watchdog config469// getWatchdog returns the current watchdog config
@@ -489,11 +489,11 @@
489489
490// setWatchdog sets the specified watchdog config490// setWatchdog sets the specified watchdog config
491var setWatchdog = func(wf *watchdogConfig) error {491var setWatchdog = func(wf *watchdogConfig) error {
492 if err := helpers.AtomicWriteFile(watchdogStartupPath, []byte(wf.Startup), 0644); err != nil {492 if err := helpers.AtomicWriteFile(watchdogStartupPath, []byte(wf.Startup), 0644, helpers.AtomicWriteFollow); err != nil {
493 return err493 return err
494 }494 }
495495
496 return helpers.AtomicWriteFile(watchdogConfigPath, []byte(wf.Config), 0644)496 return helpers.AtomicWriteFile(watchdogConfigPath, []byte(wf.Config), 0644, helpers.AtomicWriteFollow)
497}497}
498498
499// for testing purposes499// for testing purposes
@@ -568,5 +568,5 @@
568 return err568 return err
569 }569 }
570570
571 return helpers.AtomicWriteFile(hostnamePath, hostnameB, 0644)571 return helpers.AtomicWriteFile(hostnamePath, hostnameB, 0644, helpers.AtomicWriteFollow)
572}572}
573573
=== modified file 'helpers/helpers.go'
--- helpers/helpers.go 2015-10-15 07:32:34 +0000
+++ helpers/helpers.go 2015-10-22 12:45:46 +0000
@@ -292,12 +292,29 @@
292 return string(bs)292 return string(bs)
293}293}
294294
295// AtomicWriteFlags are a bitfield of flags for AtomicWriteFile
296type AtomicWriteFlags uint
297
298const (
299 // AtomicWriteFollow makes AtomicWriteFile follows symlinks
300 AtomicWriteFollow AtomicWriteFlags = 1 << iota
301)
302
295// AtomicWriteFile updates the filename atomically and works otherwise303// AtomicWriteFile updates the filename atomically and works otherwise
296// like io/ioutil.WriteFile()304// like io/ioutil.WriteFile()
297//305//
298// Note that it won't follow symlinks and will replace existing symlinks306// Note that it won't follow symlinks and will replace existing symlinks
299// with the real file307// with the real file
300func AtomicWriteFile(filename string, data []byte, perm os.FileMode) (err error) {308func AtomicWriteFile(filename string, data []byte, perm os.FileMode, flags AtomicWriteFlags) (err error) {
309 if flags&AtomicWriteFollow != 0 {
310 if fn, err := os.Readlink(filename); err == nil || (fn != "" && os.IsNotExist(err)) {
311 if filepath.IsAbs(fn) {
312 filename = fn
313 } else {
314 filename = filepath.Join(filepath.Dir(filename), fn)
315 }
316 }
317 }
301 tmp := filename + "." + MakeRandomString(12)318 tmp := filename + "." + MakeRandomString(12)
302319
303 // XXX: if go switches to use aio_fsync, we need to open the dir for writing320 // XXX: if go switches to use aio_fsync, we need to open the dir for writing
304321
=== modified file 'helpers/helpers_test.go'
--- helpers/helpers_test.go 2015-10-19 10:38:22 +0000
+++ helpers/helpers_test.go 2015-10-22 12:45:46 +0000
@@ -241,7 +241,7 @@
241 tmpdir := c.MkDir()241 tmpdir := c.MkDir()
242242
243 p := filepath.Join(tmpdir, "foo")243 p := filepath.Join(tmpdir, "foo")
244 err := AtomicWriteFile(p, []byte("canary"), 0644)244 err := AtomicWriteFile(p, []byte("canary"), 0644, 0)
245 c.Assert(err, IsNil)245 c.Assert(err, IsNil)
246246
247 content, err := ioutil.ReadFile(p)247 content, err := ioutil.ReadFile(p)
@@ -258,7 +258,7 @@
258 tmpdir := c.MkDir()258 tmpdir := c.MkDir()
259259
260 p := filepath.Join(tmpdir, "foo")260 p := filepath.Join(tmpdir, "foo")
261 err := AtomicWriteFile(p, []byte(""), 0600)261 err := AtomicWriteFile(p, []byte(""), 0600, 0)
262 c.Assert(err, IsNil)262 c.Assert(err, IsNil)
263263
264 st, err := os.Stat(p)264 st, err := os.Stat(p)
@@ -266,6 +266,102 @@
266 c.Assert(st.Mode()&os.ModePerm, Equals, os.FileMode(0600))266 c.Assert(st.Mode()&os.ModePerm, Equals, os.FileMode(0600))
267}267}
268268
269func (ts *HTestSuite) TestAtomicWriteFileOverwrite(c *C) {
270 tmpdir := c.MkDir()
271 p := filepath.Join(tmpdir, "foo")
272 c.Assert(ioutil.WriteFile(p, []byte("hello"), 0644), IsNil)
273 c.Assert(AtomicWriteFile(p, []byte("hi"), 0600, 0), IsNil)
274
275 content, err := ioutil.ReadFile(p)
276 c.Assert(err, IsNil)
277 c.Assert(string(content), Equals, "hi")
278}
279
280func (ts *HTestSuite) TestAtomicWriteFileSymlinkNoFollow(c *C) {
281 tmpdir := c.MkDir()
282 rodir := filepath.Join(tmpdir, "ro")
283 p := filepath.Join(rodir, "foo")
284 s := filepath.Join(tmpdir, "foo")
285 c.Assert(os.MkdirAll(rodir, 0755), IsNil)
286 c.Assert(os.Symlink(s, p), IsNil)
287 c.Assert(os.Chmod(rodir, 0500), IsNil)
288 defer os.Chmod(rodir, 0700)
289
290 err := AtomicWriteFile(p, []byte("hi"), 0600, 0)
291 c.Assert(err, NotNil)
292}
293
294func (ts *HTestSuite) TestAtomicWriteFileAbsoluteSymlinks(c *C) {
295 tmpdir := c.MkDir()
296 rodir := filepath.Join(tmpdir, "ro")
297 p := filepath.Join(rodir, "foo")
298 s := filepath.Join(tmpdir, "foo")
299 c.Assert(os.MkdirAll(rodir, 0755), IsNil)
300 c.Assert(os.Symlink(s, p), IsNil)
301 c.Assert(os.Chmod(rodir, 0500), IsNil)
302 defer os.Chmod(rodir, 0700)
303
304 err := AtomicWriteFile(p, []byte("hi"), 0600, AtomicWriteFollow)
305 c.Assert(err, IsNil)
306
307 content, err := ioutil.ReadFile(p)
308 c.Assert(err, IsNil)
309 c.Assert(string(content), Equals, "hi")
310}
311
312func (ts *HTestSuite) TestAtomicWriteFileOverwriteAbsoluteSymlink(c *C) {
313 tmpdir := c.MkDir()
314 rodir := filepath.Join(tmpdir, "ro")
315 p := filepath.Join(rodir, "foo")
316 s := filepath.Join(tmpdir, "foo")
317 c.Assert(os.MkdirAll(rodir, 0755), IsNil)
318 c.Assert(os.Symlink(s, p), IsNil)
319 c.Assert(os.Chmod(rodir, 0500), IsNil)
320 defer os.Chmod(rodir, 0700)
321
322 c.Assert(ioutil.WriteFile(s, []byte("hello"), 0644), IsNil)
323 c.Assert(AtomicWriteFile(p, []byte("hi"), 0600, AtomicWriteFollow), IsNil)
324
325 content, err := ioutil.ReadFile(p)
326 c.Assert(err, IsNil)
327 c.Assert(string(content), Equals, "hi")
328}
329
330func (ts *HTestSuite) TestAtomicWriteFileRelativeSymlinks(c *C) {
331 tmpdir := c.MkDir()
332 rodir := filepath.Join(tmpdir, "ro")
333 p := filepath.Join(rodir, "foo")
334 c.Assert(os.MkdirAll(rodir, 0755), IsNil)
335 c.Assert(os.Symlink("../foo", p), IsNil)
336 c.Assert(os.Chmod(rodir, 0500), IsNil)
337 defer os.Chmod(rodir, 0700)
338
339 err := AtomicWriteFile(p, []byte("hi"), 0600, AtomicWriteFollow)
340 c.Assert(err, IsNil)
341
342 content, err := ioutil.ReadFile(p)
343 c.Assert(err, IsNil)
344 c.Assert(string(content), Equals, "hi")
345}
346
347func (ts *HTestSuite) TestAtomicWriteFileOverwriteRelativeSymlink(c *C) {
348 tmpdir := c.MkDir()
349 rodir := filepath.Join(tmpdir, "ro")
350 p := filepath.Join(rodir, "foo")
351 s := filepath.Join(tmpdir, "foo")
352 c.Assert(os.MkdirAll(rodir, 0755), IsNil)
353 c.Assert(os.Symlink("../foo", p), IsNil)
354 c.Assert(os.Chmod(rodir, 0500), IsNil)
355 defer os.Chmod(rodir, 0700)
356
357 c.Assert(ioutil.WriteFile(s, []byte("hello"), 0644), IsNil)
358 c.Assert(AtomicWriteFile(p, []byte("hi"), 0600, AtomicWriteFollow), IsNil)
359
360 content, err := ioutil.ReadFile(p)
361 c.Assert(err, IsNil)
362 c.Assert(string(content), Equals, "hi")
363}
364
269func (ts *HTestSuite) TestAtomicWriteFileNoOverwriteTmpExisting(c *C) {365func (ts *HTestSuite) TestAtomicWriteFileNoOverwriteTmpExisting(c *C) {
270 tmpdir := c.MkDir()366 tmpdir := c.MkDir()
271 realMakeRandomString := MakeRandomString367 realMakeRandomString := MakeRandomString
@@ -280,7 +376,7 @@
280 err := ioutil.WriteFile(p+".4", []byte(""), 0644)376 err := ioutil.WriteFile(p+".4", []byte(""), 0644)
281 c.Assert(err, IsNil)377 c.Assert(err, IsNil)
282378
283 err = AtomicWriteFile(p, []byte(""), 0600)379 err = AtomicWriteFile(p, []byte(""), 0600, 0)
284 c.Assert(err, ErrorMatches, "open .*: file exists")380 c.Assert(err, ErrorMatches, "open .*: file exists")
285}381}
286382
287383
=== modified file 'partition/bootloader_uboot.go'
--- partition/bootloader_uboot.go 2015-07-24 12:00:01 +0000
+++ partition/bootloader_uboot.go 2015-10-22 12:45:46 +0000
@@ -261,7 +261,7 @@
261 }261 }
262262
263 if updateNeeded {263 if updateNeeded {
264 return atomicWriteFile(path, buf.Bytes(), 0644)264 return atomicWriteFile(path, buf.Bytes(), 0644, 0)
265 }265 }
266266
267 return nil267 return nil
268268
=== modified file 'partition/bootloader_uboot_test.go'
--- partition/bootloader_uboot_test.go 2015-07-24 11:58:04 +0000
+++ partition/bootloader_uboot_test.go 2015-10-22 12:45:46 +0000
@@ -291,9 +291,9 @@
291 s.makeFakeUbootEnv(c)291 s.makeFakeUbootEnv(c)
292292
293 atomiCall := false293 atomiCall := false
294 atomicWriteFile = func(a string, b []byte, c os.FileMode) error {294 atomicWriteFile = func(a string, b []byte, c os.FileMode, f helpers.AtomicWriteFlags) error {
295 atomiCall = true295 atomiCall = true
296 return helpers.AtomicWriteFile(a, b, c)296 return helpers.AtomicWriteFile(a, b, c, f)
297 }297 }
298298
299 partition := New()299 partition := New()
@@ -311,9 +311,9 @@
311 c.Assert(ioutil.WriteFile(bootloaderUbootEnvFile, []byte(""), 0644), IsNil)311 c.Assert(ioutil.WriteFile(bootloaderUbootEnvFile, []byte(""), 0644), IsNil)
312312
313 atomiCall := false313 atomiCall := false
314 atomicWriteFile = func(a string, b []byte, c os.FileMode) error {314 atomicWriteFile = func(a string, b []byte, c os.FileMode, f helpers.AtomicWriteFlags) error {
315 atomiCall = true315 atomiCall = true
316 return helpers.AtomicWriteFile(a, b, c)316 return helpers.AtomicWriteFile(a, b, c, f)
317 }317 }
318318
319 partition := New()319 partition := New()
320320
=== modified file 'partition/migrate_grub.go'
--- partition/migrate_grub.go 2015-09-16 11:19:03 +0000
+++ partition/migrate_grub.go 2015-10-22 12:45:46 +0000
@@ -149,5 +149,5 @@
149 }149 }
150 }150 }
151151
152 return helpers.AtomicWriteFile(bootloaderGrubConfigFile, []byte(newGrubConfig), 0644)152 return helpers.AtomicWriteFile(bootloaderGrubConfigFile, []byte(newGrubConfig), 0644, 0)
153}153}
154154
=== modified file 'snappy/auth.go'
--- snappy/auth.go 2015-06-04 22:04:09 +0000
+++ snappy/auth.go 2015-10-22 12:45:46 +0000
@@ -139,7 +139,7 @@
139 return nil139 return nil
140 }140 }
141141
142 return helpers.AtomicWriteFile(targetFile, []byte(outStr), 0600)142 return helpers.AtomicWriteFile(targetFile, []byte(outStr), 0600, 0)
143}143}
144144
145// ReadStoreToken reads a token previously write via WriteStoreToken145// ReadStoreToken reads a token previously write via WriteStoreToken
146146
=== modified file 'snappy/click.go'
--- snappy/click.go 2015-10-15 07:32:34 +0000
+++ snappy/click.go 2015-10-22 12:45:46 +0000
@@ -758,7 +758,7 @@
758 if err != nil {758 if err != nil {
759 return err759 return err
760 }760 }
761 if err := helpers.AtomicWriteFile(filepath.Join(clickMetaDir, cm.Name+".manifest"), []byte(outStr), 0644); err != nil {761 if err := helpers.AtomicWriteFile(filepath.Join(clickMetaDir, cm.Name+".manifest"), []byte(outStr), 0644, 0); err != nil {
762 return err762 return err
763 }763 }
764764
765765
=== modified file 'snappy/firstboot.go'
--- snappy/firstboot.go 2015-10-22 09:32:32 +0000
+++ snappy/firstboot.go 2015-10-22 12:45:46 +0000
@@ -135,7 +135,7 @@
135 ethfile := filepath.Join(ethdir, eth)135 ethfile := filepath.Join(ethdir, eth)
136 data := fmt.Sprintf("allow-hotplug %[1]s\niface %[1]s inet dhcp\n", eth)136 data := fmt.Sprintf("allow-hotplug %[1]s\niface %[1]s inet dhcp\n", eth)
137137
138 if err := helpers.AtomicWriteFile(ethfile, []byte(data), 0644); err != nil {138 if err := helpers.AtomicWriteFile(ethfile, []byte(data), 0644, 0); err != nil {
139 return err139 return err
140 }140 }
141141
142142
=== modified file 'snappy/hwaccess.go'
--- snappy/hwaccess.go 2015-09-29 07:07:13 +0000
+++ snappy/hwaccess.go 2015-10-22 12:45:46 +0000
@@ -91,7 +91,7 @@
91 out = append(out, '\n')91 out = append(out, '\n')
9292
93 additionalFile := getHWAccessJSONFile(snapname)93 additionalFile := getHWAccessJSONFile(snapname)
94 if err := helpers.AtomicWriteFile(additionalFile, out, 0640); err != nil {94 if err := helpers.AtomicWriteFile(additionalFile, out, 0640, 0); err != nil {
95 return err95 return err
96 }96 }
9797
@@ -130,7 +130,7 @@
130 // In both cases, updatedRules will have the right content.130 // In both cases, updatedRules will have the right content.
131 updatedRules := append(rules, newRule...)131 updatedRules := append(rules, newRule...)
132132
133 if err := helpers.AtomicWriteFile(udevRulesFile, updatedRules, 0644); nil != err {133 if err := helpers.AtomicWriteFile(udevRulesFile, updatedRules, 0644, 0); nil != err {
134 return err134 return err
135 }135 }
136136
@@ -250,7 +250,7 @@
250 out = out + rule + "\n"250 out = out + rule + "\n"
251 }251 }
252252
253 if err := helpers.AtomicWriteFile(udevRulesFile, []byte(out), 0644); nil != err {253 if err := helpers.AtomicWriteFile(udevRulesFile, []byte(out), 0644, 0); nil != err {
254 return err254 return err
255 }255 }
256 } else {256 } else {

Subscribers

People subscribed via source and target branches