Bug Summary

File:usd/usd_file.c
Location:line 414, column 5
Description:Dereference of null pointer (loaded from variable 'usdP')

Annotated Source Code

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
35typedef off64_t osi_lloff_t;
36#define osi_llseeklseek lseek64
37#else /* O_LARGEFILE */
38#ifdef AFS_HAVE_LLSEEK
39typedef offset_t osi_lloff_t;
40#define osi_llseeklseek llseek
41#else /* AFS_HAVE_LLSEEK */
42typedef 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
59static int
60usd_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
77static int
78usd_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
95extern osi_lloff_t osi_llseeklseek(int, osi_lloff_t, int);
96
97static int
98usd_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
116static int
117usd_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
270static int
271usd_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
303static int
304usd_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
383static int
384usd_FileDummyClose(usd_handle_t usd)
385{
386 free(usd);
387 return 0;
388}
389
390int
391usd_Open(const char *path, int oflag, int mode, usd_handle_t * usdP)
392{
393 return usd_FileOpen(path, oflag, mode, usdP);
394}
395
396static int
397usd_FileStandardInput(usd_handle_t * usdP)
398{
399 usd_handle_t usd;
400
401 if (usdP)
1
Taking false branch
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;
2
Dereference of null pointer (loaded from variable 'usdP')
415
416 return 0;
417}
418
419int
420usd_StandardInput(usd_handle_t * usdP)
421{
422 return usd_FileStandardInput(usdP);
423}
424
425static int
426usd_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
448int
449usd_StandardOutput(usd_handle_t * usdP)
450{
451 return usd_FileStandardOutput(usdP);
452}