int free_x11display(x11display_t * x11disp) { int err; if (x11disp->idmap) { memblock_t mblock = memblock_INIT(sizeof(x11windowmap_t), (uint8_t*)x11disp->idmap); err = FREE_MM(&mblock); if ( x11disp->sys_display && XCloseDisplay(x11disp->sys_display)) { err = ECOMM; TRACESYSCALL_ERRLOG("XCloseDisplay", err); } x11disp->idmap = 0; x11disp->sys_display = 0; if (err) goto ONERR; } return 0 ; ONERR: TRACEEXITFREE_ERRLOG(err); return err; }
int initfiltered_eglconfig(/*out*/eglconfig_t * eglconf, struct opengl_display_t * egldisp, const int32_t config_attributes[], eglconfig_filter_f filter, void * user) { int err; EGLint egl_attrib_list[2*gconfig__NROF]; EGLConfig * eglconfig = 0; memblock_t mblock; err = convertConfigListToEGL_eglconfig(&egl_attrib_list, config_attributes); if (err) goto ONERR; EGLint num_config; EGLBoolean isOK = eglChooseConfig( egldisp, egl_attrib_list, 0, 0, &num_config); if (!isOK) { err = EINVAL; goto ONERR; } // TODO: implement tempstack_memory_allocator // allocate memory from tempstack instead of real stack err = ALLOC_ERR_MM(&s_eglconfig_errtimer, sizeof(EGLConfig) * (unsigned)num_config, &mblock); if (err) goto ONERR; eglconfig = (EGLConfig *) mblock.addr; isOK = eglChooseConfig( egldisp, egl_attrib_list, eglconfig, num_config, &num_config); if (!isOK) { err = EINVAL; goto ONERR; } EGLint i; for (i = 0; i < num_config; ++i) { EGLint visualid; isOK = eglGetConfigAttrib( egldisp, eglconfig[i], EGL_NATIVE_VISUAL_ID, &visualid); if (filter(eglconfig[i], visualid, user)) { // set out param *eglconf = eglconfig[i]; break; } } (void) FREE_ERR_MM(&s_eglconfig_errtimer, &mblock); if (i == num_config) return ESRCH; return 0; ONERR: if (eglconfig) (void) FREE_MM(&mblock); TRACEEXIT_ERRLOG(err); return err; }
int delete_syslogininfo(syslogin_info_t** info) { int err; syslogin_info_t* delobj = *info; if (delobj) { *info = 0; memblock_t mblock = memblock_INIT(delobj->size, (uint8_t*)delobj); err = FREE_MM(&mblock); if (err) goto ONERR; } return 0; ONERR: TRACEEXITFREE_ERRLOG(err); return err; }
int new_syslogininfo(/*out*/syslogin_info_t** info, sys_userid_t uid) { int err; memblock_t mblock = memblock_FREE; slock_mutex(&s_syslogininfo_lock); errno = 0; struct passwd* pwd = getpwuid(uid); if (!pwd) { if (errno) { err = errno; TRACESYSCALL_ERRLOG("getpwuid(uid)", err); PRINTUINT32_ERRLOG(uid); } else { err = ENOENT; } goto UNLOCK; } size_t namesize = strlen(pwd->pw_name) + 1; // size username size_t nrofgrp = 0; #define GELEMSIZE (sizeof(sys_groupid_t) + sizeof(char*)) setgrent(); for (;;) { errno = 0; struct group* grp = getgrent(); if (!grp) { if (errno) { err = errno; TRACESYSCALL_ERRLOG("getgrent", err); goto UNLOCK; } break; } bool ismatch = (grp->gr_gid == pwd->pw_gid); for (int i = 0; !ismatch && grp->gr_mem[i]; ++i) { ismatch = (0 == strcmp(grp->gr_mem[i], pwd->pw_name)); } if (ismatch) { size_t len = strlen(grp->gr_name); if (nrofgrp == (SIZE_MAX/GELEMSIZE) || namesize >= SIZE_MAX/2 || len >= SIZE_MAX/2) { err = ENOMEM; goto UNLOCK; } nrofgrp ++; namesize += len + 1; } } size_t size = sizeof(syslogin_info_t) + namesize; size_t arrsize = nrofgrp * GELEMSIZE; if (size <= namesize) size = 0; size += arrsize; if (size <= arrsize) { err = ENOMEM; goto UNLOCK; } err = ALLOC_MM(size, &mblock); if (err) goto UNLOCK; syslogin_info_t* newobj = (syslogin_info_t*) mblock.addr; uint8_t* data = mblock.addr + sizeof(syslogin_info_t); size_t datasize = size - sizeof(syslogin_info_t); size_t dataoff; newobj->size = size; newobj->uid = uid; newobj->nrgroups = nrofgrp; newobj->gmain = 0; newobj->gname = (const char**) data; dataoff = nrofgrp * sizeof(char*); newobj->gid = (sys_groupid_t*) (data + dataoff); dataoff += nrofgrp * sizeof(sys_groupid_t); size_t fieldsize = strlen(pwd->pw_name) + 1; if (fieldsize > (datasize - dataoff)) { err = EAGAIN; goto UNLOCK; } memcpy(data + dataoff, pwd->pw_name, fieldsize); newobj->uname = (char*) (data + dataoff); dataoff += fieldsize; setgrent(); for (size_t gi = 0; gi < nrofgrp; ) { errno = 0; struct group* grp = getgrent(); if (!grp) { err = errno ? errno : ENOENT; TRACESYSCALL_ERRLOG("getgrent", err); goto UNLOCK; } bool ismatch = (grp->gr_gid == pwd->pw_gid); for (int i = 0; !ismatch && grp->gr_mem[i]; ++i) { ismatch = (0 == strcmp(grp->gr_mem[i], pwd->pw_name)); } if (ismatch) { fieldsize = strlen(grp->gr_name) + 1; if (fieldsize > (datasize - dataoff)) { err = EAGAIN; goto UNLOCK; } char* gname = (char*) (data + dataoff); dataoff += fieldsize; memcpy(gname, grp->gr_name, fieldsize); if (grp->gr_gid == pwd->pw_gid) { newobj->gmain = gi; } newobj->gid[gi] = grp->gr_gid; newobj->gname[gi] = gname; ++gi; } } *info = newobj; UNLOCK: endgrent(); endpwent(); sunlock_mutex(&s_syslogininfo_lock); if (err) goto ONERR; return 0; ONERR: FREE_MM(&mblock); if (ENOENT != err) { TRACEEXIT_ERRLOG(err); } return err; }
static int test_read(directory_t * tempdir) { filereader_t frd = filereader_FREE; const size_t B = sizebuffer_filereader(); memblock_t mem = memblock_FREE; memstream_ro_t buffer = memstream_FREE; // prepare TEST(0 == RESIZE_MM(2*B+1, &mem)); for (size_t i = 0; i < 2*B+1; ++i) { addr_memblock(&mem)[i] = (uint8_t)(13*i); } TEST(0 == save_file("single", B, addr_memblock(&mem), tempdir)); TEST(0 == save_file("double", 2*B+1, addr_memblock(&mem), tempdir)); // prepare: single buffer TEST(0 == init_filereader(&frd, "single", tempdir)); // TEST release_filereader: changes nothing if frd.nrfreebuffer == 2 release_filereader(&frd); TEST(0 == frd.unreadsize); TEST(0 == frd.nextindex); TEST(2 == frd.nrfreebuffer); TEST(0 == frd.fileoffset); for (int ti = 0; ti < 2; ++ti) { // TEST unread_filereader unread_filereader(&frd); if (0 == ti) { // call ignored if frd.nrfreebuffer == 2 TEST(0 == frd.unreadsize); } else { // next call to readnext_filereader returns same buffer TEST(B == frd.unreadsize); } TEST(0 == frd.nextindex); TEST(2 == frd.nrfreebuffer); TEST(0 == frd.fileoffset); // TEST readnext_filereader: reads one buffer TEST(0 == readnext_filereader(&frd, &buffer)); // check buffer TEST(B == size_memstream(&buffer)); TEST(buffer.next == frd.page[0].addr); TEST(buffer.end == frd.page[0].addr + frd.page[0].size); // check frd TEST(0 == frd.unreadsize); // all read TEST(1 == frd.nextindex); // nextindex incremented TEST(1 == frd.nrfreebuffer); // acquired 1 buffer TEST(B == castPoff_size(frd.fileoffset)); // check content for (size_t i = 0; isnext_memstream(&buffer); ++i) { uint8_t byte = nextbyte_memstream(&buffer); TEST(byte == (uint8_t)(13*i)); } } // TEST readnext_filereader: ENODATA TEST(ENODATA == readnext_filereader(&frd, &buffer)); // TEST release_filereader: releases single buffer release_filereader(&frd); TEST(0 == frd.unreadsize); TEST(1 == frd.nextindex); TEST(2 == frd.nrfreebuffer); TEST(B == castPoff_size(frd.fileoffset)); // TEST readnext_filereader: ENODATA TEST(ENODATA == readnext_filereader(&frd, &buffer)); // unprepare TEST(0 == free_filereader(&frd)); // prepare: double buffer TEST(0 == init_filereader(&frd, "double", tempdir)); for (size_t i = 0, offset = 0; i < 3; ++i) { // TEST release_filereader: frd.nrfreebuffer == 2 ==> does nothing release_filereader(&frd); TEST( 0 == frd.unreadsize); TEST( 0 == frd.nextindex); TEST( 2 == frd.nrfreebuffer); TEST( offset == castPoff_size(frd.fileoffset)); // TEST unread_filereader: frd.nrfreebuffer == 2 ==> does nothing unread_filereader(&frd); TEST( 0 == frd.unreadsize); TEST( 0 == frd.nextindex); TEST( 2 == frd.nrfreebuffer); TEST( offset == castPoff_size(frd.fileoffset)); const size_t S = (i != 2 ? B/2 : 1); for (unsigned U = 1; U <= 1; --U) { // test unread for (size_t n = 0, u = (U == 1 || S == 1)?0:S; n <= 1; ++n, u -= u?S:0) { // TEST readnext_filereader: reads one buffer TEST( 0 == readnext_filereader(&frd, &buffer)); // check buffer TEST( buffer.next == frd.page[n].addr); TEST( buffer.end == frd.page[n].addr + S); // check frd TEST( u == frd.unreadsize); TEST( (!n) == frd.nextindex); TEST( (!n) == frd.nrfreebuffer); TEST( (offset + S) == castPoff_size(frd.fileoffset)); // check content for (; isnext_memstream(&buffer); ++offset) { uint8_t byte = nextbyte_memstream(&buffer); TEST(byte == (uint8_t)(13*offset)); } if (S == 1) break; } // TEST readnext_filereader: more than 2 buffers or ENODATA const uint8_t N = frd.nextindex; buffer = (memstream_ro_t) memstream_FREE; TEST( (N?ENODATA:ENOBUFS) == readnext_filereader(&frd, &buffer)); TEST( N == iseof_filereader(&frd)); // check buffer TEST( 0 == buffer.next); TEST( 0 == buffer.end); // check frd TEST( 0 == frd.unreadsize); TEST( N == frd.nextindex); TEST( N == frd.nrfreebuffer); TEST( offset == castPoff_size(frd.fileoffset)); if (U) { for (size_t n = N+1u, u = S; n <= 2; ++n, u += S) { // TEST unread_filereader: unreads second buffer unread_filereader(&frd); // check frd TEST( u == frd.unreadsize); TEST( (n==1) == frd.nextindex); TEST( n == frd.nrfreebuffer); offset -= S; TEST( offset == castPoff_size(frd.fileoffset)); } } } const int N = frd.nextindex; for (int n = N+1; n <= 2; ++n) { // TEST release_filereader: mark last buffer as unused release_filereader(&frd); TEST( 0 == frd.unreadsize); TEST( (N==1) == frd.nextindex); TEST( n == frd.nrfreebuffer); TEST( offset == castPoff_size(frd.fileoffset)); } } // unprepare TEST(0 == free_filereader(&frd)); // TEST readnext_filereader: ioerror is returned TEST(0 == init_filereader(&frd, "double", tempdir)); TEST( 0 == readnext_filereader(&frd, &buffer)); for (unsigned i = 1; i < 15; ++i) { setioerror_filereader(&frd, (int) i); const unsigned err = (unsigned) readnext_filereader(&frd, &buffer); TEST( err == i); } TEST(0 == free_filereader(&frd)); // unprepare TEST(0 == FREE_MM(&mem)); TEST(0 == removefile_directory(tempdir, "single")); TEST(0 == removefile_directory(tempdir, "double")); return 0; ONERR: FREE_MM(&mem); removefile_directory(tempdir, "single"); removefile_directory(tempdir, "double"); return EINVAL; }