48
\$\begingroup\$

(Just open 50 tabs in Google Chrome :D (just kidding, no you can't))

Shortest code for infinite disk I/O any language, C# example:

using System.IO;

namespace FileApp {
    static class Program {
        public static void Main() {
            do {
                File.WriteAllText("a", "a");
                File.Delete("a");
            } while (true);
        }
    }
}

You can't just fill the entire disk though, as then it would halt in the end and would be finite.

And you can't do reading only, infinite writing has to happen. (It has to kill my SSD after enough runtime.)

Get cracking! :)

\$\endgroup\$
18
  • 6
    \$\begingroup\$ Does reading files instead of writing them also count as disk I/O? What about writing to /dev/null? (Is yes>/dev/null a valid Bash answer?) \$\endgroup\$
    – Doorknob
    Apr 1, 2016 at 12:33
  • 2
    \$\begingroup\$ Can it take any input ? \$\endgroup\$ Apr 1, 2016 at 14:22
  • 29
    \$\begingroup\$ Dang man...what did your SSD do to you? \$\endgroup\$
    – R. Kap
    Apr 1, 2016 at 23:14
  • 2
    \$\begingroup\$ As I can't hope to compete with 6 byte solutions, would creating the file ./a with the 3 byte contents ./a count for a bonus prize for lateral thinking? AFAIK just executing a file causes some file system writing to take place on many systems, because at the very least 'last access time' gets updated as a byproduct ;-) \$\endgroup\$
    – Stilez
    Apr 2, 2016 at 13:57
  • 3
    \$\begingroup\$ Many of these answers will write the data into the same space over and over. That does not result in an actual disk write even if the data differs. (Extreme case, dos -> windows communications. I wrote 4k of data in dos and read it back in Windows--so long as data was flowing the disk light would stay off.) \$\endgroup\$ Apr 2, 2016 at 23:40

34 Answers 34

48
\$\begingroup\$

PowerShell v2+, 10 bytes

for(){1>1}

Simply loops infinitely with an empty for loop. Each iteration, we output the integer 1 (implicitly converted to a string) with the > redirect operator, which overwrites the file named 1 in the local directory.

\$\endgroup\$
7
  • \$\begingroup\$ Could you replace the second 1 with anything else (that makes a valid file name) or does it have to be 1? \$\endgroup\$
    – anon
    Apr 1, 2016 at 21:53
  • 1
    \$\begingroup\$ On my Windows VM, Winload.exe is sufficient... \$\endgroup\$
    – Comintern
    Apr 1, 2016 at 23:07
  • \$\begingroup\$ I think it has to be a number because if it is a letter then it would be treated as a variable, to treat it as a string quotes are required, and they waste bytes. :P \$\endgroup\$ Apr 2, 2016 at 15:14
  • 1
    \$\begingroup\$ @QPaysTaxes MathuSum has it correct. The second 1 needs to be a number of some sort in order for the implicit parsing to work correctly. Anything from [0-9] would work the same. \$\endgroup\$ Apr 4, 2016 at 12:17
  • 1
    \$\begingroup\$ @Nacht Maybe it's a quirk of my particular environment, then. In my ISE (PSv4 Win8.1), replacing the second 1 with anything non-numeric (and not specified either as .\a or a.txt or the like) results in a parse error. \$\endgroup\$ Apr 5, 2016 at 12:21
27
\$\begingroup\$

Pyth, 6 bytes

#.w]]0

Pyth's only file output command is .w. When called on a string, it writes that string to a file in append mode, which is no good for the purpose of this question. When called on a 2-d array, it writes the corresponding image to that file, overwriting the file contents. That's what this program does. The default file output name is o.png, so this program infinitely overwrites the file o.png with a 1-pixel white image. # is an infinite loop.

\$\endgroup\$
0
26
\$\begingroup\$

DOS/Batch: 4 bytes

%0>x

This batch file will call itself (%0) and redirect (>) the output to a file called x. Since echo is on by default, this will output the path and command.

\$\endgroup\$
8
  • \$\begingroup\$ Will this run out of disk space eventually, or is the output overwritten? \$\endgroup\$ Apr 11, 2016 at 12:46
  • 1
    \$\begingroup\$ @MathuSumMut: With > it will be overwritten. >> would append \$\endgroup\$ Apr 11, 2016 at 20:15
  • 1
    \$\begingroup\$ You win then I guess :P \$\endgroup\$ Apr 11, 2016 at 20:39
  • 2
    \$\begingroup\$ @ΈρικΚωνσταντόπουλος: That's true. In that case, a file with 0 byte is produced, not generating I/O as expected by this challenge. But it's not our task to consider every case, otherwise you might want to turn off caching, virus scanners, ... \$\endgroup\$ May 24, 2016 at 19:17
  • 1
    \$\begingroup\$ Writing a 0 byte file will still cause disk I/O, as it has to update the last-modified time within the directory. \$\endgroup\$
    – user62131
    Dec 13, 2016 at 14:43
26
\$\begingroup\$

If you want a shorter (but more boring than my other one) answer:

Bash, 5 bytes

>w;$0

I could make that shorter if there's a command (less than 3 bytes long) that writes something to disk I/O. Something like sync would work, but sync is 4 bytes 😛

Note: this doesn't work when run straight from bash, only when put in a script and run as the script name. (i.e. echo 'w>w;$0' > bomb; chmod 755 bomb; ./bomb)

\$\endgroup\$
9
  • 1
    \$\begingroup\$ Looks like it's a tie between me and @isaacg - who wins? \$\endgroup\$
    – Daniel
    Apr 2, 2016 at 3:09
  • 8
    \$\begingroup\$ I prefer using exec (or . $0). I think this will run out of PIDs. \$\endgroup\$
    – muru
    Apr 2, 2016 at 8:30
  • 1
    \$\begingroup\$ Is the first w needed here? For me simply >w creates an empty file w, and doing that in a loop will create infinite I/O because the mtime metadata needs to be updated continually. \$\endgroup\$ Apr 3, 2016 at 12:17
  • 1
    \$\begingroup\$ If that qualifies @HenningMakholm then I'll put it in. \$\endgroup\$
    – Daniel
    Apr 3, 2016 at 13:29
  • 2
    \$\begingroup\$ The script only contains these bytes. Since it's bash there's no compiler or anything fancy needed. \$\endgroup\$
    – Daniel
    Apr 4, 2016 at 13:33
16
\$\begingroup\$

Ruby, 22 20 bytes

loop{open(?a,?w)<<1}

Repeatedly truncates and writes a 1 to the file a.

Thanks to Ventero for 2 bytes!

\$\endgroup\$
3
  • 3
    \$\begingroup\$ open(?a,?w)<<1 to save 2 bytes. \$\endgroup\$
    – Ventero
    Apr 1, 2016 at 15:29
  • \$\begingroup\$ Thank you, doorknob, for honouring us with your presence. I am humbled. \$\endgroup\$ Apr 3, 2016 at 10:59
  • \$\begingroup\$ Does that leak file descriptors? Or does it get closed when it goes out of scope? (IDK Ruby, sorry). \$\endgroup\$ May 14, 2016 at 6:31
13
\$\begingroup\$

cmd, 14 bytes

:a
cd>1
goto a

Infinitly overwrites the file 1 with the string to the current directory


I'm new here: Are windows new lines (CR LF) counted as two bytes?

\$\endgroup\$
2
  • 13
    \$\begingroup\$ Welcome to PPCG! Windows, at least modern systems, should be able to handle just LF without issue. The above works for me with just LF on Windows 8.1, so your 14 bytes is correct. \$\endgroup\$ Apr 1, 2016 at 15:34
  • \$\begingroup\$ CR LF2CR1LF1 \$\endgroup\$ May 15, 2016 at 15:50
13
\$\begingroup\$

Bash + coreutils, 10

yes \>b|sh

Writes a continuous stream of >b, which is piped to sh for evaluation. >b simply truncates a file called b to zero bytes each time.

\$\endgroup\$
2
  • 4
    \$\begingroup\$ +1 because your name is really appropriate to what this snippet of code will do \$\endgroup\$ Apr 4, 2016 at 17:43
  • \$\begingroup\$ Why b and not c? \$\endgroup\$ Jun 5, 2017 at 2:17
9
\$\begingroup\$

Perl 5, 27 32 22 bytes

{{open my$h,'>o'}redo}

If simply changing the modification timestamp of a file suffices...

Quick explanation:

{ # Braces implicitly create/mark a loop.
    { # They also create closures, for `my` variables.
        open my $filehandle, '>', 'o';    # Writing to file "o".
        # close $filehandle;   # Called implicitly when
                               # variable gets destroyed.
    } # $filehandle gets destroyed because there are no references to it.
    redo; # ...the loop.
}

Previous solution (32 bytes): {{open my$h,'>o';print$h 1}redo}

Edit: {open F,'O';print F 1;redo} ← Didn't test the code before posting; now I had to correct it.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ :o a perl variable not prefixed with $! \$\endgroup\$
    – cat
    Apr 2, 2016 at 2:22
  • \$\begingroup\$ @cat: It's not a regular variable, like a scalar, array, or hash. It is simply a bareword. Depending on context, a bareword can be taken as a sub (a function), a glob, I think, or a filehandle. (Maybe others too?) \$\endgroup\$
    – g4v3
    Apr 4, 2016 at 7:46
8
\$\begingroup\$

PHP, 60 30 17 16 15 bytes

Updated yet again as per @manatwork suggested:

while(!`cd>1`);

Also now tested.


A bit of cheating 22 bytes:

while(exec('>1 dir'));

Earlier suggestion by @manatwork 30 bytes:

while(file_put_contents(1,1));

NOT TESTED (no php available on this computer) 43 bytes:

for($a=fopen(1,'w');fputs($a,1);fclose($a))

A golfed original 45 bytes:

$a=fopen(1,'w');while(fputs($a,1))rewind($a);

My first post here, joined because I just had to try this out: as long as file write succeeds, rewind file pointer to start.


Just can't get smaller than the file_put_contents().

\$\endgroup\$
7
  • 5
    \$\begingroup\$ while(file_put_contents(1,1)); should be enough. Note that running full scripts from command line as php -r '…' is acceptable as per consensus on meta Running PHP with -r instead of code tags. \$\endgroup\$
    – manatwork
    Apr 1, 2016 at 13:13
  • \$\begingroup\$ Is this actually writing to disk or just a buffer in memory? \$\endgroup\$ Apr 1, 2016 at 14:33
  • 1
    \$\begingroup\$ @manatwork Oh man! I knew there's always room for improvement, but that much... too bad that function hasn't got shorter name. :D I don't know about the buffer.. I wonder if I should update the answer with that shorter solution. \$\endgroup\$
    – diynevala
    Apr 1, 2016 at 18:47
  • 2
    \$\begingroup\$ If it's shorter, please do update your answer, go ahead! :) \$\endgroup\$ Apr 1, 2016 at 21:35
  • \$\begingroup\$ Is it allowed to call exec() from php? I realize it is no more in php's "scope". \$\endgroup\$
    – diynevala
    Apr 2, 2016 at 5:59
7
\$\begingroup\$

sh, 11 bytes

w>w;exec $0

Save this to a file without special characters, such as loop.sh, make it executable, and run it with ./loop.sh or similar.

This writes the output of the command w to the file w, overwriting the previous value each time. Then, it replaces itself with a fresh version of the same program, so it can run infinitely.

\$\endgroup\$
4
  • \$\begingroup\$ this is missing a second >. also, assuming you have a "special" $PATH and "special" umask/filesystem, you can go for w>>w;$0, brining it down to 7 chars \$\endgroup\$
    – mnagel
    Apr 1, 2016 at 19:09
  • \$\begingroup\$ @mnagel >> is append, it will eventually fill the disk \$\endgroup\$
    – cat
    Apr 1, 2016 at 20:14
  • 1
    \$\begingroup\$ @mnagel but you're right about not needing exec,I didn't realize that. Someone else has done it, so I won't update, though \$\endgroup\$
    – isaacg
    Apr 1, 2016 at 20:42
  • 3
    \$\begingroup\$ Or . $0 instead of exec $0, perhaps? I don't know if that will run cause a stack overflow or something, though. ... Yep, it segfaulted. \$\endgroup\$
    – muru
    Apr 2, 2016 at 8:45
7
\$\begingroup\$

C, 95 94 93 89 78 90 89 76 75 bytes

#include<stdio.h>
main(){for(FILE*f=fopen("a","w");;fputc(0,f),fclose(f));}   

Again, sudo watch -n1 lsof -p `pidof inf` seems to say this is valid.

HOW DID I NOT SEE THAT SPACE D:<

Thanks @Jens for shaving off 13 bytes :D

\$\endgroup\$
17
  • 1
    \$\begingroup\$ The w+ mode is read and write, initially truncating the file. Since you don't need to read, you can shave off a byte with just w, which also truncates the file, but doesn't open the file in read mode. \$\endgroup\$
    – user45941
    Apr 1, 2016 at 16:14
  • 1
    \$\begingroup\$ No need for return 0; if the loop never terminates. \$\endgroup\$
    – Jens
    Apr 2, 2016 at 11:33
  • 1
    \$\begingroup\$ Why not use fputc(1,f) instead of the super-verbose fprintf(f," ")? \$\endgroup\$
    – Jens
    Apr 2, 2016 at 11:37
  • 1
    \$\begingroup\$ main(){for(FILE*f=fopen("a","w");;fputc(1,f),fclose(f));} since an empty conditional in for means true. 76 bytes. \$\endgroup\$
    – Jens
    Apr 2, 2016 at 11:49
  • 1
    \$\begingroup\$ @PeterCordes PPCG is not Stack Overflow; please do not make edits to others' answers which change code or other major parts of the answer. Typo fixes are fine, but anything beyod that (including corrections of factually incorrect statements) should be suggested in the comments. \$\endgroup\$
    – cat
    May 14, 2016 at 12:24
6
\$\begingroup\$

Bash, 26 bytes

yes>y&while :;do rm y;done

If I were to expand this one-liner, I would get this:

yes > y &      # Write out infinitely to the file y in the current directory
while true     # Let's do something forever
do             # Here's what we're going to do
    rm y       # delete y
done           # That's all we're going to do

This can't exactly compete with the 10 byte PowerShell line, but it'll hold its own against the others. See my other answer for the 6 byte version.

\$\endgroup\$
9
  • 2
    \$\begingroup\$ while :;ls>l;done \$\endgroup\$ Apr 1, 2016 at 14:33
  • 1
    \$\begingroup\$ The good old exec trick will do better: ls>l;exec $0. Shorter, but boring. \$\endgroup\$
    – manatwork
    Apr 1, 2016 at 14:46
  • \$\begingroup\$ :>l;exec $0 - file creation is writing the inode \$\endgroup\$
    – user24582
    Apr 1, 2016 at 14:50
  • 7
    \$\begingroup\$ Even though you delete y, yes will still continue to write to the same file handle that it had. Run lsof | grep yes and you should see something like /path/to/y (deleted). This will fill up the disk and fail. \$\endgroup\$
    – muru
    Apr 2, 2016 at 8:43
  • 4
    \$\begingroup\$ Instead of rm y you can use >y which will truncate the existing file. It is also a bit shorter. \$\endgroup\$
    – aragaer
    Apr 2, 2016 at 21:47
6
\$\begingroup\$

TI-BASIC, 12 bytes

While 1
Archive A
UnArchive A
End

Alternate solution by user lirtosiast with the same size:

While 1
SetUpEditor
Archive ∟1
End

This will work on the TI-83+ and TI-84+ series of calculators.

Yes, this also works if A is already archived or is not initialized at all at the start of the program! The program is only 12 bytes because of tokenization.

\$\endgroup\$
7
  • \$\begingroup\$ I don't know if the flash memory used by the calculators counts as "disk". \$\endgroup\$
    – lirtosiast
    Apr 3, 2016 at 21:01
  • 1
    \$\begingroup\$ @lirtosiast In Jamy's defense, SSDs are made of flash memory =) \$\endgroup\$
    – Cort Ammon
    Apr 4, 2016 at 0:37
  • \$\begingroup\$ In any case, the byte count is at least 10 bytes less. The 2nd Mem screen counts a header equal to 9 bytes + the length of the program name, but we don't here so you can subtract it out. \$\endgroup\$
    – lirtosiast
    Apr 4, 2016 at 1:27
  • \$\begingroup\$ @lirtosiast This repeatedly writes and reads to the ROM (permanent memory) of the calculator, not the RAM. Of course, calculators don't have an actual hard drive inside :) \$\endgroup\$ Apr 4, 2016 at 17:57
  • \$\begingroup\$ @lirtosiast Thanks, I didn't know about that! (I was wondering why the amount of bytes my TI-84+ reported didn't match up with my hand-counting...) I've updated my answer. \$\endgroup\$ Apr 4, 2016 at 18:05
6
\$\begingroup\$

CPython 3.5, 33 16 bytes

while 1:open("a")

Yes, really. :D

\$\endgroup\$
2
  • \$\begingroup\$ while 1:open("a","w") is shorter and strace shows that python is doing open, fstat64 and close, definitely I/O operations. If the file a already exists, it can be even shorter: while 1:open('a') which still generates an open, fstat64 and close, and even modifies atime of the file. \$\endgroup\$ Apr 5, 2016 at 11:00
  • \$\begingroup\$ @RadovanGarabík :0 Thank you, I didn't know that handy piece of information! Of course, it's implementation specific. \$\endgroup\$
    – cat
    Apr 5, 2016 at 11:26
5
\$\begingroup\$

MATL, 10 bytes

`1[]T3$Z#T

Explanation

This is an infinite loop that writes number 1 to a file called inout in current directory, overwriting previous file's contents.

`       % do...while loop
  1     %   push number 1
  []    %   push empty array
  T     %   push "true"
  3$Z#  %   fwrite function. First input is file content. Second is file name;
        %   defaults to "inout" if empty. Third indicates that any previous
        %   file contents should be discarded
  T     %   push "true": loop condition 
        % implicitly end loop. Loop condition is "true", so the loop is infinite
\$\endgroup\$
5
\$\begingroup\$

Haskell, 20 bytes

f=writeFile"b""a">>f

Write the string "a" to a file named "b" and repeat. writeFile overwrites the file if it exists.

\$\endgroup\$
4
\$\begingroup\$

JavaScript (Node.js), 43 41 bytes

(c=x=>require("fs").writeFile("a",x,c))()

Writes null to a file named a, then repeat.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ What about writing c or x to the file? Saves 2 bytes. Also, doesn't require`fs` work? \$\endgroup\$
    – Charlie
    Apr 7, 2016 at 14:43
  • 1
    \$\begingroup\$ @Charlie Good point with writing c or x. require`fs` unfortunately doesn't work, because using backticks to call a function calls it with the first arguments as ["fs"] (array, which first and only element is the passed string) instead of "fs" (just the string). Try console.log`test` for example. \$\endgroup\$ Apr 7, 2016 at 15:02
4
\$\begingroup\$

ZSH, 14 bytes

for ((;;)) :>:

Zsh, unlike Bash and other Bourne-like shells, allows loops without the do ... done fence, provided the condition is suitably delimited.

Alternatively, with while:

while {} {:>:}

Note that : is a builtin. You can't suspend this loop.

The principle is the same as in Digital Trauma's answer - nothing is written to the file, the IO is purely from creating and truncating the file.

\$\endgroup\$
2
  • \$\begingroup\$ I gotta say, I never thought I'd see muru, the muru, come play Code Golf. Welcome to PPCG :D \$\endgroup\$
    – cat
    Apr 2, 2016 at 10:58
  • 1
    \$\begingroup\$ @cat Thanks. :D I have played once before. \$\endgroup\$
    – muru
    Apr 2, 2016 at 10:59
3
\$\begingroup\$

Rust, 84 Bytes

fn main(){loop{use std::io::Write;std::fs::File::create("a").unwrap().write(b"a");}}

File::create truncates an existing file, thus ensuring that we don't run out of disk space.

The used Compiler (1.9 Nightly) issues a warning about the unused result of write(...) but compiles nevertheless.

\$\endgroup\$
3
\$\begingroup\$

C, 92 bytes

#include <stdio.h>
main(){for(FILE*f=fopen("a","w+");fprintf(f," "),!fclose(f);;);return 0;}

While it looks like you could save 1 byte by

  for(FILE*f=fopen("a","w+");fprintf(f," ")+fclose(f);;){}

the problem with that loop is that + doesn't give you the guaranteed order.

Or recursive - shouldn't overflow if the compiler properly implements tail recursion (f is in an explicit inner scope)

85 bytes

#include <stdio.h>
main(){{FILE*f=fopen("a","w+");fprintf(f," ");fclose(f);}main();}
\$\endgroup\$
3
  • \$\begingroup\$ Hopefully the 85-byte version does not blow the stack. :P \$\endgroup\$ Apr 1, 2016 at 21:30
  • 2
    \$\begingroup\$ @MathuSumMut: Easy fix: require compiling with optimizations. Tail call recursion saves the day. \$\endgroup\$
    – Joshua
    Apr 3, 2016 at 22:53
  • 1
    \$\begingroup\$ There's a lot of scope for saving bytes here. See my answer for packing stuff inside the for(;;), and for shorter functions than fprintf. If you did need to include stdio.h (which you don't), you don't need a space: #include<stdio.h> \$\endgroup\$ May 15, 2016 at 14:03
3
\$\begingroup\$

Mathematica, 14 bytes

For[,1>0,a>>a]

Repeatedly writes the string "a" to a file named a in the current directory, creating it if it doesn't exist.

\$\endgroup\$
2
  • \$\begingroup\$ would it write the string "a" or the contents of the variable a? And if the latter, what would it do if that variable were not yet defined? \$\endgroup\$ May 19, 2016 at 21:53
  • \$\begingroup\$ @MichaelStern It writes the variable a, which is undefined, so it just writes a\n. \$\endgroup\$ May 20, 2016 at 0:24
3
\$\begingroup\$

C, 40 bytes

main(){for(;;)write(open("a",1)," ",1);}

It will quickly run out of file descriptors, though; this can be overcome with:

45, 43 bytes

main(f){for(f=open("a",1);;)write(f,"",1);}
\$\endgroup\$
11
  • \$\begingroup\$ Why doesn't f have a type in the second? \$\endgroup\$
    – cat
    Apr 3, 2016 at 2:53
  • 2
    \$\begingroup\$ @cat In C (very K&R style) it defaults to int. \$\endgroup\$
    – edmz
    Apr 3, 2016 at 8:23
  • 1
    \$\begingroup\$ gcc and clang won't compile the 2nd version. Even GNU C doesn't allow dynamic initialization of a static/global variable (a call to open() isn't a compile-time constant). Also, it will run out of disk space, because there's no lseek. Maybe try utime("a","") in the loop, which will keep updating the ctime. (You still have to open to create a file of known name). \$\endgroup\$ May 14, 2016 at 5:59
  • \$\begingroup\$ @PeterCordes You're right, thanks for pointing out. Fixed. \$\endgroup\$
    – edmz
    May 15, 2016 at 13:28
  • \$\begingroup\$ Still doesn't satisfy the OP's requirement of not filling up the disk eventually, but maybe still worth keeping as an answer. (Unless you have an idea better than my answer's close/reopen(O_TRUNC) in a loop.) Contrary to my previous comment, updating timestamps only usually doesn't really produce actual disk I/O on Linux. Like maybe one write per 24 hours with lazytime, as I said in my answer. \$\endgroup\$ May 15, 2016 at 13:37
3
\$\begingroup\$

C on amd64 Linux, 36 bytes (timestamp only), 52 49 bytes (real disk activity)

I hard-code the open(2) flags, so this is not portable to other ABIs. Linux on other platforms likely uses the same O_TRUNC, etc., but other POSIX OSes may not.

+4 bytes to pass a correct permission arg to make sure the file is created with owner write access, see below. (This happens to work with gcc 5.2)

somewhat-portable ANSI C, 38/51 bytes (timestamp only), 52/67 bytes (real disk activity)

Based on @Cat's answer, with a tip from @Jens.

The first number is for implementations where an int can hold FILE *fopen()'s return value, second number if we can't do that. On Linux, heap addresses happen to be in the low 32 bits of address space, so it works even without -m32 or -mx32. (Declaring void*fopen(); is shorter than #include <stdio.h>)


Timestamp metadata I/O only:

main(){for(;;)close(open("a",577));}   // Linux x86-64

//void*fopen();       // compile with -m32 or -mx32 or whatever, so an int holds a pointer.
main(){for(;;)fclose(fopen("a","w"));}

Writing a byte, actually hitting the disk on Linux 4.2.0 + XFS + lazytime:

main(){for(;write(open("a",577),"",1);close(3));}

write is the for-loop condition, which is fine since it always returns 1. close is the increment.

// semi-portable: storing a FILE* in an int.  Works on many systems
main(f){for(;f=fopen("a","w");fclose(f))fputc(0,f);}                 // 52 bytes

// Should be highly portable, except to systems that require prototypes for all functions.
void*f,*fopen();main(){for(;f=fopen("a","w");fclose(f))fputc(0,f);}   // 67 bytes

Explanation of the non-portable version:

The file is created with random garbage permissions. With gcc 5.2, with -O0 or -O3, it happens to include owner write permission, but this is not guaranteed. 0666 is decimal 438. A 3rd arg to open would take another 4 bytes. We're already hard-coding O_TRUNC and so on, but this could break with a different compiler or libc on the same ABI.

We can't omit the 2nd arg to open, because the garbage value happens to include O_EXCL, and O_TRUNC|O_APPEND, so open fails with EINVAL.


We don't need to save the return value from open(). We assume it's 3, because it always will be. Even if we start with fd 3 open, it will be closed after the first iteration. Worst-case, open keeps opening new fds until 3 is the last available file descriptor. So, up to the first 65531 write() calls could fail with EBADF, but will then work normally with every open creating fd = 3.

577 = 0x241 = O_WRONLY|O_CREAT|O_TRUNC on x86-64 Linux. Without O_TRUNC, the inode mod time and change time aren't updated, so a shorter arg isn't possible. O_TRUNC is still essential for the version that calls write to produce actual disk activity, not rewrite in place.

I see some answers that open("a",1). O_CREAT is required if a doesn't already exist. O_CREAT is defined as octal 0100 (64, 0x40) on Linux.


No resource leaks, so it can run forever. strace output:

open("a", O_WRONLY|O_CREAT|O_TRUNC, 03777762713526650) = 3
close(3)                                = 0
... repeating

or

open("a", O_WRONLY|O_CREAT|O_TRUNC, 01) = 3
write(3, "\0", 1)                       = 1   # This is the terminating 0 byte in the empty string we pass to write(2)
close(3)                                = 0

I got the decimal value of the open flags for this ABI using strace -eraw=open on my C++ version.

On a filesystem with the Linux lazytime mount option enabled, a change that only affects inode timestamps will only cause one write per 24 hours. With that mount option disabled, timestamp updating might be a viable way to wear out your SSD. (However, several other answers only do metadata I/O).


alternatives:

shorter non-working:

main(){for(;;)close(write(open("a",577),"",3));} uses write's return value to pass a 3 arg to close. It saves another byte, but doesn't work with gcc -O0 or -O3 on amd64. The garbage in the 3rd arg to open is different, and doesn't include write permission. a gets created the first time, but future iterations all fail with -EACCESS.

longer, working, with different system calls:

main(c){for(open("a",65);pwrite(3,"",1);)sync();} rewrites a byte in-place and calls sync() to sync all filesystems system-wide. This keeps the drive light lit up.

We don't care which byte, so we don't pass 4th arg to pwrite. Yay for sparse files:

$ ll -s a
300K -rwx-wx--- 1 peter peter 128T May 15 11:43 a

Writing one byte at an offset of ~128TiB led to xfs using 300kiB of space to hold the extent map, I guess. Don't try this on OS X with HFS+: IIRC, HFS+ doesn't support sparse files, so it will fill the disk.

XFS is a proper 64bit filesystem, supporting individual files up to 8 exabytes. i.e. 2^63-1, the maximum value off_t can hold.

strace output:

open("a", O_WRONLY|O_CREAT, 03777711166007270) = 3
pwrite(3, "\0", 1, 139989929353760)     = 1
sync()                                  = 0
pwrite(3, "\0", 1, 139989929380071)     = 1
sync()                                  = 0
...
\$\endgroup\$
2
\$\begingroup\$

Racket, 46 bytes

(do()(#f)(write-to-file'a"f"#:exists'replace))
\$\endgroup\$
2
  • 1
    \$\begingroup\$ I was thinking of answering in Racket, but you beat me to it. :P \$\endgroup\$
    – cat
    Apr 3, 2016 at 2:49
  • \$\begingroup\$ Out of curiosity, did you find a shorter answer? \$\endgroup\$
    – Winny
    Apr 3, 2016 at 6:20
1
\$\begingroup\$

Factor, 73 bytes

USING: io.files io.encodings
[ 0 "a" utf8 set-file-contents ] [ t ] while

Sets the file contents to the nul byte forever.

\$\endgroup\$
1
\$\begingroup\$

CBM BASIC 7.0, 9 bytes

0dS"a":rU

This program, when run, repeatedly saves itself to disk. Here's a more readable version which doesn't use BASIC keyword abbreviations:

0 dsave "a" : run
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Does it run out of cassette tape though? ;) \$\endgroup\$ Apr 4, 2016 at 10:18
  • 1
    \$\begingroup\$ @MathuSumMut that would be 0 SAVE "A" : RUN \$\endgroup\$
    – ceilingcat
    Feb 25, 2017 at 22:39
1
\$\begingroup\$

Python, 32 bytes

while 1:open("a","w").write("b")

Note that if run on python 3, this will produce an infinite number of warnings. Also, it will probably run out of fds if run in a non-refcounting implementation.

\$\endgroup\$
1
  • \$\begingroup\$ Just as a note, a shorter answer exists without the write and the "w" part of the open command. \$\endgroup\$
    – Riker
    May 14, 2016 at 2:14
1
\$\begingroup\$

Dyalog APL 15.0, 17 bytes (non-competing)

(⊢⊣⊃⎕NPUT⊢)⍣≢'A'1

Chrome currently renders U+2262 wrong. The above line should look like (⊢⊣⊃⎕NPUT⊢)⍣̸≡'A'1.

This is non-competing because version 15 has not been released yet.

Applies the function (⊢⊣⊃⎕NPUT⊢) on 'A'1 until the input is changed (i.e. never):

⊢⊣⊃⎕NPUT⊢ is a function train:

┌─┼───┐      
⊢ ⊣ ┌─┼─────┐
    ⊃ ⎕NPUT ⊢

The rightmost returns 'A'1 unmodified; this (filename, overwrite-flag) will be the right argument to `⎕NPUT'.

'⊃' returns the first element of 'A'1 ('A'); this is the data to be written.

Then ⎕NPUT is run, and reports how many bytes were written (2 or 3 depending on OS); this becomes the right argument to the .

The leftmost again returns 'A'1 unmodified; this is the left argument to the .

ignores its right argument and returns the left argument ('A'1), this becomes the new value fed to .

Since the new value is identical to the old one, the operation is continued (forever).

\$\endgroup\$
1
\$\begingroup\$

SmileBASIC, 12 bytes

SAVE"A
EXEC.
\$\endgroup\$
1
  • \$\begingroup\$ Doesn’t it run out of cassette tape though? \$\endgroup\$ Jan 1, 2019 at 10:18
0
\$\begingroup\$

vim text editor, 10 bytes

qa:w<enter>@aq@a

8 bytes if you do not could the execution command @a

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.