int good_strcmp (const char* str1, const char* str2) { int len = strlen (str1); if (len != strlen (str2)) return -1; return my_memcmp (str1, str2, len); }
bool verify_cleanliness_of_clean_buffer(struct FS_Buffer_Cache * cache, struct FS_Buffer * buf) { struct FS_Buffer dupe_buffer; if (buf->flags & FS_BUFFER_DIRTY) { return 1; } else { dupe_buffer.data = Malloc(cache->fsBlockSize); if (dupe_buffer.data != NULL) { dupe_buffer.fsBlockNum = buf->fsBlockNum; /* Read block data into buffer. */ Do_Buffer_IO(cache, &dupe_buffer, Block_Read); if (my_memcmp(buf->data, dupe_buffer.data, cache->fsBlockSize) == 0) { Free(dupe_buffer.data); return 1; } else { Free(dupe_buffer.data); return 0; } return 1; } else { /* assume it's good, we're oom. */ return 1; } } }
char do_div(t_nb *res, t_nb *n1, t_nb *n2, t_base *s_base) { t_nb *tmp; t_nb *to_free; int cmp; if (!(tmp = mk_zero(s_base->base[0]))) return (-1); cmp = 0; while (n1->len > tmp->len || (tmp->len == n1->len && (cmp = my_memcmp(tmp->nb, n1->nb, n1->len)) < 0)) { add_one(res, n1->len, s_base->base_len); to_free = tmp; if (!(tmp = inf_add(tmp, n2, s_base, 0))) return (-1); free(to_free->nb); free(to_free); } if (n1->len < tmp->len || cmp > 0) sub_one(res, n1->len, s_base->base_len); free(tmp->nb); free(tmp); return (0); }
int main() { char arr11[] = {0, '1', '5', '6', '9'}; char arr12[] = {0, '1', '2', '6', '9'}; char arr21[] = {0, 1, '\0', 4, 5}; char arr22[] = {0, 1, 'a', 'b', 'c'}; char arr31[] = {0, 1, 2, 3, 4}; char arr32[] = {0, 1, 2, 3, 4}; printf("arr11[]={\\0,1,5,6,9} \narr12[]={\\0,1,2,6,9} \nmy_memcmp()=%d\n\n", my_memcmp(arr11, arr12, 5)); printf("arr21[]={\\0,1,\\0,4,5} \narr22[]={\\0,1,a,b,c} \nmy_memcmp()=%d\n\n", my_memcmp(arr21, arr22, 5)); printf("arr31[]={\\0,1,2,3,4} \narr32[]={\\0,1,2,3,4} \nmy_memcmp()=%d\n\n", my_memcmp(arr31, arr32, 5)); return 0; }
/* 查找并返回s2字符串在s1的起始地址 */ char *my_strstr(const char *s1, const char *s2) { int n = my_strlen(s2); while (*s1 != '\0') { if (!my_memcmp(s1++, s2, n)) { return (char *)s1 - 1; } } return nullptr; }
int main () { printf ("== Launching sanity test ==\n"); assert (my_memcpy (NULL, NULL, 0) == NULL); assert (my_memcmp (NULL, NULL, 0) == 0); assert (my_memset (NULL, 0, 0) == NULL); printf ("== Sanity test succeded ==\n"); return 0; }
/***************************************************************************************** * WriteEepromBytes * Function : Write data into EEPROM at addr * Action : * Input : addr--the address which start to Write, buffer--the pointer to buffer used to store data len-- the length of data needed to read * Output : None * Return : 1--success 0--fail *****************************************************************************************/ uint8 WriteEepromBytes(const void *buffer, uint16 addr, uint16 lenth)//(uint16 addr, const void *buffer, uint16 lenth) { uint16 repeat, bleng; uint8 cbak[EE_PAGELEN]; if (lenth == 0) { return FALSE; } do { //(addr % EE_PAGELEN) 已经写完的长度 if(((addr % EE_PAGELEN) + lenth) > EE_PAGELEN) //已经写的长度加上要写数据的长度大于一页的长度 { bleng = EE_PAGELEN - (addr % EE_PAGELEN); lenth -= bleng;//下一页需要多少长度 } else //比一页的长度小 则直接赋值 { bleng = lenth; lenth = 0; } for(repeat = 3; repeat!= 0; repeat--) { read_IIC_bytes(cbak, EEPROM_DEV, addr, bleng);//(addr, cbak, bleng, EEPROM_DEV) if(my_memcmp((uint8*)buffer, cbak, bleng)==0)//比较buffer和cbak在bleng个字节的值 { repeat = 3; // wirte ok! break; // if the data is same,break } if(!Write_IIC_Bytes(buffer, EEPROM_DEV, addr, bleng))//(addr, buffer, bleng, EEPROM_DEV)) { return FALSE; } } if(0 == repeat) { return FALSE; } buffer = (uint8 *)buffer + bleng; addr += bleng; }while(lenth != 0); return TRUE; }
int cam_gen(t_data *data) { t_cam cam; t_cam old; t_bunny_position origin; cam_init_gen(data, &old, &origin); while (cam_path_read(data->path, &cam) == 0) { data->pix = data->big; data->obj.cam = cam; if (my_memcmp(&cam, &old, sizeof(t_cam)) != 0) gen_scene(data); old = cam; if (jif_add(data->jif, data->pix)) return (1); bunny_blit(&data->win->buffer, &data->pix->clipable, &origin); bunny_display(data->win); } return (0); }
void add_memfilechunk(MemFile *compare, MemFile *current, char *buf, unsigned int size) { static MemFileChunk *compchunk=NULL; MemFileChunk *curchunk; /* this function inits when compare != NULL or when current==NULL */ if(compare) { compchunk= compare->chunks.first; return; } if(current==NULL) { compchunk= NULL; return; } curchunk= MEM_mallocN(sizeof(MemFileChunk), "MemFileChunk"); curchunk->size= size; curchunk->buf= NULL; curchunk->ident= 0; BLI_addtail(¤t->chunks, curchunk); /* we compare compchunk with buf */ if(compchunk) { if(compchunk->size == curchunk->size) { if( my_memcmp((int *)compchunk->buf, (int *)buf, size/4)==0) { curchunk->buf= compchunk->buf; curchunk->ident= 1; } } compchunk= compchunk->next; } /* not equal... */ if(curchunk->buf==NULL) { curchunk->buf= MEM_mallocN(size, "Chunk buffer"); memcpy(curchunk->buf, buf, size); current->size += size; } }
static void sigusr1_handler( int signo, siginfo_t *info, void *context ) { ssize_t recvlen; char mybuf[20]; unsigned int myprio; mqd_t *q = (mqd_t *)info->si_value.sival_ptr; CYG_TEST_PASS_FAIL( SIGUSR1 == signo, "correct signal number #1" ); CYG_TEST_PASS_FAIL( SIGUSR1 == info->si_signo, "correct signal number #2" ); CYG_TEST_PASS_FAIL( SI_MESGQ == info->si_code, "correct signal code" ); signals++; // retrieve message and compare with buf recvlen = mq_receive( *q, mybuf, sizeof(mybuf), &myprio ); CYG_TEST_PASS_FAIL( recvlen == my_strlen(buf), "receive message length" ); CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, mybuf, my_strlen(buf)), "received message data intact" ); CYG_TEST_PASS_FAIL( prio == myprio, "received at correct priority" ); }
int main(void) { #if 0 unsigned long a, b; printf("input a :"); scanf("%ld", &a); printf("input b :"); scanf("%ld", &b); printf("gcd(%ld,%ld) = %ld\n", a, b, gcd(a, b)); #endif char dst[100]; char *src = "hello world\n"; char *tmp = dst; int i, count; printf("input count : "); scanf("%d", &count); for(i = 0; i < sizeof(dst); i++) dst[i] = i; while(count) { if((*tmp = *src) != 0) src++; tmp++; count--; } for(i = 0; i < sizeof(dst); i++) printf((i+1)%16 ? "%.2x " : "%.2x\n", dst[i]); printf("\nmemcmp = %d\n", my_memcmp("aahh", "aaa", 3)); return 0; }
int main(void) { mqd_t q1, q2; char buf[20]; ssize_t recvlen; unsigned int prio; struct mq_attr attr, oattr; mode_t mode; int err; CYG_TEST_INIT(); CYG_TEST_INFO( "Starting POSIX message test 1" ); q1 = mq_open( "/mq1", O_RDWR ); CYG_TEST_PASS_FAIL( q1 == (mqd_t)-1, "error for non-existent queue" ); CYG_TEST_PASS_FAIL( ENOENT == errno, "errno correct for non-existent queue" ); attr.mq_flags = 0; attr.mq_maxmsg = 4; attr.mq_msgsize = 20; mode = S_IRWXU|S_IRWXG|S_IRWXO; // rwx for all q1 = mq_open( "/mq1", O_CREAT|O_NONBLOCK|O_WRONLY, mode, &attr ); CYG_TEST_PASS_FAIL( q1 != (mqd_t)-1, "simple mq_open (write only)" ); err = mq_getattr( q1, &attr ); CYG_TEST_PASS_FAIL( 0 == err, "simple mq_getattr" ); CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && (20 == attr.mq_msgsize) && (O_NONBLOCK == (attr.mq_flags & O_NONBLOCK)) && (O_RDONLY != (attr.mq_flags & O_RDONLY)) && (O_WRONLY == (attr.mq_flags & O_WRONLY)) && (O_RDWR != (attr.mq_flags & O_RDWR)) && (0 == attr.mq_curmsgs ), "getattr attributes correct" ); err = mq_send( q1, "Vik is brill", sizeof("Vik is brill"), 10 ); CYG_TEST_PASS_FAIL( 0 == err, "simple mq_send" ); err = mq_getattr( q1, &attr ); CYG_TEST_PASS_FAIL( 0 == err, "simple mq_getattr after send" ); CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && (20 == attr.mq_msgsize) && (O_NONBLOCK == (attr.mq_flags & O_NONBLOCK)) && (O_RDONLY != (attr.mq_flags & O_RDONLY)) && (O_WRONLY == (attr.mq_flags & O_WRONLY)) && (O_RDWR != (attr.mq_flags & O_RDWR)) && (1 == attr.mq_curmsgs ), "getattr attributes correct #2" ); q2 = mq_open( "/mq1", O_RDONLY|O_CREAT|O_EXCL ); CYG_TEST_PASS_FAIL( q2 == (mqd_t)-1, "error for exclusive open of existing queue" ); CYG_TEST_PASS_FAIL( EEXIST == errno, "errno correct for exclusive open of existing queue" ); q2 = mq_open( "/mq1", O_RDONLY ); CYG_TEST_PASS_FAIL( q2 != (mqd_t)-1, "simple mq_open (read only)" ); err = mq_getattr( q2, &attr ); CYG_TEST_PASS_FAIL( 0 == err, "simple mq_getattr, different mqd_t" ); CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && (20 == attr.mq_msgsize) && (O_NONBLOCK != (attr.mq_flags & O_NONBLOCK)) && (O_RDONLY == (attr.mq_flags & O_RDONLY)) && (O_WRONLY != (attr.mq_flags & O_WRONLY)) && (O_RDWR != (attr.mq_flags & O_RDWR)) && (1 == attr.mq_curmsgs ), "getattr attributes correct #3" ); err = mq_close( q2 ); CYG_TEST_PASS_FAIL( 0 == err, "simple mq_close" ); q2 = mq_open( "/mq1", O_RDONLY ); CYG_TEST_PASS_FAIL( q2 != (mqd_t)-1, "mq_open reopen (read only)" ); err = mq_getattr( q2, &attr ); CYG_TEST_PASS_FAIL( 0 == err, "simple mq_getattr, different mqd_t" ); CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && (20 == attr.mq_msgsize) && (O_NONBLOCK != (attr.mq_flags & O_NONBLOCK)) && (O_RDONLY == (attr.mq_flags & O_RDONLY)) && (O_WRONLY != (attr.mq_flags & O_WRONLY)) && (O_RDWR != (attr.mq_flags & O_RDWR)) && (1 == attr.mq_curmsgs ), "getattr attributes correct #4" ); recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); CYG_TEST_PASS_FAIL( recvlen == sizeof("Vik is brill"), "receive message length" ); CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, "Vik is brill", sizeof("Vik is brill")), "received message data intact" ); CYG_TEST_PASS_FAIL( 10 == prio, "received at correct priority" ); err = mq_getattr( q1, &attr ); CYG_TEST_PASS_FAIL( 0 == err, "simple mq_getattr after send" ); CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && (20 == attr.mq_msgsize) && (O_NONBLOCK == (attr.mq_flags & O_NONBLOCK)) && (O_RDONLY != (attr.mq_flags & O_RDONLY)) && (O_WRONLY == (attr.mq_flags & O_WRONLY)) && (O_RDWR != (attr.mq_flags & O_RDWR)) && (0 == attr.mq_curmsgs ), "getattr attributes correct #5" ); attr.mq_flags |= O_NONBLOCK; err = mq_setattr( q2, &attr, &oattr ); CYG_TEST_PASS_FAIL( 0 == err, "mq_setattr O_NONBLOCK" ); CYG_TEST_PASS_FAIL( (4 == oattr.mq_maxmsg) && (20 == oattr.mq_msgsize) && (O_NONBLOCK != (oattr.mq_flags & O_NONBLOCK)) && (O_RDONLY == (oattr.mq_flags & O_RDONLY)) && (O_WRONLY != (oattr.mq_flags & O_WRONLY)) && (O_RDWR != (oattr.mq_flags & O_RDWR)) && (0 == oattr.mq_curmsgs ), "old attribute correct" ); err = mq_getattr( q2, &attr ); CYG_TEST_PASS_FAIL( 0 == err, "mq_getattr after O_NONBLOCK" ); CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && (20 == attr.mq_msgsize) && (O_NONBLOCK == (attr.mq_flags & O_NONBLOCK)) && (O_RDONLY == (attr.mq_flags & O_RDONLY)) && (O_WRONLY != (attr.mq_flags & O_WRONLY)) && (O_RDWR != (attr.mq_flags & O_RDWR)) && (0 == attr.mq_curmsgs ), "new attribute correct" ); recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); CYG_TEST_PASS_FAIL( recvlen == (ssize_t)-1, "mq_receive, empty buffer, non-blocking" ); CYG_TEST_PASS_FAIL( EAGAIN == errno, "errno correct for non-blocking" ); err = mq_send( q2, "foo", sizeof("foo"), 1 ); CYG_TEST_PASS_FAIL( -1 == err, "error on mq_send on read-only descriptor" ); CYG_TEST_PASS_FAIL( EBADF == errno, "errno correct for mq_send on r/o descriptor" ); err = mq_send( q2, "supercalifragilisticexpealidocious", 21, 2 ); CYG_TEST_PASS_FAIL( -1 == err, "error on mq_send (message too long)" ); CYG_TEST_PASS_FAIL( EMSGSIZE == errno, "errno correct for mq_send (message too long)" ); err = mq_send( q1, "", sizeof(""), 5 ); CYG_TEST_PASS_FAIL( 0 == err, "mq_send \"\"" ); err = mq_send( q1, "I love Vik", sizeof("I love Vik"), 7 ); CYG_TEST_PASS_FAIL( 0 == err, "mq_send (different priority)" ); err = mq_send( q1, "a lot!", sizeof("a lot!"), 7 ); CYG_TEST_PASS_FAIL( 0 == err, "mq_send (same priority)" ); err = mq_send( q1, "Vik is a babe", sizeof("Vik is a babe"), 6 ); CYG_TEST_PASS_FAIL( 0 == err, "mq_send (middle priority)" ); err = mq_send( q1, "wibble", sizeof("wibble"), 6 ); CYG_TEST_PASS_FAIL( -1 == err, "error on mq_send with full queue" ); CYG_TEST_PASS_FAIL( EAGAIN == errno, "errno correct for mq_send full queue" ); err = mq_getattr( q2, &attr ); CYG_TEST_PASS_FAIL( 0 == err, "mq_getattr after sends" ); CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && (20 == attr.mq_msgsize) && (O_NONBLOCK == (attr.mq_flags & O_NONBLOCK)) && (O_RDONLY == (attr.mq_flags & O_RDONLY)) && (O_WRONLY != (attr.mq_flags & O_WRONLY)) && (O_RDWR != (attr.mq_flags & O_RDWR)) && (4 == attr.mq_curmsgs ), "getattr attributes correct #5" ); recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); CYG_TEST_PASS_FAIL( recvlen == sizeof("I love Vik"), "receive message length (prioritized) #1" ); CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, "I love Vik", sizeof("I love Vik")), "received message data intact (prioritized) #1" ); CYG_TEST_PASS_FAIL( 7 == prio, "received at correct priority (prioritized) #1" ); recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); CYG_TEST_PASS_FAIL( recvlen == sizeof("a lot!"), "receive message length (prioritized) #2" ); CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, "a lot!", sizeof("a lot!")), "received message data intact (prioritized) #2" ); CYG_TEST_PASS_FAIL( 7 == prio, "received at correct priority (prioritized) #2" ); recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); CYG_TEST_PASS_FAIL( recvlen == sizeof("Vik is a babe"), "receive message length (prioritized) #3" ); CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, "Vik is a babe", sizeof("Vik is a babe")), "received message data intact (prioritized) #3" ); CYG_TEST_PASS_FAIL( 6 == prio, "received at correct priority (prioritized) #3" ); recvlen = mq_receive( q2, buf, 0, &prio ); CYG_TEST_PASS_FAIL( recvlen == (ssize_t)-1, "mq_receive, zero-sized buffer" ); recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); CYG_TEST_PASS_FAIL( recvlen == sizeof(""), "receive message length (prioritized) #4" ); CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, "", sizeof("")), "received message data intact (prioritized) #4" ); CYG_TEST_PASS_FAIL( 5 == prio, "received at correct priority (prioritzed) #4" ); recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); CYG_TEST_PASS_FAIL( recvlen == (ssize_t)-1, "mq_receive, empty buffer, non-blocking #2" ); CYG_TEST_PASS_FAIL( EAGAIN == errno, "errno correct for non-blocking #2" ); err = mq_send( q1, "12345678901234567890", 20, 15 ); CYG_TEST_PASS_FAIL( 0 == err, "mq_send (before closing)" ); err = mq_unlink( "/foo" ); CYG_TEST_PASS_FAIL( -1 == err, "mq_unlink (wrong name)" ); CYG_TEST_PASS_FAIL( ENOENT == errno, "errno correct for mq_unlink (wrong name)" ); err = mq_unlink( "/mq1" ); CYG_TEST_PASS_FAIL( 0 == err, "mq_unlink (before closing)" ); err = mq_close( q1 ); CYG_TEST_PASS_FAIL( 0 == err, "mq_close (send descriptor)" ); recvlen = mq_receive( q2, buf, sizeof(buf), &prio ); CYG_TEST_PASS_FAIL( recvlen == 20, "receive message length (mid close)" ); CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, "12345678901234567890", 20 ), "received message data intact (mid close)" ); CYG_TEST_PASS_FAIL( 15 == prio, "received at correct priority (mid close)" ); err = mq_close( q2 ); CYG_TEST_PASS_FAIL( 0 == err, "mq_close (receive descriptor)" ); q1 = mq_open( "/mq1", O_RDONLY ); CYG_TEST_PASS_FAIL( q1 == (mqd_t)-1, "error for non-existent queue" ); CYG_TEST_PASS_FAIL( ENOENT == errno, "errno correct for non-existent queue" ); CYG_TEST_EXIT("POSIX message test 1"); return 0; } // main()
/************************************************************************* * GET THE NEXT DIRECTORY ENTRY FROM A DIRECTORY BLOCK * * - This procedure uses static local variables * - These variables are initialized by setting "first_time" to TRUE * - Entries, which are zeroed, are skipped. * - If we get a new block-number which was previously used as an active * directory-block and is referred more than one time in the reference * bit-map, we skip it. * - All blocks used are marked as being used * * Parameters : parent = Pointer to the parent directory entry * first_time = Init flag * block = pointer to var to hold the actual block number * off = pointer to var to hold the actual offset (index) * Return : A pointer to the entry or NULL, if no more valid blocks * are available. This signals the end of the inspection * *************************************************************************/ struct dir_elem * get_next_entry ( struct inode *parent, word first_time, daddr_t *block, word *off ) { static word index; static struct buf *bp; static word bnr, empty; /* get_next_entry is called the */ if ( first_time ) /* first time */ { #if DEBUG IOdebug (" get_next_entry : First time initialization."); #endif index = 0; /* Initialization of index */ empty = 0; /* No empty entry at first */ } #if DEBUG IOdebug (" get_next_entry : Get a new entry."); #endif /* An unknown number of blocks */ for ( ;; ) /* referred by the dir-blks */ { /* Scan all directory entries */ for ( ; index < i_fs.fs_maxdpb ; index++ ) { if ( index == 0 ) /* Beginning of a new block ? */ { /* After first try, we have to */ /* release previously used blks */ if ( ! first_time ) { if ( changes_de ) { #if DEBUG IOdebug (" get_next_entry : Update modified directory-block on disk."); #endif test_bwrite ( bp ); } else { #if DEBUG IOdebug (" get_next_entry : Release non modified directory-block"); #endif brelse ( bp->b_tbp, TAIL ); } } /* Loop until we get an "unused"*/ /* and single referred block-num*/ for ( ;; ) { /* Get a "new" blocknumber */ bnr = get_next_bnr ( parent, first_time, FALSE ); /* We have reached the last blk */ if ( bnr == 0 ) /* The last entry in this di - */ /* rectory was reached: */ return (struct dir_elem *) NULL; /* Multiple use of this block ? */ if ( bitmap_get_used (bnr) && bitmap_get (bnr) > 1 ) { #if DEBUG IOdebug (" get_next_entry : Skip over multiple referred dir-block."); #endif first_time = FALSE; continue; } else /* We have a usable block-num */ break; } /* Mark the block as being used */ bitmap_set_used (bnr); /* Read the block into memory */ bp = bread ( 0, bnr, 1, SAVEA ); changes_de = 0; /* Nothing changed so far... */ } /* Wiped out content ? ( A mode-field */ /* set to FREE is ignored, because it */ /* could be an error. ) */ if ( ! my_memcmp ( (void *) &dir_cmp, (void *) &bp->b_un.b_dir[index], sizeof (struct dir_elem) ) ) { empty++; /* Another empty slot found */ continue; /* Get the next entry */ } *block = bnr; /* Save block-number and index */ *off = index; index++; /* Next entry */ /* Return the new entry */ return &bp->b_un.b_dir[*off]; } /* end of <for (index)> */ /* After examination of a whole */ /* block we check whether we */ /* have found any non-zeroed */ /* directory entry. */ if ( empty == i_fs.fs_maxdpb ) { #if DEBUG IOdebug (" get_next_entry : Block %d is totally empty", bnr ); #endif first_time = FALSE; /* To prevent get_next_bnr() */ /* from another initialization */ } empty = 0; /* We have no empty entries at */ /* first again. */ index = 0; /* Start-position in a new */ /* directory block */ } /* end of <for (;;)> */ }
int main(void) { mqd_t q1; struct mq_attr attr; mode_t mode; int err; ssize_t recvlen; char mybuf[20]; unsigned int myprio; struct sigevent ev; struct sigaction act; CYG_TEST_INIT(); CYG_TEST_INFO( "Starting POSIX message test 2" ); #if 0 if ( 0 != pthread_create( &thr, NULL, &thread, NULL ) ) { CYG_TEST_FAIL_FINISH( "Couldn't create a helper thread" ); } #endif attr.mq_flags = 0; attr.mq_maxmsg = 4; attr.mq_msgsize = 20; mode = S_IRWXU|S_IRWXG|S_IRWXO; // rwx for all q1 = mq_open( "/mq1", O_CREAT|O_NONBLOCK|O_RDWR, mode, &attr ); CYG_TEST_PASS_FAIL( q1 != (mqd_t)-1, "simple mq_open (write only)" ); err = mq_getattr( q1, &attr ); CYG_TEST_PASS_FAIL( 0 == err, "simple mq_getattr" ); CYG_TEST_PASS_FAIL( (4 == attr.mq_maxmsg) && (20 == attr.mq_msgsize) && (O_NONBLOCK == (attr.mq_flags & O_NONBLOCK)) && (O_RDWR == (attr.mq_flags & O_RDWR)) && (0 == attr.mq_curmsgs ), "getattr attributes correct" ); act.sa_sigaction = &sigusr1_handler; sigfillset( &act.sa_mask ); // enable all signals act.sa_flags = SA_SIGINFO; if ( 0 != sigaction( SIGUSR1, &act, NULL ) ) { CYG_TEST_FAIL_FINISH( "Couldn't register signal handler" ); } ev.sigev_notify = SIGEV_SIGNAL; ev.sigev_signo = SIGUSR1; ev.sigev_value.sival_ptr = (void *)&q1; err = mq_notify( q1, &ev ); CYG_TEST_PASS_FAIL( 0 == err, "simple mq_notify" ); my_strcpy( buf, "Vik is the best" ); prio = 7; err = mq_send( q1, buf, my_strlen(buf), prio ); CYG_TEST_PASS_FAIL( 0 == err, "mq_send #1" ); CYG_TEST_PASS_FAIL( 1 == signals, "got notification" ); my_strcpy( buf, "Scrummy Vik" ); prio = 6; err = mq_send( q1, buf, my_strlen(buf), prio ); CYG_TEST_PASS_FAIL( 0 == err, "mq_send #2" ); CYG_TEST_PASS_FAIL( 1 == signals, "correctly didn't get notification" ); recvlen = mq_receive( q1, mybuf, sizeof(mybuf), &myprio ); CYG_TEST_PASS_FAIL( recvlen == my_strlen(buf), "receive message length" ); CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, mybuf, my_strlen(buf)), "received message data intact" ); CYG_TEST_PASS_FAIL( prio == myprio, "received at correct priority" ); err = mq_notify( q1, &ev ); CYG_TEST_PASS_FAIL( 0 == err, "mq_notify #2" ); err = mq_notify( q1, &ev ); CYG_TEST_PASS_FAIL( -1 == err, "second mq_notify returns error" ); CYG_TEST_PASS_FAIL( EBUSY == errno, "errno correct for second mq_notify error" ); err = mq_notify( q1, NULL ); CYG_TEST_PASS_FAIL( 0 == err, "clear notification" ); my_strcpy( buf, "Vik is k3wl" ); prio = 8; err = mq_send( q1, buf, my_strlen(buf), prio ); CYG_TEST_PASS_FAIL( 0 == err, "mq_send #2" ); CYG_TEST_PASS_FAIL( 1 == signals, "correctly didn't get notification #2" ); recvlen = mq_receive( q1, mybuf, sizeof(mybuf), &myprio ); CYG_TEST_PASS_FAIL( recvlen == my_strlen(buf), "receive message length" ); CYG_TEST_PASS_FAIL( 0 == my_memcmp( buf, mybuf, my_strlen(buf)), "received message data intact" ); CYG_TEST_PASS_FAIL( prio == myprio, "received at correct priority" ); err = mq_close( q1 ); CYG_TEST_PASS_FAIL( 0 == err, "mq_close" ); err = mq_unlink( "/mq1" ); CYG_TEST_PASS_FAIL( 0 == err, "mq_unlink" ); CYG_TEST_EXIT("POSIX message test 2"); return 0; } // main()
/************************************************************************ * BASIC TEST ROUTINES TO CHECK UNIQUE DATA STRUCTURES LIKE SUPERBLOCK AND * ROOT DIRECTORY AND GET MEMORY FOR THE CHECKER * * - Make sure, that the superblock and all copies are valid. * * THIS TEST HAS BEEN REMOVED FROM THE BASIC VERSION, BECAUSE THE SUPERBLOCK * DATA IS ACTUALLY NOT USED BY THE FILE-SERVER. ALL DATA, DESCRIBING A FILE * SYSTEM IS DERIVED FROM 'devinfo'. ON THE OTHER SIDE, IT IS A NON-TRIVIAL * TASK TO FIND OTHER, EVENTUALLY PARTLY DAMAGED SUPERBLOCKS ON THE MEDIA TO * BE CHECKED. TO HAVE A BASIC IDEA, WHETHER THE RELEVANT DATA (number of * cyl.groups, cyl.group size and cyl.group offset) KEPT IN THE 'devinfo'- * FILE AND ON DISK DESCRIBE THE SAME PHYSICAL DISK, THEY ARE COMPARED FOR * ALL CYLINDER-GROUPS. * * - Compare the # number of free blocks in the bit-maps with the * values, referenced in the cylinder group info structs. * - Allocate all needed memory for the checker. * - Check the root-directory inode and look for the /lost+found - directory * * Parameter : - nothing - * Return : TRUE = no error at all * FALSE = occurrence of a fatal error * *************************************************************************/ word check_unique ( void ) { struct fs tmp; /* For intermediate operation */ struct buf *bp, *bp_2; word cgnr, i, j, c, free_cnt, ecnt, try, off; /*--------- Make a basic comparison of file-system parameters ---------*/ IOdebug ("%s*** Step 1.1 : Plausibility test of file-system parameters", S_INFO); /* cgnr and ncg are the values */ /* taken from devinfo. If no */ /* valid superblock is found */ /* there or the disk parameters */ /* are different, the checking */ /* process is aborted. */ /* Make incore copies of the */ /* superblock data into i_fs and*/ /* incore_fs. */ /*------------------ Tests on the super-block -------------------------*/ /* We have to copy the first */ /* superblock from the cg 0 info-block. */ bp = bread ( 0, 2, 1, SAVEA ); memcpy ( &tmp, &bp->b_un.b_info->fs, sizeof (struct fs) ); brelse ( bp->b_tbp, TAIL ); /* Run until we have a valid copy and */ /* scan the cylinder groups */ for ( cgnr = 0 , try = -1 ;; cgnr++ ) { corrupt_cnt = 0; /* At the beginning: no errors at all */ try++; /* Count the tries which are needed to */ /* get a valid super-block. */ #if DEBUG IOdebug (" check_unique : Try to validate a sample superblock."); #endif /*------- I.Definitely errors ----------*/ /* Block-no 1-3 are always the same ! */ if ( tmp.fs_sblknr != 1 || tmp.fs_iblknr != 2 || tmp.fs_rblknr != 3 ) corrupt_cnt++; /* The magic number is fixed. */ if ( tmp.fs_magic != MAGIC_NUMBER ) corrupt_cnt++; if ( tmp.fs_szfs != sizeof (struct fs) ) corrupt_cnt++; if ( tmp.fs_szcg != sizeof (struct cg) ) corrupt_cnt++; /*------ II.Plausibility errors --------*/ if ( tmp.fs_size != tmp.fs_cgsize * tmp.fs_ncg ) corrupt_cnt++; if ( tmp.fs_dsize != tmp.fs_size - tmp.fs_ncg - 3 ) corrupt_cnt++; if ( tmp.fs_fsize != tmp.fs_bsize / tmp.fs_frag ) corrupt_cnt++; if ( tmp.fs_maxdpb != tmp.fs_bsize / sizeof (struct dir_elem) ) corrupt_cnt++; if ( tmp.fs_maxcontig != tmp.fs_bsize / sizeof (daddr_t) ) corrupt_cnt++; if ( tmp.fs_ncgcgoff != tmp.fs_ncg * tmp.fs_cgoffset ) corrupt_cnt++; if ( tmp.fs_minfree < 0 || tmp.fs_minfree > 99 ) corrupt_cnt++; if ( tmp.fs_psmal > tmp.fs_maxpsz || tmp.fs_pmedi > tmp.fs_maxpsz || tmp.fs_phuge > tmp.fs_maxpsz ) corrupt_cnt++; /* Were there errors detected ? */ if ( corrupt_cnt ) { unique_err++; if ( cgnr == 0 ) cgnr++; IOdebug ("The Superblock is damaged (%d errors counted) !", corrupt_cnt); /* Is it possible to select */ /* automatically a new one ? */ if ( tmp.fs_size == tmp.fs_cgsize * tmp.fs_ncg && tmp.fs_ncgcgoff == tmp.fs_cgoffset * tmp.fs_ncg && tmp.fs_size != 0 && tmp.fs_ncgcgoff != 0 ) { IOdebug ("Try to interpret block no: %d as an info-block.", map_cgtoib (cgnr,tmp.fs_cgoffset,tmp.fs_cgsize)); /* Read in info-blk from next cg */ bp = bread ( 0, map_cgtoib (cgnr,tmp.fs_cgoffset,tmp.fs_cgsize), 1, SAVEA ); /* There are possibly two reasons why we cannot */ /* read the block. If we have used a block-num */ /* which is invalid, we need help from the user */ /* to find a correct number for an info-block */ /* Copy in temporary struct */ memcpy ( &tmp, &bp->b_un.b_info->fs, sizeof (struct fs) ); /* Release unused packet */ brelse ( bp->b_tbp, TAIL ); /* Try to validate the new copy */ /* of the Superblock. */ continue; } else /* No automatically selection: */ /* Give the user the choice to */ { /* select manually a new one */ IOdebug ("Unable to select a new info block automatically!"); /* Assisted search or manual */ /* 'rebuild' of a superblock! */ return FALSE; } } else /* No errors were detected */ { if ( try > 0 ) IOdebug ("Valid superblock in use now !"); /* Keep the valid data incore */ /* in a separated storage area. */ memcpy ( &incore_fs, &tmp, sizeof (struct fs) ); /* Make a copy in i_fs, which is*/ /* for exclusive checker's use */ memcpy ( &i_fs, &tmp, sizeof (struct fs) ); break; /* We can finish the search for */ /* a valid superblock ! */ } /* end of <if (corrupt_cnt)> */ } /* end of <for(cgnr)> */ /* At this point we are sure, that the incore- */ /* copy of the super-block is valid. So we can */ /* use it further on, if we need file system */ /* parameters! */ { /* Update each cylinder-group */ /* if necessary. */ for ( cgnr = 0 ; cgnr < i_fs.fs_ncg ; cgnr++ ) { /* Read appropriate info block */ bp = bread ( 0, map_cgtoib (cgnr,i_fs.fs_cgoffset,i_fs.fs_cgsize), 1, SAVEA ); #if DEBUG IOdebug (" check_unique : Compare it with the copy in cylinder-group %d.", cgnr); #endif /* Updating is only recommended, */ /* if changes were made. */ if ( my_memcmp ( &i_fs, &bp->b_un.b_info->fs, tmp.fs_szfs ) ) { #if DEBUG IOdebug (" check_unique : Copy superblock to cylinder-group %d.", cgnr); #endif unique_err++; /* Update it's superblock copy */ memcpy ( &bp->b_un.b_info->fs, &i_fs, sizeof (struct fs) ); /* ... and write it back to disk */ fst.corrected_sb++; test_bwrite ( bp ); } else /* They are the same: don't copy */ brelse ( bp->b_tbp, TAIL ); } /* end <for (cgnr)> */ } /* Report differences between data kept */ /* in the superblock and in the 'devinfo'*/ /* structures */ #if DEBUG IOdebug (" check_unique : Compare 'devinfo' data with the superblock"); #endif if ( i_fs.fs_ncg != vvi->CgCount ) IOdebug ("Number of cylinder groups Sb : %4d / devinfo : %d", i_fs.fs_ncg, vvi->CgCount); if ( i_fs.fs_cgsize != vvi->CgSize ) IOdebug ("Size of a cylinder group Sb : %4d / devinfo : %d", i_fs.fs_cgsize, vvi->CgSize); if ( i_fs.fs_cgoffset != vvi->CgOffset ) IOdebug ("Relative offset into a cylinder group Sb : %4d / devinfo : %d", i_fs.fs_cgoffset, vvi->CgOffset); if ( i_fs.fs_psmal != fsi->SmallPkt ) IOdebug ("Size of a of small packet Sb : %d / devinfo : %d", i_fs.fs_psmal, fsi->SmallPkt); if ( i_fs.fs_pmedi != fsi->MediumPkt ) IOdebug ("Size of a of medium packet Sb : %d / devinfo : %d", i_fs.fs_pmedi, fsi->MediumPkt); if ( i_fs.fs_phuge != fsi->HugePkt ) IOdebug ("Size of a huge packet Sb : %d / devinfo : %d", i_fs.fs_phuge, fsi->HugePkt); if ( i_fs.fs_pscnt != fsi->SmallCount ) IOdebug ("Number of samll packets Sb : %d / devinfo : %d", i_fs.fs_pscnt, fsi->SmallCount); if ( i_fs.fs_pmcnt != fsi->MediumCount ) IOdebug ("Number of medium packtes Sb : %d / devinfo : %d", i_fs.fs_pmcnt, fsi->MediumCount); if ( i_fs.fs_phcnt != fsi->HugeCount ) IOdebug ("Number of huge packets Sb : %d / devinfo : %d", i_fs.fs_phcnt, fsi->HugeCount); if ( i_fs.fs_maxnii != fsi->MaxInodes ) IOdebug ("Maximal number of incore inodes Sb : %d / devinfo : %d", i_fs.fs_maxnii, fsi->MaxInodes); if ( i_fs.fs_minfree != vvi->MinFree ) IOdebug ("Percentage of space to be kept free Sb : %d / devinfo : %d", i_fs.fs_minfree, vvi->MinFree); /*---- To ease addressing of info-blocks: create an info-bnr table ----*/ #if DEBUG IOdebug (" check_unique : Create an info-block number table."); #endif /* Calculate all block numbers */ for ( cgnr = 0 ; cgnr < i_fs.fs_ncg ; cgnr++ ) /* ... and fill the table */ info_blocks[cgnr] = map_cgtoib (cgnr, i_fs.fs_cgoffset, i_fs.fs_cgsize); /*--------- Discrepancy between bit-maps and cg-info ? ----------------*/ /* This part is only used to detect differences */ /* in the bit-maps and summary-structures and */ /* to report them. No attempts to correct them */ /* are made. This is done later by check_blocks.*/ IOdebug ("%s*** Step 1.2 : First inspection of bitmap-data", S_INFO); /* Scan all cylinder groups */ for ( corrupt_cnt = 0 , cgnr = 0 ; cgnr < i_fs.fs_ncg ; cgnr++ ) { /* Read the cg info-block */ bp = bread ( 0, info_blocks[cgnr], 1, SAVEA ); /* Read error */ if ( bp == (struct buf *) NULL ) { IOdebug ("%sUnexpected read error for block no: %d.", S_SERIOUS, info_blocks[cgnr]); return FALSE; } if ( bp->b_un.b_info->cgx.cg_cgx != cgnr ) { IOdebug ("%sInvalid cgnr (%d) found in info block %d!", S_WARNING, bp->b_un.b_info->cgx.cg_cgx ,cgnr); } /* Scan through the bit-map ! */ for ( i = 0 , free_cnt = 0 , ecnt = 0 ; i < i_fs.fs_cgsize ; i++ ) { switch ( bp->b_un.b_info->cgx.cg_free[i] ) { /* Test for errors */ case 0x00 : free_cnt++; break; case 0xff : continue; break; default : ecnt++; fst.bitmap_errors++; corrupt_cnt++; } } if ( free_cnt != bp->b_un.b_info->cgx.cg_s.s_nbfree ) { /* By comparing with cg-sum */ corrupt_cnt++; unique_err++; fst.summary_errors++; IOdebug ("%sDifferent number of free blocks found.", S_WARNING); IOdebug ("%s> Cyl. Group : %d FREE counted= %d cg-summary= %u", S_INFO, cgnr, free_cnt, bp->b_un.b_info->cgx.cg_s.s_nbfree); } /* Definitely errors in maps ? */ if ( ecnt ) /* ( != 0 && != 0xff ) */ { unique_err++; IOdebug ("%sCorrupted bits in bit-map found.", S_WARNING); IOdebug ("%s> Cyl. Group : %d ERRORS =%d blocks", S_INFO, cgnr, ecnt); /* We have reached the limit ? */ if ( ecnt > i_fs.fs_cgsize * maxbmerr / 100 ) { /* Note cg-bitmap as unusable */ cg_bitmap_usable[cgnr] = FALSE; IOdebug ("%sThe bit-map is not usable!", S_SERIOUS); } else cg_bitmap_usable[cgnr] = TRUE; } /* We have found a bitmap in an */ else /* usable state ! */ cg_bitmap_usable[cgnr] = TRUE; /* Release unused block */ brelse ( bp->b_tbp, TAIL ); } /* end < for (cgnr) > */ /*--------- Allocate enough memory for a reference bit-map array ------*/ IOdebug ("%s*** Step 1.3 : Allocate memory for reference bit-map array.", S_INFO); bit_maps_allocated = alloc_ref_maps (); if ( ! bit_maps_allocated ) /* No success again, that's bad! */ { IOdebug ("%sUnable to allocate memory for reference bit-maps.", S_FATAL); return FALSE; } /* Blocks 0-2 always allocated ! */ bit_maps[0][0] = 1; /* Boot-block */ found_blocks++; bitmap_incr (1); /* Summary block */ found_blocks++; /* Mark all info-blocks as being */ /* allocated. */ for ( cgnr = 0 ; cgnr < i_fs.fs_ncg ; cgnr++ ) { found_blocks++; bitmap_incr (info_blocks[cgnr]); } /*----------- Prepare the hash-table for directory entries ------------*/ #if DEBUG IOdebug (" check_unique : Prepare directory-entry hash table."); #endif /* We have to initialize all */ for ( i = 0 ; i < DEHASHSZ ; i++ ) /* hash-pointers ! */ de_hash_tab[i].denxt = (struct de_name *) NULL; /*------ Prepare the hash-table for duplicate block numbers ---------*/ #if DEBUG IOdebug (" check_unique : Prepare duplicate block-number hash table."); #endif /* We have to initialize all */ for ( i = 0 ; i < DUPHASHSZ ; i++ ) /* hash-pointers ! */ dup_hash_tab[i].dupnxt = (struct dup_bnr *) NULL; /*-------- Prepare the hash-table for symbolic link references ------*/ #if DEBUG IOdebug (" check_unique : Prepare symbolic-link hash-table."); #endif /* We have to initialize all */ for ( i = 0 ; i < LINKHASHSZ ; i++ ) /* hash-pointers */ link_hash_tab[i].lnnxt = (struct de_link *) NULL; /*--------------- Valid root directory data ? -------------------------*/ IOdebug ("%s*** Step 1.4 : Check the root directory inode.", S_INFO); /* Read summary block with the */ bp = bread ( 0, 1, 1, SAVEA ); /* root-dir inode in it. */ /* if read fails, longjmp */ /* term_jmp */ changes_de = 0; /* Nothing done so far ... */ /* Check the root-dir entry */ if ( ! validate_entry ( &bp->b_un.b_sum->root_dir , "/", Type_Directory, TRUE ) ) { /* Is it totally damaged ! */ /* It is a very dangerous situation, if we have no root-*/ /* directory available. The user can create an */ /* empty one and hope, that lost subdiretory-information*/ /* is picked up during the "lost+found" pass over the */ /* cylinder-group bit-maps. */ unique_err++; IOdebug ("%sThe root-directory is not usable !", S_SERIOUS); /* Pioneer's work: we create a */ /* new inode from scratch ! */ IOdebug ("%sA new root-directory is created from scratch.", S_INFO); /* Pioneer's work: we create a */ /* new root-inode from scratch */ create_new_root_dir ( &bp->b_un.b_sum->root_dir ); /* Write the root-inode back on */ /* disk. */ test_bwrite ( bp ); } else /* After finding a usable root- */ { /* directory entry ... */ if (!bp->b_un.b_sum->sum_same) unique_err++; if ( changes_de ) /* Any changes made ? */ { #if DEBUG IOdebug (" check_unique : Update root-directory inode on disk."); #endif unique_err++; /* Write corrected summary-block */ test_bwrite ( bp ); /* directly to disk */ } else brelse ( bp->b_tbp, TAIL ); } /*---------------- Look for the "lost+found" directory --------------*/ IOdebug ("%s*** Step 1.5 : Look for the '/lost+found'- directory.", S_INFO); bp = bread ( 0, 1, 1, SAVEA ); /* Get root-directory */ /* if read fails, longjmp */ /* term_jmp */ /* Look for the "lost+found"-dir */ bp_2 = search_entry ( &bp->b_un.b_sum->root_dir.de_inode, "lost+found", &off ); /* We have found it ? */ if ( bp_2 != (struct buf *) NULL ) { /* We have found a usable */ lost_found = TRUE; /* /lost+found - directory. */ brelse ( bp_2->b_tbp, TAIL ); brelse ( bp->b_tbp, TAIL ); } /* If we have not found the */ else /* /lost+found-inode, we have to */ { /* create a new one. */ IOdebug ("%sUnable to find a '/lost+found' entry in the root-directory.", S_WARNING); IOdebug ("%sA new '/lost+found' entry is created.", S_INFO); unique_err++; if ( create_lostfound_inode ( &bp->b_un.b_sum->root_dir.de_inode ) ) { IOdebug ("%sHave created a new /lost+found directory!", S_INFO); lost_found = TRUE; test_bwrite ( bp ); /* Write modified root back. */ } else /* We cannot create a /lost+found*/ { /* inode, because we have no */ /* slot available. */ IOdebug ("%sCannot create a new '/lost+found' directory !", S_WARNING); lost_found = FALSE; brelse ( bp->b_tbp, TAIL ); } } return TRUE; } /*-- Procedures dealing with the creation of a new basic structures ---*/ /************************************************************************ * CREATE A TOTALLY EMPTY ROOT-DIRECTORY ENTRY FROM SCRATCH * * - This procedure is called, if the checker was not able to find a * valid root-directory. * * Parameter : dp = Pointer to the root directory-element * Return : - nothing - * ***********************************************************************/ static void create_new_root_dir ( struct dir_elem *dp ) { Date date; #if DEBUG IOdebug (" create_new_root_dir : Create the new entry"); #endif /* Clear the directory-entry */ memset ( dp, 0, sizeof (struct dir_elem) ); /* .. and fill in with the data */ /* for the root-directory */ strcpy ( dp->de_name, i_fs.fs_name ); dp->de_inode.i_mode = Type_Directory; dp->de_inode.i_matrix = DefDirMatrix; date = GetDate (); dp->de_inode.i_ctime = date; dp->de_inode.i_mtime = date; dp->de_inode.i_atime = date; }