| File: | usd/usd_file.c |
| Location: | line 443, column 5 |
| Description: | Dereference of null pointer (loaded from variable 'usdP') |
| 1 | /* | ||
| 2 | * Copyright 2000, International Business Machines Corporation and others. | ||
| 3 | * All Rights Reserved. | ||
| 4 | * | ||
| 5 | * This software has been released under the terms of the IBM Public | ||
| 6 | * License. For details, see the LICENSE file in the top-level source | ||
| 7 | * directory or online at http://www.openafs.org/dl/license10.html | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <afsconfig.h> | ||
| 11 | #include <afs/param.h> | ||
| 12 | |||
| 13 | #include <roken.h> | ||
| 14 | |||
| 15 | #if defined(AFS_AIX_ENV) | ||
| 16 | #include <sys/tape.h> | ||
| 17 | #include <sys/statfs.h> | ||
| 18 | #else | ||
| 19 | #ifdef AFS_DARWIN_ENV | ||
| 20 | #include <sys/ioccom.h> | ||
| 21 | #endif | ||
| 22 | #if defined(AFS_DUX40_ENV) || defined(AFS_OBSD_ENV) || defined(AFS_NBSD_ENV) || (defined(AFS_DARWIN_ENV) && !defined(AFS_DARWIN100_ENV)) | ||
| 23 | #include <sys/ioctl.h> | ||
| 24 | #endif | ||
| 25 | #ifndef AFS_DARWIN100_ENV | ||
| 26 | #include <sys/mtio.h> | ||
| 27 | #endif | ||
| 28 | #endif /* AFS_AIX_ENV */ | ||
| 29 | |||
| 30 | #include <afs/afs_assert.h> | ||
| 31 | |||
| 32 | #include "usd.h" | ||
| 33 | |||
| 34 | #ifdef O_LARGEFILE | ||
| 35 | typedef off64_t osi_lloff_t; | ||
| 36 | #define osi_llseeklseek lseek64 | ||
| 37 | #else /* O_LARGEFILE */ | ||
| 38 | #ifdef AFS_HAVE_LLSEEK | ||
| 39 | typedef offset_t osi_lloff_t; | ||
| 40 | #define osi_llseeklseek llseek | ||
| 41 | #else /* AFS_HAVE_LLSEEK */ | ||
| 42 | typedef off_t osi_lloff_t; | ||
| 43 | #define osi_llseeklseek lseek | ||
| 44 | #endif /* AFS_HAVE_LLSEEK */ | ||
| 45 | #endif /* O_LARGEFILE */ | ||
| 46 | |||
| 47 | /* | ||
| 48 | * This macro should be used inside assertions wherever offset/hyper | ||
| 49 | * conversion occur. A good compiler in a 64 bit environment will | ||
| 50 | * elide the entire statement if the offset type is 64 bits wide. | ||
| 51 | */ | ||
| 52 | #define osi_hFitsInOff(val)((sizeof(osi_lloff_t) == 4) ? (((val) & 0xffffffff00000000LL ) == 0) : 1) \ | ||
| 53 | ((sizeof(osi_lloff_t) == 4) ? (((val) & 0xffffffff00000000LL) == 0) : 1) | ||
| 54 | |||
| 55 | /************ End of osi wrappers ***********************************/ | ||
| 56 | |||
| 57 | /* Implementation of user space device I/O for regular POSIX files. */ | ||
| 58 | |||
| 59 | static int | ||
| 60 | usd_FileRead(usd_handle_t usd, char *buf, afs_uint32 nbytes, | ||
| 61 | afs_uint32 * xferdP) | ||
| 62 | { | ||
| 63 | int fd = (intptr_t)(usd->handle); | ||
| 64 | int got; | ||
| 65 | |||
| 66 | got = read(fd, buf, nbytes); | ||
| 67 | if (got == -1) { | ||
| 68 | if (xferdP) | ||
| 69 | *xferdP = 0; | ||
| 70 | return errno(* __error()); | ||
| 71 | } | ||
| 72 | if (xferdP) | ||
| 73 | *xferdP = got; | ||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | |||
| 77 | static int | ||
| 78 | usd_FileWrite(usd_handle_t usd, char *buf, afs_uint32 nbytes, | ||
| 79 | afs_uint32 * xferdP) | ||
| 80 | { | ||
| 81 | int fd = (intptr_t)(usd->handle); | ||
| 82 | int sent; | ||
| 83 | |||
| 84 | sent = write(fd, buf, nbytes); | ||
| 85 | if (sent == -1) { | ||
| 86 | if (xferdP) | ||
| 87 | *xferdP = 0; | ||
| 88 | return errno(* __error()); | ||
| 89 | } | ||
| 90 | if (xferdP) | ||
| 91 | *xferdP = sent; | ||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | extern osi_lloff_t osi_llseeklseek(int, osi_lloff_t, int); | ||
| 96 | |||
| 97 | static int | ||
| 98 | usd_FileSeek(usd_handle_t usd, afs_int64 reqOff, int whence, | ||
| 99 | afs_int64 * curOffP) | ||
| 100 | { | ||
| 101 | int fd = (intptr_t)(usd->handle); | ||
| 102 | osi_lloff_t lloff; | ||
| 103 | |||
| 104 | if (!osi_hFitsInOff(reqOff)((sizeof(osi_lloff_t) == 4) ? (((reqOff) & 0xffffffff00000000LL ) == 0) : 1)) | ||
| 105 | return EINVAL22; | ||
| 106 | |||
| 107 | lloff = osi_llseeklseek(fd, reqOff, whence); | ||
| 108 | if (lloff == (((osi_lloff_t) 0) - 1)) | ||
| 109 | return errno(* __error()); | ||
| 110 | if (curOffP) | ||
| 111 | *curOffP = lloff; | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int | ||
| 117 | usd_FileIoctl(usd_handle_t usd, int req, void *arg) | ||
| 118 | { | ||
| 119 | int fd = (intptr_t)(usd->handle); | ||
| 120 | #ifdef O_LARGEFILE | ||
| 121 | struct stat64 info; | ||
| 122 | #else /* O_LARGEFILE */ | ||
| 123 | struct stat info; | ||
| 124 | #endif /* O_LARGEFILE */ | ||
| 125 | #ifdef AFS_AIX_ENV | ||
| 126 | struct statfs fsinfo; /* AIX stat structure doesn't have st_blksize */ | ||
| 127 | #endif /* AFS_AIX_ENV */ | ||
| 128 | afs_int64 size; | ||
| 129 | int code = 0; | ||
| 130 | |||
| 131 | switch (req) { | ||
| 132 | case USD_IOCTL_GETBLKSIZE9: | ||
| 133 | #ifdef AFS_AIX_ENV | ||
| 134 | code = fstatfs(fd, &fsinfo); | ||
| 135 | if (code) { | ||
| 136 | *((long *)arg) = (long)4096; | ||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | break; | ||
| 140 | #endif /* AFS_AIX_ENV */ | ||
| 141 | case USD_IOCTL_GETTYPE1: | ||
| 142 | case USD_IOCTL_GETDEV3: | ||
| 143 | case USD_IOCTL_GETSIZE6: | ||
| 144 | #ifdef O_LARGEFILE | ||
| 145 | code = fstat64(fd, &info); | ||
| 146 | #else /* O_LARGEFILE */ | ||
| 147 | code = fstat(fd, &info); | ||
| 148 | #endif /* O_LARGEFILE */ | ||
| 149 | if (code) | ||
| 150 | return errno(* __error()); | ||
| 151 | break; | ||
| 152 | } | ||
| 153 | |||
| 154 | switch (req) { | ||
| 155 | case USD_IOCTL_GETTYPE1: | ||
| 156 | *(int *)arg = info.st_mode & S_IFMT0170000; | ||
| 157 | break; | ||
| 158 | case USD_IOCTL_GETDEV3: | ||
| 159 | if (!(S_ISCHR(info.st_mode)(((info.st_mode) & 0170000) == 0020000) || S_ISBLK(info.st_mode)(((info.st_mode) & 0170000) == 0060000))) | ||
| 160 | return ENODEV19; /* not a device */ | ||
| 161 | *(dev_t *) arg = info.st_rdev; | ||
| 162 | break; | ||
| 163 | case USD_IOCTL_GETSIZE6: | ||
| 164 | if (S_ISCHR(info.st_mode)(((info.st_mode) & 0170000) == 0020000) || S_ISBLK(info.st_mode)(((info.st_mode) & 0170000) == 0060000)) | ||
| 165 | return ENOTTY25; /* shouldn't be a device */ | ||
| 166 | *(afs_int64 *)arg = info.st_size; | ||
| 167 | break; | ||
| 168 | case USD_IOCTL_GETFULLNAME2: | ||
| 169 | *(char **)arg = usd->fullPathName; | ||
| 170 | break; | ||
| 171 | |||
| 172 | case USD_IOCTL_SETSIZE7: | ||
| 173 | |||
| 174 | /* We could just use ftruncate in all cases. (This even works on AIX; | ||
| 175 | * I tried it). -blake 931118 */ | ||
| 176 | |||
| 177 | /* However, I'm pretty sure this doesn't work on Ultrix so I am | ||
| 178 | * unsure about OSF/1 and HP/UX. 931118 */ | ||
| 179 | |||
| 180 | size = *(afs_int64 *) arg; | ||
| 181 | if (!osi_hFitsInOff(size)((sizeof(osi_lloff_t) == 4) ? (((size) & 0xffffffff00000000LL ) == 0) : 1)) | ||
| 182 | return EFBIG27; | ||
| 183 | #ifdef O_LARGEFILE | ||
| 184 | code = ftruncate64(fd, size); | ||
| 185 | #else /* O_LARGEFILE */ | ||
| 186 | code = ftruncate(fd, size); | ||
| 187 | #endif /* O_LARGEFILE */ | ||
| 188 | if (code == -1) | ||
| 189 | code = errno(* __error()); | ||
| 190 | return code; | ||
| 191 | |||
| 192 | case USD_IOCTL_TAPEOPERATION8: | ||
| 193 | { | ||
| 194 | #ifdef AFS_DARWIN100_ENV | ||
| 195 | code = EOPNOTSUPP45; | ||
| 196 | #else | ||
| 197 | usd_tapeop_t *tapeOpp = (usd_tapeop_t *) arg; | ||
| 198 | #if defined(AFS_AIX_ENV) | ||
| 199 | struct stop os_tapeop; | ||
| 200 | |||
| 201 | if (tapeOpp->tp_op == USDTAPE_WEOF0) { | ||
| 202 | os_tapeop.st_op = STWEOF; | ||
| 203 | } else if (tapeOpp->tp_op == USDTAPE_REW1) { | ||
| 204 | os_tapeop.st_op = STREW; | ||
| 205 | } else if (tapeOpp->tp_op == USDTAPE_FSF2) { | ||
| 206 | os_tapeop.st_op = STFSF; | ||
| 207 | } else if (tapeOpp->tp_op == USDTAPE_BSF3) { | ||
| 208 | os_tapeop.st_op = STRSF; | ||
| 209 | } else if (tapeOpp->tp_op == USDTAPE_PREPARE4) { | ||
| 210 | return 0; | ||
| 211 | } else if (tapeOpp->tp_op == USDTAPE_SHUTDOWN5) { | ||
| 212 | return 0; | ||
| 213 | } else { | ||
| 214 | /* unsupported tape operation */ | ||
| 215 | return EINVAL22; | ||
| 216 | } | ||
| 217 | os_tapeop.st_count = tapeOpp->tp_count; | ||
| 218 | |||
| 219 | code = ioctl(fd, STIOCTOP, &os_tapeop); | ||
| 220 | #else | ||
| 221 | struct mtop os_tapeop; | ||
| 222 | |||
| 223 | if (tapeOpp->tp_op == USDTAPE_WEOF0) { | ||
| 224 | os_tapeop.mt_op = MTWEOF0; | ||
| 225 | } else if (tapeOpp->tp_op == USDTAPE_REW1) { | ||
| 226 | os_tapeop.mt_op = MTREW5; | ||
| 227 | } else if (tapeOpp->tp_op == USDTAPE_FSF2) { | ||
| 228 | os_tapeop.mt_op = MTFSF1; | ||
| 229 | } else if (tapeOpp->tp_op == USDTAPE_BSF3) { | ||
| 230 | os_tapeop.mt_op = MTBSF2; | ||
| 231 | } else if (tapeOpp->tp_op == USDTAPE_PREPARE4) { | ||
| 232 | return 0; | ||
| 233 | } else if (tapeOpp->tp_op == USDTAPE_SHUTDOWN5) { | ||
| 234 | return 0; | ||
| 235 | } else { | ||
| 236 | /* unsupported tape operation */ | ||
| 237 | return EINVAL22; | ||
| 238 | } | ||
| 239 | os_tapeop.mt_count = tapeOpp->tp_count; | ||
| 240 | |||
| 241 | code = ioctl(fd, MTIOCTOP((unsigned long) ((0x80000000) | (((sizeof(struct mtop)) & ((1 << 13) - 1)) << 16) | ((('m')) << 8) | ((1)))), &os_tapeop); | ||
| 242 | #endif /* AFS_AIX_ENV */ | ||
| 243 | #endif | ||
| 244 | if (code == -1) { | ||
| 245 | code = errno(* __error()); | ||
| 246 | } else { | ||
| 247 | code = 0; | ||
| 248 | } | ||
| 249 | return code; | ||
| 250 | } | ||
| 251 | |||
| 252 | case USD_IOCTL_GETBLKSIZE9: | ||
| 253 | if (S_ISCHR(info.st_mode)(((info.st_mode) & 0170000) == 0020000) || S_ISBLK(info.st_mode)(((info.st_mode) & 0170000) == 0060000)) { | ||
| 254 | *((long *)arg) = (long)4096; | ||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | #ifdef AFS_AIX_ENV | ||
| 258 | *((long *)arg) = (long)fsinfo.f_bsize; | ||
| 259 | #else /* AFS_AIX_ENV */ | ||
| 260 | *((long *)arg) = (long)info.st_blksize; | ||
| 261 | #endif /* AFS_AIX_ENV */ | ||
| 262 | break; | ||
| 263 | |||
| 264 | default: | ||
| 265 | return EINVAL22; | ||
| 266 | } | ||
| 267 | return code; | ||
| 268 | } | ||
| 269 | |||
| 270 | static int | ||
| 271 | usd_FileClose(usd_handle_t usd) | ||
| 272 | { | ||
| 273 | int fd = (intptr_t)(usd->handle); | ||
| 274 | int code = 0; | ||
| 275 | int ccode; | ||
| 276 | |||
| 277 | /* I can't really believe this is necessary. On the one hand the user | ||
| 278 | * space code always uses character devices, which aren't supposed to do | ||
| 279 | * any buffering. On the other, I very much doubt fsyncing a regular file | ||
| 280 | * being salvaged is ever necessary. But the salvager used to do this | ||
| 281 | * before returning, so... */ | ||
| 282 | |||
| 283 | if (usd->openFlags & (O_WRONLY0x0001 | O_RDWR0x0002)) { | ||
| 284 | int mode; | ||
| 285 | code = usd_FileIoctl(usd, USD_IOCTL_GETTYPE1, &mode); | ||
| 286 | if (code == 0 && S_ISBLK(mode)(((mode) & 0170000) == 0060000)) { | ||
| 287 | if (fsync(fd) < 0) | ||
| 288 | code = errno(* __error()); | ||
| 289 | } | ||
| 290 | } | ||
| 291 | |||
| 292 | ccode = close(fd); | ||
| 293 | if (!code && ccode) | ||
| 294 | code = errno(* __error()); | ||
| 295 | |||
| 296 | if (usd->fullPathName) | ||
| 297 | free(usd->fullPathName); | ||
| 298 | free(usd); | ||
| 299 | |||
| 300 | return code; | ||
| 301 | } | ||
| 302 | |||
| 303 | static int | ||
| 304 | usd_FileOpen(const char *path, int flags, int mode, usd_handle_t * usdP) | ||
| 305 | { | ||
| 306 | int fd; | ||
| 307 | int oflags; | ||
| 308 | usd_handle_t usd; | ||
| 309 | int code; | ||
| 310 | |||
| 311 | if (usdP) | ||
| 312 | *usdP = NULL((void *)0); | ||
| 313 | |||
| 314 | oflags = (flags & USD_OPEN_RDWR1) ? O_RDWR0x0002 : O_RDONLY0x0000; | ||
| 315 | |||
| 316 | #ifdef O_SYNC0x0080 /* AFS_DARWIN_ENV XXX */ | ||
| 317 | if (flags & USD_OPEN_SYNC2) | ||
| 318 | oflags |= O_SYNC0x0080; | ||
| 319 | #endif | ||
| 320 | |||
| 321 | if (flags & USD_OPEN_CREATE0x10) | ||
| 322 | oflags |= O_CREAT0x0200; | ||
| 323 | |||
| 324 | #ifdef O_LARGEFILE | ||
| 325 | fd = open64(path, oflags | O_LARGEFILE, mode); | ||
| 326 | #else /* O_LARGEFILE */ | ||
| 327 | fd = open(path, oflags, mode); | ||
| 328 | #endif /* O_LARGEFILE */ | ||
| 329 | if (fd == -1) | ||
| 330 | return errno(* __error()); | ||
| 331 | |||
| 332 | usd = (usd_handle_t) malloc(sizeof(*usd)); | ||
| 333 | memset(usd, 0, sizeof(*usd)); | ||
| 334 | usd->handle = (void *)(intptr_t)fd; | ||
| 335 | usd->read = usd_FileRead; | ||
| 336 | usd->write = usd_FileWrite; | ||
| 337 | usd->seek = usd_FileSeek; | ||
| 338 | usd->ioctl = usd_FileIoctl; | ||
| 339 | usd->close = usd_FileClose; | ||
| 340 | usd->fullPathName = (char *)malloc(strlen(path) + 1); | ||
| 341 | strcpy(usd->fullPathName, path); | ||
| 342 | usd->openFlags = flags; | ||
| 343 | |||
| 344 | code = 0; | ||
| 345 | if (flags & (USD_OPEN_RLOCK4 | USD_OPEN_WLOCK8)) { | ||
| 346 | #ifdef O_LARGEFILE | ||
| 347 | struct flock64 fl; | ||
| 348 | #else /* O_LARGEFILE */ | ||
| 349 | struct flock fl; | ||
| 350 | #endif /* O_LARGEFILE */ | ||
| 351 | |||
| 352 | /* make sure both lock bits aren't set */ | ||
| 353 | assert(~flags & (USD_OPEN_RLOCK | USD_OPEN_WLOCK))do{if (!(~flags & (4 | 8))) AssertionFailed("usd_file.c", 353);}while(0); | ||
| 354 | |||
| 355 | fl.l_type = ((flags & USD_OPEN_RLOCK4) ? F_RDLCK1 : F_WRLCK3); | ||
| 356 | fl.l_whence = SEEK_SET0; | ||
| 357 | fl.l_start = (osi_lloff_t) 0; | ||
| 358 | fl.l_len = (osi_lloff_t) 0; /* whole file */ | ||
| 359 | #ifdef O_LARGEFILE | ||
| 360 | code = fcntl(fd, F_SETLK64, &fl); | ||
| 361 | #else /* O_LARGEFILE */ | ||
| 362 | code = fcntl(fd, F_SETLK12, &fl); | ||
| 363 | #endif /* O_LARGEFILE */ | ||
| 364 | if (code == -1) | ||
| 365 | code = errno(* __error()); | ||
| 366 | |||
| 367 | /* If we're trying to obtain a write lock on a real disk, then the | ||
| 368 | * aggregate must not be attached by the kernel. If so, unlock it | ||
| 369 | * and fail. | ||
| 370 | * WARNING: The code to check for the above has been removed when this | ||
| 371 | * file was ported from DFS src. It should be put back if | ||
| 372 | * this library is used to access hard disks | ||
| 373 | */ | ||
| 374 | } | ||
| 375 | |||
| 376 | if (code == 0 && usdP) | ||
| 377 | *usdP = usd; | ||
| 378 | else | ||
| 379 | usd_FileClose(usd); | ||
| 380 | return code; | ||
| 381 | } | ||
| 382 | |||
| 383 | static int | ||
| 384 | usd_FileDummyClose(usd_handle_t usd) | ||
| 385 | { | ||
| 386 | free(usd); | ||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | |||
| 390 | int | ||
| 391 | usd_Open(const char *path, int oflag, int mode, usd_handle_t * usdP) | ||
| 392 | { | ||
| 393 | return usd_FileOpen(path, oflag, mode, usdP); | ||
| 394 | } | ||
| 395 | |||
| 396 | static int | ||
| 397 | usd_FileStandardInput(usd_handle_t * usdP) | ||
| 398 | { | ||
| 399 | usd_handle_t usd; | ||
| 400 | |||
| 401 | if (usdP) | ||
| 402 | *usdP = NULL((void *)0); | ||
| 403 | |||
| 404 | usd = (usd_handle_t) malloc(sizeof(*usd)); | ||
| 405 | memset(usd, 0, sizeof(*usd)); | ||
| 406 | usd->handle = (void *)((unsigned long)0); | ||
| 407 | usd->read = usd_FileRead; | ||
| 408 | usd->write = usd_FileWrite; | ||
| 409 | usd->seek = usd_FileSeek; | ||
| 410 | usd->ioctl = usd_FileIoctl; | ||
| 411 | usd->close = usd_FileDummyClose; | ||
| 412 | usd->fullPathName = "STDIN"; | ||
| 413 | usd->openFlags = 0; | ||
| 414 | *usdP = usd; | ||
| 415 | |||
| 416 | return 0; | ||
| 417 | } | ||
| 418 | |||
| 419 | int | ||
| 420 | usd_StandardInput(usd_handle_t * usdP) | ||
| 421 | { | ||
| 422 | return usd_FileStandardInput(usdP); | ||
| 423 | } | ||
| 424 | |||
| 425 | static int | ||
| 426 | usd_FileStandardOutput(usd_handle_t * usdP) | ||
| 427 | { | ||
| 428 | usd_handle_t usd; | ||
| 429 | |||
| 430 | if (usdP) | ||
| |||
| 431 | *usdP = NULL((void *)0); | ||
| 432 | |||
| 433 | usd = (usd_handle_t) malloc(sizeof(*usd)); | ||
| 434 | memset(usd, 0, sizeof(*usd)); | ||
| 435 | usd->handle = (void *)((unsigned long)1); | ||
| 436 | usd->read = usd_FileRead; | ||
| 437 | usd->write = usd_FileWrite; | ||
| 438 | usd->seek = usd_FileSeek; | ||
| 439 | usd->ioctl = usd_FileIoctl; | ||
| 440 | usd->close = usd_FileDummyClose; | ||
| 441 | usd->fullPathName = "STDOUT"; | ||
| 442 | usd->openFlags = 0; | ||
| 443 | *usdP = usd; | ||
| |||
| 444 | |||
| 445 | return 0; | ||
| 446 | } | ||
| 447 | |||
| 448 | int | ||
| 449 | usd_StandardOutput(usd_handle_t * usdP) | ||
| 450 | { | ||
| 451 | return usd_FileStandardOutput(usdP); | ||
| 452 | } |