{"id":7711,"date":"2026-08-08T00:01:33","date_gmt":"2026-08-08T07:01:33","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=7711"},"modified":"2026-08-01T12:41:21","modified_gmt":"2026-08-01T19:41:21","slug":"rubbing-a-file-raw","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=7711","title":{"rendered":"Rubbing a File Raw"},"content":{"rendered":"<p>About six years ago, I wrote about <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=4036\">opening a file in the raw<\/a>. Specifically, using the <em>open()<\/em> function to access file data at a low level. This approach uses file descriptors (integers) to track file I\/O as opposed to the file handles used by the high-level <em>fopen()<\/em> family of functions. It turns out that you can do more with raw file access than just read and write data.<br \/>\n<!--more--><br \/>\nThe following code provides an example of raw file access. It creates a file <code>test.txt<\/code> and writes the word &#8220;Hello!&#8221; to the file. The operations follow the same order as when using formatted file I\/O: The file is opened. Data is written to the file. The file is closed. These functions &mdash; <em>open()<\/em>, <em>write()<\/em>, and <em>close()<\/em> &mdash; use an integer file descriptor as their reference, not a file handle.<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2026_08_08-Lesson.c\" rel=\"noopener\" target=\"_blank\">2026_08_08-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;fcntl.h&gt;\r\n#include &lt;unistd.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n\r\nint main()\r\n{\r\n    char filename[] = \"test.txt\";\r\n    int fd;\r\n    mode_t filemode = O_CREAT | O_WRONLY;\r\n\r\n    <span class=\"comments\">\/* open\/create the file *\/<\/span>\r\n    fd = open(filename,filemode);\r\n    if( fd==-1 )\r\n    {\r\n        fprintf(stderr,\"Unable to create %s\\n\",filename);\r\n        perror(\"ERROR: \");\r\n        exit(1);\r\n    }\r\n\r\n    <span class=\"comments\">\/* write data to the file *\/<\/span>\r\n    write(fd,\"Hello!\\n\",8);\r\n\r\n    <span class=\"comments\">\/* clean-up *\/<\/span>\r\n    close(fd);\r\n    return 0;\r\n}<\/pre>\n<p>The <em>open()<\/em> function returns a file descriptor value, saved in <em>int<\/em> variable <code>fd<\/code>. If the value returned is -1, some sorta error happened, in which case appropriate messages are output and the program exits.<\/p>\n<p>The file is opened with two modes applied, saved in <em>mode_t<\/em> variable <code>filemode<\/code>:<\/p>\n<p><code>O_CREAT<\/code> creates the file if it doesn&#8217;t exist.<\/p>\n<p><code>O_WRONLY<\/code> opens the file for writing only.<\/p>\n<p>Upon opening\/creating the file successfully, the <em>write()<\/em> function sends the string <code>\"Hello!\\n\"<\/code> to the file; the function requires the file descriptor number, string, and the number of bytes to write: <code>write(fd,\"Hello!\\n\",8);<\/code> The value 8 includes all characters in the string, plus the terminating null character.<\/p>\n<p>After the <em>close()<\/em> function closes the file, the program ends. No output is generated. To confirm that everything worked, use the <em>ls<\/em> command in a terminal window. Better, <em>cat<\/em> the file to check its contents:<\/p>\n<pre>$ cat test.txt\r\nHello!<\/pre>\n<p>This code successfully wrote the text <em>Hello (newline)<\/em> to a file, <code>test.txt<\/code>, which it created. But keep in mind that the <code>open()<\/code> function is directed to open\/create the file. This effect has unusual consequences when you&#8217;re not careful.<\/p>\n<p>Change the string in the <em>write()<\/em> function to read <code>\"X\\n\"<\/code> and set the number of bytes to write to 3:<\/p>\n<p><code>write(fd,\"X\\n\",3);<\/code><\/p>\n<p>Rebuild and re-run the program, and then examine the contents of the <code>test.txt<\/code> file to see the following:<\/p>\n<pre>$ cat test.txt\r\nX\r\nllo<\/pre>\n<p>The <code>O_CREAT<\/code> flag creates or opens a file, but any existing file isn&#8217;t destroyed nor is any data deleted. Further, the file position indicator is set to zero when the file is opened. The effect is that any new information written to the file overwrites what&#8217;s already there.<\/p>\n<p>To remedy this situation, and to have the <em>open()<\/em> function overwrite an existing file, add the <code>O_TRUNC<\/code> mode at Line 10:<\/p>\n<p><code>mode_t filemode = O_CREAT | O_WRONLY | O_TRUNC;<\/code><\/p>\n<p>Running this update, creates a file <code>test.txt<\/code> that only contains the new data written to it. The <code>O_TRUNC<\/code> flag resizes the file to zero as it&#8217;s opened, removing any existing contents.<\/p>\n<p>As an alternative, you can use the <em>creat()<\/em> function instead of <em>open()<\/em>. This function works identically to the <em>open()<\/em> function with the <code>O_CREAT<\/code>, <code>O_WRONLY<\/code>, and <code>O_TRUNC<\/code> flags specified. Update the code to replace <em>open()<\/em> with this statement:<\/p>\n<p><code>fd = creat(filename,0);<\/code><\/p>\n<p>And remove the statement declaring <em>mode_t<\/em> variable <code>filemode<\/code> to avoid an unused variable warning.<\/p>\n<p>The updated program creates a new file to replace any existing file.<\/p>\n<p>Yes, you can always surrender and use <em>fopen()<\/em> instead of <em>open()<\/em>. Life is easier that way. But then you&#8217;ll never discover the wonders of the <em>dup()<\/em> function, which I cover in next week&#8217;s Lesson.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Raw file access uses file descriptors, which have some interesting properties. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7711\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-7711","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7711","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7711"}],"version-history":[{"count":3,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7711\/revisions"}],"predecessor-version":[{"id":7717,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7711\/revisions\/7717"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7711"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7711"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7711"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}