Make error checking more robust, so that the resulting image is more trustworthy (especially when generated automatically, such as on a build server). The program will now return an exit code of 0 only if everything went perfectly. Warnings (skipping files or directories, but still producing a well-formed image) are printed on stderr, and the error code will be |= 2. Errors (a well-formed image could not be created) have an error code |= 1. Index: mkyaffs2image/mkyaffs2image.c =================================================================== --- mkyaffs2image.orig/mkyaffs2image.c 2010-08-26 14:08:27.000000000 -0600 +++ mkyaffs2image/mkyaffs2image.c 2010-08-26 16:48:46.000000000 -0600 @@ -64,9 +64,25 @@ static int outFile; static int error; +static int savedErrno; static int convert_endian = 0; +static void fatal(const char *fn) +{ + perror(fn); + error |= 1; + exit(error); +} + +static int warn(const char *fn) +{ + savedErrno = errno; + perror(fn); + error |= 2; + return error; +} + static int obj_compare(const void *a, const void * b) { objItem *oa, *ob; @@ -98,7 +114,7 @@ { // oops! not enough space in the object array fprintf(stderr,"Not enough space in object array\n"); - exit(2); + exit(1); } } @@ -169,8 +185,8 @@ yaffs_PackedTags2 pt; char spareData[spareSize]; - error = write(outFile,data,chunkSize); - if(error < 0) return error; + if (write(outFile,data,chunkSize) != chunkSize) + fatal("write"); yaffs_InitialiseTags(&t); @@ -198,8 +214,9 @@ memset(spareData, 0xff, sizeof(spareData)); shuffle_oob(spareData, &pt); - return write(outFile,spareData,sizeof(spareData)); - + if (write(outFile,spareData,sizeof(spareData)) != sizeof(spareData)) + fatal("write"); + return 0; } #define SWAP32(x) ((((x) & 0x000000FF) << 24) | \ @@ -282,7 +299,10 @@ oh->parentObjectId = parent; if (strlen(name)+1 > sizeof(oh->name)) - return -1; + { + errno = ENAMETOOLONG; + return warn("object name"); + } memset(oh->name,0,sizeof(oh->name)); strcpy(oh->name,name); @@ -312,7 +332,10 @@ if(t == YAFFS_OBJECT_TYPE_SYMLINK) { if (strlen(alias)+1 > sizeof(oh->alias)) - return -1; + { + errno = ENAMETOOLONG; + return warn("object alias"); + } memset(oh->alias,0,sizeof(oh->alias)); strcpy(oh->alias,alias); } @@ -336,8 +359,11 @@ nDirectories++; dir = opendir(path); - - if(dir) + if(!dir) + { + warn("opendir"); + } + else { while((entry = readdir(dir)) != NULL) { @@ -357,7 +383,11 @@ continue; } - lstat(full_name,&stats); + if (lstat(full_name,&stats) < 0) + { + warn("lstat"); + continue; + } if(S_ISLNK(stats.st_mode) || S_ISREG(stats.st_mode) || @@ -378,7 +408,7 @@ { /* we need to make a hard link */ printf("hard link to object %d\n",equivalentObj); - error = write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL); + write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL); } else { @@ -392,18 +422,20 @@ memset(symname,0, sizeof(symname)); - readlink(full_name,symname,sizeof(symname) -1); - - printf("symlink to \"%s\"\n",symname); - error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname); - + if (readlink(full_name,symname,sizeof(symname) -1) < 0) + { + warn("readlink"); + } + else + { + printf("symlink to \"%s\"\n",symname); + write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname); + } } else if(S_ISREG(stats.st_mode)) { printf("file, "); - error = write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL); - - if(error >= 0) + if(write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL) == 0) { int h; __u8 bytes[chunkSize]; @@ -421,14 +453,14 @@ memset(bytes,0xff,sizeof(bytes)); } if(nBytes < 0) - error = nBytes; + warn("read"); printf("%d data chunks written\n",chunk); close(h); } else { - perror("Error opening file"); + warn("open"); } } @@ -437,35 +469,36 @@ else if(S_ISSOCK(stats.st_mode)) { printf("socket\n"); - error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); + write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); } else if(S_ISFIFO(stats.st_mode)) { printf("fifo\n"); - error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); + write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); } else if(S_ISCHR(stats.st_mode)) { printf("character device\n"); - error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); + write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); } else if(S_ISBLK(stats.st_mode)) { printf("block device\n"); - error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); + write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL); } else if(S_ISDIR(stats.st_mode)) { printf("directory\n"); - error = write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL); -// NCB modified 10/9/2001 process_directory(1,full_name); - process_directory(newObj,full_name); + if (write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL) == 0) + process_directory(newObj,full_name); } } } else { - printf(" we don't handle this type\n"); + fprintf(stderr, "%s: unhandled type\n", full_name); + error |= 2; + savedErrno = EINVAL; } } } @@ -519,16 +552,15 @@ } printf("Processing directory %s into image file %s\n",argv[1],argv[2]); - error = write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL); - if(error) - error = process_directory(YAFFS_OBJECTID_ROOT,argv[1]); + if(write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL) == 0) + process_directory(YAFFS_OBJECTID_ROOT,argv[1]); close(outFile); - if(error < 0) + if(error) { + errno = savedErrno; perror("operation incomplete"); - exit(1); } else { @@ -537,6 +569,6 @@ "%d NAND pages\n",nObjects, nDirectories, nPages); } - exit(0); + exit(error); }