stream.c 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. stream.c
  9. Abstract:
  10. This module implements the higher level file stream interface.
  11. Author:
  12. Evan Green 18-Jun-2013
  13. Environment:
  14. User Mode C Library
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "libcp.h"
  20. #include <assert.h>
  21. #include <errno.h>
  22. #include <fcntl.h>
  23. #include <stdio.h>
  24. #include <stdio_ext.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <sys/stat.h>
  28. //
  29. // ---------------------------------------------------------------- Definitions
  30. //
  31. //
  32. // Define the number of standard handles.
  33. //
  34. #define STANDARD_HANDLE_COUNT 3
  35. //
  36. // Define the creation mask for stream files.
  37. //
  38. #define STREAM_FILE_CREATION_MASK \
  39. (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
  40. //
  41. // Define the maximum size of the stack-allocated print buffer.
  42. //
  43. #define STREAM_PRINT_BUFFER_SIZE 128
  44. //
  45. // ------------------------------------------------------ Data Type Definitions
  46. //
  47. /*++
  48. Structure Description:
  49. This structure defines the print context used for streams. This allows
  50. unbuffered streams to batch prints, rather than write them out character by
  51. character.
  52. Members:
  53. Stream - Store a pointer to the file stream to print to.
  54. Buffer - Stores a pointer to the buffered print output for unbuffered
  55. streams.
  56. BufferNextIndex - Stores the index into the buffer to store the next
  57. character.
  58. CharactersWritten - Stores the number of characters actually written to the
  59. stream.
  60. --*/
  61. typedef struct _STREAM_PRINT_CONTEXT {
  62. FILE *Stream;
  63. CHAR Buffer[STREAM_PRINT_BUFFER_SIZE];
  64. ULONG BufferNextIndex;
  65. ULONG CharactersWritten;
  66. } STREAM_PRINT_CONTEXT, *PSTREAM_PRINT_CONTEXT;
  67. //
  68. // ----------------------------------------------- Internal Function Prototypes
  69. //
  70. PFILE
  71. ClpCreateFileStructure (
  72. ULONG Descriptor,
  73. ULONG OpenFlags,
  74. ULONG BufferMode
  75. );
  76. VOID
  77. ClpDestroyFileStructure (
  78. PFILE File
  79. );
  80. BOOL
  81. ClpFileFormatWriteCharacter (
  82. INT Character,
  83. PPRINT_FORMAT_CONTEXT Context
  84. );
  85. INT
  86. ClpConvertStreamModeStringToOpenFlags (
  87. PSTR ModeString,
  88. INT *OpenFlags
  89. );
  90. //
  91. // -------------------------------------------------------------------- Globals
  92. //
  93. //
  94. // Define the standard file handle pointers.
  95. //
  96. LIBC_API FILE *stdin;
  97. LIBC_API FILE *stdout;
  98. LIBC_API FILE *stderr;
  99. //
  100. // Store the global list of streams, protected by a single global spin lock.
  101. //
  102. LIST_ENTRY ClStreamList;
  103. pthread_mutex_t ClStreamListLock;
  104. //
  105. // ------------------------------------------------------------------ Functions
  106. //
  107. LIBC_API
  108. FILE *
  109. fopen (
  110. const char *FileName,
  111. const char *Mode
  112. )
  113. /*++
  114. Routine Description:
  115. This routine opens the given file and associates a stream with it.
  116. Arguments:
  117. FileName - Supplies a pointer to a string containing the path to the file
  118. to open.
  119. Mode - Supplies a pointer to a null terminated string specifying the mode
  120. to open the file with. Valid value are "r", "w", "a", and may optionally
  121. have a + or b appended to it. The + symbol opens the file for updating,
  122. meaning that the system does not flush immediately after writes. The "b"
  123. option has no effect.
  124. Return Value:
  125. Returns a pointer to the file stream on success.
  126. NULL on failure, and errno contains more information.
  127. --*/
  128. {
  129. mode_t CreatePermissions;
  130. int Descriptor;
  131. int Error;
  132. FILE *NewFile;
  133. int OpenFlags;
  134. BOOL Success;
  135. CreatePermissions = STREAM_FILE_CREATION_MASK;
  136. Descriptor = -1;
  137. NewFile = NULL;
  138. OpenFlags = 0;
  139. Success = FALSE;
  140. //
  141. // Get the open flags.
  142. //
  143. Error = ClpConvertStreamModeStringToOpenFlags((PSTR)Mode, &OpenFlags);
  144. if (Error != 0) {
  145. goto fopenEnd;
  146. }
  147. //
  148. // Open up the file with the operating system.
  149. //
  150. Descriptor = open(FileName, OpenFlags, CreatePermissions);
  151. if (Descriptor == -1) {
  152. goto fopenEnd;
  153. }
  154. NewFile = ClpCreateFileStructure(Descriptor, OpenFlags, _IOFBF);
  155. if (NewFile == NULL) {
  156. goto fopenEnd;
  157. }
  158. Success = TRUE;
  159. fopenEnd:
  160. if (Success == FALSE) {
  161. if (NewFile != NULL) {
  162. if (NewFile->Descriptor != -1) {
  163. close(NewFile->Descriptor);
  164. }
  165. if (NewFile->Buffer != NULL) {
  166. free(NewFile->Buffer);
  167. }
  168. free(NewFile);
  169. NewFile = NULL;
  170. }
  171. }
  172. if (Error != 0) {
  173. errno = Error;
  174. }
  175. return NewFile;
  176. }
  177. LIBC_API
  178. FILE *
  179. fdopen (
  180. int OpenFileDescriptor,
  181. const char *Mode
  182. )
  183. /*++
  184. Routine Description:
  185. This routine associates a stream with the given file descriptor. The mode
  186. argument must agree with the flags the original descriptor was opened with.
  187. On success, the stream now "owns" the file descriptor, a call to fclose
  188. on the stream will also call close on the underlying descriptor.
  189. Arguments:
  190. OpenFileDescriptor - Supplies the open file descriptor to create a stream
  191. around.
  192. Mode - Supplies a pointer to a null terminated string specifying the mode
  193. to open the file with. Valid value are "r", "w", "a", and may optionally
  194. have a + or b appended to it. The + symbol opens the file for updating,
  195. meaning that the system does not flush immediately after writes. The "b"
  196. option has no effect.
  197. Return Value:
  198. Returns a pointer to the file stream on success.
  199. NULL on failure, and errno contains more information.
  200. --*/
  201. {
  202. int Error;
  203. FILE *NewFile;
  204. int OpenFlags;
  205. NewFile = NULL;
  206. OpenFlags = 0;
  207. if (OpenFileDescriptor == -1) {
  208. Error = EBADF;
  209. goto fdopenEnd;
  210. }
  211. Error = ClpConvertStreamModeStringToOpenFlags((PSTR)Mode, &OpenFlags);
  212. if (Error != 0) {
  213. goto fdopenEnd;
  214. }
  215. NewFile = ClpCreateFileStructure(OpenFileDescriptor, OpenFlags, _IOFBF);
  216. if (NewFile == NULL) {
  217. Error = ENOMEM;
  218. goto fdopenEnd;
  219. }
  220. Error = 0;
  221. fdopenEnd:
  222. if (Error != 0) {
  223. if (NewFile != NULL) {
  224. if (NewFile->Buffer != NULL) {
  225. free(NewFile->Buffer);
  226. }
  227. free(NewFile);
  228. NewFile = NULL;
  229. }
  230. }
  231. if (Error != 0) {
  232. errno = Error;
  233. }
  234. return NewFile;
  235. }
  236. LIBC_API
  237. FILE *
  238. freopen (
  239. const char *FileName,
  240. const char *Mode,
  241. FILE *Stream
  242. )
  243. /*++
  244. Routine Description:
  245. This routine attempts to flush the given stream and close any file
  246. descriptor associated with the stream. Failure to flush or close the
  247. file descriptor is ignored. The error and end-of-file indicators are
  248. cleared. This routine then attempts to open the given file with the given
  249. mode and associate it with the stream. The previous file descriptor
  250. associated with this stream is closed whether or not the new descriptor
  251. could be opened.
  252. The standard says that passing in NULL for the file name will change the
  253. permissions of the existing descriptor. This implementation currently does
  254. not support that and sets errno to EBADF if attempted.
  255. Arguments:
  256. FileName - Supplies a pointer to the path to open and associate with this
  257. stream.
  258. Mode - Supplies a pointer to the string describing the desired access to
  259. this path. This takes the same format as the fopen mode string.
  260. Stream - Supplies a pointer to the open stream.
  261. Return Value:
  262. Returns a pointer to the given stream on success, now with a different
  263. file descriptor.
  264. NULL on failure, and errno will be set to contain more information.
  265. --*/
  266. {
  267. int Error;
  268. int NewDescriptor;
  269. int OpenFlags;
  270. NewDescriptor = -1;
  271. if (Stream == NULL) {
  272. errno = EBADF;
  273. return NULL;
  274. }
  275. ClpLockStream(Stream);
  276. //
  277. // Flush and close the original descriptor.
  278. //
  279. fflush_unlocked(Stream);
  280. if (Stream->Descriptor != -1) {
  281. close(Stream->Descriptor);
  282. Stream->Descriptor = -1;
  283. }
  284. //
  285. // Get the open flags.
  286. //
  287. OpenFlags = 0;
  288. Error = ClpConvertStreamModeStringToOpenFlags((PSTR)Mode, &OpenFlags);
  289. if (Error != 0) {
  290. goto freopenEnd;
  291. }
  292. //
  293. // Consider implementing support for changing permissions on the currently
  294. // open file if people trying to use that.
  295. //
  296. assert(FileName != NULL);
  297. //
  298. // Open up the new descriptor.
  299. //
  300. NewDescriptor = open(FileName, OpenFlags);
  301. if (NewDescriptor < 0) {
  302. NewDescriptor = -1;
  303. Error = errno;
  304. goto freopenEnd;
  305. }
  306. freopenEnd:
  307. //
  308. // Set the underlying descriptor to the new descriptor, which may or may
  309. // not have failed to open.
  310. //
  311. Stream->Descriptor = NewDescriptor;
  312. Stream->OpenFlags = OpenFlags;
  313. Stream->BufferNextIndex = 0;
  314. Stream->BufferValidSize = 0;
  315. Stream->Flags &= (FILE_FLAG_BUFFER_ALLOCATED | FILE_FLAG_STANDARD_IO);
  316. if ((OpenFlags & O_ACCMODE) != O_WRONLY) {
  317. Stream->Flags |= FILE_FLAG_CAN_READ;
  318. }
  319. ClpUnlockStream(Stream);
  320. return Stream;
  321. }
  322. LIBC_API
  323. int
  324. fclose (
  325. FILE *Stream
  326. )
  327. /*++
  328. Routine Description:
  329. This routine closes an open file stream.
  330. Arguments:
  331. Stream - Supplies a pointer to the open stream.
  332. Return Value:
  333. 0 on success.
  334. Returns EOF if there was an error flushing or closing the stream.
  335. --*/
  336. {
  337. int Result;
  338. Result = fflush(Stream);
  339. if (Stream->Descriptor != -1) {
  340. Result |= close(Stream->Descriptor);
  341. Stream->Descriptor = -1;
  342. }
  343. //
  344. // Don't actually free the stream if it's one of the standard ones.
  345. // Applications have come to expect to be able to fclose stdout and then
  346. // freopen it.
  347. //
  348. if ((Stream->Flags & FILE_FLAG_STANDARD_IO) == 0) {
  349. ClpDestroyFileStructure(Stream);
  350. }
  351. return Result;
  352. }
  353. LIBC_API
  354. size_t
  355. fread (
  356. void *Buffer,
  357. size_t Size,
  358. size_t ItemCount,
  359. FILE *Stream
  360. )
  361. /*++
  362. Routine Description:
  363. This routine reads from a file stream.
  364. Arguments:
  365. Buffer - Supplies a pointer to the buffer where the data will be returned.
  366. Size - Supplies the size of each element to read.
  367. ItemCount - Supplies the number of elements to read.
  368. Stream - Supplies a pointer to the file stream object to read from.
  369. Return Value:
  370. Returns the number of elements successfully read from the file. On failure,
  371. the error indicator for the stream will be set, and errno will set to
  372. provide details on the error that occurred.
  373. --*/
  374. {
  375. size_t Result;
  376. ClpLockStream(Stream);
  377. Result = fread_unlocked(Buffer, Size, ItemCount, Stream);
  378. ClpUnlockStream(Stream);
  379. return Result;
  380. }
  381. LIBC_API
  382. size_t
  383. fread_unlocked (
  384. void *Buffer,
  385. size_t Size,
  386. size_t ItemCount,
  387. FILE *Stream
  388. )
  389. /*++
  390. Routine Description:
  391. This routine reads from a file stream without acquiring the internal file
  392. lock.
  393. Arguments:
  394. Buffer - Supplies a pointer to the buffer where the data will be returned.
  395. Size - Supplies the size of each element to read.
  396. ItemCount - Supplies the number of elements to read.
  397. Stream - Supplies a pointer to the file stream object to read from.
  398. Return Value:
  399. Returns the number of elements successfully read from the file. On failure,
  400. the error indicator for the stream will be set, and errno will set to
  401. provide details on the error that occurred.
  402. --*/
  403. {
  404. size_t BytesToRead;
  405. ssize_t Result;
  406. size_t TotalBytesRead;
  407. size_t TotalBytesToRead;
  408. TotalBytesRead = 0;
  409. TotalBytesToRead = Size * ItemCount;
  410. if ((Stream->Flags & FILE_FLAG_CAN_READ) == 0) {
  411. Stream->Flags |= FILE_FLAG_ERROR;
  412. errno = EACCES;
  413. return 0;
  414. }
  415. if (Stream->Descriptor == -1) {
  416. errno = EBADF;
  417. return 0;
  418. }
  419. if ((Size == 0) || (ItemCount == 0)) {
  420. return 0;
  421. }
  422. //
  423. // Set the last operation to be a read.
  424. //
  425. Stream->Flags |= FILE_FLAG_READ_LAST;
  426. //
  427. // If the unget character is valid, stick that in there first.
  428. //
  429. if ((Stream->Flags & FILE_FLAG_UNGET_VALID) != 0) {
  430. *((PUCHAR)Buffer) = Stream->UngetCharacter;
  431. Stream->Flags &= ~FILE_FLAG_UNGET_VALID;
  432. TotalBytesRead += 1;
  433. if (TotalBytesRead == TotalBytesToRead) {
  434. return TotalBytesRead / Size;
  435. }
  436. }
  437. //
  438. // For unbuffered streams, just read the file contents directly.
  439. //
  440. if (Stream->BufferMode == _IONBF) {
  441. ClpFlushAllStreams(FALSE, Stream);
  442. while (TotalBytesRead != TotalBytesToRead) {
  443. do {
  444. Result = read(Stream->Descriptor,
  445. Buffer + TotalBytesRead,
  446. TotalBytesToRead - TotalBytesRead);
  447. } while ((Result < 0) && (errno == EINTR));
  448. if (Result <= 0) {
  449. if (Result < 0) {
  450. Stream->Flags |= FILE_FLAG_ERROR;
  451. } else {
  452. Stream->Flags |= FILE_FLAG_END_OF_FILE;
  453. }
  454. break;
  455. }
  456. TotalBytesRead += Result;
  457. }
  458. return TotalBytesRead / Size;
  459. }
  460. assert(Stream->Buffer != NULL);
  461. //
  462. // Grab as much as needed out of the buffer.
  463. //
  464. BytesToRead = Stream->BufferValidSize - Stream->BufferNextIndex;
  465. if (BytesToRead > (TotalBytesToRead - TotalBytesRead)) {
  466. BytesToRead = TotalBytesToRead - TotalBytesRead;
  467. }
  468. memcpy(Buffer + TotalBytesRead,
  469. Stream->Buffer + Stream->BufferNextIndex,
  470. BytesToRead);
  471. TotalBytesRead += BytesToRead;
  472. Stream->BufferNextIndex += BytesToRead;
  473. if (Stream->BufferNextIndex == Stream->BufferValidSize) {
  474. Stream->BufferNextIndex = 0;
  475. Stream->BufferValidSize = 0;
  476. }
  477. //
  478. // Do direct reads to the caller's buffer if they're as large as the
  479. // buffer itself to avoid silly copies.
  480. //
  481. if (TotalBytesToRead >= Stream->BufferSize) {
  482. while (TotalBytesRead != TotalBytesToRead) {
  483. BytesToRead = TotalBytesToRead - TotalBytesRead;
  484. do {
  485. Result = read(Stream->Descriptor,
  486. Buffer + TotalBytesRead,
  487. BytesToRead);
  488. } while ((Result == -1) && (errno == EINTR));
  489. if (Result <= 0) {
  490. if (Result < 0) {
  491. Stream->Flags |= FILE_FLAG_ERROR;
  492. } else {
  493. Stream->Flags |= FILE_FLAG_END_OF_FILE;
  494. }
  495. break;
  496. }
  497. TotalBytesRead += Result;
  498. }
  499. //
  500. // This is a smaller read, use the buffer.
  501. //
  502. } else {
  503. while (TotalBytesRead != TotalBytesToRead) {
  504. //
  505. // The buffer should have been cleared out by the first portion of
  506. // this function or fully satisfied by it.
  507. //
  508. assert((Stream->BufferValidSize == 0) &&
  509. (Stream->BufferNextIndex == 0));
  510. do {
  511. Result = read(Stream->Descriptor,
  512. Stream->Buffer,
  513. Stream->BufferSize);
  514. } while ((Result == -1) && (errno == EINTR));
  515. if (Result <= 0) {
  516. if (Result < 0) {
  517. Stream->Flags |= FILE_FLAG_ERROR;
  518. } else {
  519. Stream->Flags |= FILE_FLAG_END_OF_FILE;
  520. }
  521. break;
  522. }
  523. BytesToRead = Result;
  524. if (BytesToRead > (TotalBytesToRead - TotalBytesRead)) {
  525. BytesToRead = TotalBytesToRead - TotalBytesRead;
  526. Stream->BufferValidSize = Result;
  527. Stream->BufferNextIndex = BytesToRead;
  528. }
  529. memcpy(Buffer + TotalBytesRead, Stream->Buffer, BytesToRead);
  530. TotalBytesRead += BytesToRead;
  531. }
  532. }
  533. return TotalBytesRead / Size;
  534. }
  535. LIBC_API
  536. size_t
  537. fwrite (
  538. const void *Buffer,
  539. size_t Size,
  540. size_t ItemCount,
  541. FILE *Stream
  542. )
  543. /*++
  544. Routine Description:
  545. This routine writes to a file stream.
  546. Arguments:
  547. Buffer - Supplies a pointer to the buffer containing the data to write.
  548. Size - Supplies the size of each element to write.
  549. ItemCount - Supplies the number of elements to write.
  550. Stream - Supplies a pointer to the file stream object to write to.
  551. Return Value:
  552. Returns the number of elements successfully written to the file. On failure,
  553. the error indicator for the stream will be set, and errno will set to
  554. provide details on the error that occurred.
  555. --*/
  556. {
  557. size_t Result;
  558. ClpLockStream(Stream);
  559. Result = fwrite_unlocked(Buffer, Size, ItemCount, Stream);
  560. ClpUnlockStream(Stream);
  561. return Result;
  562. }
  563. LIBC_API
  564. size_t
  565. fwrite_unlocked (
  566. const void *Buffer,
  567. size_t Size,
  568. size_t ItemCount,
  569. FILE *Stream
  570. )
  571. /*++
  572. Routine Description:
  573. This routine writes to a file stream without acquiring the internal file
  574. lock.
  575. Arguments:
  576. Buffer - Supplies a pointer to the buffer containing the data to write.
  577. Size - Supplies the size of each element to write.
  578. ItemCount - Supplies the number of elements to write.
  579. Stream - Supplies a pointer to the file stream object to write to.
  580. Return Value:
  581. Returns the number of elements successfully written to the file. On failure,
  582. the error indicator for the stream will be set, and errno will set to
  583. provide details on the error that occurred.
  584. --*/
  585. {
  586. size_t BytesToWrite;
  587. ULONG CharacterIndex;
  588. BOOL Flush;
  589. ssize_t Result;
  590. PSTR String;
  591. size_t TotalBytesToWrite;
  592. size_t TotalBytesWritten;
  593. TotalBytesWritten = 0;
  594. TotalBytesToWrite = Size * ItemCount;
  595. if ((Stream->OpenFlags & O_WRONLY) == 0) {
  596. errno = EACCES;
  597. return 0;
  598. }
  599. if (TotalBytesToWrite == 0) {
  600. return 0;
  601. }
  602. if (Stream->Descriptor == -1) {
  603. errno = EBADF;
  604. return 0;
  605. }
  606. //
  607. // The unget character isn't valid after things have been written.
  608. //
  609. if ((Stream->Flags & FILE_FLAG_UNGET_VALID) != 0) {
  610. Stream->Flags &= ~FILE_FLAG_UNGET_VALID;
  611. }
  612. //
  613. // For unbuffered streams or large writes, just write the file contents
  614. // directly.
  615. //
  616. if ((Stream->BufferMode == _IONBF) ||
  617. (TotalBytesToWrite > Stream->BufferSize)) {
  618. if (fflush_unlocked(Stream) != 0) {
  619. return -1;
  620. }
  621. //
  622. // Set the last thing that happened to be a write.
  623. //
  624. Stream->Flags &= ~FILE_FLAG_READ_LAST;
  625. while (TotalBytesWritten != TotalBytesToWrite) {
  626. do {
  627. Result = write(Stream->Descriptor,
  628. Buffer + TotalBytesWritten,
  629. TotalBytesToWrite - TotalBytesWritten);
  630. } while ((Result < 0) && (errno == EINTR));
  631. if (Result <= 0) {
  632. Stream->Flags |= FILE_FLAG_ERROR;
  633. break;
  634. }
  635. TotalBytesWritten += Result;
  636. }
  637. return TotalBytesWritten / Size;
  638. }
  639. //
  640. // If the last thing that happened was a read, flush the buffer.
  641. //
  642. if ((Stream->Flags & FILE_FLAG_READ_LAST) != 0) {
  643. if (fflush_unlocked(Stream) != 0) {
  644. return -1;
  645. }
  646. Stream->Flags &= ~FILE_FLAG_READ_LAST;
  647. }
  648. //
  649. // Loop writing stuff to the buffer and flushing the buffer.
  650. //
  651. Flush = FALSE;
  652. while (TotalBytesWritten != TotalBytesToWrite) {
  653. BytesToWrite = Stream->BufferSize - Stream->BufferNextIndex;
  654. if (BytesToWrite > (TotalBytesToWrite - TotalBytesWritten)) {
  655. BytesToWrite = TotalBytesToWrite - TotalBytesWritten;
  656. }
  657. //
  658. // If the buffer is line buffered, look for a newline, which would
  659. // indicate the need to flush, and cut the copy short if one is found.
  660. //
  661. if (Stream->BufferMode == _IOLBF) {
  662. String = (PSTR)Buffer + TotalBytesWritten;
  663. for (CharacterIndex = 0;
  664. CharacterIndex < BytesToWrite;
  665. CharacterIndex += 1) {
  666. if (String[CharacterIndex] == '\n') {
  667. Flush = TRUE;
  668. BytesToWrite = CharacterIndex + 1;
  669. break;
  670. }
  671. }
  672. }
  673. assert(Stream->BufferNextIndex + BytesToWrite <= Stream->BufferSize);
  674. //
  675. // If there is any space left, copy the bytes into the buffer.
  676. //
  677. if (BytesToWrite != 0) {
  678. memcpy(Stream->Buffer + Stream->BufferNextIndex,
  679. (PVOID)Buffer + TotalBytesWritten,
  680. BytesToWrite);
  681. assert(Stream->BufferValidSize == Stream->BufferNextIndex);
  682. Stream->BufferNextIndex += BytesToWrite;
  683. Stream->BufferValidSize = Stream->BufferNextIndex;
  684. if (Stream->BufferNextIndex == Stream->BufferSize) {
  685. Flush = TRUE;
  686. }
  687. TotalBytesWritten += BytesToWrite;
  688. //
  689. // If there's no space left, flush the buffer to make more.
  690. //
  691. } else {
  692. Flush = TRUE;
  693. }
  694. //
  695. // For the buffer not to want to flush it had better be done.
  696. //
  697. assert((Flush != FALSE) || (TotalBytesWritten == TotalBytesToWrite));
  698. if (Flush != FALSE) {
  699. if (fflush_unlocked(Stream) < 0) {
  700. break;
  701. }
  702. }
  703. }
  704. return TotalBytesWritten / Size;
  705. }
  706. LIBC_API
  707. int
  708. fflush (
  709. FILE *Stream
  710. )
  711. /*++
  712. Routine Description:
  713. This routine flushes any data sitting in the file stream that has not yet
  714. made it out to the operating system. This is only relevant for output
  715. streams.
  716. Arguments:
  717. Stream - Supplies a pointer to the open file stream to flush.
  718. Return Value:
  719. 0 on success.
  720. EOF on failure, and errno will be set to contain more information.
  721. --*/
  722. {
  723. int Result;
  724. if (Stream == NULL) {
  725. ClpFlushAllStreams(FALSE, NULL);
  726. return 0;
  727. }
  728. ClpLockStream(Stream);
  729. Result = fflush_unlocked(Stream);
  730. ClpUnlockStream(Stream);
  731. return Result;
  732. }
  733. LIBC_API
  734. int
  735. fflush_unlocked (
  736. FILE *Stream
  737. )
  738. /*++
  739. Routine Description:
  740. This routine flushes any data sitting in the file stream that has not yet
  741. made it out to the operating system. This routine does not acquire the
  742. internal stream lock. This is only relevant for output streams.
  743. Arguments:
  744. Stream - Supplies a pointer to the open file stream to flush.
  745. Return Value:
  746. 0 on success.
  747. EOF on failure, and errno will be set to contain more information.
  748. --*/
  749. {
  750. ssize_t BytesWritten;
  751. off_t Offset;
  752. int PreviousError;
  753. ssize_t Result;
  754. if (Stream == NULL) {
  755. ClpFlushAllStreams(FALSE, NULL);
  756. return 0;
  757. }
  758. Result = 0;
  759. if (Stream->BufferMode == _IONBF) {
  760. return 0;
  761. }
  762. if (Stream->Descriptor == -1) {
  763. errno = EBADF;
  764. return EOF;
  765. }
  766. //
  767. // If the buffer is full of read data, try and back up the file pointer.
  768. // Ignore failures.
  769. //
  770. if ((Stream->Flags & FILE_FLAG_READ_LAST) != 0) {
  771. Offset = Stream->BufferValidSize - Stream->BufferNextIndex;
  772. if ((Stream->Flags & FILE_FLAG_UNGET_VALID) != 0) {
  773. Offset += 1;
  774. }
  775. PreviousError = errno;
  776. lseek(Stream->Descriptor, -Offset, SEEK_CUR);
  777. errno = PreviousError;
  778. //
  779. // The buffer is full of dirty data. Write it out.
  780. //
  781. } else {
  782. BytesWritten = 0;
  783. while (BytesWritten < Stream->BufferNextIndex) {
  784. do {
  785. Result = write(Stream->Descriptor,
  786. Stream->Buffer + BytesWritten,
  787. Stream->BufferNextIndex - BytesWritten);
  788. } while ((Result < 0) && (errno == EINTR));
  789. if (Result <= 0) {
  790. Stream->Flags |= FILE_FLAG_ERROR;
  791. return EOF;
  792. }
  793. BytesWritten += Result;
  794. }
  795. }
  796. Stream->BufferNextIndex = 0;
  797. Stream->BufferValidSize = 0;
  798. Stream->Flags &= ~FILE_FLAG_UNGET_VALID;
  799. return 0;
  800. }
  801. LIBC_API
  802. long
  803. ftell (
  804. FILE *Stream
  805. )
  806. /*++
  807. Routine Description:
  808. This routine returns the given stream's file position.
  809. Arguments:
  810. Stream - Supplies a pointer to the open file stream.
  811. Return Value:
  812. Returns the current file position on success.
  813. -1 on failure, and errno will be set to contain more information.
  814. --*/
  815. {
  816. off_t Result;
  817. Result = ftello(Stream);
  818. if ((long)Result != Result) {
  819. errno = ERANGE;
  820. return -1;
  821. }
  822. return (long)Result;
  823. }
  824. LIBC_API
  825. off_t
  826. ftello (
  827. FILE *Stream
  828. )
  829. /*++
  830. Routine Description:
  831. This routine returns the given stream's file position.
  832. Arguments:
  833. Stream - Supplies a pointer to the open file stream.
  834. Return Value:
  835. Returns the current file position on success.
  836. -1 on failure, and errno will be set to contain more information.
  837. --*/
  838. {
  839. off_t Result;
  840. //
  841. // One might ask why the lock needs to be held for what amounts to just a
  842. // single read. The answer is that the file position may be larger than
  843. // the native integer size of the machine, and so the read may not be
  844. // atomic. Without the lock, a torn read could result. This could be
  845. // optimized for 64-bit systems where those reads are atomic.
  846. //
  847. ClpLockStream(Stream);
  848. Result = ftello_unlocked(Stream);
  849. ClpUnlockStream(Stream);
  850. return Result;
  851. }
  852. LIBC_API
  853. off64_t
  854. ftello64 (
  855. FILE *Stream
  856. )
  857. /*++
  858. Routine Description:
  859. This routine returns the given stream's file position.
  860. Arguments:
  861. Stream - Supplies a pointer to the open file stream.
  862. Return Value:
  863. Returns the current file position on success.
  864. -1 on failure, and errno will be set to contain more information.
  865. --*/
  866. {
  867. return ftello(Stream);
  868. }
  869. LIBC_API
  870. off_t
  871. ftello_unlocked (
  872. FILE *Stream
  873. )
  874. /*++
  875. Routine Description:
  876. This routine returns the given stream's file position.
  877. Arguments:
  878. Stream - Supplies a pointer to the open file stream.
  879. Return Value:
  880. Returns the current file position on success.
  881. -1 on failure, and errno will be set to contain more information.
  882. --*/
  883. {
  884. off_t NewOffset;
  885. NewOffset = lseek(Stream->Descriptor, 0, SEEK_CUR);
  886. if (NewOffset == -1) {
  887. return -1;
  888. }
  889. if ((Stream->Flags & FILE_FLAG_READ_LAST) != 0) {
  890. NewOffset -= Stream->BufferValidSize - Stream->BufferNextIndex;
  891. if ((Stream->Flags & FILE_FLAG_UNGET_VALID) != 0) {
  892. NewOffset -= 1;
  893. }
  894. } else {
  895. NewOffset += Stream->BufferValidSize;
  896. }
  897. return NewOffset;
  898. }
  899. LIBC_API
  900. int
  901. fseek (
  902. FILE *Stream,
  903. long Offset,
  904. int Whence
  905. )
  906. /*++
  907. Routine Description:
  908. This routine sets the file position indicator for the given stream. If a
  909. read or write error occurs, the error indicator will be set for the stream
  910. and fseek fails. This routine will undo any effects of a previous call to
  911. unget.
  912. Arguments:
  913. Stream - Supplies a pointer to the open file stream.
  914. Offset - Supplies the offset from the reference point given in the Whence
  915. argument.
  916. Whence - Supplies the reference location to base the offset off of. Valid
  917. value are:
  918. SEEK_SET - The offset will be added to the the beginning of the file.
  919. SEEK_CUR - The offset will be added to the current file position.
  920. SEEK_END - The offset will be added to the end of the file.
  921. Return Value:
  922. 0 on success.
  923. -1 on failure, and errno will be set to contain more information.
  924. --*/
  925. {
  926. int Result;
  927. ClpLockStream(Stream);
  928. Result = fseeko_unlocked(Stream, Offset, Whence);
  929. ClpUnlockStream(Stream);
  930. return Result;
  931. }
  932. LIBC_API
  933. int
  934. fseeko (
  935. FILE *Stream,
  936. off_t Offset,
  937. int Whence
  938. )
  939. /*++
  940. Routine Description:
  941. This routine sets the file position indicator for the given stream. If a
  942. read or write error occurs, the error indicator will be set for the stream
  943. and fseek fails. This routine will undo any effects of a previous call to
  944. unget.
  945. Arguments:
  946. Stream - Supplies a pointer to the open file stream.
  947. Offset - Supplies the offset from the reference point given in the Whence
  948. argument.
  949. Whence - Supplies the reference location to base the offset off of. Valid
  950. value are:
  951. SEEK_SET - The offset will be added to the the beginning of the file.
  952. SEEK_CUR - The offset will be added to the current file position.
  953. SEEK_END - The offset will be added to the end of the file.
  954. Return Value:
  955. 0 on success.
  956. -1 on failure, and errno will be set to contain more information.
  957. --*/
  958. {
  959. int Result;
  960. ClpLockStream(Stream);
  961. Result = fseeko_unlocked(Stream, Offset, Whence);
  962. ClpUnlockStream(Stream);
  963. return Result;
  964. }
  965. LIBC_API
  966. int
  967. fseeko64 (
  968. FILE *Stream,
  969. off64_t Offset,
  970. int Whence
  971. )
  972. /*++
  973. Routine Description:
  974. This routine sets the file position indicator for the given stream. If a
  975. read or write error occurs, the error indicator will be set for the stream
  976. and fseek fails. This routine will undo any effects of a previous call to
  977. unget.
  978. Arguments:
  979. Stream - Supplies a pointer to the open file stream.
  980. Offset - Supplies the offset from the reference point given in the Whence
  981. argument.
  982. Whence - Supplies the reference location to base the offset off of. Valid
  983. value are:
  984. SEEK_SET - The offset will be added to the the beginning of the file.
  985. SEEK_CUR - The offset will be added to the current file position.
  986. SEEK_END - The offset will be added to the end of the file.
  987. Return Value:
  988. 0 on success.
  989. -1 on failure, and errno will be set to contain more information.
  990. --*/
  991. {
  992. return fseeko(Stream, Offset, Whence);
  993. }
  994. LIBC_API
  995. int
  996. fseeko_unlocked (
  997. FILE *Stream,
  998. off_t Offset,
  999. int Whence
  1000. )
  1001. /*++
  1002. Routine Description:
  1003. This routine sets the file position indicator for the given stream. If a
  1004. read or write error occurs, the error indicator will be set for the stream
  1005. and fseek fails. This routine does not acquire the internal stream lock.
  1006. Arguments:
  1007. Stream - Supplies a pointer to the open file stream.
  1008. Offset - Supplies the offset from the reference point given in the Whence
  1009. argument.
  1010. Whence - Supplies the reference location to base the offset off of. Valid
  1011. value are:
  1012. SEEK_SET - The offset will be added to the the beginning of the file.
  1013. SEEK_CUR - The offset will be added to the current file position.
  1014. SEEK_END - The offset will be added to the end of the file.
  1015. Return Value:
  1016. 0 on success.
  1017. -1 on failure, and errno will be set to contain more information.
  1018. --*/
  1019. {
  1020. //
  1021. // It would be great to save the system call (or several) if the seek is
  1022. // currently within the buffer, however apps (like m4 for example) rely on
  1023. // using fseek to determine whether a descriptor is seekable, so ultimately
  1024. // this function has to hit lseek somewhere.
  1025. //
  1026. fflush_unlocked(Stream);
  1027. Stream->BufferNextIndex = 0;
  1028. Stream->BufferValidSize = 0;
  1029. Stream->Flags &= ~(FILE_FLAG_END_OF_FILE | FILE_FLAG_ERROR);
  1030. if (lseek(Stream->Descriptor, Offset, Whence) != -1) {
  1031. return 0;
  1032. }
  1033. return -1;
  1034. }
  1035. LIBC_API
  1036. int
  1037. fgetpos (
  1038. FILE *Stream,
  1039. fpos_t *Position
  1040. )
  1041. /*++
  1042. Routine Description:
  1043. This routine returns an opaque structure representing the current absolute
  1044. position within the given stream.
  1045. Arguments:
  1046. Stream - Supplies a pointer to the open file stream.
  1047. Position - Supplies a pointer where the opaque position will be returned.
  1048. Callers must not presume that they can cast this type to an integer or
  1049. compare these types in any way, they only serve as possible inputs to
  1050. fsetpos to restore a file position to its current location.
  1051. Return Value:
  1052. 0 on success.
  1053. -1 on failure, and errno will contain more information.
  1054. --*/
  1055. {
  1056. off_t Offset;
  1057. int Result;
  1058. ClpLockStream(Stream);
  1059. Offset = ftello_unlocked(Stream);
  1060. if (Offset == -1) {
  1061. Result = -1;
  1062. goto getposEnd;
  1063. }
  1064. Position->Offset = Offset;
  1065. Position->ShiftState = Stream->ShiftState;
  1066. Result = 0;
  1067. getposEnd:
  1068. ClpUnlockStream(Stream);
  1069. return Result;
  1070. }
  1071. LIBC_API
  1072. int
  1073. fsetpos (
  1074. FILE *Stream,
  1075. const fpos_t *Position
  1076. )
  1077. /*++
  1078. Routine Description:
  1079. This routine sets the current file position.
  1080. Arguments:
  1081. Stream - Supplies a pointer to the open file stream.
  1082. Position - Supplies a pointer where the opaque position that was returned
  1083. by a previous call to fgetpos.
  1084. Return Value:
  1085. 0 on success.
  1086. -1 on failure, and errno will contain more information.
  1087. --*/
  1088. {
  1089. int Result;
  1090. ClpLockStream(Stream);
  1091. Result = fseeko_unlocked(Stream, Position->Offset, SEEK_SET);
  1092. if (Result != 0) {
  1093. goto setposEnd;
  1094. }
  1095. Stream->ShiftState = Position->ShiftState;
  1096. Result = 0;
  1097. setposEnd:
  1098. ClpUnlockStream(Stream);
  1099. return Result;
  1100. }
  1101. LIBC_API
  1102. void
  1103. rewind (
  1104. FILE *Stream
  1105. )
  1106. /*++
  1107. Routine Description:
  1108. This routine positions the file indicator back to the beginning. It shall
  1109. be equivalent to fseek(Stream, 0, SEEK_SET) except that it also clears
  1110. the error indicator.
  1111. Arguments:
  1112. Stream - Supplies a pointer to the open file stream.
  1113. Return Value:
  1114. None. Applications wishing to detect an error occurring during this
  1115. function should set errno 0, call the function, and then check errno.
  1116. --*/
  1117. {
  1118. fseek(Stream, 0, SEEK_SET);
  1119. clearerr(Stream);
  1120. return;
  1121. }
  1122. LIBC_API
  1123. int
  1124. fileno (
  1125. FILE *Stream
  1126. )
  1127. /*++
  1128. Routine Description:
  1129. This routine returns the integer file descriptor associated with the given
  1130. stream.
  1131. Arguments:
  1132. Stream - Supplies a pointer to the open file stream.
  1133. Return Value:
  1134. Returns the integer value of the file descriptor associated with the given
  1135. stream on success.
  1136. -1 on failure, and errno will contain more information.
  1137. --*/
  1138. {
  1139. if (Stream == NULL) {
  1140. errno = EBADF;
  1141. return -1;
  1142. }
  1143. return Stream->Descriptor;
  1144. }
  1145. LIBC_API
  1146. int
  1147. fgetc (
  1148. FILE *Stream
  1149. )
  1150. /*++
  1151. Routine Description:
  1152. This routine reads one byte from the given file stream.
  1153. Arguments:
  1154. Stream - Supplies a pointer to the open file stream.
  1155. Return Value:
  1156. Returns the byte on success.
  1157. EOF on failure or the end of the file, and errno will contain more
  1158. information.
  1159. --*/
  1160. {
  1161. int Result;
  1162. ClpLockStream(Stream);
  1163. Result = fgetc_unlocked(Stream);
  1164. ClpUnlockStream(Stream);
  1165. return Result;
  1166. }
  1167. LIBC_API
  1168. int
  1169. fgetc_unlocked (
  1170. FILE *Stream
  1171. )
  1172. /*++
  1173. Routine Description:
  1174. This routine reads one byte from the given file stream without acquiring
  1175. the internal stream lock.
  1176. Arguments:
  1177. Stream - Supplies a pointer to the open file stream.
  1178. Return Value:
  1179. Returns the byte on success.
  1180. EOF on failure or the end of the file, and errno will contain more
  1181. information.
  1182. --*/
  1183. {
  1184. unsigned char Byte;
  1185. ssize_t Result;
  1186. ORIENT_STREAM(Stream, FILE_FLAG_BYTE_ORIENTED);
  1187. Result = fread_unlocked(&Byte, 1, 1, Stream);
  1188. if (Result == 0) {
  1189. return EOF;
  1190. }
  1191. return Byte;
  1192. }
  1193. LIBC_API
  1194. int
  1195. getchar (
  1196. void
  1197. )
  1198. /*++
  1199. Routine Description:
  1200. This routine reads one byte from stdin.
  1201. Arguments:
  1202. None.
  1203. Return Value:
  1204. Returns the byte from stdin on success.
  1205. -1 on failure, and errno will contain more information.
  1206. --*/
  1207. {
  1208. return fgetc(stdin);
  1209. }
  1210. LIBC_API
  1211. int
  1212. getchar_unlocked (
  1213. void
  1214. )
  1215. /*++
  1216. Routine Description:
  1217. This routine reads one byte from stdin without acquiring the file lock.
  1218. Arguments:
  1219. None.
  1220. Return Value:
  1221. Returns the byte from stdin on success.
  1222. -1 on failure, and errno will contain more information.
  1223. --*/
  1224. {
  1225. return fgetc_unlocked(stdin);
  1226. }
  1227. LIBC_API
  1228. int
  1229. getc (
  1230. FILE *Stream
  1231. )
  1232. /*++
  1233. Routine Description:
  1234. This routine reads one byte from the given file stream. It is equivalent to
  1235. the fgetc function.
  1236. Arguments:
  1237. Stream - Supplies a pointer to the open file stream.
  1238. Return Value:
  1239. Returns the byte on success.
  1240. EOF on failure or the end of the file, and errno will contain more
  1241. information.
  1242. --*/
  1243. {
  1244. return fgetc(Stream);
  1245. }
  1246. LIBC_API
  1247. int
  1248. getc_unlocked (
  1249. FILE *Stream
  1250. )
  1251. /*++
  1252. Routine Description:
  1253. This routine reads one byte from the given file stream, without acquiring
  1254. the internal file lock. It is equivalent to the fgetc_unlocked function.
  1255. Arguments:
  1256. Stream - Supplies a pointer to the open file stream.
  1257. Return Value:
  1258. Returns the byte on success.
  1259. EOF on failure or the end of the file, and errno will contain more
  1260. information.
  1261. --*/
  1262. {
  1263. return fgetc_unlocked(Stream);
  1264. }
  1265. LIBC_API
  1266. char *
  1267. gets (
  1268. char *Line
  1269. )
  1270. /*++
  1271. Routine Description:
  1272. This routine gets a line of input from standard in, writing bytes to the
  1273. supplied line until a newline or end of file is reached. The newline (if
  1274. found) will be discarded and the string null terminated.
  1275. Use of this function is highly discouraged, as there is no bound on the
  1276. size of text the user can put on one line. Any use of this function is a
  1277. security hole. Use fgets instead.
  1278. Arguments:
  1279. Line - Supplies a pointer where the line will be returned on success.
  1280. Return Value:
  1281. Returns a pointer to the supplied line buffer on success.
  1282. NULL if EOF was encountered.
  1283. --*/
  1284. {
  1285. int Character;
  1286. int Index;
  1287. Character = EOF;
  1288. if (Line == NULL) {
  1289. return NULL;
  1290. }
  1291. //
  1292. // Loop reading in characters.
  1293. //
  1294. Index = 0;
  1295. while (TRUE) {
  1296. Character = fgetc(stdin);
  1297. if (Character == EOF) {
  1298. break;
  1299. }
  1300. if (Character == '\n') {
  1301. break;
  1302. }
  1303. Line[Index] = Character;
  1304. Index += 1;
  1305. }
  1306. Line[Index] = '\0';
  1307. if (Character == EOF) {
  1308. return NULL;
  1309. }
  1310. return Line;
  1311. }
  1312. LIBC_API
  1313. char *
  1314. fgets (
  1315. char *Buffer,
  1316. int BufferSize,
  1317. FILE *Stream
  1318. )
  1319. /*++
  1320. Routine Description:
  1321. This routine reads bytes from the given stream and places them in the
  1322. given buffer until the buffer fills up, a newline is read and transferred,
  1323. or the end of the file is reached. The string is then terminated with a
  1324. null byte.
  1325. Arguments:
  1326. Buffer - Supplies a pointer to the buffer where the read characters should
  1327. be returned.
  1328. BufferSize - Supplies the size of the supplied buffer in bytes.
  1329. Stream - Supplies a pointer to the file stream to read out of.
  1330. Return Value:
  1331. Returns the given buffer on success. If the stream is at end-of-file, the
  1332. end-of-file indicator shall be set and this routine returns NULL. If a
  1333. read error occurs, the error indicator for the stream shall be set, and
  1334. this routine returns NULL. The errno variable may also be set to contain
  1335. more information.
  1336. --*/
  1337. {
  1338. char *Result;
  1339. ClpLockStream(Stream);
  1340. Result = fgets_unlocked(Buffer, BufferSize, Stream);
  1341. ClpUnlockStream(Stream);
  1342. return Result;
  1343. }
  1344. LIBC_API
  1345. char *
  1346. fgets_unlocked (
  1347. char *Buffer,
  1348. int BufferSize,
  1349. FILE *Stream
  1350. )
  1351. /*++
  1352. Routine Description:
  1353. This routine reads bytes from the given stream and places them in the
  1354. given buffer until the buffer fills up, a newline is read and transferred,
  1355. or the end of the file is reached. The string is then terminated with a
  1356. null byte.
  1357. Arguments:
  1358. Buffer - Supplies a pointer to the buffer where the read characters should
  1359. be returned.
  1360. BufferSize - Supplies the size of the supplied buffer in bytes.
  1361. Stream - Supplies a pointer to the file stream to read out of.
  1362. Return Value:
  1363. Returns the given buffer on success. If the stream is at end-of-file, the
  1364. end-of-file indicator shall be set and this routine returns NULL. If a
  1365. read error occurs, the error indicator for the stream shall be set, and
  1366. this routine returns NULL. The errno variable may also be set to contain
  1367. more information.
  1368. --*/
  1369. {
  1370. int Character;
  1371. int Index;
  1372. Character = EOF;
  1373. if ((Buffer == NULL) || (BufferSize < 1)) {
  1374. return NULL;
  1375. }
  1376. //
  1377. // Loop reading in characters until the buffer is full.
  1378. //
  1379. Index = 0;
  1380. while (Index < BufferSize - 1) {
  1381. Character = fgetc_unlocked(Stream);
  1382. if (Character == EOF) {
  1383. break;
  1384. }
  1385. Buffer[Index] = Character;
  1386. Index += 1;
  1387. if (Character == '\n') {
  1388. break;
  1389. }
  1390. }
  1391. Buffer[Index] = '\0';
  1392. if (Index == 0) {
  1393. return NULL;
  1394. }
  1395. return Buffer;
  1396. }
  1397. LIBC_API
  1398. int
  1399. fputc (
  1400. int Character,
  1401. FILE *Stream
  1402. )
  1403. /*++
  1404. Routine Description:
  1405. This routine writes a byte to the given file stream.
  1406. Arguments:
  1407. Character - Supplies the character (converted to an unsigned char) to
  1408. write.
  1409. Stream - Supplies the stream to write the character to.
  1410. Return Value:
  1411. Returns the byte it has written on success.
  1412. EOF on failure, and errno will contain more information.
  1413. --*/
  1414. {
  1415. int Result;
  1416. ClpLockStream(Stream);
  1417. Result = fputc_unlocked(Character, Stream);
  1418. ClpUnlockStream(Stream);
  1419. return Result;
  1420. }
  1421. LIBC_API
  1422. int
  1423. fputc_unlocked (
  1424. int Character,
  1425. FILE *Stream
  1426. )
  1427. /*++
  1428. Routine Description:
  1429. This routine writes a byte to the given file stream without acquiring the
  1430. internal stream lock.
  1431. Arguments:
  1432. Character - Supplies the character (converted to an unsigned char) to
  1433. write.
  1434. Stream - Supplies the stream to write the character to.
  1435. Return Value:
  1436. Returns the byte it has written on success.
  1437. EOF on failure, and errno will contain more information.
  1438. --*/
  1439. {
  1440. unsigned char Byte;
  1441. int Result;
  1442. ORIENT_STREAM(Stream, FILE_FLAG_BYTE_ORIENTED);
  1443. Byte = (unsigned char)Character;
  1444. Result = fwrite_unlocked(&Byte, 1, 1, Stream);
  1445. if (Result > 0) {
  1446. return Byte;
  1447. }
  1448. return EOF;
  1449. }
  1450. LIBC_API
  1451. int
  1452. putc (
  1453. int Character,
  1454. FILE *Stream
  1455. )
  1456. /*++
  1457. Routine Description:
  1458. This routine writes a byte to the given file stream. It is equivalent to
  1459. the fputc function.
  1460. Arguments:
  1461. Character - Supplies the character (converted to an unsigned char) to
  1462. write.
  1463. Stream - Supplies the stream to write the character to.
  1464. Return Value:
  1465. Returns the byte it has written on success.
  1466. EOF on failure, and errno will contain more information.
  1467. --*/
  1468. {
  1469. return fputc(Character, Stream);
  1470. }
  1471. LIBC_API
  1472. int
  1473. putc_unlocked (
  1474. int Character,
  1475. FILE *Stream
  1476. )
  1477. /*++
  1478. Routine Description:
  1479. This routine writes a byte to the given file stream without acquiring the
  1480. stream lock. It is equivalent to the fputc_unlocked function.
  1481. Arguments:
  1482. Character - Supplies the character (converted to an unsigned char) to
  1483. write.
  1484. Stream - Supplies the stream to write the character to.
  1485. Return Value:
  1486. Returns the byte it has written on success.
  1487. EOF on failure, and errno will contain more information.
  1488. --*/
  1489. {
  1490. return fputc_unlocked(Character, Stream);
  1491. }
  1492. LIBC_API
  1493. int
  1494. putchar (
  1495. int Character
  1496. )
  1497. /*++
  1498. Routine Description:
  1499. This routine writes a byte to standard out. This routine is equivalent to
  1500. fputc(Character, stdout).
  1501. Arguments:
  1502. Character - Supplies the character (converted to an unsigned char) to
  1503. write.
  1504. Return Value:
  1505. Returns the byte it has written on success.
  1506. EOF on failure, and errno will contain more information.
  1507. --*/
  1508. {
  1509. return fputc(Character, stdout);
  1510. }
  1511. LIBC_API
  1512. int
  1513. putchar_unlocked (
  1514. int Character
  1515. )
  1516. /*++
  1517. Routine Description:
  1518. This routine writes a byte to standard out, without acquiring the stream
  1519. lock. This routine is equivalent to fputc_unlocked(Character, stdout).
  1520. Arguments:
  1521. Character - Supplies the character (converted to an unsigned char) to
  1522. write.
  1523. Return Value:
  1524. Returns the byte it has written on success.
  1525. EOF on failure, and errno will contain more information.
  1526. --*/
  1527. {
  1528. return fputc_unlocked(Character, stdout);
  1529. }
  1530. LIBC_API
  1531. int
  1532. puts (
  1533. const char *String
  1534. )
  1535. /*++
  1536. Routine Description:
  1537. This routine writes the given string to standard out. The null terminating
  1538. byte is not written.
  1539. Arguments:
  1540. String - Supplies a pointer to the null terminated string to write to.
  1541. Stream - Supplies the stream to write the character to.
  1542. Return Value:
  1543. Returns a non-negative number on success.
  1544. Returns EOF on failure, and the error indicator will be set for the stream.
  1545. The errno variable will also be set to provide more information.
  1546. --*/
  1547. {
  1548. int Result;
  1549. Result = fputs(String, stdout);
  1550. if (Result == EOF) {
  1551. return Result;
  1552. }
  1553. return fputc('\n', stdout);
  1554. }
  1555. LIBC_API
  1556. int
  1557. fputs (
  1558. const char *String,
  1559. FILE *Stream
  1560. )
  1561. /*++
  1562. Routine Description:
  1563. This routine writes the given string to the given file stream. The null
  1564. terminating byte is not written.
  1565. Arguments:
  1566. String - Supplies a pointer to the null terminated string to write to.
  1567. Stream - Supplies the stream to write the character to.
  1568. Return Value:
  1569. Returns a non-negative number on success.
  1570. Returns EOF on failure, and the error indicator will be set for the stream.
  1571. The errno variable will also be set to provide more information.
  1572. --*/
  1573. {
  1574. int Result;
  1575. ClpLockStream(Stream);
  1576. Result = fputs_unlocked(String, Stream);
  1577. ClpUnlockStream(Stream);
  1578. return Result;
  1579. }
  1580. LIBC_API
  1581. int
  1582. fputs_unlocked (
  1583. const char *String,
  1584. FILE *Stream
  1585. )
  1586. /*++
  1587. Routine Description:
  1588. This routine writes the given string to the given file stream. The null
  1589. terminating byte is not written. This routine does not acquire the stream
  1590. lock.
  1591. Arguments:
  1592. String - Supplies a pointer to the null terminated string to write to.
  1593. Stream - Supplies the stream to write the character to.
  1594. Return Value:
  1595. Returns a non-negative number on success.
  1596. Returns EOF on failure, and the error indicator will be set for the stream.
  1597. The errno variable will also be set to provide more information.
  1598. --*/
  1599. {
  1600. size_t Length;
  1601. int Result;
  1602. Result = 0;
  1603. if (String == NULL) {
  1604. return Result;
  1605. }
  1606. ORIENT_STREAM(Stream, FILE_FLAG_BYTE_ORIENTED);
  1607. Length = strlen(String);
  1608. Result = fwrite_unlocked(String, 1, Length, Stream);
  1609. if (Result == Length) {
  1610. return Result;
  1611. }
  1612. return EOF;
  1613. }
  1614. LIBC_API
  1615. int
  1616. ungetc (
  1617. int Character,
  1618. FILE *Stream
  1619. )
  1620. /*++
  1621. Routine Description:
  1622. This routine pushes the specified character back onto the input stream. The
  1623. pushed back character shall be returned by subsequent reads on that stream
  1624. in the reverse order of their pushing. A successful intervening call to
  1625. seek or flush will discard any pushed back bytes for the stream. One byte
  1626. of push back is provided.
  1627. Arguments:
  1628. Character - Supplies the character (converted to an unsigned char) to
  1629. push back.
  1630. Stream - Supplies the stream to push the character on to.
  1631. Return Value:
  1632. Returns the byte pushed back on success.
  1633. EOF on failure, and errno will contain more information.
  1634. --*/
  1635. {
  1636. int Result;
  1637. ClpLockStream(Stream);
  1638. Result = ungetc_unlocked(Character, Stream);
  1639. ClpUnlockStream(Stream);
  1640. return Result;
  1641. }
  1642. LIBC_API
  1643. int
  1644. ungetc_unlocked (
  1645. int Character,
  1646. FILE *Stream
  1647. )
  1648. /*++
  1649. Routine Description:
  1650. This routine pushes the specified character back onto the input stream. The
  1651. pushed back character shall be returned by subsequent reads on that stream
  1652. in the reverse order of their pushing. A successful intervening call to
  1653. seek or flush will discard any pushed back bytes for the stream. One byte
  1654. of push back is provided. This routine does not acquire the internal
  1655. stream lock.
  1656. Arguments:
  1657. Character - Supplies the character (converted to an unsigned char) to
  1658. push back.
  1659. Stream - Supplies the stream to push the character on to.
  1660. Return Value:
  1661. Returns the byte pushed back on success.
  1662. EOF on failure, and errno will contain more information.
  1663. --*/
  1664. {
  1665. unsigned char Byte;
  1666. if (Character == EOF) {
  1667. return EOF;
  1668. }
  1669. ORIENT_STREAM(Stream, FILE_FLAG_BYTE_ORIENTED);
  1670. Byte = (unsigned char)Character;
  1671. if ((Stream->Flags & FILE_FLAG_UNGET_VALID) == 0) {
  1672. Stream->Flags |= FILE_FLAG_UNGET_VALID;
  1673. Stream->Flags &= ~FILE_FLAG_END_OF_FILE;
  1674. Stream->UngetCharacter = Byte;
  1675. return Byte;
  1676. }
  1677. return EOF;
  1678. }
  1679. LIBC_API
  1680. int
  1681. setvbuf (
  1682. FILE *Stream,
  1683. char *Buffer,
  1684. int Mode,
  1685. size_t BufferSize
  1686. )
  1687. /*++
  1688. Routine Description:
  1689. This routine sets the buffering mode and buffer (optionally) for the given
  1690. file stream.
  1691. Arguments:
  1692. Stream - Supplies a pointer to the file stream whose buffering
  1693. characteristics should be altered.
  1694. Buffer - Supplies an optional pointer to the buffer to use for fully
  1695. buffered or line buffered mode. If either of those two modes are
  1696. supplied and this buffer is not supplied, one will be malloced.
  1697. Mode - Supplies the buffering mode to set for this file stream. Valid
  1698. value are:
  1699. _IONBF - Disable buffering on this file stream. All reads and writes
  1700. will go straight to the low level I/O interface.
  1701. _IOFBF - Fully buffered mode. The stream interface will batch reads
  1702. and writes to the low level I/O interface to optimize performance.
  1703. _IOLBF - Line buffered mode. This mode behaves the same as fully
  1704. buffered mode, except that the buffer is flushed automatically when
  1705. a newline character is written to the stream. For input buffers,
  1706. the behavior is no different from fully buffered mode.
  1707. BufferSize - Supplies the size of the supplied buffer in bytes.
  1708. Return Value:
  1709. 0 on success.
  1710. -1 on failure, and errno will contain more information.
  1711. --*/
  1712. {
  1713. int Result;
  1714. Result = -1;
  1715. ClpLockStream(Stream);
  1716. if ((Mode != _IOLBF) && (Mode != _IOFBF) && (Mode != _IONBF)) {
  1717. errno = EINVAL;
  1718. goto setvbufEnd;
  1719. }
  1720. //
  1721. // Flush the file for safety, even though generally users aren't supposed
  1722. // to call this after they've started doing I/O on the stream.
  1723. //
  1724. fflush_unlocked(Stream);
  1725. //
  1726. // Free the old buffer.
  1727. //
  1728. if (((Stream->Flags & FILE_FLAG_BUFFER_ALLOCATED) != 0) &&
  1729. (Stream->Buffer != NULL)) {
  1730. free(Stream->Buffer);
  1731. Stream->Flags &= ~FILE_FLAG_BUFFER_ALLOCATED;
  1732. }
  1733. Stream->Buffer = NULL;
  1734. //
  1735. // Un-buffered mode is easy, just leave the buffer NULLed out.
  1736. //
  1737. if (Mode == _IONBF) {
  1738. Stream->BufferSize = 0;
  1739. //
  1740. // For buffered mode, either use the buffer they provided or allocate
  1741. // one.
  1742. //
  1743. } else {
  1744. if ((Buffer == NULL) || (BufferSize == 0)) {
  1745. if (BufferSize == 0) {
  1746. BufferSize = BUFSIZ;
  1747. }
  1748. Buffer = malloc(BufferSize);
  1749. if (Buffer == NULL) {
  1750. errno = ENOMEM;
  1751. goto setvbufEnd;
  1752. }
  1753. Stream->Flags |= FILE_FLAG_BUFFER_ALLOCATED;
  1754. }
  1755. Stream->Buffer = Buffer;
  1756. Stream->BufferSize = BufferSize;
  1757. }
  1758. Stream->BufferMode = Mode;
  1759. Result = 0;
  1760. setvbufEnd:
  1761. ClpUnlockStream(Stream);
  1762. return Result;
  1763. }
  1764. LIBC_API
  1765. void
  1766. setbuf (
  1767. FILE *Stream,
  1768. char *Buffer
  1769. )
  1770. /*++
  1771. Routine Description:
  1772. This routine sets the internal buffer on a stream. If the given buffer is
  1773. not NULL, this routine shall be equivalent to:
  1774. setvbuf(Stream, Buffer, _IOFBF, BUFSIZ);
  1775. or,
  1776. setvbuf(Stream, Buffer, _IONBF, BUFSIZ);
  1777. if the given buffer is a NULL pointer.
  1778. Arguments:
  1779. Stream - Supplies a pointer to the file stream.
  1780. Buffer - Supplies the optional buffer to use.
  1781. Return Value:
  1782. None.
  1783. --*/
  1784. {
  1785. if (Buffer != NULL) {
  1786. setvbuf(Stream, Buffer, _IOFBF, BUFSIZ);
  1787. } else {
  1788. setvbuf(Stream, Buffer, _IONBF, BUFSIZ);
  1789. }
  1790. return;
  1791. }
  1792. LIBC_API
  1793. void
  1794. clearerr (
  1795. FILE *Stream
  1796. )
  1797. /*++
  1798. Routine Description:
  1799. This routine clears the error and end-of-file indicators for the given
  1800. stream.
  1801. Arguments:
  1802. Stream - Supplies a pointer to the file stream.
  1803. Return Value:
  1804. None.
  1805. --*/
  1806. {
  1807. ClpLockStream(Stream);
  1808. clearerr_unlocked(Stream);
  1809. ClpUnlockStream(Stream);
  1810. return;
  1811. }
  1812. LIBC_API
  1813. void
  1814. clearerr_unlocked (
  1815. FILE *Stream
  1816. )
  1817. /*++
  1818. Routine Description:
  1819. This routine clears the error and end-of-file indicators for the given
  1820. stream. This routine does not acquire the file lock.
  1821. Arguments:
  1822. Stream - Supplies a pointer to the file stream.
  1823. Return Value:
  1824. None.
  1825. --*/
  1826. {
  1827. Stream->Flags &= ~(FILE_FLAG_ERROR | FILE_FLAG_END_OF_FILE);
  1828. return;
  1829. }
  1830. LIBC_API
  1831. int
  1832. feof (
  1833. FILE *Stream
  1834. )
  1835. /*++
  1836. Routine Description:
  1837. This routine returns whether or not the current stream has attempted to
  1838. read beyond the end of the file.
  1839. Arguments:
  1840. Stream - Supplies a pointer to the file stream.
  1841. Return Value:
  1842. Returns non-zero if the end of file indicator is set for the given stream.
  1843. --*/
  1844. {
  1845. int Result;
  1846. ClpLockStream(Stream);
  1847. Result = feof_unlocked(Stream);
  1848. ClpUnlockStream(Stream);
  1849. return Result;
  1850. }
  1851. LIBC_API
  1852. int
  1853. feof_unlocked (
  1854. FILE *Stream
  1855. )
  1856. /*++
  1857. Routine Description:
  1858. This routine returns whether or not the current stream has attempted to
  1859. read beyond the end of the file, without acquiring the file lock.
  1860. Arguments:
  1861. Stream - Supplies a pointer to the file stream.
  1862. Return Value:
  1863. Returns non-zero if the end of file indicator is set for the given stream.
  1864. --*/
  1865. {
  1866. if ((Stream->Flags & FILE_FLAG_END_OF_FILE) != 0) {
  1867. return TRUE;
  1868. }
  1869. return FALSE;
  1870. }
  1871. LIBC_API
  1872. int
  1873. ferror (
  1874. FILE *Stream
  1875. )
  1876. /*++
  1877. Routine Description:
  1878. This routine returns whether or not the error indicator is set for the
  1879. current stream.
  1880. Arguments:
  1881. Stream - Supplies a pointer to the file stream.
  1882. Return Value:
  1883. Returns non-zero if the error indicator is set for the given stream.
  1884. --*/
  1885. {
  1886. int Result;
  1887. ClpLockStream(Stream);
  1888. Result = ferror_unlocked(Stream);
  1889. ClpUnlockStream(Stream);
  1890. return Result;
  1891. }
  1892. LIBC_API
  1893. int
  1894. ferror_unlocked (
  1895. FILE *Stream
  1896. )
  1897. /*++
  1898. Routine Description:
  1899. This routine returns whether or not the error indicator is set for the
  1900. current stream, without acquiring the file lock.
  1901. Arguments:
  1902. Stream - Supplies a pointer to the file stream.
  1903. Return Value:
  1904. Returns non-zero if the error indicator is set for the given stream.
  1905. --*/
  1906. {
  1907. if ((Stream->Flags & FILE_FLAG_ERROR) != 0) {
  1908. return TRUE;
  1909. }
  1910. return FALSE;
  1911. }
  1912. LIBC_API
  1913. void
  1914. flockfile (
  1915. FILE *Stream
  1916. )
  1917. /*++
  1918. Routine Description:
  1919. This routine explicitly locks a file stream. It can be used on the standard
  1920. I/O streams to group a batch of I/O together.
  1921. Arguments:
  1922. Stream - Supplies a pointer to the file stream.
  1923. Return Value:
  1924. None.
  1925. --*/
  1926. {
  1927. return ClpLockStream(Stream);
  1928. }
  1929. LIBC_API
  1930. int
  1931. ftrylockfile (
  1932. FILE *Stream
  1933. )
  1934. /*++
  1935. Routine Description:
  1936. This routine attempts to acquire the lock for a given stream.
  1937. Arguments:
  1938. Stream - Supplies a pointer to the file stream.
  1939. Return Value:
  1940. 0 if the lock was successfully acquired.
  1941. Non-zero if the file lock could not be acquired.
  1942. --*/
  1943. {
  1944. if (ClpTryToLockStream(Stream) != FALSE) {
  1945. return 0;
  1946. }
  1947. return -1;
  1948. }
  1949. LIBC_API
  1950. void
  1951. funlockfile (
  1952. FILE *Stream
  1953. )
  1954. /*++
  1955. Routine Description:
  1956. This routine explicitly unlocks a file stream that had been previously
  1957. locked with flockfile or ftrylockfile (on a successful attempt).
  1958. Arguments:
  1959. Stream - Supplies a pointer to the file stream.
  1960. Return Value:
  1961. None.
  1962. --*/
  1963. {
  1964. return ClpUnlockStream(Stream);
  1965. }
  1966. LIBC_API
  1967. int
  1968. printf (
  1969. const char *Format,
  1970. ...
  1971. )
  1972. /*++
  1973. Routine Description:
  1974. This routine prints a formatted string to the standard output file stream.
  1975. Arguments:
  1976. Format - Supplies the printf format string.
  1977. ... - Supplies a variable number of arguments, as required by the printf
  1978. format string argument.
  1979. Return Value:
  1980. Returns the number of bytes successfully converted, not including the null
  1981. terminator.
  1982. Returns a negative number if an error was encountered.
  1983. --*/
  1984. {
  1985. va_list Arguments;
  1986. int Result;
  1987. va_start(Arguments, Format);
  1988. Result = vfprintf(stdout, Format, Arguments);
  1989. va_end(Arguments);
  1990. return Result;
  1991. }
  1992. LIBC_API
  1993. int
  1994. fprintf (
  1995. FILE *Stream,
  1996. const char *Format,
  1997. ...
  1998. )
  1999. /*++
  2000. Routine Description:
  2001. This routine prints a formatted string to the given file stream.
  2002. Arguments:
  2003. Stream - Supplies the file stream to print to.
  2004. Format - Supplies the printf format string.
  2005. ... - Supplies a variable number of arguments, as required by the printf
  2006. format string argument.
  2007. Return Value:
  2008. Returns the number of bytes successfully converted, not including the null
  2009. terminator.
  2010. Returns a negative number if an error was encountered.
  2011. --*/
  2012. {
  2013. va_list Arguments;
  2014. int Result;
  2015. va_start(Arguments, Format);
  2016. Result = vfprintf(Stream, Format, Arguments);
  2017. va_end(Arguments);
  2018. return Result;
  2019. }
  2020. LIBC_API
  2021. int
  2022. fprintf_unlocked (
  2023. FILE *Stream,
  2024. const char *Format,
  2025. ...
  2026. )
  2027. /*++
  2028. Routine Description:
  2029. This routine prints a formatted string to the given file stream. This
  2030. routine does not acquire the stream lock.
  2031. Arguments:
  2032. Stream - Supplies the file stream to print to.
  2033. Format - Supplies the printf format string.
  2034. ... - Supplies a variable number of arguments, as required by the printf
  2035. format string argument.
  2036. Return Value:
  2037. Returns the number of bytes successfully converted, not including the null
  2038. terminator.
  2039. Returns a negative number if an error was encountered.
  2040. --*/
  2041. {
  2042. va_list Arguments;
  2043. int Result;
  2044. va_start(Arguments, Format);
  2045. Result = vfprintf_unlocked(Stream, Format, Arguments);
  2046. va_end(Arguments);
  2047. return Result;
  2048. }
  2049. LIBC_API
  2050. int
  2051. vfprintf (
  2052. FILE *File,
  2053. const char *Format,
  2054. va_list Arguments
  2055. )
  2056. /*++
  2057. Routine Description:
  2058. This routine prints a formatted string to the given file pointer.
  2059. Arguments:
  2060. File - Supplies a pointer to the file stream to output to.
  2061. Format - Supplies the printf format string.
  2062. Arguments - Supplies the argument list to the format string. The va_end
  2063. macro is not invoked on this list.
  2064. Return Value:
  2065. Returns the number of bytes successfully converted. A null terminator is
  2066. not written.
  2067. Returns a negative number if an error was encountered.
  2068. --*/
  2069. {
  2070. int Result;
  2071. ClpLockStream(File);
  2072. Result = vfprintf_unlocked(File, Format, Arguments);
  2073. ClpUnlockStream(File);
  2074. return Result;
  2075. }
  2076. LIBC_API
  2077. int
  2078. vfprintf_unlocked (
  2079. FILE *File,
  2080. const char *Format,
  2081. va_list Arguments
  2082. )
  2083. /*++
  2084. Routine Description:
  2085. This routine prints a formatted string to the given file pointer. This
  2086. routine does not acquire the stream lock.
  2087. Arguments:
  2088. File - Supplies a pointer to the file stream to output to.
  2089. Format - Supplies the printf format string.
  2090. Arguments - Supplies the argument list to the format string. The va_end
  2091. macro is not invoked on this list.
  2092. Return Value:
  2093. Returns the number of bytes successfully converted. A null terminator is
  2094. not written.
  2095. Returns a negative number if an error was encountered.
  2096. --*/
  2097. {
  2098. ULONG CharactersWritten;
  2099. PRINT_FORMAT_CONTEXT PrintContext;
  2100. STREAM_PRINT_CONTEXT StreamContext;
  2101. StreamContext.Stream = File;
  2102. StreamContext.BufferNextIndex = 0;
  2103. StreamContext.CharactersWritten = 0;
  2104. memset(&PrintContext, 0, sizeof(PRINT_FORMAT_CONTEXT));
  2105. PrintContext.Context = &StreamContext;
  2106. PrintContext.WriteCharacter = ClpFileFormatWriteCharacter;
  2107. RtlInitializeMultibyteState(&(PrintContext.State),
  2108. CharacterEncodingDefault);
  2109. RtlFormat(&PrintContext, (PSTR)Format, Arguments);
  2110. //
  2111. // Flush the remaining buffered bytes if necessary.
  2112. //
  2113. if (File->BufferMode == _IONBF) {
  2114. if (StreamContext.BufferNextIndex != 0) {
  2115. CharactersWritten = fwrite_unlocked(StreamContext.Buffer,
  2116. 1,
  2117. StreamContext.BufferNextIndex,
  2118. File);
  2119. if (CharactersWritten > 0) {
  2120. StreamContext.CharactersWritten += CharactersWritten;
  2121. }
  2122. }
  2123. CharactersWritten = StreamContext.CharactersWritten;
  2124. assert(CharactersWritten <= PrintContext.CharactersWritten);
  2125. } else {
  2126. CharactersWritten = PrintContext.CharactersWritten;
  2127. }
  2128. return CharactersWritten;
  2129. }
  2130. LIBC_API
  2131. int
  2132. vprintf (
  2133. const char *Format,
  2134. va_list Arguments
  2135. )
  2136. /*++
  2137. Routine Description:
  2138. This routine prints a formatted string to the standard output file stream.
  2139. Arguments:
  2140. Format - Supplies the printf format string.
  2141. Arguments - Supplies the argument list to the format string. The va_end
  2142. macro is not invoked on this list.
  2143. Return Value:
  2144. Returns the number of bytes successfully converted, not including the null
  2145. terminator.
  2146. Returns a negative number if an error was encountered.
  2147. --*/
  2148. {
  2149. return vfprintf(stdout, Format, Arguments);
  2150. }
  2151. BOOL
  2152. ClpInitializeFileIo (
  2153. VOID
  2154. )
  2155. /*++
  2156. Routine Description:
  2157. This routine initializes the file I/O subsystem of the C library.
  2158. Arguments:
  2159. None.
  2160. Return Value:
  2161. TRUE on success.
  2162. FALSE on failure.
  2163. --*/
  2164. {
  2165. pthread_mutexattr_t Attribute;
  2166. ULONG BufferMode;
  2167. BOOL Result;
  2168. Result = FALSE;
  2169. //
  2170. // Initialize the global stream list.
  2171. //
  2172. INITIALIZE_LIST_HEAD(&ClStreamList);
  2173. pthread_mutexattr_init(&Attribute);
  2174. pthread_mutexattr_settype(&Attribute, PTHREAD_MUTEX_RECURSIVE);
  2175. pthread_mutex_init(&ClStreamListLock, &Attribute);
  2176. pthread_mutexattr_destroy(&Attribute);
  2177. //
  2178. // Create file pointers for the three standard streams. Standard in and
  2179. // standard out are fully buffered only if they are not pointing at an
  2180. // interactive device.
  2181. //
  2182. BufferMode = _IOFBF;
  2183. if (isatty(STDIN_FILENO) != 0) {
  2184. BufferMode = _IOLBF;
  2185. }
  2186. stdin = ClpCreateFileStructure(STDIN_FILENO, O_RDONLY, BufferMode);
  2187. if (stdin == NULL) {
  2188. goto InitializeFileIoEnd;
  2189. }
  2190. stdin->Flags |= FILE_FLAG_STANDARD_IO;
  2191. BufferMode = _IOFBF;
  2192. if (isatty(STDOUT_FILENO) != 0) {
  2193. BufferMode = _IOLBF;
  2194. }
  2195. stdout = ClpCreateFileStructure(STDOUT_FILENO, O_WRONLY, BufferMode);
  2196. if (stdout == NULL) {
  2197. goto InitializeFileIoEnd;
  2198. }
  2199. stdout->Flags |= FILE_FLAG_STANDARD_IO;
  2200. //
  2201. // Standard error is never buffered. Default to unbuffered.
  2202. //
  2203. stderr = ClpCreateFileStructure(STDERR_FILENO, O_WRONLY, _IONBF);
  2204. if (stderr == NULL) {
  2205. goto InitializeFileIoEnd;
  2206. }
  2207. stderr->Flags |= FILE_FLAG_STANDARD_IO;
  2208. Result = TRUE;
  2209. InitializeFileIoEnd:
  2210. if (Result == FALSE) {
  2211. if (stdin != NULL) {
  2212. ClpDestroyFileStructure(stdin);
  2213. stdin = NULL;
  2214. }
  2215. if (stdout != NULL) {
  2216. ClpDestroyFileStructure(stdout);
  2217. stdout = NULL;
  2218. }
  2219. if (stderr != NULL) {
  2220. ClpDestroyFileStructure(stderr);
  2221. stderr = NULL;
  2222. }
  2223. }
  2224. return Result;
  2225. }
  2226. VOID
  2227. ClpLockStream (
  2228. FILE *Stream
  2229. )
  2230. /*++
  2231. Routine Description:
  2232. This routine locks the file stream.
  2233. Arguments:
  2234. Stream - Supplies a pointer to the stream to lock.
  2235. Return Value:
  2236. None.
  2237. --*/
  2238. {
  2239. int Status;
  2240. if ((Stream->Flags & FILE_FLAG_DISABLE_LOCKING) != 0) {
  2241. return;
  2242. }
  2243. Status = pthread_mutex_lock(&(Stream->Lock));
  2244. ASSERT(Status == 0);
  2245. return;
  2246. }
  2247. BOOL
  2248. ClpTryToLockStream (
  2249. FILE *Stream
  2250. )
  2251. /*++
  2252. Routine Description:
  2253. This routine makes a single attempt at locking the file stream. If locking
  2254. is disabled on the stream, this always returns TRUE.
  2255. Arguments:
  2256. Stream - Supplies a pointer to the stream to try to lock.
  2257. Return Value:
  2258. TRUE if the lock was successfully acquired.
  2259. FALSE if the lock was not successfully acquired.
  2260. --*/
  2261. {
  2262. int Status;
  2263. if ((Stream->Flags & FILE_FLAG_DISABLE_LOCKING) != 0) {
  2264. return TRUE;
  2265. }
  2266. Status = pthread_mutex_trylock(&(Stream->Lock));
  2267. if (Status == 0) {
  2268. return TRUE;
  2269. }
  2270. return FALSE;
  2271. }
  2272. VOID
  2273. ClpUnlockStream (
  2274. FILE *Stream
  2275. )
  2276. /*++
  2277. Routine Description:
  2278. This routine unlocks the file stream.
  2279. Arguments:
  2280. Stream - Supplies a pointer to the stream to unlock.
  2281. Return Value:
  2282. None.
  2283. --*/
  2284. {
  2285. if ((Stream->Flags & FILE_FLAG_DISABLE_LOCKING) != 0) {
  2286. return;
  2287. }
  2288. pthread_mutex_unlock(&(Stream->Lock));
  2289. return;
  2290. }
  2291. VOID
  2292. ClpFlushAllStreams (
  2293. BOOL AllUnlocked,
  2294. PFILE UnlockedStream
  2295. )
  2296. /*++
  2297. Routine Description:
  2298. This routine flushes every stream in the application.
  2299. Arguments:
  2300. AllUnlocked - Supplies a boolean that if TRUE flushes every stream without
  2301. acquiring the file lock. This is used during aborts.
  2302. UnlockedStream - Supplies a specific stream that when flushed should be
  2303. flushed unlocked.
  2304. Return Value:
  2305. None.
  2306. --*/
  2307. {
  2308. PLIST_ENTRY CurrentEntry;
  2309. PFILE Stream;
  2310. pthread_mutex_lock(&ClStreamListLock);
  2311. CurrentEntry = ClStreamList.Next;
  2312. while (CurrentEntry != &ClStreamList) {
  2313. Stream = LIST_VALUE(CurrentEntry, FILE, ListEntry);
  2314. CurrentEntry = CurrentEntry->Next;
  2315. //
  2316. // Flush any dirty streams.
  2317. //
  2318. if ((Stream->Flags & FILE_FLAG_READ_LAST) == 0) {
  2319. if ((AllUnlocked != FALSE) || (Stream == UnlockedStream)) {
  2320. fflush_unlocked(Stream);
  2321. } else {
  2322. fflush(Stream);
  2323. }
  2324. }
  2325. }
  2326. pthread_mutex_unlock(&ClStreamListLock);
  2327. return;
  2328. }
  2329. //
  2330. // --------------------------------------------------------- Internal Functions
  2331. //
  2332. PFILE
  2333. ClpCreateFileStructure (
  2334. ULONG Descriptor,
  2335. ULONG OpenFlags,
  2336. ULONG BufferMode
  2337. )
  2338. /*++
  2339. Routine Description:
  2340. This routine creates a file stream structure.
  2341. Arguments:
  2342. Descriptor - Supplies the underlying file descriptor number associated with
  2343. this stream.
  2344. OpenFlags - Supplies the flags the file was opened with.
  2345. BufferMode - Supplies the buffering mode for the file.
  2346. Return Value:
  2347. Returns a pointer to the created file on success.
  2348. NULL on allocation failure.
  2349. --*/
  2350. {
  2351. pthread_mutexattr_t Attribute;
  2352. FILE *File;
  2353. BOOL Result;
  2354. Result = FALSE;
  2355. File = malloc(sizeof(FILE));
  2356. if (File == NULL) {
  2357. goto CreateFileEnd;
  2358. }
  2359. RtlZeroMemory(File, sizeof(FILE));
  2360. File->Descriptor = Descriptor;
  2361. File->OpenFlags = OpenFlags;
  2362. pthread_mutexattr_init(&Attribute);
  2363. pthread_mutexattr_settype(&Attribute, PTHREAD_MUTEX_RECURSIVE);
  2364. pthread_mutex_init(&(File->Lock), &Attribute);
  2365. pthread_mutexattr_destroy(&Attribute);
  2366. File->BufferMode = BufferMode;
  2367. if ((OpenFlags & O_ACCMODE) != O_WRONLY) {
  2368. File->Flags |= FILE_FLAG_CAN_READ;
  2369. if ((OpenFlags & O_ACCMODE) == O_RDONLY) {
  2370. File->Flags |= FILE_FLAG_READ_LAST;
  2371. }
  2372. }
  2373. //
  2374. // If the stream is anything other than non-buffered, create a buffer for
  2375. // it.
  2376. //
  2377. if (File->BufferMode != _IONBF) {
  2378. File->Buffer = malloc(BUFSIZ);
  2379. if (File->Buffer == NULL) {
  2380. goto CreateFileEnd;
  2381. }
  2382. File->BufferSize = BUFSIZ;
  2383. File->Flags |= FILE_FLAG_BUFFER_ALLOCATED;
  2384. }
  2385. //
  2386. // Add the file to the global list, making it officially open for business.
  2387. //
  2388. pthread_mutex_lock(&ClStreamListLock);
  2389. INSERT_AFTER(&(File->ListEntry), &ClStreamList);
  2390. pthread_mutex_unlock(&ClStreamListLock);
  2391. Result = TRUE;
  2392. CreateFileEnd:
  2393. if (Result == FALSE) {
  2394. if (File != NULL) {
  2395. if (File->Buffer != NULL) {
  2396. free(File->Buffer);
  2397. }
  2398. free(File);
  2399. File = NULL;
  2400. }
  2401. }
  2402. return File;
  2403. }
  2404. VOID
  2405. ClpDestroyFileStructure (
  2406. PFILE File
  2407. )
  2408. /*++
  2409. Routine Description:
  2410. This routine destroys a file stream structure.
  2411. Arguments:
  2412. File - Supplies a pointer to the file stream structure to destroy.
  2413. Return Value:
  2414. None.
  2415. --*/
  2416. {
  2417. if (File != NULL) {
  2418. if (File->ListEntry.Next != NULL) {
  2419. pthread_mutex_lock(&ClStreamListLock);
  2420. LIST_REMOVE(&(File->ListEntry));
  2421. pthread_mutex_unlock(&ClStreamListLock);
  2422. }
  2423. File->ListEntry.Next = NULL;
  2424. if (((File->Flags & FILE_FLAG_BUFFER_ALLOCATED) != 0) &&
  2425. (File->Buffer != NULL)) {
  2426. free(File->Buffer);
  2427. }
  2428. pthread_mutex_destroy(&(File->Lock));
  2429. free(File);
  2430. }
  2431. return;
  2432. }
  2433. BOOL
  2434. ClpFileFormatWriteCharacter (
  2435. INT Character,
  2436. PPRINT_FORMAT_CONTEXT Context
  2437. )
  2438. /*++
  2439. Routine Description:
  2440. This routine writes a character to the output during a printf-style
  2441. formatting operation.
  2442. Arguments:
  2443. Character - Supplies the character to be written.
  2444. Context - Supplies a pointer to the printf-context.
  2445. Return Value:
  2446. TRUE on success.
  2447. FALSE on failure.
  2448. --*/
  2449. {
  2450. ULONG CharactersWritten;
  2451. PSTREAM_PRINT_CONTEXT StreamContext;
  2452. StreamContext = Context->Context;
  2453. //
  2454. // If the stream is buffered in any way, then pass the character on to the
  2455. // stream.
  2456. //
  2457. if (StreamContext->Stream->BufferMode != _IONBF) {
  2458. if (fputc_unlocked(Character, StreamContext->Stream) == -1) {
  2459. return FALSE;
  2460. }
  2461. //
  2462. // If the stream is unbuffered, then locally buffer some characters
  2463. // together before flushing. This reduces the number of system calls
  2464. // required for fprintf on unbuffered streams.
  2465. //
  2466. } else {
  2467. StreamContext->Buffer[StreamContext->BufferNextIndex] = Character;
  2468. StreamContext->BufferNextIndex += 1;
  2469. //
  2470. // If the local buffer is full, then write to the stream. This will
  2471. // flush the data immediately.
  2472. //
  2473. if (StreamContext->BufferNextIndex == STREAM_PRINT_BUFFER_SIZE) {
  2474. StreamContext->BufferNextIndex = 0;
  2475. CharactersWritten = fwrite_unlocked(StreamContext->Buffer,
  2476. 1,
  2477. STREAM_PRINT_BUFFER_SIZE,
  2478. StreamContext->Stream);
  2479. if (CharactersWritten < 0) {
  2480. return FALSE;
  2481. }
  2482. StreamContext->CharactersWritten += CharactersWritten;
  2483. if (CharactersWritten != STREAM_PRINT_BUFFER_SIZE) {
  2484. return FALSE;
  2485. }
  2486. }
  2487. }
  2488. return TRUE;
  2489. }
  2490. INT
  2491. ClpConvertStreamModeStringToOpenFlags (
  2492. PSTR ModeString,
  2493. INT *OpenFlags
  2494. )
  2495. /*++
  2496. Routine Description:
  2497. This routine converts a mode string supplied with a stream open command to
  2498. a set of open flags.
  2499. Arguments:
  2500. ModeString - Supplies a pointer to the mode string.
  2501. OpenFlags - Supplies a pointer where the open flags will be returned.
  2502. Return Value:
  2503. 0 on success.
  2504. Returns an error number on failure.
  2505. --*/
  2506. {
  2507. INT Flags;
  2508. Flags = 0;
  2509. *OpenFlags = 0;
  2510. //
  2511. // Get the open flags.
  2512. //
  2513. while (*ModeString != '\0') {
  2514. switch (*ModeString) {
  2515. case 'r':
  2516. Flags |= O_RDONLY;
  2517. break;
  2518. case 'w':
  2519. Flags |= O_WRONLY | O_CREAT | O_TRUNC;
  2520. break;
  2521. case 'a':
  2522. Flags |= O_WRONLY | O_CREAT | O_APPEND;
  2523. break;
  2524. case '+':
  2525. Flags &= ~O_ACCMODE;
  2526. Flags |= O_RDWR;
  2527. break;
  2528. case 'b':
  2529. case 't':
  2530. break;
  2531. //
  2532. // TODO: Open the file with O_CLOEXEC.
  2533. //
  2534. case 'e':
  2535. break;
  2536. case 'x':
  2537. Flags |= O_EXCL;
  2538. break;
  2539. default:
  2540. return EINVAL;
  2541. }
  2542. ModeString += 1;
  2543. }
  2544. *OpenFlags = Flags;
  2545. return 0;
  2546. }