void print_polygon(FILE* fptr, struct Polygon* self) { if (!self) return; size_t ncaps=0; struct CapVec* cap_vec=NULL; cap_vec = self->cap_vec; ncaps = cap_vec ? cap_vec->size : 0; fprintf(fptr, "polygon %ld ( %ld caps, %.16g weight, %ld pixel, %.16g str):\n", self->poly_id, ncaps, self->weight, self->pixel_id, self->area); if (ncaps > 0) { size_t i=0; struct Cap *cap = &cap_vec->data[0]; for (i=0; i<ncaps; i++) { print_cap(fptr,cap); cap++; } } }
int main(int argc, char**argv){ //--- create variables and initialize them. init() char* video_device = VIDEO_DEVICE; // 1) -------- 打开设备 /dev/video*: -------- printf("--------------------------------------\n"); printf("Step 1: Open devide using V4L2.\n"); if(argc>1) { video_device=argv[1]; printf(" Select: %s\n", video_device); } // create a handler for /dev/video* device: // 采用阻塞模式打开;若为非阻塞模式:O_RDWR | O_NONBLOCK int fdwr = 0; // for /dev/video* handler if(NON_BLOCK_VIDEO){ fdwr = open(video_device, O_RDWR | O_NONBLOCK); printf(" Open: %s using NON_BLOCK mode\n", video_device); } else{ fdwr = open(video_device, O_RDWR); printf(" Open: %s using BLOCK mode\n", video_device); } assert(fdwr >= 0); printf("--------------------------------------\n"); // 2) -------- 查询设备属性 -------- printf("Step 2: v4l2_capacity check:\n"); struct v4l2_capability vid_caps; memset(&vid_caps, 0, sizeof(vid_caps)); int ret_code = 0; // for checking the V4L2 ioctl() method return status. ret_code = ioctl(fdwr, VIDIOC_QUERYCAP, &vid_caps); assert(ret_code != -1); if(debug==1) print_cap(&vid_caps); // 3) 设置视频的制式和帧格式: printf("Step 3: v4l2_format check/set:\n"); struct v4l2_format vid_format; memset(&vid_format, 0, sizeof(vid_format)); // ret_code = ioctl(fdwr, VIDIOC_G_FMT, &vid_format); if(V4L2_BUF_TYPE == CAPTURE){ vid_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; } else{ vid_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; } vid_format.fmt.pix.width = FRAME_WIDTH; vid_format.fmt.pix.height = FRAME_HEIGHT; vid_format.fmt.pix.pixelformat = FRAME_FORMAT; // size_t framesize; // size_t linewidth; __u32 framesize; __u32 linewidth; if(!format_properties(vid_format.fmt.pix.pixelformat, vid_format.fmt.pix.width, vid_format.fmt.pix.height, &linewidth, &framesize)) { printf("unable to guess correct settings for format '%d'\n", FRAME_FORMAT); } else{ // printf("FrameSize = %d\n", framesize); // printf("linewidth = %d\n", linewidth); } // check: http://lxr.free-electrons.com/source/include/uapi/linux/videodev2.h#L87 vid_format.fmt.pix.field = V4L2_FIELD_NONE; // V4L2_FIELD_ANY // check: http://lxr.free-electrons.com/source/include/uapi/linux/videodev2.h#L185 vid_format.fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; // vid_format.fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; vid_format.fmt.pix.sizeimage = framesize; vid_format.fmt.pix.bytesperline = linewidth; if(debug==1) print_format(&vid_format); ret_code = ioctl(fdwr, VIDIOC_S_FMT, &vid_format); assert(ret_code != -1); /* // After set v4l2_format, read it back for double check. // Just to make sure that there is no mis-set and the sys 'secretly' // set the parameters to some 'default' value. if(debug == 1){ ret_code = ioctl(fdwr, VIDIOC_G_FMT, &vid_format); assert(ret_code != -1); printf("after set, get it back to double check:\n"); print_format(&vid_format); } */ /* struct v4l2_fmtdesc vid_desc; vid_desc.index = 0; if(debug==1) print_desc(fdwr,&vid_desc); */ // 4) Check the video standard: // in general the standard is either PAL(720*576) for asian; or NTSC (720*480) for EU. // in our virtual camera scenario, the "v4l2_standard" does not matter much. // 4.1) get the current video standard: printf("Step 4: check the video standard.\n"); //struct v4l2_std_id vid_std_id; // 64 bit length var. struct v4l2_standard vid_std; v4l2_std_id std_id; ret_code = ioctl(fdwr, VIDIOC_G_STD, &std_id); if(ret_code == -1){ printf(" Acquire video standard ERROR:%d\n",ret_code); } else{ memset(&vid_std, 0, sizeof(vid_std)); vid_std.index = 0; // emun from the first one: while(0 == ioctl(fdwr, VIDIOC_ENUMSTD, &vid_std)){ if(vid_std.id & std_id){ printf("Current video standard: %s\n", vid_std.name); } vid_std.index++; } } struct v4l2_streamparm parm; memset(&parm, 0, sizeof(parm)); parm.type =vid_format.type; ret_code = ioctl(fdwr,VIDIOC_G_PARM,&parm); if(ret_code == -1) printf("get parameter failed."); parm.parm.output.timeperframe.numerator = 1000; parm.parm.output.timeperframe.denominator = FPS * parm.parm.output.timeperframe.numerator; if(ioctl(fdwr,VIDIOC_S_PARM,&parm)==0){ struct v4l2_fract *tf = &parm.parm.output.timeperframe; if(!tf->denominator || !tf->numerator) printf("invalid frame rate\n"); else printf(" Frame Rate =%.3f fps\n", 1.0 * tf->denominator/tf->numerator); } // printf(" v4l2_streamparm set/check:\n"); printf(" parm.type(capture=1/output=2) =%d\n", parm.type); printf(" parm.parm.output.capability =0x%4x\n", parm.parm.output.capability); printf("--------------------------------------\n"); // 5) request buffer: printf("Step 5: Request video buffers\n"); struct v4l2_requestbuffers req; req.count = NUM_BUFFER; req.memory = V4L2_MEMORY_MMAP; req.type = vid_format.type; // V4L2_BUF_TYPE_VIDEO_OUTPUT = 2; ret_code = ioctl(fdwr, VIDIOC_REQBUFS, &req); if(debug == 1){ print_requestbuffers(&req); } tp_buffers *data; // malloc() + memset (p, 0, size); data= (struct buffer*) calloc(req.count, sizeof( tp_buffers)); //data=(tp_buffers*) calloc(req.count,sizeof (tp_buffers)); if(!data){ printf ("Out of memory/n"); exit (EXIT_FAILURE); } int index = 0; // set the parameter for every buffer in the buf_arr[], // to make sure they are the same as thos in the 'req'. for(index=0; index<req.count; index++){ memset(&buf_arr[index], 0, sizeof(buf_arr[index])); buf_arr[index].index = index; buf_arr[index].type = vid_format.type; buf_arr[index].memory = req.memory; // should be V4L2_MEMORY_MMAP; // 查询序号为i 的缓冲区,得到其起始物理地址和大小 if(-1 == ioctl (fdwr, VIDIOC_QUERYBUF, &buf_arr[index])) exit(-1); data[index].length = buf_arr[index].length; // 映射内存 data[index].start = mmap(NULL, buf_arr[index].length, PROT_READ | PROT_WRITE, MAP_SHARED, fdwr, buf_arr[index].m.offset); if(MAP_FAILED == data[index].start) exit(-1); // printf(" data[%d].start = 0x%08x", index, data[index].start); printf(" data[%d].length = %d\n", index, data[index].length); // printf("buf.length = %d, framesize = %d ,buf.m.offset = %d\n", // buf_arr[index].length,(int)framesize,buf_arr[index].m.offset); } // 6) assign buffers to the queue. printf("step 6: assign buffers to the queue.\n"); // Queue buffers: for(index = 0; index < req.count; index++){ ioctl(fdwr, VIDIOC_QBUF, &buf_arr[index]); } // STREAM-ON enum v4l2_buf_type type = vid_format.type; ret_code = ioctl(fdwr, VIDIOC_STREAMON, &type); assert(ret_code != -1); // image streaming testing. // need to convert from RGBA format to YUYV format, // and then QBUF to the buffer array. int color = 128; // write AVOS mFrame image to buffers[ind]: const int BENCH = 255; FILE * bmp_fd = NULL; BYTE bmp_header[128]; int bmp_width; int bmp_height; int bmp_header_len; BYTE * rgb = NULL; BYTE * yuv = NULL; char *pic[4]={"1.bmp","2.bmp","3.bmp","4.bmp"}; // char *pic[4]={"5.bmp","5.bmp","5.bmp","5.bmp"}; while(1){ /* // set image/ if(color >= BENCH) color = color % BENCH; else color++; for(index=0; index < req.count; index++){ // memset(data[index].start, color,1179648); memset(data[index].start, 128,1024); memset(data[index].start+1024, 255,vid_format.fmt.pix.sizeimage-1024); }*/ for(index=0; index < req.count; index++){ // printf("%s\n",pic[index]); bmp_fd = fopen(pic[index],"rb"); if(!bmp_fd) { fprintf(stderr,"open bmp file failed!\n"); exit(1); } fgets(bmp_header,sizeof(bmp_header),bmp_fd); bmp_header_len = get_long_value(&bmp_header[10]); bmp_width = get_long_value(&bmp_header[18]); bmp_height = get_long_value(&bmp_header[22]); fclose(bmp_fd); // printf("hearder_len:%d\n",bmp_header_len); // printf("image :%d*%d\n",bmp_width,bmp_height); // printf("width*height*2:%d\n",bmp_width*bmp_height*2); // printf("sizeimage:%d\n",vid_format.fmt.pix.sizeimage); rgb = malloc(bmp_width*bmp_height*sizeof(RGBTRIPLE)+bmp_header_len); if(!rgb) { fprintf(stderr,"rgb malloc failed\n"); } yuv = malloc(bmp_width*bmp_height*sizeof(YUVTRIPLE)); if(!yuv) { fprintf(stderr,"yuv malloc failed\n"); } // fread(rgb,bmp_width*bmp_height*3+bmp_header_len,1,bmp_fd); bmp_fd = fopen(pic[index],"rb"); fread(rgb,bmp_width*bmp_height*sizeof(RGBTRIPLE)+bmp_header_len,1,bmp_fd); bgr2yuv(yuv,(RGBTRIPLE *)(rgb+bmp_header_len),bmp_width,bmp_height); memcpy(data[index].start, yuv,vid_format.fmt.pix.sizeimage); if(rgb) { free(rgb); } if(yuv) { free(yuv); } fclose(bmp_fd); } for(index = 0; index < req.count; index++){ //buf_arr[index].m.offset = 0; // usleep(40000); sleep(1); ioctl(fdwr, VIDIOC_QBUF, &buf_arr[index]); } <<<<<<< HEAD // usleep(1/FPS * 1000 * 1000); usleep(40000); ======= // usleep(40000); >>>>>>> d1308ed6e339365aa9876a4e3f265d74eb880e0a
static int read_eegsignal(int bsigcheck, int pass) { struct eegdev* dev; int type = grp[0].datatype; size_t strides[3]; void *eeg_t = NULL, *exg_t = NULL; int32_t *tri_t = NULL; int ntri, fs, i, baddata, retcode = 1; size_t tsize = (type == EGD_FLOAT ? sizeof(float) : sizeof(double)); // Reset global variable used to track the expected signal checking = 0; nstot = nsread = 0; if (!(dev = open_device(grp))) goto exit; // Get number of channels and configure structures grp[0].sensortype = egd_sensor_type("eeg"); grp[1].sensortype = egd_sensor_type("undefined"); grp[2].sensortype = egd_sensor_type("trigger"); strides[0] = grp[0].nch*tsize; strides[1] = grp[1].nch*tsize; strides[2] = grp[2].nch*sizeof(int32_t); ntri = grp[2].nch; eeg_t = calloc(strides[0], NSAMPLE); exg_t = calloc(strides[1], NSAMPLE); tri_t = calloc(strides[2], NSAMPLE); fs = print_cap(dev); if (test_chinfo(dev)) { fprintf(stderr, "\tTest_chinfo failed\n"); goto exit; } if (egd_acq_setup(dev, 3, strides, 3, grp)) goto exit; if (egd_start(dev)) goto exit; for (i=0; i < fs*DURATION; i += NSAMPLE) { if (egd_get_data(dev, NSAMPLE, eeg_t, exg_t, tri_t) < 0) { fprintf(stderr, "\tAcq failed at sample %i\n",i); goto exit; } // No checking if (!bsigcheck) { if (simple_trigger_check(i, NSAMPLE, ntri, tri_t)) retcode = 2; continue; } if (type == EGD_FLOAT) baddata = check_signals_f(NSAMPLE, eeg_t, exg_t, tri_t); else baddata = check_signals_d(NSAMPLE, eeg_t, exg_t, tri_t); if (baddata) { retcode = 2; break; } } if (egd_stop(dev)) goto exit; if (egd_close(dev)) goto exit; dev = NULL; if (retcode == 1) retcode = 0; exit: if (retcode == 1) fprintf(stderr, "\terror caught at pass %i: %s", pass, strerror(errno)); egd_close(dev); free(eeg_t); free(exg_t); free(tri_t); return retcode; }
int main(int argc, char **argv) { int width = 640; int height = 480; int fd = open("/dev/video0", O_RDWR | O_NONBLOCK); int stat = 0; if (fd < 0) { D_ERROR("can not open device."); return -1; } struct v4l2_capability cap = {0}; stat = ioctl(fd, VIDIOC_QUERYCAP, &cap); if (stat == -1) { D_ERROR("can not get device capability."); return -1; } print_cap(&cap); int input_index = 0; stat = ioctl(fd, VIDIOC_G_INPUT, &input_index); if (stat == -1) { D_ERROR("can not get current input"); return -1; } D_PVAR_INT(input_index); struct v4l2_input input; memset(&input, 0, sizeof(input)); input.index = 0; D_PRINT("enum input"); do { stat = ioctl(fd, VIDIOC_ENUMINPUT, &input); if (stat == -1) { break; } D_PVAR_INT(input.index); D_PVAR_STR(input.name); input.index++; } while (1); D_PRINT("enum input end"); v4l2_std_id std; do { stat = ioctl(fd, VIDIOC_QUERYSTD, &std); } while (stat == -1 && errno == EAGAIN); if (stat == -1) { D_ERROR("can not get current video standard."); //return -1; } struct v4l2_standard standard; memset(&standard, 0, sizeof(standard)); D_PRINT("enum video standard."); while (1) { stat = ioctl(fd, VIDIOC_ENUMSTD, &standard); if (stat == -1) { break; } D_PVAR_INT(standard.index); D_PVAR_STR(standard.name); if (std == standard.id) { D_PRINT("above is current video standard."); } standard.index++; } D_PRINT("enum video standard end."); struct v4l2_fmtdesc fmtdesc; memset(&fmtdesc, 0, sizeof(fmtdesc)); fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; D_PRINT("enum image format."); while (1) { stat = ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc); if (stat == -1) { break; } D_PVAR_INT(fmtdesc.index); D_PVAR_STR(fmtdesc.description); fmtdesc.index++; } D_PRINT("enum image format end."); struct v4l2_format fmt; fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = width; fmt.fmt.pix.height = height; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; D_PRINT("set format"); stat = ioctl(fd, VIDIOC_S_FMT, &fmt); if (stat == -1) { D_ERROR("can not set video format"); return -1; } if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG) { D_ERROR("can not set specific format"); struct v4l2_fmtdesc fmtqury; memset(&fmtqury, 0, sizeof(fmtqury)); fmtqury.pixelformat == fmt.fmt.pix.pixelformat; stat = ioctl(fd, VIDIOC_ENUM_FMT, &fmtqury); if (stat == -1) { printf("real format: %s\n", fmtqury.description); } printf("format = %d\n", fmt.fmt.pix.pixelformat); return -1; } struct v4l2_requestbuffers req; memset(&req, 0, sizeof(struct v4l2_requestbuffers)); req.count = 4; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; stat = ioctl(fd, VIDIOC_REQBUFS, &req); if (stat == -1) { D_ERROR("can not require buffers"); return -1; } buffers = (struct buffer *)malloc(sizeof(struct buffer) * req.count); int i = 0; for (i = 0; i < req.count; i++) { struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; stat = ioctl(fd, VIDIOC_QUERYBUF, &buf); if (stat == -1) { D_ERROR("can not query buffer"); return -1; } buffers[i].length = buf.length; buffers[i].start = mmap(NULL, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, buf.m.offset); if (MAP_FAILED == buffers[i].start) { D_ERROR("mmap error"); return -1; } stat = ioctl(fd, VIDIOC_QBUF, &buf); if (stat == -1) { D_ERROR("can not put buf in queue"); return -1; } } enum v4l2_buf_type stream_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; D_PRINT("stream on."); stat = ioctl(fd, VIDIOC_STREAMON, &stream_type); if (stat == -1) { D_ERROR("can not turn stream on"); return -1; } i = 0; char filename[4096] = {0}; D_PRINT("start loop"); while (1) { fd_set fds; FD_ZERO(&fds); FD_SET(fd, &fds); int ret = 0; ret = select(fd + 1, &fds, NULL, NULL, NULL); if (ret == -1) { if (EINTR == errno) { continue; } D_ERROR("select error."); return -1; } struct v4l2_buffer buf; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; stat = ioctl(fd, VIDIOC_DQBUF, &buf); if (stat == -1) { D_ERROR("can not out queue"); return -1; } sprintf(filename, "out/frame%d.jpg", i); printf("index: %d, out: %s\n", buf.index, filename); FILE *out = fopen(filename, "wb"); //fprintf(out, "P6\n%d %d\n255\n",640, 480); fwrite(buffers[buf.index].start, 1, buf.length, out); fclose(out); ioctl(fd, VIDIOC_QBUF, &buf); i++; } stat = ioctl(fd, VIDIOC_STREAMOFF, &stream_type); if (stat == -1) { D_ERROR("can not turn stream off"); return -1; } close(fd); return 0; }
/* * Common body for the cap: module commands. These commands * share a large amount of common behavior, so it is convenient * to centralize things and use the cmd argument to handle the * small differences. * * entry: * cmd - One of the CAP_CMD_T_* constants listed above, specifying * which command to implement. * obj_state, argc, argv - Standard command arguments */ static elfedit_cmdret_t cmd_body(CAP_CMD_T cmd, elfedit_obj_state_t *obj_state, int argc, const char *argv[]) { ARGSTATE argstate; Cap *cap; const char *cap_name; Word cap_ndx; elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; PRINT_CAP_T print_type = PRINT_CAP_T_ALL; Word ndx; int print_only = 0; int do_autoprint = 1; /* Process the optional arguments */ process_args(obj_state, argc, argv, &argstate); cap = argstate.cap.data; cap_name = argstate.cap.sec->sec_name; cap_ndx = argstate.cap.sec->sec_shndx; /* Check number of arguments, gather information */ switch (cmd) { case CAP_CMD_T_DUMP: /* cap:dump can accept an optional index argument */ if (argstate.argc > 1) elfedit_command_usage(); print_only = 1; if (argstate.argc == 1) ndx = arg_to_index(&argstate, argstate.argv[0], MSG_ORIG(MSG_STR_ELT), print_only, &print_type); break; case CAP_CMD_T_TAG: case CAP_CMD_T_VALUE: print_only = (argstate.argc != 2); if (argstate.argc > 0) { if (argstate.argc > 2) elfedit_command_usage(); ndx = arg_to_index(&argstate, argstate.argv[0], MSG_ORIG(MSG_STR_ELT), print_only, &print_type); } break; case CAP_CMD_T_DELETE: if ((argstate.argc < 1) || (argstate.argc > 2)) elfedit_command_usage(); ndx = arg_to_index(&argstate, argstate.argv[0], MSG_ORIG(MSG_STR_ELT), 0, &print_type); do_autoprint = 0; break; case CAP_CMD_T_MOVE: if ((argstate.argc < 2) || (argstate.argc > 3)) elfedit_command_usage(); ndx = arg_to_index(&argstate, argstate.argv[0], MSG_ORIG(MSG_STR_ELT), 0, &print_type); do_autoprint = 0; break; case CAP_CMD_T_HW1: print_only = (argstate.argc == 0); ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( ELFEDIT_CONST_CA, CA_SUNW_HW_1, 1), MSG_ORIG(MSG_STR_VALUE), print_only, &print_type); break; case CAP_CMD_T_SF1: print_only = (argstate.argc == 0); ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( ELFEDIT_CONST_CA, CA_SUNW_SF_1, 1), MSG_ORIG(MSG_STR_VALUE), print_only, &print_type); break; case CAP_CMD_T_HW2: print_only = (argstate.argc == 0); ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( ELFEDIT_CONST_CA, CA_SUNW_HW_2, 1), MSG_ORIG(MSG_STR_VALUE), print_only, &print_type); break; default: /* Note expected: All commands should have been caught above */ elfedit_command_usage(); break; } /* If this is a request to print current values, do it and return */ if (print_only) { print_cap(cmd, 0, &argstate, print_type, ndx); return (ELFEDIT_CMDRET_NONE); } switch (cmd) { /* * CAP_CMD_T_DUMP can't get here: It is a print-only * command. */ case CAP_CMD_T_TAG: { Conv_inv_buf_t inv_buf1, inv_buf2; Word c_tag = (Word) elfedit_atoconst(argstate.argv[1], ELFEDIT_CONST_CA); if (cap[ndx].c_tag == c_tag) { elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_OK), cap_ndx, cap_name, EC_WORD(ndx), conv_cap_tag(c_tag, 0, &inv_buf1)); } else { elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_S_CHG), cap_ndx, cap_name, EC_WORD(ndx), conv_cap_tag(cap[ndx].c_tag, 0, &inv_buf1), conv_cap_tag(c_tag, 0, &inv_buf2)); cap[ndx].c_tag = c_tag; ret = ELFEDIT_CMDRET_MOD; } } break; case CAP_CMD_T_VALUE: { Xword c_val; if (argstate.optmask & CAP_OPT_F_STRVAL) { argstate_add_str(&argstate, TRUE); c_val = elfedit_strtab_insert(obj_state, argstate.str.sec, NULL, argstate.argv[1]); } else { c_val = (Xword) elfedit_atoui(argstate.argv[1], NULL); } if (cap[ndx].c_un.c_val == c_val) { elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_X_OK), argstate.cap.sec->sec_shndx, argstate.cap.sec->sec_name, EC_WORD(ndx), EC_XWORD(c_val)); } else { elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_X_CHG), argstate.cap.sec->sec_shndx, argstate.cap.sec->sec_name, EC_WORD(ndx), EC_XWORD(cap[ndx].c_un.c_val), EC_XWORD(c_val)); cap[ndx].c_un.c_val = c_val; ret = ELFEDIT_CMDRET_MOD; } } break; case CAP_CMD_T_DELETE: { Word cnt = (argstate.argc == 1) ? 1 : (Word) elfedit_atoui_range(argstate.argv[1], MSG_ORIG(MSG_STR_COUNT), 1, argstate.cap.grp_end_ndx - ndx + 1, NULL); const char *msg_prefix = elfedit_sec_msgprefix(argstate.cap.sec); /* * We want to limit the deleted elements to be * in the range of the current capabilities group, * and for the resulting NULL elements to be inserted * at the end of the group, rather than at the end * of the section. To do this, we set the array length * in the call to the delete function so that it thinks * the array ends with the current group. * * The delete function will catch attempts to delete * past this virtual end, but the error message will * not make sense to the user. In order to prevent that, * we check for the condition here and provide a more * useful error. */ if ((ndx + cnt - 1) > argstate.cap.grp_end_ndx) elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_GRPARRBNDS), msg_prefix, argstate.cap.grp_start_ndx, argstate.cap.grp_end_ndx, cap_group_id(&argstate)); elfedit_array_elts_delete(msg_prefix, cap, sizeof (Cap), argstate.cap.grp_end_ndx + 1, ndx, cnt); ret = ELFEDIT_CMDRET_MOD; } break; case CAP_CMD_T_MOVE: { Cap save; Word cnt; Word dstndx; const char *msg_prefix = elfedit_sec_msgprefix(argstate.cap.sec); dstndx = (Word) elfedit_atoui_range(argstate.argv[1], MSG_ORIG(MSG_STR_DST_INDEX), argstate.cap.grp_start_ndx, argstate.cap.grp_end_ndx, NULL); if (argstate.argc == 2) { cnt = 1; } else { Word max; max = argstate.cap.grp_end_ndx - ((ndx > dstndx) ? ndx : dstndx) + 1; cnt = (Word) elfedit_atoui_range( argstate.argv[2], MSG_ORIG(MSG_STR_COUNT), 1, max, NULL); } /* * Moves are required to be self contained within * the bounds of the selected capability group. * The move utility function contains bounds checking, * but is not sub-array aware. Hence, we bounds check * check it here, and then hand of the validated * operation to the move utility function to execute. */ if ((ndx < argstate.cap.grp_start_ndx) || ((ndx + cnt) > argstate.cap.grp_end_ndx) || (dstndx < argstate.cap.grp_start_ndx) || ((dstndx + cnt) > argstate.cap.grp_end_ndx)) elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_GRPARRBNDS), msg_prefix, argstate.cap.grp_start_ndx, argstate.cap.grp_end_ndx, cap_group_id(&argstate)); elfedit_array_elts_move(msg_prefix, cap, sizeof (save), argstate.cap.grp_end_ndx + 1, ndx, dstndx, cnt, &save); ret = ELFEDIT_CMDRET_MOD; } break; case CAP_CMD_T_HW1: { ret = cap_set(&argstate, cap, ndx, cap_ndx, cap_name, CA_SUNW_HW_1, ELFEDIT_CONST_HW1_SUNW); } break; case CAP_CMD_T_SF1: { ret = cap_set(&argstate, cap, ndx, cap_ndx, cap_name, CA_SUNW_SF_1, ELFEDIT_CONST_SF1_SUNW); } break; case CAP_CMD_T_HW2: { ret = cap_set(&argstate, cap, ndx, cap_ndx, cap_name, CA_SUNW_HW_2, ELFEDIT_CONST_HW2_SUNW); } break; } /* * If we modified the capabilities section header, tell libelf. */ if (ret == ELFEDIT_CMDRET_MOD) elfedit_modified_data(argstate.cap.sec); /* Do autoprint */ if (do_autoprint) print_cap(cmd, 1, &argstate, print_type, ndx); return (ret); }