1*b1e34412SAlexey Dobriyan /* 2*b1e34412SAlexey Dobriyan * Copyright (c) 2025 Alexey Dobriyan <adobriyan@gmail.com> 3*b1e34412SAlexey Dobriyan * 4*b1e34412SAlexey Dobriyan * Permission to use, copy, modify, and distribute this software for any 5*b1e34412SAlexey Dobriyan * purpose with or without fee is hereby granted, provided that the above 6*b1e34412SAlexey Dobriyan * copyright notice and this permission notice appear in all copies. 7*b1e34412SAlexey Dobriyan * 8*b1e34412SAlexey Dobriyan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9*b1e34412SAlexey Dobriyan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10*b1e34412SAlexey Dobriyan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11*b1e34412SAlexey Dobriyan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12*b1e34412SAlexey Dobriyan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13*b1e34412SAlexey Dobriyan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14*b1e34412SAlexey Dobriyan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15*b1e34412SAlexey Dobriyan */ 16*b1e34412SAlexey Dobriyan #undef _GNU_SOURCE 17*b1e34412SAlexey Dobriyan #define _GNU_SOURCE 18*b1e34412SAlexey Dobriyan #undef NDEBUG 19*b1e34412SAlexey Dobriyan #include <assert.h> 20*b1e34412SAlexey Dobriyan #include <errno.h> 21*b1e34412SAlexey Dobriyan #include <fcntl.h> 22*b1e34412SAlexey Dobriyan #include <string.h> 23*b1e34412SAlexey Dobriyan #include <unistd.h> 24*b1e34412SAlexey Dobriyan #include <sched.h> 25*b1e34412SAlexey Dobriyan /* 26*b1e34412SAlexey Dobriyan * Test that lseek("/proc/net/dev/", 0, SEEK_SET) 27*b1e34412SAlexey Dobriyan * a) works, 28*b1e34412SAlexey Dobriyan * b) does what you think it does. 29*b1e34412SAlexey Dobriyan */ 30*b1e34412SAlexey Dobriyan int main(void) 31*b1e34412SAlexey Dobriyan { 32*b1e34412SAlexey Dobriyan /* /proc/net/dev output is deterministic in fresh netns only. */ 33*b1e34412SAlexey Dobriyan if (unshare(CLONE_NEWNET) == -1) { 34*b1e34412SAlexey Dobriyan if (errno == ENOSYS || errno == EPERM) { 35*b1e34412SAlexey Dobriyan return 4; 36*b1e34412SAlexey Dobriyan } 37*b1e34412SAlexey Dobriyan return 1; 38*b1e34412SAlexey Dobriyan } 39*b1e34412SAlexey Dobriyan 40*b1e34412SAlexey Dobriyan const int fd = open("/proc/net/dev", O_RDONLY); 41*b1e34412SAlexey Dobriyan assert(fd >= 0); 42*b1e34412SAlexey Dobriyan 43*b1e34412SAlexey Dobriyan char buf1[4096]; 44*b1e34412SAlexey Dobriyan const ssize_t rv1 = read(fd, buf1, sizeof(buf1)); 45*b1e34412SAlexey Dobriyan /* 46*b1e34412SAlexey Dobriyan * Not "<=", this file can't be empty: 47*b1e34412SAlexey Dobriyan * there is header, "lo" interface with some zeroes. 48*b1e34412SAlexey Dobriyan */ 49*b1e34412SAlexey Dobriyan assert(0 < rv1); 50*b1e34412SAlexey Dobriyan assert(rv1 <= sizeof(buf1)); 51*b1e34412SAlexey Dobriyan 52*b1e34412SAlexey Dobriyan /* Believe it or not, this line broke one day. */ 53*b1e34412SAlexey Dobriyan assert(lseek(fd, 0, SEEK_SET) == 0); 54*b1e34412SAlexey Dobriyan 55*b1e34412SAlexey Dobriyan char buf2[4096]; 56*b1e34412SAlexey Dobriyan const ssize_t rv2 = read(fd, buf2, sizeof(buf2)); 57*b1e34412SAlexey Dobriyan /* Not "<=", see above. */ 58*b1e34412SAlexey Dobriyan assert(0 < rv2); 59*b1e34412SAlexey Dobriyan assert(rv2 <= sizeof(buf2)); 60*b1e34412SAlexey Dobriyan 61*b1e34412SAlexey Dobriyan /* Test that lseek rewinds to the beginning of the file. */ 62*b1e34412SAlexey Dobriyan assert(rv1 == rv2); 63*b1e34412SAlexey Dobriyan assert(memcmp(buf1, buf2, rv1) == 0); 64*b1e34412SAlexey Dobriyan 65*b1e34412SAlexey Dobriyan /* Contents of the file is not validated: this test is about lseek(). */ 66*b1e34412SAlexey Dobriyan 67*b1e34412SAlexey Dobriyan return 0; 68*b1e34412SAlexey Dobriyan } 69