Bug Summary

File:file.c
Location:line 298, column 7
Description:Function call argument is an uninitialized value

Annotated Source Code

1/*
2 * Copyright © 2002 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
13 *
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include "xcursorint.h"
24#include <stdlib.h>
25#include <string.h>
26
27XcursorImage *
28XcursorImageCreate (int width, int height)
29{
30 XcursorImage *image;
31
32 image = malloc (sizeof (XcursorImage) +
33 width * height * sizeof (XcursorPixel));
34 if (!image)
35 return NULL((void*)0);
36 image->version = XCURSOR_IMAGE_VERSION1;
37 image->pixels = (XcursorPixel *) (image + 1);
38 image->size = width > height ? width : height;
39 image->width = width;
40 image->height = height;
41 image->delay = 0;
42 return image;
43}
44
45void
46XcursorImageDestroy (XcursorImage *image)
47{
48 free (image);
49}
50
51XcursorImages *
52XcursorImagesCreate (int size)
53{
54 XcursorImages *images;
55
56 images = malloc (sizeof (XcursorImages) +
57 size * sizeof (XcursorImage *));
58 if (!images)
59 return NULL((void*)0);
60 images->nimage = 0;
61 images->images = (XcursorImage **) (images + 1);
62 images->name = NULL((void*)0);
63 return images;
64}
65
66void
67XcursorImagesDestroy (XcursorImages *images)
68{
69 int n;
70
71 if (!images)
72 return;
73
74 for (n = 0; n < images->nimage; n++)
75 XcursorImageDestroy (images->images[n]);
76 if (images->name)
77 free (images->name);
78 free (images);
79}
80
81void
82XcursorImagesSetName (XcursorImages *images, const char *name)
83{
84 char *new;
85
86 if (!images || !name)
87 return;
88
89 new = strdup (name);
90
91 if (!new)
92 return;
93
94 if (images->name)
95 free (images->name);
96 images->name = new;
97}
98
99XcursorComment *
100XcursorCommentCreate (XcursorUInt comment_type, int length)
101{
102 XcursorComment *comment;
103
104 if (length > XCURSOR_COMMENT_MAX_LEN0x100000)
105 return NULL((void*)0);
106
107 comment = malloc (sizeof (XcursorComment) + length + 1);
108 if (!comment)
109 return NULL((void*)0);
110 comment->version = XCURSOR_COMMENT_VERSION1;
111 comment->comment_type = comment_type;
112 comment->comment = (char *) (comment + 1);
113 comment->comment[0] = '\0';
114 return comment;
115}
116
117void
118XcursorCommentDestroy (XcursorComment *comment)
119{
120 free (comment);
121}
122
123XcursorComments *
124XcursorCommentsCreate (int size)
125{
126 XcursorComments *comments;
127
128 comments = malloc (sizeof (XcursorComments) +
129 size * sizeof (XcursorComment *));
130 if (!comments)
131 return NULL((void*)0);
132 comments->ncomment = 0;
133 comments->comments = (XcursorComment **) (comments + 1);
134 return comments;
135}
136
137void
138XcursorCommentsDestroy (XcursorComments *comments)
139{
140 int n;
141
142 if (!comments)
143 return;
144
145 for (n = 0; n < comments->ncomment; n++)
146 XcursorCommentDestroy (comments->comments[n]);
147 free (comments);
148}
149
150static XcursorBool
151_XcursorReadUInt (XcursorFile *file, XcursorUInt *u)
152{
153 unsigned char bytes[4];
154
155 if (!file || !u)
156 return XcursorFalse0;
157
158 if ((*file->read) (file, bytes, 4) != 4)
159 return XcursorFalse0;
160 *u = ((bytes[0] << 0) |
161 (bytes[1] << 8) |
162 (bytes[2] << 16) |
163 (bytes[3] << 24));
164 return XcursorTrue1;
165}
166
167static XcursorBool
168_XcursorReadBytes (XcursorFile *file, char *bytes, int length)
169{
170 if (!file || !bytes || (*file->read) (file, (unsigned char *) bytes, length) != length)
171 return XcursorFalse0;
172 return XcursorTrue1;
173}
174
175static XcursorBool
176_XcursorWriteUInt (XcursorFile *file, XcursorUInt u)
177{
178 unsigned char bytes[4];
179
180 if (!file)
26
Taking false branch
33
Taking false branch
40
Taking false branch
47
Taking false branch
181 return XcursorFalse0;
182
183 bytes[0] = u;
184 bytes[1] = u >> 8;
185 bytes[2] = u >> 16;
186 bytes[3] = u >> 24;
187 if ((*file->write) (file, bytes, 4) != 4)
27
Calling '_XcursorStdioFileWrite'
28
Returning from '_XcursorStdioFileWrite'
29
Taking false branch
34
Calling '_XcursorStdioFileWrite'
35
Returning from '_XcursorStdioFileWrite'
36
Taking false branch
41
Calling '_XcursorStdioFileWrite'
42
Returning from '_XcursorStdioFileWrite'
43
Taking false branch
48
Calling '_XcursorStdioFileWrite'
49
Returning from '_XcursorStdioFileWrite'
50
Taking false branch
188 return XcursorFalse0;
189 return XcursorTrue1;
190}
191
192static XcursorBool
193_XcursorWriteBytes (XcursorFile *file, char *bytes, int length)
194{
195 if (!file || !bytes || (*file->write) (file, (unsigned char *) bytes, length) != length)
196 return XcursorFalse0;
197 return XcursorTrue1;
198}
199
200static void
201_XcursorFileHeaderDestroy (XcursorFileHeader *fileHeader)
202{
203 free (fileHeader);
204}
205
206static XcursorFileHeader *
207_XcursorFileHeaderCreate (XcursorUInt ntoc)
208{
209 XcursorFileHeader *fileHeader;
210
211 if (ntoc > 0x10000)
12
Assuming 'ntoc' is <= 65536
13
Taking false branch
212 return NULL((void*)0);
213 fileHeader = malloc (sizeof (XcursorFileHeader) +
14
Uninitialized value stored to field 'type'
214 ntoc * sizeof (XcursorFileToc));
215 if (!fileHeader)
15
Assuming 'fileHeader' is non-null
16
Taking false branch
216 return NULL((void*)0);
217 fileHeader->magic = XCURSOR_MAGIC0x72756358;
218 fileHeader->header = XCURSOR_FILE_HEADER_LEN(4 * 4);
219 fileHeader->version = XCURSOR_FILE_VERSION((1 << 16) | (0));
220 fileHeader->ntoc = ntoc;
221 fileHeader->tocs = (XcursorFileToc *) (fileHeader + 1);
222 return fileHeader;
223}
224
225static XcursorFileHeader *
226_XcursorReadFileHeader (XcursorFile *file)
227{
228 XcursorFileHeader head, *fileHeader;
229 XcursorUInt skip;
230 int n;
231
232 if (!file)
233 return NULL((void*)0);
234
235 if (!_XcursorReadUInt (file, &head.magic))
236 return NULL((void*)0);
237 if (head.magic != XCURSOR_MAGIC0x72756358)
238 return NULL((void*)0);
239 if (!_XcursorReadUInt (file, &head.header))
240 return NULL((void*)0);
241 if (!_XcursorReadUInt (file, &head.version))
242 return NULL((void*)0);
243 if (!_XcursorReadUInt (file, &head.ntoc))
244 return NULL((void*)0);
245 skip = head.header - XCURSOR_FILE_HEADER_LEN(4 * 4);
246 if (skip)
247 if ((*file->seek) (file, skip, SEEK_CUR1) == EOF(-1))
248 return NULL((void*)0);
249 fileHeader = _XcursorFileHeaderCreate (head.ntoc);
250 if (!fileHeader)
251 return NULL((void*)0);
252 fileHeader->magic = head.magic;
253 fileHeader->header = head.header;
254 fileHeader->version = head.version;
255 fileHeader->ntoc = head.ntoc;
256 for (n = 0; n < fileHeader->ntoc; n++)
257 {
258 if (!_XcursorReadUInt (file, &fileHeader->tocs[n].type))
259 break;
260 if (!_XcursorReadUInt (file, &fileHeader->tocs[n].subtype))
261 break;
262 if (!_XcursorReadUInt (file, &fileHeader->tocs[n].position))
263 break;
264 }
265 if (n != fileHeader->ntoc)
266 {
267 _XcursorFileHeaderDestroy (fileHeader);
268 return NULL((void*)0);
269 }
270 return fileHeader;
271}
272
273static XcursorUInt
274_XcursorFileHeaderLength (XcursorFileHeader *fileHeader)
275{
276 return (XCURSOR_FILE_HEADER_LEN(4 * 4) +
277 fileHeader->ntoc * XCURSOR_FILE_TOC_LEN(3 * 4));
278}
279
280static XcursorBool
281_XcursorWriteFileHeader (XcursorFile *file, XcursorFileHeader *fileHeader)
282{
283 int toc;
284
285 if (!file || !fileHeader)
24
Taking false branch
286 return XcursorFalse0;
287
288 if (!_XcursorWriteUInt (file, fileHeader->magic))
25
Calling '_XcursorWriteUInt'
30
Returning from '_XcursorWriteUInt'
31
Taking false branch
289 return XcursorFalse0;
290 if (!_XcursorWriteUInt (file, fileHeader->header))
32
Calling '_XcursorWriteUInt'
37
Returning from '_XcursorWriteUInt'
38
Taking false branch
291 return XcursorFalse0;
292 if (!_XcursorWriteUInt (file, fileHeader->version))
39
Calling '_XcursorWriteUInt'
44
Returning from '_XcursorWriteUInt'
45
Taking false branch
293 return XcursorFalse0;
294 if (!_XcursorWriteUInt (file, fileHeader->ntoc))
46
Calling '_XcursorWriteUInt'
51
Returning from '_XcursorWriteUInt'
52
Taking false branch
295 return XcursorFalse0;
296 for (toc = 0; toc < fileHeader->ntoc; toc++)
53
Loop condition is true. Entering loop body
297 {
298 if (!_XcursorWriteUInt (file, fileHeader->tocs[toc].type))
54
Function call argument is an uninitialized value
299 return XcursorFalse0;
300 if (!_XcursorWriteUInt (file, fileHeader->tocs[toc].subtype))
301 return XcursorFalse0;
302 if (!_XcursorWriteUInt (file, fileHeader->tocs[toc].position))
303 return XcursorFalse0;
304 }
305 return XcursorTrue1;
306}
307
308static XcursorBool
309_XcursorSeekToToc (XcursorFile *file,
310 XcursorFileHeader *fileHeader,
311 int toc)
312{
313 if (!file || !fileHeader || \
314 (*file->seek) (file, fileHeader->tocs[toc].position, SEEK_SET0) == EOF(-1))
315 return XcursorFalse0;
316 return XcursorTrue1;
317}
318
319static XcursorBool
320_XcursorFileReadChunkHeader (XcursorFile *file,
321 XcursorFileHeader *fileHeader,
322 int toc,
323 XcursorChunkHeader *chunkHeader)
324{
325 if (!file || !fileHeader || !chunkHeader)
326 return XcursorFalse0;
327 if (!_XcursorSeekToToc (file, fileHeader, toc))
328 return XcursorFalse0;
329 if (!_XcursorReadUInt (file, &chunkHeader->header))
330 return XcursorFalse0;
331 if (!_XcursorReadUInt (file, &chunkHeader->type))
332 return XcursorFalse0;
333 if (!_XcursorReadUInt (file, &chunkHeader->subtype))
334 return XcursorFalse0;
335 if (!_XcursorReadUInt (file, &chunkHeader->version))
336 return XcursorFalse0;
337 /* sanity check */
338 if (chunkHeader->type != fileHeader->tocs[toc].type ||
339 chunkHeader->subtype != fileHeader->tocs[toc].subtype)
340 return XcursorFalse0;
341 return XcursorTrue1;
342}
343
344static XcursorBool
345_XcursorFileWriteChunkHeader (XcursorFile *file,
346 XcursorFileHeader *fileHeader,
347 int toc,
348 XcursorChunkHeader *chunkHeader)
349{
350 if (!file || !fileHeader || !chunkHeader)
351 return XcursorFalse0;
352 if (!_XcursorSeekToToc (file, fileHeader, toc))
353 return XcursorFalse0;
354 if (!_XcursorWriteUInt (file, chunkHeader->header))
355 return XcursorFalse0;
356 if (!_XcursorWriteUInt (file, chunkHeader->type))
357 return XcursorFalse0;
358 if (!_XcursorWriteUInt (file, chunkHeader->subtype))
359 return XcursorFalse0;
360 if (!_XcursorWriteUInt (file, chunkHeader->version))
361 return XcursorFalse0;
362 return XcursorTrue1;
363}
364
365#define dist(a,b)((a) > (b) ? (a) - (b) : (b) - (a)) ((a) > (b) ? (a) - (b) : (b) - (a))
366
367static XcursorDim
368_XcursorFindBestSize (XcursorFileHeader *fileHeader,
369 XcursorDim size,
370 int *nsizesp)
371{
372 int n;
373 int nsizes = 0;
374 XcursorDim bestSize = 0;
375 XcursorDim thisSize;
376
377 if (!fileHeader || !nsizesp)
378 return 0;
379
380 for (n = 0; n < fileHeader->ntoc; n++)
381 {
382 if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE0xfffd0002)
383 continue;
384 thisSize = fileHeader->tocs[n].subtype;
385 if (!bestSize || dist (thisSize, size)((thisSize) > (size) ? (thisSize) - (size) : (size) - (thisSize
))
< dist (bestSize, size)((bestSize) > (size) ? (bestSize) - (size) : (size) - (bestSize
))
)
386 {
387 bestSize = thisSize;
388 nsizes = 1;
389 }
390 else if (thisSize == bestSize)
391 nsizes++;
392 }
393 *nsizesp = nsizes;
394 return bestSize;
395}
396
397static int
398_XcursorFindImageToc (XcursorFileHeader *fileHeader,
399 XcursorDim size,
400 int count)
401{
402 int toc;
403 XcursorDim thisSize;
404
405 if (!fileHeader)
406 return 0;
407
408 for (toc = 0; toc < fileHeader->ntoc; toc++)
409 {
410 if (fileHeader->tocs[toc].type != XCURSOR_IMAGE_TYPE0xfffd0002)
411 continue;
412 thisSize = fileHeader->tocs[toc].subtype;
413 if (thisSize != size)
414 continue;
415 if (!count)
416 break;
417 count--;
418 }
419 if (toc == fileHeader->ntoc)
420 return -1;
421 return toc;
422}
423
424static XcursorImage *
425_XcursorReadImage (XcursorFile *file,
426 XcursorFileHeader *fileHeader,
427 int toc)
428{
429 XcursorChunkHeader chunkHeader;
430 XcursorImage head;
431 XcursorImage *image;
432 int n;
433 XcursorPixel *p;
434
435 if (!file || !fileHeader)
436 return NULL((void*)0);
437
438 if (!_XcursorFileReadChunkHeader (file, fileHeader, toc, &chunkHeader))
439 return NULL((void*)0);
440 if (!_XcursorReadUInt (file, &head.width))
441 return NULL((void*)0);
442 if (!_XcursorReadUInt (file, &head.height))
443 return NULL((void*)0);
444 if (!_XcursorReadUInt (file, &head.xhot))
445 return NULL((void*)0);
446 if (!_XcursorReadUInt (file, &head.yhot))
447 return NULL((void*)0);
448 if (!_XcursorReadUInt (file, &head.delay))
449 return NULL((void*)0);
450 /* sanity check data */
451 if (head.width >= 0x10000 || head.height > 0x10000)
452 return NULL((void*)0);
453 if (head.width == 0 || head.height == 0)
454 return NULL((void*)0);
455 if (head.xhot > head.width || head.yhot > head.height)
456 return NULL((void*)0);
457
458 /* Create the image and initialize it */
459 image = XcursorImageCreate (head.width, head.height);
460 if (chunkHeader.version < image->version)
461 image->version = chunkHeader.version;
462 image->size = chunkHeader.subtype;
463 image->xhot = head.xhot;
464 image->yhot = head.yhot;
465 image->delay = head.delay;
466 n = image->width * image->height;
467 p = image->pixels;
468 while (n--)
469 {
470 if (!_XcursorReadUInt (file, p))
471 {
472 XcursorImageDestroy (image);
473 return NULL((void*)0);
474 }
475 p++;
476 }
477 return image;
478}
479
480static XcursorUInt
481_XcursorImageLength (XcursorImage *image)
482{
483 if (!image)
484 return 0;
485
486 return XCURSOR_IMAGE_HEADER_LEN((4 * 4) + (5*4)) + (image->width * image->height) * 4;
487}
488
489static XcursorBool
490_XcursorWriteImage (XcursorFile *file,
491 XcursorFileHeader *fileHeader,
492 int toc,
493 XcursorImage *image)
494{
495 XcursorChunkHeader chunkHeader;
496 int n;
497 XcursorPixel *p;
498
499 if (!file || !fileHeader || !image)
500 return XcursorFalse0;
501
502 /* sanity check data */
503 if (image->width > XCURSOR_IMAGE_MAX_SIZE0x7fff ||
504 image->height > XCURSOR_IMAGE_MAX_SIZE0x7fff)
505 return XcursorFalse0;
506 if (image->width == 0 || image->height == 0)
507 return XcursorFalse0;
508 if (image->xhot > image->width || image->yhot > image->height)
509 return XcursorFalse0;
510
511 /* write chunk header */
512 chunkHeader.header = XCURSOR_IMAGE_HEADER_LEN((4 * 4) + (5*4));
513 chunkHeader.type = XCURSOR_IMAGE_TYPE0xfffd0002;
514 chunkHeader.subtype = image->size;
515 chunkHeader.version = XCURSOR_IMAGE_VERSION1;
516
517 if (!_XcursorFileWriteChunkHeader (file, fileHeader, toc, &chunkHeader))
518 return XcursorFalse0;
519
520 /* write extra image header fields */
521 if (!_XcursorWriteUInt (file, image->width))
522 return XcursorFalse0;
523 if (!_XcursorWriteUInt (file, image->height))
524 return XcursorFalse0;
525 if (!_XcursorWriteUInt (file, image->xhot))
526 return XcursorFalse0;
527 if (!_XcursorWriteUInt (file, image->yhot))
528 return XcursorFalse0;
529 if (!_XcursorWriteUInt (file, image->delay))
530 return XcursorFalse0;
531
532 /* write the image */
533 n = image->width * image->height;
534 p = image->pixels;
535 while (n--)
536 {
537 if (!_XcursorWriteUInt (file, *p))
538 return XcursorFalse0;
539 p++;
540 }
541 return XcursorTrue1;
542}
543
544static XcursorComment *
545_XcursorReadComment (XcursorFile *file,
546 XcursorFileHeader *fileHeader,
547 int toc)
548{
549 XcursorChunkHeader chunkHeader;
550 XcursorUInt length;
551 XcursorComment *comment;
552
553 if (!file || !fileHeader)
554 return NULL((void*)0);
555
556 /* read chunk header */
557 if (!_XcursorFileReadChunkHeader (file, fileHeader, toc, &chunkHeader))
558 return NULL((void*)0);
559 /* read extra comment header fields */
560 if (!_XcursorReadUInt (file, &length))
561 return NULL((void*)0);
562 comment = XcursorCommentCreate (chunkHeader.subtype, length);
563 if (!comment)
564 return NULL((void*)0);
565 if (!_XcursorReadBytes (file, comment->comment, length))
566 {
567 XcursorCommentDestroy (comment);
568 return NULL((void*)0);
569 }
570 comment->comment[length] = '\0';
571 return comment;
572}
573
574static XcursorUInt
575_XcursorCommentLength (XcursorComment *comment)
576{
577 return XCURSOR_COMMENT_HEADER_LEN((4 * 4) + (1 *4)) + strlen (comment->comment);
578}
579
580static XcursorBool
581_XcursorWriteComment (XcursorFile *file,
582 XcursorFileHeader *fileHeader,
583 int toc,
584 XcursorComment *comment)
585{
586 XcursorChunkHeader chunkHeader;
587 XcursorUInt length;
588
589 if (!file || !fileHeader || !comment || !comment->comment)
590 return XcursorFalse0;
591
592 length = strlen (comment->comment);
593
594 /* sanity check data */
595 if (length > XCURSOR_COMMENT_MAX_LEN0x100000)
596 return XcursorFalse0;
597
598 /* read chunk header */
599 chunkHeader.header = XCURSOR_COMMENT_HEADER_LEN((4 * 4) + (1 *4));
600 chunkHeader.type = XCURSOR_COMMENT_TYPE0xfffe0001;
601 chunkHeader.subtype = comment->comment_type;
602 chunkHeader.version = XCURSOR_COMMENT_VERSION1;
603
604 if (!_XcursorFileWriteChunkHeader (file, fileHeader, toc, &chunkHeader))
605 return XcursorFalse0;
606
607 /* write extra comment header fields */
608 if (!_XcursorWriteUInt (file, length))
609 return XcursorFalse0;
610
611 if (!_XcursorWriteBytes (file, comment->comment, length))
612 return XcursorFalse0;
613 return XcursorTrue1;
614}
615
616XcursorImage *
617XcursorXcFileLoadImage (XcursorFile *file, int size)
618{
619 XcursorFileHeader *fileHeader;
620 XcursorDim bestSize;
621 int nsize;
622 int toc;
623 XcursorImage *image;
624
625 if (size < 0)
626 return NULL((void*)0);
627 fileHeader = _XcursorReadFileHeader (file);
628 if (!fileHeader)
629 return NULL((void*)0);
630 bestSize = _XcursorFindBestSize (fileHeader, (XcursorDim) size, &nsize);
631 if (!bestSize)
632 return NULL((void*)0);
633 toc = _XcursorFindImageToc (fileHeader, bestSize, 0);
634 if (toc < 0)
635 return NULL((void*)0);
636 image = _XcursorReadImage (file, fileHeader, toc);
637 _XcursorFileHeaderDestroy (fileHeader);
638 return image;
639}
640
641XcursorImages *
642XcursorXcFileLoadImages (XcursorFile *file, int size)
643{
644 XcursorFileHeader *fileHeader;
645 XcursorDim bestSize;
646 int nsize;
647 XcursorImages *images;
648 int n;
649 int toc;
650
651 if (!file || size < 0)
652 return NULL((void*)0);
653 fileHeader = _XcursorReadFileHeader (file);
654 if (!fileHeader)
655 return NULL((void*)0);
656 bestSize = _XcursorFindBestSize (fileHeader, (XcursorDim) size, &nsize);
657 if (!bestSize)
658 {
659 _XcursorFileHeaderDestroy (fileHeader);
660 return NULL((void*)0);
661 }
662 images = XcursorImagesCreate (nsize);
663 if (!images)
664 {
665 _XcursorFileHeaderDestroy (fileHeader);
666 return NULL((void*)0);
667 }
668 for (n = 0; n < nsize; n++)
669 {
670 toc = _XcursorFindImageToc (fileHeader, bestSize, n);
671 if (toc < 0)
672 break;
673 images->images[images->nimage] = _XcursorReadImage (file, fileHeader,
674 toc);
675 if (!images->images[images->nimage])
676 break;
677 images->nimage++;
678 }
679 _XcursorFileHeaderDestroy (fileHeader);
680 if (images->nimage != nsize)
681 {
682 XcursorImagesDestroy (images);
683 images = NULL((void*)0);
684 }
685 return images;
686}
687
688XcursorImages *
689XcursorXcFileLoadAllImages (XcursorFile *file)
690{
691 XcursorFileHeader *fileHeader;
692 XcursorImage *image;
693 XcursorImages *images;
694 int nimage;
695 int n;
696 int toc;
697
698 if (!file)
699 return NULL((void*)0);
700
701 fileHeader = _XcursorReadFileHeader (file);
702 if (!fileHeader)
703 return NULL((void*)0);
704 nimage = 0;
705 for (n = 0; n < fileHeader->ntoc; n++)
706 {
707 switch (fileHeader->tocs[n].type) {
708 case XCURSOR_IMAGE_TYPE0xfffd0002:
709 nimage++;
710 break;
711 }
712 }
713 images = XcursorImagesCreate (nimage);
714 if (!images)
715 {
716 _XcursorFileHeaderDestroy (fileHeader);
717 return NULL((void*)0);
718 }
719 for (toc = 0; toc < fileHeader->ntoc; toc++)
720 {
721 switch (fileHeader->tocs[toc].type) {
722 case XCURSOR_IMAGE_TYPE0xfffd0002:
723 image = _XcursorReadImage (file, fileHeader, toc);
724 if (image)
725 {
726 images->images[images->nimage] = image;
727 images->nimage++;
728 }
729 break;
730 }
731 }
732 _XcursorFileHeaderDestroy (fileHeader);
733 if (images->nimage != nimage)
734 {
735 XcursorImagesDestroy (images);
736 images = NULL((void*)0);
737 }
738 return images;
739}
740
741XcursorBool
742XcursorXcFileLoad (XcursorFile *file,
743 XcursorComments **commentsp,
744 XcursorImages **imagesp)
745{
746 XcursorFileHeader *fileHeader;
747 int nimage;
748 int ncomment;
749 XcursorImages *images;
750 XcursorImage *image;
751 XcursorComment *comment;
752 XcursorComments *comments;
753 int toc;
754
755 if (!file)
756 return 0;
757 fileHeader = _XcursorReadFileHeader (file);
758 if (!fileHeader)
759 return 0;
760 nimage = 0;
761 ncomment = 0;
762 for (toc = 0; toc < fileHeader->ntoc; toc++)
763 {
764 switch (fileHeader->tocs[toc].type) {
765 case XCURSOR_COMMENT_TYPE0xfffe0001:
766 ncomment++;
767 break;
768 case XCURSOR_IMAGE_TYPE0xfffd0002:
769 nimage++;
770 break;
771 }
772 }
773 images = XcursorImagesCreate (nimage);
774 if (!images)
775 return 0;
776 comments = XcursorCommentsCreate (ncomment);
777 if (!comments)
778 {
779 XcursorImagesDestroy (images);
780 return 0;
781 }
782 for (toc = 0; toc < fileHeader->ntoc; toc++)
783 {
784 switch (fileHeader->tocs[toc].type) {
785 case XCURSOR_COMMENT_TYPE0xfffe0001:
786 comment = _XcursorReadComment (file, fileHeader, toc);
787 if (comment)
788 {
789 comments->comments[comments->ncomment] = comment;
790 comments->ncomment++;
791 }
792 break;
793 case XCURSOR_IMAGE_TYPE0xfffd0002:
794 image = _XcursorReadImage (file, fileHeader, toc);
795 if (image)
796 {
797 images->images[images->nimage] = image;
798 images->nimage++;
799 }
800 break;
801 }
802 }
803 _XcursorFileHeaderDestroy (fileHeader);
804 if (images->nimage != nimage || comments->ncomment != ncomment)
805 {
806 XcursorImagesDestroy (images);
807 XcursorCommentsDestroy (comments);
808 images = NULL((void*)0);
809 comments = NULL((void*)0);
810 return XcursorFalse0;
811 }
812 *imagesp = images;
813 *commentsp = comments;
814 return XcursorTrue1;
815}
816
817XcursorBool
818XcursorXcFileSave (XcursorFile *file,
819 const XcursorComments *comments,
820 const XcursorImages *images)
821{
822 XcursorFileHeader *fileHeader;
823 XcursorUInt position;
824 int n;
825 int toc;
826
827 if (!file || !comments || !images)
10
Taking false branch
828 return XcursorFalse0;
829
830 fileHeader = _XcursorFileHeaderCreate (comments->ncomment + images->nimage);
11
Calling '_XcursorFileHeaderCreate'
17
Returning from '_XcursorFileHeaderCreate'
831 if (!fileHeader)
18
Taking false branch
832 return XcursorFalse0;
833
834 position = _XcursorFileHeaderLength (fileHeader);
19
Calling '_XcursorFileHeaderLength'
20
Returning from '_XcursorFileHeaderLength'
835
836 /*
837 * Compute the toc. Place the images before the comments
838 * as they're more often read
839 */
840
841 toc = 0;
842 for (n = 0; n < images->nimage; n++)
21
Loop condition is false. Execution continues on line 851
843 {
844 fileHeader->tocs[toc].type = XCURSOR_IMAGE_TYPE0xfffd0002;
845 fileHeader->tocs[toc].subtype = images->images[n]->size;
846 fileHeader->tocs[toc].position = position;
847 position += _XcursorImageLength (images->images[n]);
848 toc++;
849 }
850
851 for (n = 0; n < comments->ncomment; n++)
22
Loop condition is false. Execution continues on line 863
852 {
853 fileHeader->tocs[toc].type = XCURSOR_COMMENT_TYPE0xfffe0001;
854 fileHeader->tocs[toc].subtype = comments->comments[n]->comment_type;
855 fileHeader->tocs[toc].position = position;
856 position += _XcursorCommentLength (comments->comments[n]);
857 toc++;
858 }
859
860 /*
861 * Write the header and the toc
862 */
863 if (!_XcursorWriteFileHeader (file, fileHeader))
23
Calling '_XcursorWriteFileHeader'
864 goto bail;
865
866 /*
867 * Write the images
868 */
869 toc = 0;
870 for (n = 0; n < images->nimage; n++)
871 {
872 if (!_XcursorWriteImage (file, fileHeader, toc, images->images[n]))
873 goto bail;
874 toc++;
875 }
876
877 /*
878 * Write the comments
879 */
880 for (n = 0; n < comments->ncomment; n++)
881 {
882 if (!_XcursorWriteComment (file, fileHeader, toc, comments->comments[n]))
883 goto bail;
884 toc++;
885 }
886
887 _XcursorFileHeaderDestroy (fileHeader);
888 return XcursorTrue1;
889bail:
890 _XcursorFileHeaderDestroy (fileHeader);
891 return XcursorFalse0;
892}
893
894static int
895_XcursorStdioFileRead (XcursorFile *file, unsigned char *buf, int len)
896{
897 FILE *f = file->closure;
898 return fread (buf, 1, len, f);
899}
900
901static int
902_XcursorStdioFileWrite (XcursorFile *file, unsigned char *buf, int len)
903{
904 FILE *f = file->closure;
905 return fwrite (buf, 1, len, f);
906}
907
908static int
909_XcursorStdioFileSeek (XcursorFile *file, long offset, int whence)
910{
911 FILE *f = file->closure;
912 return fseek (f, offset, whence);
913}
914
915static void
916_XcursorStdioFileInitialize (FILE *stdfile, XcursorFile *file)
917{
918 file->closure = stdfile;
919 file->read = _XcursorStdioFileRead;
920 file->write = _XcursorStdioFileWrite;
921 file->seek = _XcursorStdioFileSeek;
922}
923
924XcursorImage *
925XcursorFileLoadImage (FILE *file, int size)
926{
927 XcursorFile f;
928
929 if (!file)
930 return NULL((void*)0);
931
932 _XcursorStdioFileInitialize (file, &f);
933 return XcursorXcFileLoadImage (&f, size);
934}
935
936XcursorImages *
937XcursorFileLoadImages (FILE *file, int size)
938{
939 XcursorFile f;
940
941 if (!file)
942 return NULL((void*)0);
943
944 _XcursorStdioFileInitialize (file, &f);
945 return XcursorXcFileLoadImages (&f, size);
946}
947
948XcursorImages *
949XcursorFileLoadAllImages (FILE *file)
950{
951 XcursorFile f;
952
953 if (!file)
954 return NULL((void*)0);
955
956 _XcursorStdioFileInitialize (file, &f);
957 return XcursorXcFileLoadAllImages (&f);
958}
959
960XcursorBool
961XcursorFileLoad (FILE *file,
962 XcursorComments **commentsp,
963 XcursorImages **imagesp)
964{
965 XcursorFile f;
966
967 if (!file || !commentsp || !imagesp)
968 return XcursorFalse0;
969
970 _XcursorStdioFileInitialize (file, &f);
971 return XcursorXcFileLoad (&f, commentsp, imagesp);
972}
973
974XcursorBool
975XcursorFileSaveImages (FILE *file, const XcursorImages *images)
976{
977 XcursorComments *comments;
978 XcursorFile f;
979 XcursorBool ret;
980
981 if (!file || !images)
982 return 0;
983 if ((comments = XcursorCommentsCreate (0)) == NULL((void*)0))
984 return 0;
985 _XcursorStdioFileInitialize (file, &f);
986 ret = XcursorXcFileSave (&f, comments, images) && fflush (file) != EOF(-1);
987 XcursorCommentsDestroy (comments);
988 return ret;
989}
990
991XcursorBool
992XcursorFileSave (FILE * file,
993 const XcursorComments *comments,
994 const XcursorImages *images)
995{
996 XcursorFile f;
997
998 if (!file || !comments || !images)
8
Taking false branch
999 return XcursorFalse0;
1000
1001 _XcursorStdioFileInitialize (file, &f);
1002 return XcursorXcFileSave (&f, comments, images) && fflush (file) != EOF(-1);
9
Calling 'XcursorXcFileSave'
1003}
1004
1005XcursorImage *
1006XcursorFilenameLoadImage (const char *file, int size)
1007{
1008 FILE *f;
1009 XcursorImage *image;
1010
1011 if (!file || size < 0)
1012 return NULL((void*)0);
1013
1014 f = fopen (file, "r");
1015 if (!f)
1016 return NULL((void*)0);
1017 image = XcursorFileLoadImage (f, size);
1018 fclose (f);
1019 return image;
1020}
1021
1022XcursorImages *
1023XcursorFilenameLoadImages (const char *file, int size)
1024{
1025 FILE *f;
1026 XcursorImages *images;
1027
1028 if (!file || size < 0)
1029 return NULL((void*)0);
1030
1031 f = fopen (file, "r");
1032 if (!f)
1033 return NULL((void*)0);
1034 images = XcursorFileLoadImages (f, size);
1035 fclose (f);
1036 return images;
1037}
1038
1039XcursorImages *
1040XcursorFilenameLoadAllImages (const char *file)
1041{
1042 FILE *f;
1043 XcursorImages *images;
1044
1045 if (!file)
1046 return NULL((void*)0);
1047
1048 f = fopen (file, "r");
1049 if (!f)
1050 return NULL((void*)0);
1051 images = XcursorFileLoadAllImages (f);
1052 fclose (f);
1053 return images;
1054}
1055
1056XcursorBool
1057XcursorFilenameLoad (const char *file,
1058 XcursorComments **commentsp,
1059 XcursorImages **imagesp)
1060{
1061 FILE *f;
1062 XcursorBool ret;
1063
1064 if (!file)
1065 return XcursorFalse0;
1066
1067 f = fopen (file, "r");
1068 if (!f)
1069 return 0;
1070 ret = XcursorFileLoad (f, commentsp, imagesp);
1071 fclose (f);
1072 return ret;
1073}
1074
1075XcursorBool
1076XcursorFilenameSaveImages (const char *file, const XcursorImages *images)
1077{
1078 FILE *f;
1079 XcursorBool ret;
1080
1081 if (!file || !images)
1082 return XcursorFalse0;
1083
1084 f = fopen (file, "w");
1085 if (!f)
1086 return 0;
1087 ret = XcursorFileSaveImages (f, images);
1088 return fclose (f) != EOF(-1) && ret;
1089}
1090
1091XcursorBool
1092XcursorFilenameSave (const char *file,
1093 const XcursorComments *comments,
1094 const XcursorImages *images)
1095{
1096 FILE *f;
1097 XcursorBool ret;
1098
1099 if (!file || !comments || !images)
1
Assuming 'file' is non-null
2
Assuming 'comments' is non-null
3
Assuming 'images' is non-null
4
Taking false branch
1100 return XcursorFalse0;
1101
1102 f = fopen (file, "w");
1103 if (!f)
5
Assuming 'f' is non-null
6
Taking false branch
1104 return 0;
1105 ret = XcursorFileSave (f, comments, images);
7
Calling 'XcursorFileSave'
1106 return fclose (f) != EOF(-1) && ret;
1107}