Browse code

pkg/system.getxattr: handle changed size case

lgetxattr(2) man page says:

> If size is specified as zero, these calls return the current size of
> the named extended attribute (and leave value unchanged). This can be
> used to determine the size of the buffer that should be supplied in a
> subsequent call. (But, bear in mind that there is a possibility that
> the attribute value may change between the two calls, so that it is
> still necessary to check the return status from the second call.)

The current code does not handle the case when the size changes between
the two calls, and the new size is larger.

Fix the above problem, and slightly simplify the code.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>

Kir Kolyshkin authored on 2020/02/26 23:44:25
Showing 1 changed files
... ...
@@ -10,24 +10,23 @@ func Lgetxattr(path string, attr string) ([]byte, error) {
10 10
 	dest := make([]byte, 128)
11 11
 	sz, errno := unix.Lgetxattr(path, attr, dest)
12 12
 
13
-	switch {
14
-	case errno == unix.ENODATA:
15
-		return nil, nil
16
-	case errno == unix.ERANGE:
17
-		// 128 byte array might just not be good enough. A dummy buffer is used
18
-		// to get the real size of the xattrs on disk
13
+	for errno == unix.ERANGE {
14
+		// Buffer too small, use zero-sized buffer to get the actual size
19 15
 		sz, errno = unix.Lgetxattr(path, attr, []byte{})
20 16
 		if errno != nil {
21 17
 			return nil, errno
22 18
 		}
23 19
 		dest = make([]byte, sz)
24 20
 		sz, errno = unix.Lgetxattr(path, attr, dest)
25
-		if errno != nil {
26
-			return nil, errno
27
-		}
21
+	}
22
+
23
+	switch {
24
+	case errno == unix.ENODATA:
25
+		return nil, nil
28 26
 	case errno != nil:
29 27
 		return nil, errno
30 28
 	}
29
+
31 30
 	return dest[:sz], nil
32 31
 }
33 32