From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202510 header.b=QiO3ws3O; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 4D4975A026F for ; Fri, 17 Oct 2025 06:44:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202510; t=1760676239; bh=wHMdhZ/wVYRDT3g+27cyeisCeXGQoBJBsl4O68b7tEE=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=QiO3ws3OwpUI8VRnuXj/Ienbz+pCmAmD0XfZphGYS8d6Om47BQ4MhvTJsia1v8DHs lcTpNPaAGP9kkVIwo6DOVoxsCOwaWST8E3AuBy4KOI62Udh8qEfH/5akVItHy6FgV3 Mn0Bm1ZlnhAwy0mpAuhBhZtS6x21lvolpTuRFB4uvXlZWTTtyVgWcpaHyamjPagW44 XEIJqv/WYAkYwpAZsYfvR6/tcRRxslHsXkFlt9aCQ8/CzPKx3gYgSDxayzpzlZ77FQ kMCncsyKdk6d86E4XzAYBpoSVpDUTSx54XXoaEJglX/yYKHkCI2YSNqz1x98aBRS1y iCLKl5UIvazNA== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4cnsfR22ZYz4wDD; Fri, 17 Oct 2025 15:43:59 +1100 (AEDT) Date: Fri, 17 Oct 2025 15:38:55 +1100 From: David Gibson To: Yumei Huang Subject: Re: [PATCH v5 2/4] util: Introduce read_file() and read_file_integer() function Message-ID: References: <20251017042743.15519-1-yuhuang@redhat.com> <20251017042743.15519-3-yuhuang@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="aRdWIcFcDRHEhV4N" Content-Disposition: inline In-Reply-To: <20251017042743.15519-3-yuhuang@redhat.com> Message-ID-Hash: GIVGQSREQ4TK536B4FSZBIAAGKTMOFY6 X-Message-ID-Hash: GIVGQSREQ4TK536B4FSZBIAAGKTMOFY6 X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: passt-dev@passt.top, sbrivio@redhat.com X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: --aRdWIcFcDRHEhV4N Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Fri, Oct 17, 2025 at 12:27:41PM +0800, Yumei Huang wrote: > Signed-off-by: Yumei Huang > --- > util.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > util.h | 10 +++++++ > 2 files changed, 94 insertions(+) >=20 > diff --git a/util.c b/util.c > index c492f90..ff21bf6 100644 > --- a/util.c > +++ b/util.c > @@ -579,6 +579,90 @@ int write_file(const char *path, const char *buf) > return len =3D=3D 0 ? 0 : -1; > } > =20 > +/** > + * read_file() - Read contents of file into a buffer > + * @path: File to read > + * @buf: Buffer to store file contents > + * @buf_size: Size of buffer > + * > + * Return: number of bytes read on success, -1 on any error, -2 on trunc= ation > +*/ > +ssize_t read_file(const char *path, char *buf, size_t buf_size) > +{ > + int fd =3D open(path, O_RDONLY | O_CLOEXEC); > + size_t total_read =3D 0; > + ssize_t rc; > + > + if (fd < 0) { > + warn_perror("Could not open %s", path); > + return -1; > + } > + > + while (total_read < buf_size) { > + rc =3D read(fd, buf + total_read, buf_size - total_read); > + > + if (rc < 0) { > + warn_perror("Couldn't read from %s", path); > + close(fd); > + return -1; > + } > + > + if (rc =3D=3D 0) > + break; > + > + total_read +=3D rc; > + } > + > + close(fd); > + > + if (total_read =3D=3D buf_size) { > + warn_perror("File %s truncated, buffer too small", path); Sorry, I should have caught this in the last version. You don't want warn_perror() here, just warn(). warn_perror() includes an error reason based on errno, but errno is not meaningful here (it will almost certainly be 0 from the close()). > + return -2; > + } > + > + buf[total_read] =3D '\0'; > + > + return total_read; > +} > + > +/** > + * read_file_integer() - Read an integer value from a file > + * @path: File to read > + * @fallback: Default value if file can't be read > + * > + * Return: Integer value, fallback on failure > +*/ > +intmax_t read_file_integer(const char *path, intmax_t fallback) > +{ > + char buf[INTMAX_STRLEN]; > + ssize_t bytes_read; > + intmax_t value; > + char *end; > + > + bytes_read =3D read_file(path, buf, sizeof(buf)); > + > + if (bytes_read < 0) > + return fallback; > + > + if (bytes_read =3D=3D 0) { > + debug("Empty file %s", path); > + return fallback; > + } > + > + errno =3D 0; > + value =3D strtoimax(buf, &end, 10); > + if (*end && *end !=3D '\n') { > + debug("Invalid format in %s", path); > + return fallback; > + } > + if (errno) { > + debug("Invalid value in %s: %s", path, buf); > + return fallback; > + } > + > + return value; > +} > + > #ifdef __ia64__ > /* Needed by do_clone() below: glibc doesn't export the prototype of __c= lone2(), > * use the description from clone(2). > diff --git a/util.h b/util.h > index 22eaac5..acfbd08 100644 > --- a/util.h > +++ b/util.h > @@ -222,6 +222,8 @@ void pidfile_write(int fd, pid_t pid); > int __daemon(int pidfile_fd, int devnull_fd); > int fls(unsigned long x); > int write_file(const char *path, const char *buf); > +ssize_t read_file(const char *path, char *buf, size_t buf_size); > +intmax_t read_file_integer(const char *path, intmax_t fallback); > int write_all_buf(int fd, const void *buf, size_t len); > int write_remainder(int fd, const struct iovec *iov, size_t iovcnt, size= _t skip); > int read_all_buf(int fd, void *buf, size_t len); > @@ -250,6 +252,14 @@ static inline const char *af_name(sa_family_t af) > =20 > #define UINT16_STRLEN (sizeof("65535")) > =20 > +/* Each byte holds roughly 2.4 decimal digits: > + * 1 bit =3D log10(2) ~=3D 0.30103 decimal digits > + * 1 byte =3D 8 bits =3D 8 x 0.30103 ~=3D 2.408 decimal digits I don't think these calculations are particularly useful to a reader. The key point is that each byte expands to at most 3 decimal digits - since 0xff =3D=3D 255, I don't think we need to talk about logs to establish that. In any case, the main reason for a comment here is not to explain the logic, but to give credit to where it came from. You got it from Claude, but Claude's info was so similar to the stack overflow page Stefano mentioned, it almost certainly took it from there. So, I'd include a link to that page. > + * Using sizeof(intmax_t) * 3 provides a safe upper bound, > + * plus 2 extra bytes for the sign and null terminator. > + */ > +#define INTMAX_STRLEN (sizeof(intmax_t) * 3 + 2) > + > /* inet address (- '\0') + port (u16) (- '\0') + ':' + '\0' */ > #define SOCKADDR_INET_STRLEN \ > (INET_ADDRSTRLEN-1 + UINT16_STRLEN-1 + sizeof(":")) > --=20 > 2.47.0 >=20 --=20 David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson --aRdWIcFcDRHEhV4N Content-Type: application/pgp-signature; name=signature.asc -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmjxyF4ACgkQzQJF27ox 2Gc5LBAAhvrtv1y9qRvtZNACePVoUTOMCFUt/AskNa4XD9P3IgHryMVmeYJbkNtL jiN0JSo9AKAPwTuneddk33EUE1tW+/mNSbvTSXuPI+VM8fv9PyhoWKhVbaGKoG7Z EwxBW1LTFNlxTLT2zX3dNK87SDXt+b/vCMCNkqCXBAR2x3UzI7LqJ/LEy3TSH3cp AiU3yGi4PfCW+lp1iquaYCYHAeugQXn0IOHl1vGOvP49Hu1N6D+5WXt0LI9ditMx 2KFd6M49GLzVMXOX2MeFZ5b+/9ISSu3iW1yi9tPb7TRIfZ/nWQ4f6hjSia2AdiXf UcHFgLRJRRNHyvof+5nYxKmkUGm9bslTfCLjcVpkm8vCcWABRGLxLApzldtx8ltg ed54DXJTxL/yF0hD7MegRo8XUr96Gqp0+xskmYUEFimdtKFEmUMEQrVIB6REjt85 fvDrfqmOj1SrGgFS5J1hc5Nh8S9UHHj4XQPlhEyy3FYDJ79wEcgzUYYIV+vouTkk o2U8zJmdU4GyrdT6WYguWhzwq1Frxzz5Xb77hbvEbvzarOkTxELIpTLWDeQxIul+ 37DqEr60OJDpLdDjBD4t3kwJ6xaf77Pzy3gOfczJkRPhhPKV6APT/W0AO/5y7igB RFDXEhR6MaY3f1sPNhDwmS+RlFaTefCl2QLgE5ldxfIqz/gF74c= =P36/ -----END PGP SIGNATURE----- --aRdWIcFcDRHEhV4N--