nsprpub/tools/tail.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "prio.h"
michael@0 7 #include "prprf.h"
michael@0 8 #include "prinit.h"
michael@0 9 #include "prthread.h"
michael@0 10 #include "prinrval.h"
michael@0 11
michael@0 12 #include "plerror.h"
michael@0 13 #include "plgetopt.h"
michael@0 14
michael@0 15 #include <stdlib.h>
michael@0 16
michael@0 17 #define BUFFER_SIZE 500
michael@0 18
michael@0 19 static PRFileDesc *out = NULL, *err = NULL;
michael@0 20
michael@0 21 static void Help(void)
michael@0 22 {
michael@0 23 PR_fprintf(err, "Usage: tail [-n <n>] [-f] [-h] <filename>\n");
michael@0 24 PR_fprintf(err, "\t-t <n> Dally time in milliseconds\n");
michael@0 25 PR_fprintf(err, "\t-n <n> Number of bytes before <eof>\n");
michael@0 26 PR_fprintf(err, "\t-f Follow the <eof>\n");
michael@0 27 PR_fprintf(err, "\t-h This message and nothing else\n");
michael@0 28 } /* Help */
michael@0 29
michael@0 30 PRIntn main(PRIntn argc, char **argv)
michael@0 31 {
michael@0 32 PRIntn rv = 0;
michael@0 33 PLOptStatus os;
michael@0 34 PRStatus status;
michael@0 35 PRFileDesc *file;
michael@0 36 PRFileInfo fileInfo;
michael@0 37 PRIntervalTime dally;
michael@0 38 char buffer[BUFFER_SIZE];
michael@0 39 PRBool follow = PR_FALSE;
michael@0 40 const char *filename = NULL;
michael@0 41 PRUint32 position = 0, seek = 0, time = 0;
michael@0 42 PLOptState *opt = PL_CreateOptState(argc, argv, "hfn:");
michael@0 43
michael@0 44 out = PR_GetSpecialFD(PR_StandardOutput);
michael@0 45 err = PR_GetSpecialFD(PR_StandardError);
michael@0 46
michael@0 47 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
michael@0 48 {
michael@0 49 if (PL_OPT_BAD == os) continue;
michael@0 50 switch (opt->option)
michael@0 51 {
michael@0 52 case 0: /* it's the filename */
michael@0 53 filename = opt->value;
michael@0 54 break;
michael@0 55 case 'n': /* bytes before end of file */
michael@0 56 seek = atoi(opt->value);
michael@0 57 break;
michael@0 58 case 't': /* dally time */
michael@0 59 time = atoi(opt->value);
michael@0 60 break;
michael@0 61 case 'f': /* follow the end of file */
michael@0 62 follow = PR_TRUE;
michael@0 63 break;
michael@0 64 case 'h': /* user wants some guidance */
michael@0 65 Help(); /* so give him an earful */
michael@0 66 return 2; /* but not a lot else */
michael@0 67 break;
michael@0 68 default:
michael@0 69 break;
michael@0 70 }
michael@0 71 }
michael@0 72 PL_DestroyOptState(opt);
michael@0 73
michael@0 74 if (0 == time) time = 1000;
michael@0 75 dally = PR_MillisecondsToInterval(time);
michael@0 76
michael@0 77 if (NULL == filename)
michael@0 78 {
michael@0 79 (void)PR_fprintf(out, "Input file not specified\n");
michael@0 80 rv = 1; goto done;
michael@0 81 }
michael@0 82 file = PR_Open(filename, PR_RDONLY, 0);
michael@0 83 if (NULL == file)
michael@0 84 {
michael@0 85 PL_FPrintError(err, "File cannot be opened for reading");
michael@0 86 return 1;
michael@0 87 }
michael@0 88
michael@0 89 status = PR_GetOpenFileInfo(file, &fileInfo);
michael@0 90 if (PR_FAILURE == status)
michael@0 91 {
michael@0 92 PL_FPrintError(err, "Cannot acquire status of file");
michael@0 93 rv = 1; goto done;
michael@0 94 }
michael@0 95 if (seek > 0)
michael@0 96 {
michael@0 97 if (seek > fileInfo.size) seek = 0;
michael@0 98 position = PR_Seek(file, (fileInfo.size - seek), PR_SEEK_SET);
michael@0 99 if (-1 == (PRInt32)position)
michael@0 100 PL_FPrintError(err, "Cannot seek to starting position");
michael@0 101 }
michael@0 102
michael@0 103 do
michael@0 104 {
michael@0 105 while (position < fileInfo.size)
michael@0 106 {
michael@0 107 PRInt32 read, bytes = fileInfo.size - position;
michael@0 108 if (bytes > sizeof(buffer)) bytes = sizeof(buffer);
michael@0 109 read = PR_Read(file, buffer, bytes);
michael@0 110 if (read != bytes)
michael@0 111 PL_FPrintError(err, "Cannot read to eof");
michael@0 112 position += read;
michael@0 113 PR_Write(out, buffer, read);
michael@0 114 }
michael@0 115
michael@0 116 if (follow)
michael@0 117 {
michael@0 118 PR_Sleep(dally);
michael@0 119 status = PR_GetOpenFileInfo(file, &fileInfo);
michael@0 120 if (PR_FAILURE == status)
michael@0 121 {
michael@0 122 PL_FPrintError(err, "Cannot acquire status of file");
michael@0 123 rv = 1; goto done;
michael@0 124 }
michael@0 125 }
michael@0 126 } while (follow);
michael@0 127
michael@0 128 done:
michael@0 129 PR_Close(file);
michael@0 130
michael@0 131 return rv;
michael@0 132 } /* main */
michael@0 133
michael@0 134 /* tail.c */

mercurial