Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
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 "prmem.h" |
michael@0 | 8 | #include "prprf.h" |
michael@0 | 9 | #include "prinit.h" |
michael@0 | 10 | #include "prerror.h" |
michael@0 | 11 | #include "prthread.h" |
michael@0 | 12 | |
michael@0 | 13 | #include "plerror.h" |
michael@0 | 14 | #include "plgetopt.h" |
michael@0 | 15 | |
michael@0 | 16 | #define DEFAULT_COUNT 10 |
michael@0 | 17 | #define DEFAULT_FILESIZE 1 |
michael@0 | 18 | #define BUFFER_SIZE 1000000 |
michael@0 | 19 | |
michael@0 | 20 | typedef enum {v_silent, v_whisper, v_shout} Verbosity; |
michael@0 | 21 | static void Verbose(Verbosity, const char*, const char*, PRIntn); |
michael@0 | 22 | |
michael@0 | 23 | #define VERBOSE(_l, _m) Verbose(_l, _m, __FILE__, __LINE__) |
michael@0 | 24 | |
michael@0 | 25 | static PRIntn test_result = 2; |
michael@0 | 26 | static PRFileDesc *output = NULL; |
michael@0 | 27 | static PRIntn verbose = v_silent; |
michael@0 | 28 | static PRIntn filesize = DEFAULT_FILESIZE; |
michael@0 | 29 | |
michael@0 | 30 | static PRIntn Usage(void) |
michael@0 | 31 | { |
michael@0 | 32 | PR_fprintf(output, "Bigfile test usage:\n"); |
michael@0 | 33 | PR_fprintf(output, ">bigfile [-G] [-d] [-v[*v]] [-s <n>] <filename>\n"); |
michael@0 | 34 | PR_fprintf(output, "\td\tdebug mode (equivalent to -vvv)\t(false)\n"); |
michael@0 | 35 | PR_fprintf(output, "\tv\tAdditional levels of output\t(none)\n"); |
michael@0 | 36 | PR_fprintf(output, "\tk\tKeep data file after exit\t(false)\n"); |
michael@0 | 37 | PR_fprintf(output, "\ts <n>\tFile size in megabytes\t\t(1 megabyte)\n"); |
michael@0 | 38 | PR_fprintf(output, "\t<filename>\tName of test file\t(none)\n"); |
michael@0 | 39 | return 2; /* nothing happened */ |
michael@0 | 40 | } /* Usage */ |
michael@0 | 41 | |
michael@0 | 42 | static PRStatus DeleteIfFound(const char *filename) |
michael@0 | 43 | { |
michael@0 | 44 | PRStatus rv; |
michael@0 | 45 | VERBOSE(v_shout, "Checking for existing file"); |
michael@0 | 46 | rv = PR_Access(filename, PR_ACCESS_WRITE_OK); |
michael@0 | 47 | if (PR_SUCCESS == rv) |
michael@0 | 48 | { |
michael@0 | 49 | VERBOSE(v_shout, "Deleting existing file"); |
michael@0 | 50 | rv = PR_Delete(filename); |
michael@0 | 51 | if (PR_FAILURE == rv) VERBOSE(v_shout, "Cannot delete big file"); |
michael@0 | 52 | } |
michael@0 | 53 | else if (PR_FILE_NOT_FOUND_ERROR != PR_GetError()) |
michael@0 | 54 | VERBOSE(v_shout, "Cannot access big file"); |
michael@0 | 55 | else rv = PR_SUCCESS; |
michael@0 | 56 | return rv; |
michael@0 | 57 | } /* DeleteIfFound */ |
michael@0 | 58 | |
michael@0 | 59 | static PRIntn Error(const char *msg, const char *filename) |
michael@0 | 60 | { |
michael@0 | 61 | PRInt32 error = PR_GetError(); |
michael@0 | 62 | if (NULL != msg) |
michael@0 | 63 | { |
michael@0 | 64 | if (0 == error) PR_fprintf(output, msg); |
michael@0 | 65 | else PL_FPrintError(output, msg); |
michael@0 | 66 | } |
michael@0 | 67 | (void)DeleteIfFound(filename); |
michael@0 | 68 | if (v_shout == verbose) PR_Abort(); |
michael@0 | 69 | return 1; |
michael@0 | 70 | } /* Error */ |
michael@0 | 71 | |
michael@0 | 72 | static void Verbose( |
michael@0 | 73 | Verbosity level, const char *msg, const char *file, PRIntn line) |
michael@0 | 74 | { |
michael@0 | 75 | if (level <= verbose) |
michael@0 | 76 | PR_fprintf(output, "[%s : %d]: %s\n", file, line, msg); |
michael@0 | 77 | } /* Verbose */ |
michael@0 | 78 | |
michael@0 | 79 | static void PrintInfo(PRFileInfo64 *info, const char *filename) |
michael@0 | 80 | { |
michael@0 | 81 | PRExplodedTime tm; |
michael@0 | 82 | char ctime[40], mtime[40]; |
michael@0 | 83 | static const char *types[] = {"FILE", "DIRECTORY", "OTHER"}; |
michael@0 | 84 | PR_fprintf( |
michael@0 | 85 | output, "[%s : %d]: File info for %s\n", |
michael@0 | 86 | __FILE__, __LINE__, filename); |
michael@0 | 87 | PR_fprintf( |
michael@0 | 88 | output, " type: %s, size: %llu bytes,\n", |
michael@0 | 89 | types[info->type - 1], info->size); |
michael@0 | 90 | |
michael@0 | 91 | PR_ExplodeTime(info->creationTime, PR_GMTParameters, &tm); |
michael@0 | 92 | (void)PR_FormatTime(ctime, sizeof(ctime), "%c GMT", &tm); |
michael@0 | 93 | PR_ExplodeTime(info->modifyTime, PR_GMTParameters, &tm); |
michael@0 | 94 | (void)PR_FormatTime(mtime, sizeof(mtime), "%c GMT", &tm); |
michael@0 | 95 | |
michael@0 | 96 | PR_fprintf( |
michael@0 | 97 | output, " creation: %s,\n modify: %s\n", ctime, mtime); |
michael@0 | 98 | } /* PrintInfo */ |
michael@0 | 99 | |
michael@0 | 100 | int main(int argc, char **argv) |
michael@0 | 101 | { |
michael@0 | 102 | PRStatus rv; |
michael@0 | 103 | char *buffer; |
michael@0 | 104 | PLOptStatus os; |
michael@0 | 105 | PRInt32 loop, bytes; |
michael@0 | 106 | PRFileInfo small_info; |
michael@0 | 107 | PRFileInfo64 big_info; |
michael@0 | 108 | PRBool keep = PR_FALSE; |
michael@0 | 109 | PRFileDesc *file = NULL; |
michael@0 | 110 | const char *filename = NULL; |
michael@0 | 111 | PRIntn count = DEFAULT_COUNT; |
michael@0 | 112 | PRInt64 filesize64, big_answer, big_size, one_meg, zero_meg, big_fragment; |
michael@0 | 113 | PRInt64 sevenFox = LL_INIT(0,0x7fffffff); |
michael@0 | 114 | |
michael@0 | 115 | PLOptState *opt = PL_CreateOptState(argc, argv, "dtvhs:"); |
michael@0 | 116 | |
michael@0 | 117 | output = PR_GetSpecialFD(PR_StandardError); |
michael@0 | 118 | PR_STDIO_INIT(); |
michael@0 | 119 | |
michael@0 | 120 | while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) |
michael@0 | 121 | { |
michael@0 | 122 | if (PL_OPT_BAD == os) continue; |
michael@0 | 123 | switch (opt->option) |
michael@0 | 124 | { |
michael@0 | 125 | case 0: |
michael@0 | 126 | filename = opt->value; |
michael@0 | 127 | break; |
michael@0 | 128 | case 'd': /* debug mode */ |
michael@0 | 129 | verbose = v_shout; |
michael@0 | 130 | break; |
michael@0 | 131 | case 'k': /* keep file */ |
michael@0 | 132 | keep = PR_TRUE; |
michael@0 | 133 | break; |
michael@0 | 134 | case 'v': /* verbosity */ |
michael@0 | 135 | if (v_shout > verbose) verbose += 1; |
michael@0 | 136 | break; |
michael@0 | 137 | case 'c': /* loop counter */ |
michael@0 | 138 | count = atoi(opt->value); |
michael@0 | 139 | break; |
michael@0 | 140 | case 's': /* filesize */ |
michael@0 | 141 | filesize = atoi(opt->value); |
michael@0 | 142 | break; |
michael@0 | 143 | case 'h': /* confused */ |
michael@0 | 144 | default: |
michael@0 | 145 | return Usage(); |
michael@0 | 146 | } |
michael@0 | 147 | } |
michael@0 | 148 | PL_DestroyOptState(opt); |
michael@0 | 149 | |
michael@0 | 150 | if (0 == count) count = DEFAULT_COUNT; |
michael@0 | 151 | if (0 == filesize) filesize = DEFAULT_FILESIZE; |
michael@0 | 152 | if (NULL == filename) |
michael@0 | 153 | { |
michael@0 | 154 | #ifdef SYMBIAN |
michael@0 | 155 | #define FILE_NAME "c:\\data\\bigfile.dat" |
michael@0 | 156 | #else |
michael@0 | 157 | #define FILE_NAME "bigfile.dat" |
michael@0 | 158 | #endif |
michael@0 | 159 | if (DEFAULT_FILESIZE != filesize) return Usage(); |
michael@0 | 160 | else filename = FILE_NAME; |
michael@0 | 161 | } |
michael@0 | 162 | |
michael@0 | 163 | if (PR_FAILURE == DeleteIfFound(filename)) return 1; |
michael@0 | 164 | |
michael@0 | 165 | test_result = 0; |
michael@0 | 166 | |
michael@0 | 167 | LL_I2L(zero_meg, 0); |
michael@0 | 168 | LL_I2L(one_meg, 1000000); |
michael@0 | 169 | LL_I2L(filesize64, filesize); |
michael@0 | 170 | buffer = (char*)PR_MALLOC(BUFFER_SIZE); |
michael@0 | 171 | LL_I2L(big_fragment, BUFFER_SIZE); |
michael@0 | 172 | LL_MUL(filesize64, filesize64, one_meg); |
michael@0 | 173 | |
michael@0 | 174 | for (loop = 0; loop < BUFFER_SIZE; ++loop) buffer[loop] = (char)loop; |
michael@0 | 175 | |
michael@0 | 176 | VERBOSE(v_whisper, "Creating big file"); |
michael@0 | 177 | file = PR_Open(filename, PR_CREATE_FILE | PR_WRONLY, 0666); |
michael@0 | 178 | if (NULL == file) return Error("PR_Open()", filename); |
michael@0 | 179 | |
michael@0 | 180 | VERBOSE(v_whisper, "Testing available space in empty file"); |
michael@0 | 181 | big_answer = file->methods->available64(file); |
michael@0 | 182 | if (!LL_IS_ZERO(big_answer)) return Error("empty available64()", filename); |
michael@0 | 183 | |
michael@0 | 184 | LL_SUB(big_size, filesize64, one_meg); |
michael@0 | 185 | VERBOSE(v_whisper, "Creating sparse big file by seeking to end"); |
michael@0 | 186 | big_answer = file->methods->seek64(file, big_size, PR_SEEK_SET); |
michael@0 | 187 | if (!LL_EQ(big_answer, big_size)) return Error("seek", filename); |
michael@0 | 188 | |
michael@0 | 189 | VERBOSE(v_whisper, "Writing block at end of sparse file"); |
michael@0 | 190 | bytes = file->methods->write(file, buffer, BUFFER_SIZE); |
michael@0 | 191 | if (bytes != BUFFER_SIZE) return Error("write", filename); |
michael@0 | 192 | |
michael@0 | 193 | VERBOSE(v_whisper, "Testing available space at end of sparse file"); |
michael@0 | 194 | big_answer = file->methods->available64(file); |
michael@0 | 195 | if (!LL_IS_ZERO(big_answer)) return Error("eof available64()", filename); |
michael@0 | 196 | |
michael@0 | 197 | VERBOSE(v_whisper, "Getting big info on sparse big file"); |
michael@0 | 198 | rv = file->methods->fileInfo64(file, &big_info); |
michael@0 | 199 | if (PR_FAILURE == rv) return Error("fileInfo64()", filename); |
michael@0 | 200 | if (v_shout <= verbose) PrintInfo(&big_info, filename); |
michael@0 | 201 | |
michael@0 | 202 | VERBOSE(v_whisper, "Getting small info on sparse big file"); |
michael@0 | 203 | rv = file->methods->fileInfo(file, &small_info); |
michael@0 | 204 | if (LL_CMP(sevenFox, <, filesize64) && (PR_SUCCESS == rv)) |
michael@0 | 205 | { |
michael@0 | 206 | VERBOSE(v_whisper, "Should have failed and didn't"); |
michael@0 | 207 | return Error("fileInfo()", filename); |
michael@0 | 208 | } |
michael@0 | 209 | else if (LL_CMP(sevenFox, >, filesize64) && (PR_FAILURE == rv)) |
michael@0 | 210 | { |
michael@0 | 211 | VERBOSE(v_whisper, "Should have succeeded and didn't"); |
michael@0 | 212 | return Error("fileInfo()", filename); |
michael@0 | 213 | } |
michael@0 | 214 | |
michael@0 | 215 | VERBOSE(v_whisper, "Rewinding big file"); |
michael@0 | 216 | big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_SET); |
michael@0 | 217 | if (!LL_IS_ZERO(big_answer)) return Error("rewind seek64()", filename); |
michael@0 | 218 | |
michael@0 | 219 | VERBOSE(v_whisper, "Establishing available space in rewound file"); |
michael@0 | 220 | big_answer = file->methods->available64(file); |
michael@0 | 221 | if (LL_NE(filesize64, big_answer)) |
michael@0 | 222 | return Error("bof available64()", filename); |
michael@0 | 223 | |
michael@0 | 224 | VERBOSE(v_whisper, "Closing big file"); |
michael@0 | 225 | rv = file->methods->close(file); |
michael@0 | 226 | if (PR_FAILURE == rv) return Error("close()", filename); |
michael@0 | 227 | |
michael@0 | 228 | VERBOSE(v_whisper, "Reopening big file"); |
michael@0 | 229 | file = PR_Open(filename, PR_RDWR, 0666); |
michael@0 | 230 | if (NULL == file) return Error("open failed", filename); |
michael@0 | 231 | |
michael@0 | 232 | VERBOSE(v_whisper, "Checking available data in reopened file"); |
michael@0 | 233 | big_answer = file->methods->available64(file); |
michael@0 | 234 | if (LL_NE(filesize64, big_answer)) |
michael@0 | 235 | return Error("reopened available64()", filename); |
michael@0 | 236 | |
michael@0 | 237 | big_answer = zero_meg; |
michael@0 | 238 | VERBOSE(v_whisper, "Rewriting every byte of big file data"); |
michael@0 | 239 | do |
michael@0 | 240 | { |
michael@0 | 241 | bytes = file->methods->write(file, buffer, BUFFER_SIZE); |
michael@0 | 242 | if (bytes != BUFFER_SIZE) |
michael@0 | 243 | return Error("write", filename); |
michael@0 | 244 | LL_ADD(big_answer, big_answer, big_fragment); |
michael@0 | 245 | } while (LL_CMP(big_answer, <, filesize64)); |
michael@0 | 246 | |
michael@0 | 247 | VERBOSE(v_whisper, "Checking position at eof"); |
michael@0 | 248 | big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_CUR); |
michael@0 | 249 | if (LL_NE(big_answer, filesize64)) |
michael@0 | 250 | return Error("file size error", filename); |
michael@0 | 251 | |
michael@0 | 252 | VERBOSE(v_whisper, "Testing available space at eof"); |
michael@0 | 253 | big_answer = file->methods->available64(file); |
michael@0 | 254 | if (!LL_IS_ZERO(big_answer)) |
michael@0 | 255 | return Error("eof available64()", filename); |
michael@0 | 256 | |
michael@0 | 257 | VERBOSE(v_whisper, "Rewinding full file"); |
michael@0 | 258 | big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_SET); |
michael@0 | 259 | if (!LL_IS_ZERO(big_answer)) return Error("bof seek64()", filename); |
michael@0 | 260 | |
michael@0 | 261 | VERBOSE(v_whisper, "Testing available space in rewound file"); |
michael@0 | 262 | big_answer = file->methods->available64(file); |
michael@0 | 263 | if (LL_NE(big_answer, filesize64)) return Error("bof available64()", filename); |
michael@0 | 264 | |
michael@0 | 265 | VERBOSE(v_whisper, "Seeking to end of big file"); |
michael@0 | 266 | big_answer = file->methods->seek64(file, filesize64, PR_SEEK_SET); |
michael@0 | 267 | if (LL_NE(big_answer, filesize64)) return Error("eof seek64()", filename); |
michael@0 | 268 | |
michael@0 | 269 | VERBOSE(v_whisper, "Getting info on big file while it's open"); |
michael@0 | 270 | rv = file->methods->fileInfo64(file, &big_info); |
michael@0 | 271 | if (PR_FAILURE == rv) return Error("fileInfo64()", filename); |
michael@0 | 272 | if (v_shout <= verbose) PrintInfo(&big_info, filename); |
michael@0 | 273 | |
michael@0 | 274 | VERBOSE(v_whisper, "Closing big file"); |
michael@0 | 275 | rv = file->methods->close(file); |
michael@0 | 276 | if (PR_FAILURE == rv) return Error("close()", filename); |
michael@0 | 277 | |
michael@0 | 278 | VERBOSE(v_whisper, "Getting info on big file after it's closed"); |
michael@0 | 279 | rv = PR_GetFileInfo64(filename, &big_info); |
michael@0 | 280 | if (PR_FAILURE == rv) return Error("fileInfo64()", filename); |
michael@0 | 281 | if (v_shout <= verbose) PrintInfo(&big_info, filename); |
michael@0 | 282 | |
michael@0 | 283 | VERBOSE(v_whisper, "Deleting big file"); |
michael@0 | 284 | rv = PR_Delete(filename); |
michael@0 | 285 | if (PR_FAILURE == rv) return Error("PR_Delete()", filename); |
michael@0 | 286 | |
michael@0 | 287 | PR_DELETE(buffer); |
michael@0 | 288 | return test_result; |
michael@0 | 289 | } /* main */ |
michael@0 | 290 | |
michael@0 | 291 | /* bigfile.c */ |