{"thread":{"id":"5559","subject":"open(2) vs fopen(3)","startedAt":"2006-09-14T09:15:13Z","lastAt":"2006-09-14T17:31:27Z","messageCount":5,"participants":["moreau francis","Andy Whitcroft","Linus Torvalds","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"26877","messageId":"20060914091513.19826.qmail@web25812.mail.ukl.yahoo.com","threadId":"5559","inReplyTo":null,"subject":"open(2) vs fopen(3)","fromName":"moreau francis","fromEmail":"francis_moreau2000@yahoo.fr","sentAt":"2006-09-14T09:15:13Z","receivedAt":"2006-09-14T09:15:13Z","isPatch":false,"sender":{"key":"francis_moreau2000@yahoo.fr","avatar":null},"body":"Hi GIT folks,\n\nI'm reading git source code and falling on this stupid question:\nWhy sometime open(2) is used and other time fopen(3) is\nprefered. I'm sorry for this dump question but I have no clue.\n\nthanks\n\nFrancis\n"},{"id":"26881","messageId":"4509348B.3060907@shadowen.org","threadId":"5559","inReplyTo":"20060914091513.19826.qmail@web25812.mail.ukl.yahoo.com","subject":"Re: open(2) vs fopen(3)","fromName":"Andy Whitcroft","fromEmail":"apw@shadowen.org","sentAt":"2006-09-14T10:52:59Z","receivedAt":"2006-09-14T10:52:59Z","isPatch":false,"sender":{"key":"apw@shadowen.org","avatar":"https://gravatar.com/avatar/d3088262854661a913ef35cc40fedcc270142d4461791142bc1ea0b2a4e2e147?d=mp&s=160"},"body":"moreau francis wrote:\n> Hi GIT folks,\n> \n> I'm reading git source code and falling on this stupid question:\n> Why sometime open(2) is used and other time fopen(3) is\n> prefered. I'm sorry for this dump question but I have no clue.\n\nIt looks very much from a quick random sampling, that open is used where\nwe are going to mmap the file for quick access.  fopen otherwise.\n\n-apw\n"},{"id":"26887","messageId":"Pine.LNX.4.64.0609140835080.4388@g5.osdl.org","threadId":"5559","inReplyTo":"20060914091513.19826.qmail@web25812.mail.ukl.yahoo.com","subject":"Re: open(2) vs fopen(3)","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-09-14T15:46:13Z","receivedAt":"2006-09-14T15:46:13Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Thu, 14 Sep 2006, moreau francis wrote:\n> \n> I'm reading git source code and falling on this stupid question:\n> Why sometime open(2) is used and other time fopen(3) is\n> prefered. I'm sorry for this dump question but I have no clue.\n\nfopen() tends to result in easier usage, especially if the file in \nquestion is a line-based ASCII file, and you can just use \"fgets()\" to \nread it. So fopen is the simple alternative for simple problems.\n\nUsing a direct open() means that you have to use the low-level IO \nfunctions (I'm ignoring the use of \"fdopen()\"), but if done right, it has \na number of advantages:\n\n - with the proper use, it's potentially more efficient (but stdio is a \n   lot more efficient if you do lots of small writes without buffering)\n\n - you can control the creation flags better (ie if you want to do an \n   exclusive open, you _have_ to use \"open()\" - there's no portable way to \n   say O_EXCL with \"fopen()\")\n\n - error conditions are a lot more obvious and repeatable with the \n   low-level things, at least so I find personally. Error handling with \n   stdio routines is _possible_, but probably because almost nobody ever \n   does it, it's not something that people are conditioned to do, so it \n   ends up beign \"strange\".\n\n   (So this third one is more a psychological issue than a really \n   technical issue - at least for me. I'd not use stdio for things I \n   might expect to do fsync() on, for example. It's _possible_, but very \n   non-intuitive, because that's now how people generally use stdio).\n\nSo it boils down to the fact that people tend to do higher-level things \nwith stdio interfaces (fopen and friends), and lower-level things with the \nraw system call (\"unistd.h\") interfaces.\n\nIn git, you'd expect to see code that actually works on the object \ndatabase or the refs using \"open()\" (both because it's low-level, and it \ngenerally wants to use O_EXCL and friends), and then things that open the \n\".gitignore\" file to use fopen() (because it's a line-based ASCII \ninterface, and it's not an \"important\" file in the sense that we don't \nreally care about some strange situation where it could give us an IO \nerror).\n\nThere might also be a difference in personality. I probably tend to use \nthe core unistd interfaces more than some other people would, and some \nother people might end up using stdio for pretty much everything.\n\n\t\t\tLinus\n"},{"id":"26894","messageId":"7vr6ye4d64.fsf@assigned-by-dhcp.cox.net","threadId":"5559","inReplyTo":"Pine.LNX.4.64.0609140835080.4388@g5.osdl.org","subject":"Re: open(2) vs fopen(3)","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-09-14T16:37:39Z","receivedAt":"2006-09-14T16:37:39Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> On Thu, 14 Sep 2006, moreau francis wrote:\n>> \n>> I'm reading git source code and falling on this stupid question:\n>> Why sometime open(2) is used and other time fopen(3) is\n>> prefered. I'm sorry for this dump question but I have no clue.\n>\n> fopen() tends to result in easier usage, especially if the file in \n> question is a line-based ASCII file, and you can just use \"fgets()\" to \n> read it. So fopen is the simple alternative for simple problems.\n>\n> Using a direct open() means that you have to use the low-level IO \n> functions (I'm ignoring the use of \"fdopen()\"), but if done right, it has \n> a number of advantages:\n>...\n>  - error conditions are a lot more obvious and repeatable with the \n>    low-level things, at least so I find personally. Error handling with \n>    stdio routines is _possible_, but probably because almost nobody ever \n>    does it, it's not something that people are conditioned to do, so it \n>    ends up beign \"strange\".\n\nAnother issue related with this is that stdio implementations\ntend to have unintuitive interaction with signals, one fine\nexample of it being the problem we fixed with commit fb7a653,\nwhere on Solaris fgets(3) did not restart the underlying read(2)\nupon SIGALRM.\n\nTechnically it was a bug on our part not Solaris, but that was\nsomething unexpected to see.\n"},{"id":"26903","messageId":"Pine.LNX.4.64.0609141023130.4388@g5.osdl.org","threadId":"5559","inReplyTo":"7vr6ye4d64.fsf@assigned-by-dhcp.cox.net","subject":"Re: open(2) vs fopen(3)","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-09-14T17:31:27Z","receivedAt":"2006-09-14T17:31:27Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Thu, 14 Sep 2006, Junio C Hamano wrote:\n>\n> Another issue related with this is that stdio implementations\n> tend to have unintuitive interaction with signals, one fine\n> example of it being the problem we fixed with commit fb7a653,\n> where on Solaris fgets(3) did not restart the underlying read(2)\n> upon SIGALRM.\n\nYeah. However, I think it's worth just posting the code in question to \nexplain _why_ error handling with stdio sucks so badly, and why nobody \ndoes it..\n\nHere's the snippet:\n\n                if (!fgets(line, sizeof(line), stdin)) {\n                        if (feof(stdin))\n                                break;\n                        if (!ferror(stdin))\n                                die(\"fgets returned NULL, not EOF, not error!\");\n                        if (errno != EINTR)\n                                die(\"fgets: %s\", strerror(errno));\n                        clearerr(stdin);\n\nso with the <stdio.h> functions, you have to check FOUR DIFFERENT THINGS \n(1: return value, 2: feof() value, 3: ferror() value, and 4: errno) to get \nthings right, and to add insult to injury, you then have to do an explicit \nclear.\n\nIn other words, the fundamental reason nobody bothers checking errors with \nstdio is that stdio just makes it a damn pain in the ass to do so - by \nhaving a million different thing you have to do (and ordering actually \nmatters).\n\nIn contrast, the <unistd.h> interfaces are a paragon of clarity: you check \njust two things - the return value, and possibly \"errno\".\n\nNow, <unistd.h> isn't perfect either, and in the kernel we have simplified \nthings further, by getting rid of \"errno\", and just having the return \nvalue contain errno too. Making things not only trivially thread-safe, but \nalso actually easier to code and understand, because you don't have \nanything to be confused about: the return value is always the only thing \nyou need to look at in order to know what went wrong.\n\nBut unistd.h sure is a lot better than stdio in this area. Of course, \nstdio.h is just a lot easier to use when you don't actually care about the \nerrors, which is also partly the _reason_ why caring about errors is so \nhard (the whole separate clearerr() and ferror() interfaces exist exactly \n_because_ people don't care about errors in many cases, and you're \nsupposed to maybe have some way to test at the end whether an error \nhappened or not).\n\nSo stdio.h is pretty much geared towards delayed error handling, which in \npractice ends up often meaning \"no error handling at all\".\n\n\t\t\tLinus\n"}]}