int main(int argc, char **argv) { FILE *in; unsigned char *msg, *sec[9]; long int last_pos; struct stat stat_buf; /* for type of grib input file */ int file_arg, i, j, num_submsgs; int n_arg; unsigned int k, ndata; float *data; double *ddata, ref; #ifdef USE_G2CLIB float missing_c_val_1, missing_c_val_2; g2int *bitmap, has_bitmap; g2float *g2_data; int ii; #endif struct ARGLIST arglist[N_ARGLIST]; int narglist = 0; const char *new_argv[N_ARGLIST]; void *local[N_ARGLIST]; int has_inv_option, last_submsg; int err, new_GDS, gdt, pdt, center; unsigned char dscale[2] = {0,0}; inv_file = stdout; // jas_init(); // gctpc initialiation init(-1,-1,"gctpc_1,txt", "gctpc_2.txt"); data = NULL; ndata = 0; /* no arguments .. help screen */ if (argc == 1) { // f_help(-1,NULL,NULL,0,inv_out,local,"most"); mode = -1; data = NULL; ndata = 0; *inv_out = 0; f_h(call_ARG0(inv_out,NULL)); fprintf(inv_file, "%s\n", inv_out); eof_bin(); eof_string(); exit(8); } setup_user_gribtable(); /* copy argv */ for (i = 0; i < argc; i++) { new_argv[i] = argv[i]; } /* scan for "inv" and input file */ has_inv_option = 0; file_arg = 0; for (i = 1; i < argc; i++) { if (new_argv[i][0] != '-') { /* must be filename */ file_arg = i; continue; } /* must be an option */ for (j = 0; j < nfunctions; j++) { if (strcmp(&(new_argv[i][1]),functions[j].name) == 0) { if (functions[j].type == inv) has_inv_option = 1; i += functions[j].nargs; break; } } } /* if no inv option, use default inventory .. put it at end */ if (has_inv_option == 0) { for (i = 0; i < argc; i++) { new_argv[i] = new_argv[i]; } new_argv[argc++] = "-s"; } /* parse parameters */ file_arg = 0; for (i = 1; i < argc; i++) { if (new_argv[i][0] != '-' || (strcmp(new_argv[i],"-") == 0) ) { /* must be filename */ if (file_arg == 0) { file_arg = i; continue; } else { fatal_error("too many grib files .. 2nd=%s", new_argv[i]); } } /* must be an option */ for (j = 0; j < nfunctions; j++) { if (strcmp(&(new_argv[i][1]),functions[j].name) == 0) { #ifdef DEBUG fprintf(stderr,"match .. -%s %d args\n", functions[j].name, functions[j].nargs); #endif /* add to function argument list */ arglist[narglist].fn = j; arglist[narglist].i_argc = i+1; if (functions[j].type == inv) has_inv_option = 1; i += functions[j].nargs; if (i >= argc) fatal_error("missing arguments option=%s",functions[j].name); narglist++; break; } } if (j == nfunctions) { fatal_error("unknown option %s", new_argv[i]); } } if (has_inv_option == 0) { fatal_error("missing arguments on last option",""); } /* initialize options mode = -1 */ #ifdef DEBUG fprintf(stderr,"init options narglist %d\n",narglist); #endif for (j = 0; j < narglist; j++) { inv_out[0] = 0; n_arg = functions[arglist[j].fn].nargs; err = 0; if (n_arg == 0) err = functions[arglist[j].fn].fn(-1,NULL,NULL,0, inv_out,local+j); else if (n_arg == 1) err = functions[arglist[j].fn].fn(-1,NULL,NULL,0, inv_out,local+j, new_argv[arglist[j].i_argc]); else if (n_arg == 2) err = functions[arglist[j].fn].fn(-1,NULL,NULL,0, inv_out,local+j, new_argv[arglist[j].i_argc],new_argv[arglist[j].i_argc+1]); else if (n_arg == 3) err = functions[arglist[j].fn].fn(-1,NULL,NULL,0, inv_out,local+j, new_argv[arglist[j].i_argc],new_argv[arglist[j].i_argc+1],new_argv[arglist[j].i_argc+2]); else if (n_arg == 4) err = functions[arglist[j].fn].fn(-1,NULL,NULL,0, inv_out,local+j, new_argv[arglist[j].i_argc],new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3]); else if (n_arg == 5) err = functions[arglist[j].fn].fn(-1,NULL,NULL,0, inv_out,local+j, new_argv[arglist[j].i_argc],new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3], new_argv[arglist[j].i_argc+4]); else if (n_arg == 6) err = functions[arglist[j].fn].fn(-1,NULL,NULL,0, inv_out,local+j, new_argv[arglist[j].i_argc],new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3], new_argv[arglist[j].i_argc+4], new_argv[arglist[j].i_argc+5]); else if (n_arg == 7) err = functions[arglist[j].fn].fn(-1,NULL,NULL,0, inv_out,local+j, new_argv[arglist[j].i_argc],new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3], new_argv[arglist[j].i_argc+4], new_argv[arglist[j].i_argc+5], new_argv[arglist[j].i_argc+6]); else if (n_arg == 8) err = functions[arglist[j].fn].fn(-1,NULL,NULL,0, inv_out,local+j, new_argv[arglist[j].i_argc],new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3], new_argv[arglist[j].i_argc+4], new_argv[arglist[j].i_argc+5], new_argv[arglist[j].i_argc+6], new_argv[arglist[j].i_argc+7]); if(inv_out[0] != 0) fprintf(inv_file, "%s", inv_out); if (err) { err_bin(); err_string(); exit(8); } } if (file_arg == 0 && argc > 1) fatal_error("no input file", ""); if (latlon == 1 && output_order_wanted != wesn) fatal_error("latitude-longitude information is only available with -order we:sn",""); /* open input file */ seq_input = 0; if (strcmp(new_argv[file_arg],"-") == 0) { seq_input = 1; in = stdin; if (mode == 98) fprintf(stderr, "grib input is stdin\n"); } else { if (stat(new_argv[file_arg], &stat_buf) != -1) { if (S_ISREG(stat_buf.st_mode)) { if (mode == 98) fprintf(stderr, "grib input is a regular file\n"); } else if (S_ISDIR(stat_buf.st_mode)) { fatal_error("grib input is a directory: %s",new_argv[file_arg]); } else if (S_ISCHR(stat_buf.st_mode)) { seq_input = 1; if (mode == 98) fprintf(stderr, "grib input is a char device\n"); } else if (S_ISBLK(stat_buf.st_mode)) { seq_input = 1; if (mode == 98) fprintf(stderr, "grib input is a block device\n"); } else if (S_ISFIFO(stat_buf.st_mode)) { seq_input = 1; if (mode == 98) fprintf(stderr, "grib input is a fifo device\n"); } else { if (mode == 98) fprintf(stderr, "grib input has an unknown type\n"); } } if ((in = fopen(new_argv[file_arg],"rb")) == NULL) { fatal_error("could not open file: %s", new_argv[file_arg]); } } /* sequential input - can not do random access */ if (seq_input && input == inv_mode) fatal_error("wgrib2 cannot random access grib input file",""); ndata = 0; data = NULL; ddata = NULL; msg_no = 1; inv_no = 0; len = pos = 0; submsg = 0; msg = NULL; if ((old_gds = (unsigned char *) malloc(GDS_max_size * sizeof(char)) ) == NULL) { fatal_error("memory allocation problem old_gds in wgrib2.main",""); } last_pos = -1; last_submsg = -1; /* if dump mode .. position io stream */ if (input == dump_mode) { while (msg_no < dump_msg) { msg = seq_input ? rd_grib2_msg_seq(in, &pos, &len, &num_submsgs) : rd_grib2_msg(in, &pos, &len, &num_submsgs); if (msg == NULL) fatal_error_i("record %d not found", dump_msg); last_pos = pos; pos += len; msg_no++; } #ifdef DEBUG printf("dump mode msg=%d\n", msg_no); #endif } /* * submsg = 0 .. beginning of unread record * submsg = i .. start at ith submsg * num_submsgs = number of submessages in grib message */ /* inventory loop */ for (;last_message == 0;) { /* need position and submessage number of message */ if (input == inv_mode || input == dump_mode) { if (input == inv_mode) { if (rd_inventory(&msg_no,&submsg, &pos)) break; } else if (input == dump_mode) { if (dump_msg == -1) break; submsg = dump_submsg; dump_msg = -1; } if (pos != last_pos) { msg = seq_input ? rd_grib2_msg_seq(in, &pos, &len, &num_submsgs) : rd_grib2_msg(in, &pos, &len, &num_submsgs); if (msg == NULL) { fatal_error_i("grib message #%d not found", msg_no); break; } last_pos = pos; last_submsg = -1; } if (pos == last_pos && submsg == last_submsg + 1) { /* read previous submessage */ if (parse_next_msg(sec) != 0) { fprintf(stderr,"\n*** grib message #%d.%d not found ***\n\n", msg_no, submsg); break; } } else { /* need to get desired submessage into sec */ if (parse_1st_msg(sec) != 0) { fprintf(stderr,"\n*** grib message #%d.1 not found ***\n\n", msg_no); break; } for (i = 2; i <= submsg; i++) { if (parse_next_msg(sec) != 0) { fprintf(stderr,"\n*** grib message #%d.%d not found ***\n\n", msg_no, i); break; } } } last_submsg = submsg; } else if (input == all_mode) { if (submsg == 0) { msg = seq_input ? rd_grib2_msg_seq(in, &pos, &len, &num_submsgs) : rd_grib2_msg(in, &pos, &len, &num_submsgs); if (msg == NULL) break; submsg = 1; } else if (submsg > num_submsgs) { pos += len; msg_no++; msg = seq_input ? rd_grib2_msg_seq(in, &pos, &len, &num_submsgs) : rd_grib2_msg(in, &pos, &len, &num_submsgs); if (msg == NULL) break; submsg = 1; } if (submsg == 1) { if (parse_1st_msg(sec) != 0) { fprintf(stderr,"illegal format: parsing 1st submessage\n"); } } else { if (parse_next_msg(sec) != 0) { fprintf(stderr,"illegal format: parsing submessages\n"); } } } if (only_submsg > 0 && only_submsg != submsg) { submsg++; continue; } if (for_mode) { if (msg_no < for_start || msg_no > for_end || ((msg_no - for_start) % for_step) != 0) { if (msg_no > for_end && input != inv_mode) last_message = 1; submsg++; continue; } } #ifdef USE_REGEX /* move inv_no++ before match_inv is made */ inv_no++; if (match) { inv_out[0] = 0; if (num_submsgs > 1) { sprintf(inv_out,"%d.%d:", msg_no, submsg); } else { sprintf(inv_out,"%d:", msg_no); } // f_match_inv(0, sec, NULL, 0, inv_out+strlen(inv_out), NULL); f_match_inv(call_ARG0(inv_out+strlen(inv_out), NULL)); if (is_match(inv_out) != 0) { submsg++; inv_no--; continue; } } #endif match_flag = 0; if (for_n_mode) { if (inv_no < for_n_start || inv_no > for_n_end || ((inv_no - for_n_start) % for_n_step) != 0) { if (inv_no > for_n_end) last_message = 1; submsg++; continue; } } /* see if new GDS */ if ((i = GB2_Sec3_size(sec)) != old_GDS_size) { new_GDS = 1; } else { new_GDS = 0; for (j = 0; j < i; j++) { if (old_gds[j] != sec[3][j]) new_GDS = 1; } } if (new_GDS) { GDS_change_no++; if (i > GDS_max_size) { free(old_gds); GDS_max_size = i; if ((old_gds = (unsigned char *) malloc(GDS_max_size) ) == NULL) { fatal_error("memory allocation problem old_gds in wgrib2.main",""); } } for (j = 0; j < i; j++) { old_gds[j] = sec[3][j]; } old_GDS_size = i; /* update grid information */ get_nxny(sec, &nx, &ny, &npnts, &res, &scan); /* get nx, ny, and scan mode of grid */ output_order = (nx == -1 || ny == -1) ? raw : output_order_wanted; if (latlon) { i = 1; if (use_gctpc && output_order == wesn) { /* use gctpc to get lat lon values */ i = gctpc_get_latlon(sec, &lon, &lat); } if (i) get_latlon(sec, &lon, &lat); /* get lat lon of grid points */ } } /* Decode NDFD WxText */ if (WxText) mk_WxKeys(sec); // any fixes to raw grib message before decode need to be placed here if (fix_ncep_2_flag) fix_ncep_2(sec); if (fix_ncep_3_flag) fix_ncep_3(sec); if (fix_ncep_4_flag) fix_ncep_4(sec); #ifdef CHECK j = code_table_5_0(sec); // type of compression /* yes this can be simplified but want to split it up in case other decoders have problems */ if (j == 0 && sec[5][19] == 0 && int2(sec[5] + 17) != 0 && ieee2flt(sec[5]+11) != 0.0) fprintf(stderr,"Warning: g2lib/g2clib/grib-api simple decode may differ from WMO standard, use -g2clib 0 for WMO standard\n"); if ((j == 2 || j == 3) && int2(sec[5]+17) != 0 && int4(sec[5] + 31) == 0 && ieee2flt(sec[5]+11) != 0.0) fprintf(stderr,"Warning: g2lib/g2clib complex decode may differ from WMO standard, use -g2clib 0 for WMO standard\n"); if (j == 40 && sec[5][19] == 0 && int2(sec[5] + 17) != 0 && ieee2flt(sec[5]+11) != 0.0) fprintf(stderr,"Warning: g2lib/g2clib jpeg deocde may differ from WMO standard, use use -g2clib 0 for WMO standard\n"); if (j == 41 && sec[5][19] == 0 && int2(sec[5] + 17) != 0 && ieee2flt(sec[5]+11) != 0.0) fprintf(stderr,"Warning: g2lib/g2clib/grib-api png decode may differ from WMO standard, use -g2clib 0 for WMO standard\n"); #endif #ifdef CHECK /* check the size of Section 7 */ /* code to check the other sizes needs to be placed in decode routines */ j = code_table_5_0(sec); // type of compression if (j == 0) { /* simple */ /* to avoid overflow on 32 bit machines */ /* old: k = (GB2_Sec5_nval(sec) * sec[5][19] + 7) / 8 + 5; */ k = 5 + (GB2_Sec5_nval(sec)/8) * sec[5][19] + (GB2_Sec5_nval(sec)%8) * (sec[5][19]/8) + ( (GB2_Sec5_nval(sec)%8) * (sec[5][19]%8) + 7) / 8; if (k != GB2_Sec7_size(sec)) { fprintf(stderr,"Detected a size mismatch, Section 7, wanted %d found %d\n", k, GB2_Sec7_size(sec)); if (decode) fatal_error("Section 7 size, mismatch, simple packing",""); } } else if (j == 4) { /* IEEE */ k = GB2_Sec5_nval(sec) * 4 + 5; if (k != GB2_Sec7_size(sec)) { fprintf(stderr,"Detected a size mismatch, Section 7, wanted %d found %d\n", k, GB2_Sec7_size(sec)); if (decode) fatal_error("Section 7 size, mismatch, IEEE packing",""); } } #endif if (decode) { #ifdef CHECK if (code_table_6_0(sec) == 0) { // has bitmap k = GB2_Sec3_npts(sec) - GB2_Sec5_nval(sec); if (k != missing_points(sec[6]+6, GB2_Sec3_npts(sec))) fatal_error_ii("inconsistent number of bitmap points sec3-sec5: %d sec6: %d", k, missing_points(sec[6]+6, GB2_Sec3_npts(sec))); } else if (code_table_6_0(sec) == 255) { // no bitmap if (GB2_Sec3_npts(sec) != GB2_Sec5_nval(sec)) fatal_error_ii("inconsistent number of data points sec3: %d sec5: %d", GB2_Sec3_npts(sec), GB2_Sec5_nval(sec)); } #endif /* allocate data */ if (GB2_Sec3_npts(sec) != ndata) { if (ndata) free(data); ndata = GB2_Sec3_npts(sec); if (ndata) { data = (float *) malloc(ndata * sizeof(float)); if (data == NULL) fatal_error("main: memory allocation failed data",""); } else { data = NULL; } } j = code_table_5_0(sec); // type of compression gdt = code_table_3_1(sec); // grid type pdt = GB2_ProdDefTemplateNo(sec); // product defintion template /* USE G2CLIB */ #ifdef USE_G2CLIB if (use_g2clib == 2) { err = g2_getfld(msg,submsg,1,1,&grib_data); if (err != 0) fatal_error_ii("Fatal g2clib decode err=%d msg=%d", err, msg_no); free_gribfield = 1; has_bitmap = grib_data->ibmap; g2_data = &(grib_data->fld[0]); if (has_bitmap == 0 || has_bitmap == 254) { bitmap = grib_data->bmap; for (i = 0; i < ndata; i++) { data[i] = (bitmap[i] == 0) ? UNDEFINED : g2_data[i]; } } else { for (i = 0; i < ndata; i++) { data[i] = g2_data[i]; } } /* complex packing uses special values for undefined */ ii = sub_missing_values(sec, &missing_c_val_1, &missing_c_val_2); if (ii == 1) { for (i = 0; i < ndata; i++) { if (data[i] == missing_c_val_1) data[i] = UNDEFINED; } } else if (ii == 2) { for (i = 0; i < ndata; i++) { if (data[i] == missing_c_val_1) data[i] = UNDEFINED; if (data[i] == missing_c_val_2) data[i] = UNDEFINED; } } } #endif /* USE INTERNAL DECODER */ if (use_g2clib != 2) { center = GB2_Center(sec); if (use_g2clib == 1) { // introduce g2clib constant field error /* g2clib ignores decimal scaling for constant fields make internal decoders look like g2clib*/ if ( (j == 0 && sec[5][19] == 0) || ((j == 2 || j == 3) && int4(sec[5] + 31) == 0) || (j == 40 && sec[5][19] == 0) || (j == 41 && sec[5][19] == 0) || (center == NCEP && j == 40000 && sec[5][19] == 0) || (center == NCEP && j == 40010 && sec[5][19] == 0) ) { dscale[0] = sec[5][17]; dscale[1] = sec[5][18]; sec[5][17] = sec[5][18] = 0; } } err = unpk_grib(sec, data); if (err != 0) fatal_error_i("Fatal decode packing type %d",err); if (use_g2clib == 1) { // fix up data /* restore decimal scaling */ if ( (j == 0 && sec[5][19] == 0) || ((j == 2 || j == 3) && int4(sec[5] + 31) == 0) || (j == 40 && sec[5][19] == 0) || (j == 41 && sec[5][19]) || (center == NCEP && j == 40000 && sec[5][19] == 0) || (center == NCEP && j == 40010 && sec[5][19] == 0) ) { sec[5][17] = dscale[0]; sec[5][18] = dscale[1]; } } } /* convert to standard output order we:sn */ if (output_order_wanted == wesn) to_we_sn_scan(data); else if (output_order_wanted == wens) to_we_ns_scan(data); } else { if (ndata) free(data); ndata = 0; data = NULL; } /* get scaling parameters */ use_scale = scaling(sec, &ref, &dec_scale, &bin_scale, &i) == 0; if (num_submsgs > 1) { fprintf(inv_file, "%d.%d%s%ld", msg_no, submsg, ":", pos); } else { fprintf(inv_file, "%d%s%ld", msg_no, ":", pos); } for (j = 0; j < narglist; j++) { /* skip execution if match_flag == 1 */ /* an output option acts as endif for match_flag */ if (match_flag == 1) { if (functions[arglist[j].fn].type == output) match_flag = 0; continue; } // if (functions[arglist[j].fn].type == inv) fprintf(inv_file, item_deliminator); if (functions[arglist[j].fn].type == inv) fprintf(inv_file, "%s", item_deliminator); if (functions[arglist[j].fn].type != setup) { inv_out[0] = 0; n_arg = functions[arglist[j].fn].nargs; if (n_arg == 0) functions[arglist[j].fn].fn(mode, sec, data, ndata, inv_out, local+j); else if (n_arg == 1) functions[arglist[j].fn].fn(mode, sec, data, ndata, inv_out, local+j, new_argv[arglist[j].i_argc]); else if (n_arg == 2) functions[arglist[j].fn].fn(mode, sec, data, ndata, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1]); else if (n_arg == 3) functions[arglist[j].fn].fn(mode, sec, data, ndata, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2]); else if (n_arg == 4) functions[arglist[j].fn].fn(mode, sec, data, ndata, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3]); else if (n_arg == 5) functions[arglist[j].fn].fn(mode, sec, data, ndata, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3], new_argv[arglist[j].i_argc+4]); else if (n_arg == 6) functions[arglist[j].fn].fn(mode, sec, data, ndata, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3], new_argv[arglist[j].i_argc+4], new_argv[arglist[j].i_argc+5]); else if (n_arg == 7) functions[arglist[j].fn].fn(mode, sec, data, ndata, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3], new_argv[arglist[j].i_argc+4], new_argv[arglist[j].i_argc+5], new_argv[arglist[j].i_argc+6]); else if (n_arg == 8) functions[arglist[j].fn].fn(mode, sec, data, ndata, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3], new_argv[arglist[j].i_argc+4], new_argv[arglist[j].i_argc+5], new_argv[arglist[j].i_argc+6], new_argv[arglist[j].i_argc+7]); if(inv_out[0] != 0) fprintf(inv_file, "%s", inv_out); } } #ifdef CHECK if (!decode) { if (code_table_6_0(sec) == 0) { // has bitmap k = GB2_Sec3_npts(sec) - GB2_Sec5_nval(sec); if (k != missing_points(sec[6]+6, GB2_Sec3_npts(sec))) fatal_error_ii("inconsistent number of bitmap points sec3-sec5: %d sec6: %d", k, missing_points(sec[6]+6, GB2_Sec3_npts(sec))); } else if (code_table_6_0(sec) == 255) { // no bitmap if (GB2_Sec3_npts(sec) != GB2_Sec5_nval(sec)) fatal_error_ii("inconsistent number of data points sec3: %d sec5: %d", GB2_Sec3_npts(sec), GB2_Sec5_nval(sec)); } } #endif submsg++; #ifdef USE_G2CLIB if (free_gribfield) { g2_free(grib_data); free_gribfield = 0;} #endif // fprintf(inv_file, "\n"); fprintf(inv_file, "%s",end_inv); if (flush_mode) fflush(inv_file); if (dump_msg > 0) break; } /* finalize all functions, call with mode = -2 */ for (j = 0; j < narglist; j++) { if (functions[arglist[j].fn].type != setup) { n_arg = functions[arglist[j].fn].nargs; inv_out[0] = 0; if (n_arg == 0) functions[arglist[j].fn].fn(-2, NULL, NULL, 0, inv_out, local+j); else if (n_arg == 1) functions[arglist[j].fn].fn(-2, NULL, NULL, 0, inv_out, local+j, new_argv[arglist[j].i_argc]); else if (n_arg == 2) functions[arglist[j].fn].fn(-2, NULL, NULL, 0, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1]); else if (n_arg == 3) functions[arglist[j].fn].fn(-2, NULL, NULL, 0, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2]); else if (n_arg == 4) functions[arglist[j].fn].fn(-2, NULL, NULL, 0, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3]); else if (n_arg == 5) functions[arglist[j].fn].fn(-2, NULL, NULL, 0, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3], new_argv[arglist[j].i_argc+4]); else if (n_arg == 6) functions[arglist[j].fn].fn(-2, NULL, NULL, 0, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3], new_argv[arglist[j].i_argc+4], new_argv[arglist[j].i_argc+5]); else if (n_arg == 7) functions[arglist[j].fn].fn(-2, NULL, NULL, 0, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3], new_argv[arglist[j].i_argc+4], new_argv[arglist[j].i_argc+5], new_argv[arglist[j].i_argc+6]); else if (n_arg == 8) functions[arglist[j].fn].fn(-2, NULL, NULL, 0, inv_out, local+j, new_argv[arglist[j].i_argc], new_argv[arglist[j].i_argc+1], new_argv[arglist[j].i_argc+2], new_argv[arglist[j].i_argc+3], new_argv[arglist[j].i_argc+4], new_argv[arglist[j].i_argc+5], new_argv[arglist[j].i_argc+6], new_argv[arglist[j].i_argc+7]); // if (inv_out[0]) fprintf(stderr, "%s\n", inv_out); if (inv_out[0]) fprintf(stderr, "%s%s", inv_out, end_inv); } } eof_bin(); eof_string(); exit(0); }
/* Scrub all the ondisk inode fields. */ STATIC void xchk_dinode( struct xfs_scrub *sc, struct xfs_dinode *dip, xfs_ino_t ino) { struct xfs_mount *mp = sc->mp; size_t fork_recs; unsigned long long isize; uint64_t flags2; uint32_t nextents; uint16_t flags; uint16_t mode; flags = be16_to_cpu(dip->di_flags); if (dip->di_version >= 3) flags2 = be64_to_cpu(dip->di_flags2); else flags2 = 0; /* di_mode */ mode = be16_to_cpu(dip->di_mode); switch (mode & S_IFMT) { case S_IFLNK: case S_IFREG: case S_IFDIR: case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: /* mode is recognized */ break; default: xchk_ino_set_corrupt(sc, ino); break; } /* v1/v2 fields */ switch (dip->di_version) { case 1: /* * We autoconvert v1 inodes into v2 inodes on writeout, * so just mark this inode for preening. */ xchk_ino_set_preen(sc, ino); break; case 2: case 3: if (dip->di_onlink != 0) xchk_ino_set_corrupt(sc, ino); if (dip->di_mode == 0 && sc->ip) xchk_ino_set_corrupt(sc, ino); if (dip->di_projid_hi != 0 && !xfs_sb_version_hasprojid32bit(&mp->m_sb)) xchk_ino_set_corrupt(sc, ino); break; default: xchk_ino_set_corrupt(sc, ino); return; } /* * di_uid/di_gid -- -1 isn't invalid, but there's no way that * userspace could have created that. */ if (dip->di_uid == cpu_to_be32(-1U) || dip->di_gid == cpu_to_be32(-1U)) xchk_ino_set_warning(sc, ino); /* di_format */ switch (dip->di_format) { case XFS_DINODE_FMT_DEV: if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode) && !S_ISSOCK(mode)) xchk_ino_set_corrupt(sc, ino); break; case XFS_DINODE_FMT_LOCAL: if (!S_ISDIR(mode) && !S_ISLNK(mode)) xchk_ino_set_corrupt(sc, ino); break; case XFS_DINODE_FMT_EXTENTS: if (!S_ISREG(mode) && !S_ISDIR(mode) && !S_ISLNK(mode)) xchk_ino_set_corrupt(sc, ino); break; case XFS_DINODE_FMT_BTREE: if (!S_ISREG(mode) && !S_ISDIR(mode)) xchk_ino_set_corrupt(sc, ino); break; case XFS_DINODE_FMT_UUID: default: xchk_ino_set_corrupt(sc, ino); break; } /* di_[amc]time.nsec */ if (be32_to_cpu(dip->di_atime.t_nsec) >= NSEC_PER_SEC) xchk_ino_set_corrupt(sc, ino); if (be32_to_cpu(dip->di_mtime.t_nsec) >= NSEC_PER_SEC) xchk_ino_set_corrupt(sc, ino); if (be32_to_cpu(dip->di_ctime.t_nsec) >= NSEC_PER_SEC) xchk_ino_set_corrupt(sc, ino); /* * di_size. xfs_dinode_verify checks for things that screw up * the VFS such as the upper bit being set and zero-length * symlinks/directories, but we can do more here. */ isize = be64_to_cpu(dip->di_size); if (isize & (1ULL << 63)) xchk_ino_set_corrupt(sc, ino); /* Devices, fifos, and sockets must have zero size */ if (!S_ISDIR(mode) && !S_ISREG(mode) && !S_ISLNK(mode) && isize != 0) xchk_ino_set_corrupt(sc, ino); /* Directories can't be larger than the data section size (32G) */ if (S_ISDIR(mode) && (isize == 0 || isize >= XFS_DIR2_SPACE_SIZE)) xchk_ino_set_corrupt(sc, ino); /* Symlinks can't be larger than SYMLINK_MAXLEN */ if (S_ISLNK(mode) && (isize == 0 || isize >= XFS_SYMLINK_MAXLEN)) xchk_ino_set_corrupt(sc, ino); /* * Warn if the running kernel can't handle the kinds of offsets * needed to deal with the file size. In other words, if the * pagecache can't cache all the blocks in this file due to * overly large offsets, flag the inode for admin review. */ if (isize >= mp->m_super->s_maxbytes) xchk_ino_set_warning(sc, ino); /* di_nblocks */ if (flags2 & XFS_DIFLAG2_REFLINK) { ; /* nblocks can exceed dblocks */ } else if (flags & XFS_DIFLAG_REALTIME) { /* * nblocks is the sum of data extents (in the rtdev), * attr extents (in the datadev), and both forks' bmbt * blocks (in the datadev). This clumsy check is the * best we can do without cross-referencing with the * inode forks. */ if (be64_to_cpu(dip->di_nblocks) >= mp->m_sb.sb_dblocks + mp->m_sb.sb_rblocks) xchk_ino_set_corrupt(sc, ino); } else { if (be64_to_cpu(dip->di_nblocks) >= mp->m_sb.sb_dblocks) xchk_ino_set_corrupt(sc, ino); } xchk_inode_flags(sc, dip, ino, mode, flags); xchk_inode_extsize(sc, dip, ino, mode, flags); /* di_nextents */ nextents = be32_to_cpu(dip->di_nextents); fork_recs = XFS_DFORK_DSIZE(dip, mp) / sizeof(struct xfs_bmbt_rec); switch (dip->di_format) { case XFS_DINODE_FMT_EXTENTS: if (nextents > fork_recs) xchk_ino_set_corrupt(sc, ino); break; case XFS_DINODE_FMT_BTREE: if (nextents <= fork_recs) xchk_ino_set_corrupt(sc, ino); break; default: if (nextents != 0) xchk_ino_set_corrupt(sc, ino); break; } /* di_forkoff */ if (XFS_DFORK_APTR(dip) >= (char *)dip + mp->m_sb.sb_inodesize) xchk_ino_set_corrupt(sc, ino); if (dip->di_anextents != 0 && dip->di_forkoff == 0) xchk_ino_set_corrupt(sc, ino); if (dip->di_forkoff == 0 && dip->di_aformat != XFS_DINODE_FMT_EXTENTS) xchk_ino_set_corrupt(sc, ino); /* di_aformat */ if (dip->di_aformat != XFS_DINODE_FMT_LOCAL && dip->di_aformat != XFS_DINODE_FMT_EXTENTS && dip->di_aformat != XFS_DINODE_FMT_BTREE) xchk_ino_set_corrupt(sc, ino); /* di_anextents */ nextents = be16_to_cpu(dip->di_anextents); fork_recs = XFS_DFORK_ASIZE(dip, mp) / sizeof(struct xfs_bmbt_rec); switch (dip->di_aformat) { case XFS_DINODE_FMT_EXTENTS: if (nextents > fork_recs) xchk_ino_set_corrupt(sc, ino); break; case XFS_DINODE_FMT_BTREE: if (nextents <= fork_recs) xchk_ino_set_corrupt(sc, ino); break; default: if (nextents != 0) xchk_ino_set_corrupt(sc, ino); } if (dip->di_version >= 3) { if (be32_to_cpu(dip->di_crtime.t_nsec) >= NSEC_PER_SEC) xchk_ino_set_corrupt(sc, ino); xchk_inode_flags2(sc, dip, ino, mode, flags, flags2); xchk_inode_cowextsize(sc, dip, ino, mode, flags, flags2); } }
int test_eval(Test_env *te, Test_op op, const char *opnd1, const char *opnd2, int do_eval) { int res; int not; struct stat b1, b2; if (!do_eval) return 0; switch ((int) op) { /* * Unary Operators */ case TO_STNZE: /* -n */ return *opnd1 != '\0'; case TO_STZER: /* -z */ return *opnd1 == '\0'; case TO_OPTION: /* -o */ if ((not = *opnd1 == '!')) opnd1++; if ((res = option(opnd1)) < 0) res = 0; else { res = Flag(res); if (not) res = !res; } return res; case TO_FILRD: /* -r */ return test_eaccess(opnd1, R_OK) == 0; case TO_FILWR: /* -w */ return test_eaccess(opnd1, W_OK) == 0; case TO_FILEX: /* -x */ return test_eaccess(opnd1, X_OK) == 0; case TO_FILAXST: /* -a */ return test_stat(opnd1, &b1) == 0; case TO_FILEXST: /* -e */ /* at&t ksh does not appear to do the /dev/fd/ thing for * this (unless the os itself handles it) */ return stat(opnd1, &b1) == 0; case TO_FILREG: /* -r */ return test_stat(opnd1, &b1) == 0 && S_ISREG(b1.st_mode); case TO_FILID: /* -d */ return test_stat(opnd1, &b1) == 0 && S_ISDIR(b1.st_mode); case TO_FILCDEV: /* -c */ return test_stat(opnd1, &b1) == 0 && S_ISCHR(b1.st_mode); case TO_FILBDEV: /* -b */ return test_stat(opnd1, &b1) == 0 && S_ISBLK(b1.st_mode); case TO_FILFIFO: /* -p */ return test_stat(opnd1, &b1) == 0 && S_ISFIFO(b1.st_mode); case TO_FILSYM: /* -h -L */ return lstat(opnd1, &b1) == 0 && S_ISLNK(b1.st_mode); case TO_FILSOCK: /* -S */ return test_stat(opnd1, &b1) == 0 && S_ISSOCK(b1.st_mode); case TO_FILCDF:/* -H HP context dependent files (directories) */ return 0; case TO_FILSETU: /* -u */ return test_stat(opnd1, &b1) == 0 && (b1.st_mode & S_ISUID) == S_ISUID; case TO_FILSETG: /* -g */ return test_stat(opnd1, &b1) == 0 && (b1.st_mode & S_ISGID) == S_ISGID; case TO_FILSTCK: /* -k */ return test_stat(opnd1, &b1) == 0 && (b1.st_mode & S_ISVTX) == S_ISVTX; case TO_FILGZ: /* -s */ return test_stat(opnd1, &b1) == 0 && b1.st_size > 0L; case TO_FILTT: /* -t */ if (opnd1 && !bi_getn(opnd1, &res)) { te->flags |= TEF_ERROR; res = 0; } else { /* generate error if in FPOSIX mode? */ res = isatty(opnd1 ? res : 0); } return res; case TO_FILUID: /* -O */ return test_stat(opnd1, &b1) == 0 && b1.st_uid == ksheuid; case TO_FILGID: /* -G */ return test_stat(opnd1, &b1) == 0 && b1.st_gid == getegid(); /* * Binary Operators */ case TO_STEQL: /* = */ if (te->flags & TEF_DBRACKET) return gmatch(opnd1, opnd2, false); return strcmp(opnd1, opnd2) == 0; case TO_STNEQ: /* != */ if (te->flags & TEF_DBRACKET) return !gmatch(opnd1, opnd2, false); return strcmp(opnd1, opnd2) != 0; case TO_STLT: /* < */ return strcmp(opnd1, opnd2) < 0; case TO_STGT: /* > */ return strcmp(opnd1, opnd2) > 0; case TO_INTEQ: /* -eq */ case TO_INTNE: /* -ne */ case TO_INTGE: /* -ge */ case TO_INTGT: /* -gt */ case TO_INTLE: /* -le */ case TO_INTLT: /* -lt */ { long v1, v2; if (!evaluate(opnd1, &v1, KSH_RETURN_ERROR, false) || !evaluate(opnd2, &v2, KSH_RETURN_ERROR, false)) { /* error already printed.. */ te->flags |= TEF_ERROR; return 1; } switch ((int) op) { case TO_INTEQ: return v1 == v2; case TO_INTNE: return v1 != v2; case TO_INTGE: return v1 >= v2; case TO_INTGT: return v1 > v2; case TO_INTLE: return v1 <= v2; case TO_INTLT: return v1 < v2; } } case TO_FILNT: /* -nt */ { int s2; /* ksh88/ksh93 succeed if file2 can't be stated * (subtly different from `does not exist'). */ return stat(opnd1, &b1) == 0 && (((s2 = stat(opnd2, &b2)) == 0 && b1.st_mtime > b2.st_mtime) || s2 < 0); } case TO_FILOT: /* -ot */ { int s1; /* ksh88/ksh93 succeed if file1 can't be stated * (subtly different from `does not exist'). */ return stat(opnd2, &b2) == 0 && (((s1 = stat(opnd1, &b1)) == 0 && b1.st_mtime < b2.st_mtime) || s1 < 0); } case TO_FILEQ: /* -ef */ return stat (opnd1, &b1) == 0 && stat (opnd2, &b2) == 0 && b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino; } (*te->error)(te, 0, "internal error: unknown op"); return 1; }
/*! * Determine if the file is a named pipe. * * This check is performed to support named pipes as logs by not rotating them * and opening them with a non-blocking flags. * * \param[in] fileName log file name * * \returns non-zero if log file is a named pipe. */ static int IsFIFO(const char *fileName) { struct stat statbuf; return (lstat(fileName, &statbuf) == 0) && (S_ISFIFO(statbuf.st_mode)); }
static int create_ghost(struct ghost_file *gf, GhostFileEntry *gfe, struct cr_img *img) { int gfd, ghost_flags, ret; char path[PATH_MAX]; ret = rst_get_mnt_root(gf->remap.rmnt_id, path, sizeof(path)); if (ret < 0) { pr_err("The %d mount is not found for ghost\n", gf->remap.rmnt_id); goto err; } snprintf(path + ret, sizeof(path) - ret, "/%s", gf->remap.rpath); ret = -1; if (S_ISFIFO(gfe->mode)) { if (mknod(path, gfe->mode, 0)) { pr_perror("Can't create node for ghost file"); goto err; } ghost_flags = O_RDWR; /* To not block */ } else if (S_ISCHR(gfe->mode) || S_ISBLK(gfe->mode)) { if (!gfe->has_rdev) { pr_err("No rdev for ghost device\n"); goto err; } if (mknod(path, gfe->mode, gfe->rdev)) { pr_perror("Can't create node for ghost dev"); goto err; } ghost_flags = O_WRONLY; } else if (S_ISDIR(gfe->mode)) { if (mkdir(path, gfe->mode)) { pr_perror("Can't make ghost dir"); goto err; } ghost_flags = O_DIRECTORY; } else ghost_flags = O_WRONLY | O_CREAT | O_EXCL; gfd = open(path, ghost_flags, gfe->mode); if (gfd < 0) { pr_perror("Can't open ghost file %s", path); goto err; } if (fchown(gfd, gfe->uid, gfe->gid) < 0) { pr_perror("Can't reset user/group on ghost %s", path); goto err_c; } if (S_ISREG(gfe->mode)) { if (copy_file(img_raw_fd(img), gfd, 0) < 0) goto err_c; } ret = 0; err_c: close(gfd); err: return ret; }
static int writeTarHeader(struct TarBallInfo *tbInfo, const char *header_name, const char *fileName, struct stat *statbuf) { struct TarHeader header; if (sizeof(header) != 512) BUG_tar_header_size(); memset(&header, 0, sizeof(struct TarHeader)); strncpy(header.name, header_name, sizeof(header.name)); /* POSIX says to mask mode with 07777. */ PUT_OCTAL(header.mode, statbuf->st_mode & 07777); PUT_OCTAL(header.uid, statbuf->st_uid); PUT_OCTAL(header.gid, statbuf->st_gid); memset(header.size, '0', sizeof(header.size)-1); /* Regular file size is handled later */ PUT_OCTAL(header.mtime, statbuf->st_mtime); /* Enter the user and group names */ safe_strncpy(header.uname, get_cached_username(statbuf->st_uid), sizeof(header.uname)); safe_strncpy(header.gname, get_cached_groupname(statbuf->st_gid), sizeof(header.gname)); if (tbInfo->hlInfo) { /* This is a hard link */ header.typeflag = LNKTYPE; strncpy(header.linkname, tbInfo->hlInfo->name, sizeof(header.linkname)); #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS /* Write out long linkname if needed */ if (header.linkname[sizeof(header.linkname)-1]) writeLongname(tbInfo->tarFd, GNULONGLINK, tbInfo->hlInfo->name, 0); #endif } else if (S_ISLNK(statbuf->st_mode)) { char *lpath = xmalloc_readlink_or_warn(fileName); if (!lpath) return FALSE; header.typeflag = SYMTYPE; strncpy(header.linkname, lpath, sizeof(header.linkname)); #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS /* Write out long linkname if needed */ if (header.linkname[sizeof(header.linkname)-1]) writeLongname(tbInfo->tarFd, GNULONGLINK, lpath, 0); #else /* If it is larger than 100 bytes, bail out */ if (header.linkname[sizeof(header.linkname)-1]) { free(lpath); bb_error_msg("names longer than "NAME_SIZE_STR" chars not supported"); return FALSE; } #endif free(lpath); } else if (S_ISDIR(statbuf->st_mode)) { header.typeflag = DIRTYPE; /* Append '/' only if there is a space for it */ if (!header.name[sizeof(header.name)-1]) header.name[strlen(header.name)] = '/'; } else if (S_ISCHR(statbuf->st_mode)) { header.typeflag = CHRTYPE; PUT_OCTAL(header.devmajor, major(statbuf->st_rdev)); PUT_OCTAL(header.devminor, minor(statbuf->st_rdev)); } else if (S_ISBLK(statbuf->st_mode)) { header.typeflag = BLKTYPE; PUT_OCTAL(header.devmajor, major(statbuf->st_rdev)); PUT_OCTAL(header.devminor, minor(statbuf->st_rdev)); } else if (S_ISFIFO(statbuf->st_mode)) { header.typeflag = FIFOTYPE; } else if (S_ISREG(statbuf->st_mode)) { if (sizeof(statbuf->st_size) > 4 && statbuf->st_size > (off_t)0777777777777LL ) { bb_error_msg_and_die("cannot store file '%s' " "of size %"OFF_FMT"d, aborting", fileName, statbuf->st_size); } header.typeflag = REGTYPE; PUT_OCTAL(header.size, statbuf->st_size); } else { bb_error_msg("%s: unknown file type", fileName); return FALSE; } #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS /* Write out long name if needed */ /* (we, like GNU tar, output long linkname *before* long name) */ if (header.name[sizeof(header.name)-1]) writeLongname(tbInfo->tarFd, GNULONGNAME, header_name, S_ISDIR(statbuf->st_mode)); #endif /* Now write the header out to disk */ chksum_and_xwrite(tbInfo->tarFd, &header); /* Now do the verbose thing (or not) */ if (tbInfo->verboseFlag) { FILE *vbFd = stdout; if (tbInfo->tarFd == STDOUT_FILENO) /* If the archive goes to stdout, verbose to stderr */ vbFd = stderr; /* GNU "tar cvvf" prints "extended" listing a-la "ls -l" */ /* We don't have such excesses here: for us "v" == "vv" */ /* '/' is probably a GNUism */ fprintf(vbFd, "%s%s\n", header_name, S_ISDIR(statbuf->st_mode) ? "/" : ""); } return TRUE; }
struct inode *wrapfs_iget(struct super_block *sb, struct inode *lower_inode) { struct wrapfs_inode_info *info; struct inode *inode; /* the new inode to return */ int err; inode = iget5_locked(sb, /* our superblock */ /* * hashval: we use inode number, but we can * also use "(unsigned long)lower_inode" * instead. */ lower_inode->i_ino, /* hashval */ wrapfs_inode_test, /* inode comparison function */ wrapfs_inode_set, /* inode init function */ lower_inode); /* data passed to test+set fxns */ if (!inode) { err = -EACCES; iput(lower_inode); return ERR_PTR(err); } /* if found a cached inode, then just return it */ if (!(inode->i_state & I_NEW)) return inode; /* initialize new inode */ info = WRAPFS_I(inode); inode->i_ino = lower_inode->i_ino; if (!igrab(lower_inode)) { err = -ESTALE; return ERR_PTR(err); } wrapfs_set_lower_inode(inode, lower_inode); inode->i_version++; /* use different set of inode ops for symlinks & directories */ if (S_ISDIR(lower_inode->i_mode)) inode->i_op = &wrapfs_dir_iops; else if (S_ISLNK(lower_inode->i_mode)) inode->i_op = &wrapfs_symlink_iops; else inode->i_op = &wrapfs_main_iops; /* use different set of file ops for directories */ if (S_ISDIR(lower_inode->i_mode)) inode->i_fop = &wrapfs_dir_fops; else inode->i_fop = &wrapfs_main_fops; inode->i_mapping->a_ops = &wrapfs_aops; inode->i_atime.tv_sec = 0; inode->i_atime.tv_nsec = 0; inode->i_mtime.tv_sec = 0; inode->i_mtime.tv_nsec = 0; inode->i_ctime.tv_sec = 0; inode->i_ctime.tv_nsec = 0; /* properly initialize special inodes */ if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) || S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode)) init_special_inode(inode, lower_inode->i_mode, lower_inode->i_rdev); /* all well, copy inode attributes */ fsstack_copy_attr_all(inode, lower_inode); fsstack_copy_inode_size(inode, lower_inode); unlock_new_inode(inode); return inode; }
/* Return: * -1 error, copy not made * 0 copy is made or user answered "no" in interactive mode * (failures to preserve mode/owner/times are not reported in exit code) */ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) { /* This is a recursive function, try to minimize stack usage */ /* NB: each struct stat is ~100 bytes */ struct stat source_stat; struct stat dest_stat; signed char retval = 0; signed char dest_exists = 0; signed char ovr; /* Inverse of cp -d ("cp without -d") */ #define FLAGS_DEREF (flags & FILEUTILS_DEREFERENCE) if ((FLAGS_DEREF ? stat : lstat)(source, &source_stat) < 0) { /* This may be a dangling symlink. * Making [sym]links to dangling symlinks works, so... */ if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) goto make_links; bb_perror_msg("cannot stat '%s'", source); return -1; } if (lstat(dest, &dest_stat) < 0) { if (errno != ENOENT) { bb_perror_msg("cannot stat '%s'", dest); return -1; } } else { if (source_stat.st_dev == dest_stat.st_dev && source_stat.st_ino == dest_stat.st_ino ) { bb_error_msg("'%s' and '%s' are the same file", source, dest); return -1; } dest_exists = 1; } #if ENABLE_SELINUX if ((flags & FILEUTILS_PRESERVE_SECURITY_CONTEXT) && is_selinux_enabled() > 0) { security_context_t con; if (lgetfilecon(source, &con) >= 0) { if (setfscreatecon(con) < 0) { bb_perror_msg("cannot set setfscreatecon %s", con); freecon(con); return -1; } } else if (errno == ENOTSUP || errno == ENODATA) { setfscreatecon_or_die(NULL); } else { bb_perror_msg("cannot lgetfilecon %s", source); return -1; } } #endif if (S_ISDIR(source_stat.st_mode)) { DIR *dp; const char *tp; struct dirent *d; mode_t saved_umask = 0; if (!(flags & FILEUTILS_RECUR)) { bb_error_msg("omitting directory '%s'", source); return -1; } /* Did we ever create source ourself before? */ tp = is_in_ino_dev_hashtable(&source_stat); if (tp) { /* We did! it's a recursion! man the lifeboats... */ bb_error_msg("recursion detected, omitting directory '%s'", source); return -1; } /* Create DEST */ if (dest_exists) { if (!S_ISDIR(dest_stat.st_mode)) { bb_error_msg("target '%s' is not a directory", dest); return -1; } /* race here: user can substitute a symlink between * this check and actual creation of files inside dest */ } else { mode_t mode; saved_umask = umask(0); mode = source_stat.st_mode; if (!(flags & FILEUTILS_PRESERVE_STATUS)) mode = source_stat.st_mode & ~saved_umask; /* Allow owner to access new dir (at least for now) */ mode |= S_IRWXU; if (mkdir(dest, mode) < 0) { umask(saved_umask); bb_perror_msg("cannot create directory '%s'", dest); return -1; } umask(saved_umask); /* need stat info for add_to_ino_dev_hashtable */ if (lstat(dest, &dest_stat) < 0) { bb_perror_msg("cannot stat '%s'", dest); return -1; } } /* remember (dev,inode) of each created dir. * NULL: name is not remembered */ add_to_ino_dev_hashtable(&dest_stat, NULL); /* Recursively copy files in SOURCE */ dp = opendir(source); if (dp == NULL) { retval = -1; goto preserve_mode_ugid_time; } while ((d = readdir(dp)) != NULL) { char *new_source, *new_dest; new_source = concat_subpath_file(source, d->d_name); if (new_source == NULL) continue; new_dest = concat_path_file(dest, d->d_name); if (copy_file(new_source, new_dest, flags) < 0) retval = -1; free(new_source); free(new_dest); } closedir(dp); if (!dest_exists && chmod(dest, source_stat.st_mode & ~saved_umask) < 0 ) { bb_perror_msg("cannot preserve %s of '%s'", "permissions", dest); /* retval = -1; - WRONG! copy *WAS* made */ } goto preserve_mode_ugid_time; } if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) { int (*lf)(const char *oldpath, const char *newpath); make_links: /* Hmm... maybe * if (DEREF && MAKE_SOFTLINK) source = realpath(source) ? * (but realpath returns NULL on dangling symlinks...) */ lf = (flags & FILEUTILS_MAKE_SOFTLINK) ? symlink : link; if (lf(source, dest) < 0) { ovr = ask_and_unlink(dest, flags); if (ovr <= 0) return ovr; if (lf(source, dest) < 0) { bb_perror_msg("cannot create link '%s'", dest); return -1; } } /* _Not_ jumping to preserve_mode_ugid_time: * (sym)links don't have those */ return 0; } if (/* "cp thing1 thing2" without -R: just open and read() from thing1 */ !(flags & FILEUTILS_RECUR) /* "cp [-opts] regular_file thing2" */ || S_ISREG(source_stat.st_mode) /* DEREF uses stat, which never returns S_ISLNK() == true. * So the below is never true: */ /* || (FLAGS_DEREF && S_ISLNK(source_stat.st_mode)) */ ) { int src_fd; int dst_fd; mode_t new_mode; if (!FLAGS_DEREF && S_ISLNK(source_stat.st_mode)) { /* "cp -d symlink dst": create a link */ goto dont_cat; } if (ENABLE_FEATURE_PRESERVE_HARDLINKS && !FLAGS_DEREF) { const char *link_target; link_target = is_in_ino_dev_hashtable(&source_stat); if (link_target) { if (link(link_target, dest) < 0) { ovr = ask_and_unlink(dest, flags); if (ovr <= 0) return ovr; if (link(link_target, dest) < 0) { bb_perror_msg("cannot create link '%s'", dest); return -1; } } return 0; } add_to_ino_dev_hashtable(&source_stat, dest); } src_fd = open_or_warn(source, O_RDONLY); if (src_fd < 0) return -1; /* Do not try to open with weird mode fields */ new_mode = source_stat.st_mode; if (!S_ISREG(source_stat.st_mode)) new_mode = 0666; // POSIX way is a security problem versus (sym)link attacks if (!ENABLE_FEATURE_NON_POSIX_CP) { dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, new_mode); } else { /* safe way: */ dst_fd = open(dest, O_WRONLY|O_CREAT|O_EXCL, new_mode); } if (dst_fd == -1) { ovr = ask_and_unlink(dest, flags); if (ovr <= 0) { close(src_fd); return ovr; } /* It shouldn't exist. If it exists, do not open (symlink attack?) */ dst_fd = open3_or_warn(dest, O_WRONLY|O_CREAT|O_EXCL, new_mode); if (dst_fd < 0) { close(src_fd); return -1; } } #if ENABLE_SELINUX if ((flags & (FILEUTILS_PRESERVE_SECURITY_CONTEXT|FILEUTILS_SET_SECURITY_CONTEXT)) && is_selinux_enabled() > 0 ) { security_context_t con; if (getfscreatecon(&con) == -1) { bb_perror_msg("getfscreatecon"); return -1; } if (con) { if (setfilecon(dest, con) == -1) { bb_perror_msg("setfilecon:%s,%s", dest, con); freecon(con); return -1; } freecon(con); } } #endif if (bb_copyfd_eof(src_fd, dst_fd) == -1) retval = -1; /* Ok, writing side I can understand... */ if (close(dst_fd) < 0) { bb_perror_msg("cannot close '%s'", dest); retval = -1; } /* ...but read size is already checked by bb_copyfd_eof */ close(src_fd); /* "cp /dev/something new_file" should not * copy mode of /dev/something */ if (!S_ISREG(source_stat.st_mode)) return retval; goto preserve_mode_ugid_time; } dont_cat: /* Source is a symlink or a special file */ /* We are lazy here, a bit lax with races... */ if (dest_exists) { errno = EEXIST; ovr = ask_and_unlink(dest, flags); if (ovr <= 0) return ovr; } if (S_ISLNK(source_stat.st_mode)) { char *lpath = xmalloc_readlink_or_warn(source); if (lpath) { int r = symlink(lpath, dest); free(lpath); if (r < 0) { bb_perror_msg("cannot create symlink '%s'", dest); return -1; } if (flags & FILEUTILS_PRESERVE_STATUS) if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0) bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest); } /* _Not_ jumping to preserve_mode_ugid_time: * symlinks don't have those */ return 0; } if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode) || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode) ) { if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) { bb_perror_msg("cannot create '%s'", dest); return -1; } } else { bb_error_msg("unrecognized file '%s' with mode %x", source, source_stat.st_mode); return -1; } preserve_mode_ugid_time: if (flags & FILEUTILS_PRESERVE_STATUS /* Cannot happen: */ /* && !(flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) */ ) { struct utimbuf times; times.actime = source_stat.st_atime; times.modtime = source_stat.st_mtime; /* BTW, utimes sets usec-precision time - just FYI */ if (utime(dest, ×) < 0) bb_perror_msg("cannot preserve %s of '%s'", "times", dest); if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) { source_stat.st_mode &= ~(S_ISUID | S_ISGID); bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest); } if (chmod(dest, source_stat.st_mode) < 0) bb_perror_msg("cannot preserve %s of '%s'", "permissions", dest); } return retval; }
int StatFile(ServerConnectionState *conn, char *sendbuffer, char *ofilename) /* Because we do not know the size or structure of remote datatypes,*/ /* the simplest way to transfer the data is to convert them into */ /* plain text and interpret them on the other side. */ { Stat cfst; struct stat statbuf, statlinkbuf; char linkbuf[CF_BUFSIZE], filename[CF_BUFSIZE]; int islink = false; TranslatePath(filename, ofilename); memset(&cfst, 0, sizeof(Stat)); if (strlen(ReadLastNode(filename)) > CF_MAXLINKSIZE) { snprintf(sendbuffer, CF_BUFSIZE, "BAD: Filename suspiciously long [%s]\n", filename); Log(LOG_LEVEL_ERR, "%s", sendbuffer); SendTransaction(&conn->conn_info, sendbuffer, 0, CF_DONE); return -1; } if (lstat(filename, &statbuf) == -1) { snprintf(sendbuffer, CF_BUFSIZE, "BAD: unable to stat file %s", filename); Log(LOG_LEVEL_VERBOSE, "%s. (lstat: %s)", sendbuffer, GetErrorStr()); SendTransaction(&conn->conn_info, sendbuffer, 0, CF_DONE); return -1; } cfst.cf_readlink = NULL; cfst.cf_lmode = 0; cfst.cf_nlink = CF_NOSIZE; memset(linkbuf, 0, CF_BUFSIZE); #ifndef __MINGW32__ // windows doesn't support symbolic links if (S_ISLNK(statbuf.st_mode)) { islink = true; cfst.cf_type = FILE_TYPE_LINK; /* pointless - overwritten */ cfst.cf_lmode = statbuf.st_mode & 07777; cfst.cf_nlink = statbuf.st_nlink; if (readlink(filename, linkbuf, CF_BUFSIZE - 1) == -1) { sprintf(sendbuffer, "BAD: unable to read link\n"); Log(LOG_LEVEL_ERR, "%s. (readlink: %s)", sendbuffer, GetErrorStr()); SendTransaction(&conn->conn_info, sendbuffer, 0, CF_DONE); return -1; } Log(LOG_LEVEL_DEBUG, "readlink '%s'", linkbuf); cfst.cf_readlink = linkbuf; } #endif /* !__MINGW32__ */ if ((!islink) && (stat(filename, &statbuf) == -1)) { Log(LOG_LEVEL_VERBOSE, "BAD: unable to stat file '%s'. (stat: %s)", filename, GetErrorStr()); SendTransaction(&conn->conn_info, sendbuffer, 0, CF_DONE); return -1; } Log(LOG_LEVEL_DEBUG, "Getting size of link deref '%s'", linkbuf); if (islink && (stat(filename, &statlinkbuf) != -1)) /* linktype=copy used by agent */ { statbuf.st_size = statlinkbuf.st_size; statbuf.st_mode = statlinkbuf.st_mode; statbuf.st_uid = statlinkbuf.st_uid; statbuf.st_gid = statlinkbuf.st_gid; statbuf.st_mtime = statlinkbuf.st_mtime; statbuf.st_ctime = statlinkbuf.st_ctime; } if (S_ISDIR(statbuf.st_mode)) { cfst.cf_type = FILE_TYPE_DIR; } if (S_ISREG(statbuf.st_mode)) { cfst.cf_type = FILE_TYPE_REGULAR; } if (S_ISSOCK(statbuf.st_mode)) { cfst.cf_type = FILE_TYPE_SOCK; } if (S_ISCHR(statbuf.st_mode)) { cfst.cf_type = FILE_TYPE_CHAR_; } if (S_ISBLK(statbuf.st_mode)) { cfst.cf_type = FILE_TYPE_BLOCK; } if (S_ISFIFO(statbuf.st_mode)) { cfst.cf_type = FILE_TYPE_FIFO; } cfst.cf_mode = statbuf.st_mode & 07777; cfst.cf_uid = statbuf.st_uid & 0xFFFFFFFF; cfst.cf_gid = statbuf.st_gid & 0xFFFFFFFF; cfst.cf_size = statbuf.st_size; cfst.cf_atime = statbuf.st_atime; cfst.cf_mtime = statbuf.st_mtime; cfst.cf_ctime = statbuf.st_ctime; cfst.cf_ino = statbuf.st_ino; cfst.cf_dev = statbuf.st_dev; cfst.cf_readlink = linkbuf; if (cfst.cf_nlink == CF_NOSIZE) { cfst.cf_nlink = statbuf.st_nlink; } #if !defined(__MINGW32__) if (statbuf.st_size > statbuf.st_blocks * DEV_BSIZE) #else # ifdef HAVE_ST_BLOCKS if (statbuf.st_size > statbuf.st_blocks * DEV_BSIZE) # else if (statbuf.st_size > ST_NBLOCKS(statbuf) * DEV_BSIZE) # endif #endif { cfst.cf_makeholes = 1; /* must have a hole to get checksum right */ } else { cfst.cf_makeholes = 0; } memset(sendbuffer, 0, CF_BUFSIZE); /* send as plain text */ Log(LOG_LEVEL_DEBUG, "OK: type = %d, mode = %" PRIoMAX ", lmode = %" PRIoMAX ", uid = %" PRIuMAX ", gid = %" PRIuMAX ", size = %" PRIdMAX ", atime=%" PRIdMAX ", mtime = %" PRIdMAX, cfst.cf_type, (uintmax_t)cfst.cf_mode, (uintmax_t)cfst.cf_lmode, (intmax_t)cfst.cf_uid, (intmax_t)cfst.cf_gid, (intmax_t) cfst.cf_size, (intmax_t) cfst.cf_atime, (intmax_t) cfst.cf_mtime); snprintf(sendbuffer, CF_BUFSIZE, "OK: %d %ju %ju %ju %ju %jd %jd %jd %jd %d %d %d %jd", cfst.cf_type, (uintmax_t)cfst.cf_mode, (uintmax_t)cfst.cf_lmode, (uintmax_t)cfst.cf_uid, (uintmax_t)cfst.cf_gid, (intmax_t)cfst.cf_size, (intmax_t) cfst.cf_atime, (intmax_t) cfst.cf_mtime, (intmax_t) cfst.cf_ctime, cfst.cf_makeholes, cfst.cf_ino, cfst.cf_nlink, (intmax_t) cfst.cf_dev); SendTransaction(&conn->conn_info, sendbuffer, 0, CF_DONE); memset(sendbuffer, 0, CF_BUFSIZE); if (cfst.cf_readlink != NULL) { strcpy(sendbuffer, "OK:"); strcat(sendbuffer, cfst.cf_readlink); } else { sprintf(sendbuffer, "OK:"); } SendTransaction(&conn->conn_info, sendbuffer, 0, CF_DONE); return 0; }
int posix_fallocate (int fd, __off_t offset, __off_t len) { struct stat64 st; if (offset < 0 || len < 0) return EINVAL; /* Perform overflow check. The outer cast relies on a GCC extension. */ if ((__off_t) ((uint64_t) offset + (uint64_t) len) < 0) return EFBIG; /* pwrite below will not do the right thing in O_APPEND mode. */ { int flags = __fcntl (fd, F_GETFL, 0); if (flags < 0 || (flags & O_APPEND) != 0) return EBADF; } /* We have to make sure that this is really a regular file. */ if (__fxstat64 (_STAT_VER, fd, &st) != 0) return EBADF; if (S_ISFIFO (st.st_mode)) return ESPIPE; if (! S_ISREG (st.st_mode)) return ENODEV; if (len == 0) { /* This is racy, but there is no good way to satisfy a zero-length allocation request. */ if (st.st_size < offset) { int ret = __ftruncate (fd, offset); if (ret != 0) ret = errno; return ret; } return 0; } /* Minimize data transfer for network file systems, by issuing single-byte write requests spaced by the file system block size. (Most local file systems have fallocate support, so this fallback code is not used there.) */ unsigned increment; { struct statfs64 f; if (__fstatfs64 (fd, &f) != 0) return errno; if (f.f_bsize == 0) increment = 512; else if (f.f_bsize < 4096) increment = f.f_bsize; else /* NFS does not propagate the block size of the underlying storage and may report a much larger value which would still leave holes after the loop below, so we cap the increment at 4096. */ increment = 4096; } /* Write a null byte to every block. This is racy; we currently lack a better option. Compare-and-swap against a file mapping might additional local races, but requires interposition of a signal handler to catch SIGBUS. */ for (offset += (len - 1) % increment; len > 0; offset += increment) { len -= increment; if (offset < st.st_size) { unsigned char c; ssize_t rsize = __pread (fd, &c, 1, offset); if (rsize < 0) return errno; /* If there is a non-zero byte, the block must have been allocated already. */ else if (rsize == 1 && c != 0) continue; } if (__pwrite (fd, "", 1, offset) != 1) return errno; } return 0; }
bool File::isPipe() const { return S_ISFIFO(getMode()); }
int vc_hostfs_open(const char *inPath, int vc_oflag) { char *path = strdup( inPath ); //char *s; int flags = 0, ret=errno; struct stat fileStat; // Replace all '\' with '/' backslash_to_slash( path ); #if 0 s = path + strlen( path ); if (( s - path ) >= 4 ) { if ( strcasecmp( &s[ -4 ], ".vll" ) == 0 ) { // The Videocore is asking for a .vll file. Since it isn't consistent with // the case, we convert .vll files to all lowercase. "vc_hostfs_open: '%s'", path ; s--; // backup to the last character (*s is on the '\0') while (( s >= path ) && ( *s != '/' )) { *s = tolower( *s ); s--; } } } #endif DEBUG_MINOR("vc_hostfs_open: '%s'", path); flags = O_RDONLY; if (vc_oflag & VC_O_WRONLY) flags = O_WRONLY; if (vc_oflag & VC_O_RDWR) flags = O_RDWR; if (vc_oflag & VC_O_APPEND) flags |= O_APPEND; if (vc_oflag & VC_O_CREAT) flags |= O_CREAT; if (vc_oflag & VC_O_TRUNC) flags |= O_TRUNC; if (vc_oflag & VC_O_EXCL) flags |= O_EXCL; //while (*path == '\\') path++; // do not want initial '\' if (flags & O_CREAT) ret = open(path, flags, S_IREAD | S_IWRITE ); else ret = open(path, flags ); if (ret < 0 ) { DEBUG_MINOR("vc_hostfs_open(%s,%d) = %d", path, vc_oflag, ret); } else { DEBUG_MINOR("vc_hostfs_open(%s,%d) = %d", path, vc_oflag, ret); } // If the file was successfully open then initialize its entry in // the file info table. If necessary, we expand the size of the table if (ret >= 0) { // File was successfully opened if (ret >= file_info_table_len) { file_info_t *p_new_file_info_table = p_file_info_table; int new_file_info_table_len = file_info_table_len; // try and allocate a bigger buffer for the file info table new_file_info_table_len += FILE_INFO_TABLE_CHUNK_LEN; p_new_file_info_table = calloc( (size_t)new_file_info_table_len, sizeof( file_info_t ) ); if (p_new_file_info_table == NULL) { // calloc failed DEBUG_MAJOR("vc_hostfs_open: file_info_table calloc failed"); assert( 0 ); } else { // calloc successful, so copy data from previous buffer to new buffer, // free previous buffer and update ptr and len info memcpy( p_new_file_info_table, p_file_info_table, sizeof( file_info_t ) * file_info_table_len ); free( p_file_info_table ); p_file_info_table = p_new_file_info_table; file_info_table_len = new_file_info_table_len; } } assert( ret < file_info_table_len ); { // initialize this file's entry in the file info table p_file_info_table[ret].is_fifo = 0; p_file_info_table[ret].read_offset = 0; } // Check whether the file is a FIFO. A FIFO does not support seeking // but we will fake, to the extent supported by the buffered file system // on the Videocore, limited FIFO seek functionality. This is for the benefit // of certain Videocore "streaming" file handlers. fstat( ret, &fileStat ); if (S_ISFIFO( fileStat.st_mode )) { // file is a FIFO, so note its fildes for future reference p_file_info_table[ret].is_fifo = 1; DEBUG_MINOR("vc_hostfs_open: file with fildes %d is a FIFO", ret); } } free( path ); return ret; }
int iop_cp(io_args_t *const args) { const char *const src = args->arg1.src; const char *const dst = args->arg2.dst; const IoCrs crs = args->arg3.crs; const io_confirm confirm = args->confirm; const int cancellable = args->cancellable; struct stat st; char block[BLOCK_SIZE]; FILE *in, *out; size_t nread; int error; struct stat src_st; const char *open_mode = "wb"; ioeta_update(args->estim, src, dst, 0, 0); #ifdef _WIN32 if(is_symlink(src) || crs != IO_CRS_APPEND_TO_FILES) { DWORD flags; int error; wchar_t *utf16_src, *utf16_dst; flags = COPY_FILE_COPY_SYMLINK; if(crs == IO_CRS_FAIL) { flags |= COPY_FILE_FAIL_IF_EXISTS; } else if(path_exists(dst, DEREF)) { /* Ask user whether to overwrite destination file. */ if(confirm != NULL && !confirm(args, src, dst)) { return 0; } } utf16_src = utf8_to_utf16(src); utf16_dst = utf8_to_utf16(dst); error = CopyFileExW(utf16_src, utf16_dst, &win_progress_cb, args, NULL, flags) == 0; if(error) { /* FIXME: use real system error message here. */ (void)ioe_errlst_append(&args->result.errors, dst, IO_ERR_UNKNOWN, "Copy file failed"); } free(utf16_src); free(utf16_dst); ioeta_update(args->estim, NULL, NULL, 1, 0); return error; } #endif /* Create symbolic link rather than copying file it points to. This check * should go before directory check as is_dir() resolves symbolic links. */ if(is_symlink(src)) { char link_target[PATH_MAX]; int error; io_args_t ln_args = { .arg1.path = link_target, .arg2.target = dst, .arg3.crs = crs, .cancellable = cancellable, .result = args->result, }; if(get_link_target(src, link_target, sizeof(link_target)) != 0) { (void)ioe_errlst_append(&args->result.errors, src, IO_ERR_UNKNOWN, "Failed to get symbolic link target"); return 1; } error = iop_ln(&ln_args); args->result = ln_args.result; if(error != 0) { (void)ioe_errlst_append(&args->result.errors, src, IO_ERR_UNKNOWN, "Failed to make symbolic link"); return 1; } return 0; } if(is_dir(src)) { (void)ioe_errlst_append(&args->result.errors, src, EISDIR, strerror(EISDIR)); return 1; } if(os_stat(src, &st) != 0) { (void)ioe_errlst_append(&args->result.errors, src, errno, strerror(errno)); return 1; } #ifndef _WIN32 /* Fifo/socket/device files don't need to be opened, their content is not * accessed. */ if(S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode) || S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) { in = NULL; } else #endif { in = os_fopen(src, "rb"); if(in == NULL) { (void)ioe_errlst_append(&args->result.errors, src, errno, strerror(errno)); return 1; } } if(crs == IO_CRS_APPEND_TO_FILES) { open_mode = "ab"; } else if(crs != IO_CRS_FAIL) { int ec; if(path_exists(dst, DEREF)) { /* Ask user whether to overwrite destination file. */ if(confirm != NULL && !confirm(args, src, dst)) { if(in != NULL && fclose(in) != 0) { (void)ioe_errlst_append(&args->result.errors, src, errno, strerror(errno)); } return 0; } } ec = unlink(dst); if(ec != 0 && errno != ENOENT) { (void)ioe_errlst_append(&args->result.errors, dst, errno, strerror(errno)); if(in != NULL && fclose(in) != 0) { (void)ioe_errlst_append(&args->result.errors, src, errno, strerror(errno)); } return ec; } /* XXX: possible improvement would be to generate temporary file name in the * destination directory, write to it and then overwrite destination file, * but this approach has disadvantage of requiring more free space on * destination file system. */ } else if(path_exists(dst, DEREF)) { (void)ioe_errlst_append(&args->result.errors, src, EEXIST, strerror(EEXIST)); if(in != NULL && fclose(in) != 0) { (void)ioe_errlst_append(&args->result.errors, src, errno, strerror(errno)); } return 1; } #ifndef _WIN32 /* Replicate fifo without even opening it. */ if(S_ISFIFO(st.st_mode)) { if(mkfifo(dst, st.st_mode & 07777) != 0) { (void)ioe_errlst_append(&args->result.errors, src, errno, strerror(errno)); return 1; } return 0; } /* Replicate socket or device file without even opening it. */ if(S_ISSOCK(st.st_mode) || S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) { if(mknod(dst, st.st_mode & (S_IFMT | 07777), st.st_rdev) != 0) { (void)ioe_errlst_append(&args->result.errors, src, errno, strerror(errno)); return 1; } return 0; } #endif out = os_fopen(dst, open_mode); if(out == NULL) { (void)ioe_errlst_append(&args->result.errors, dst, errno, strerror(errno)); if(fclose(in) != 0) { (void)ioe_errlst_append(&args->result.errors, src, errno, strerror(errno)); } return 1; } error = 0; if(crs == IO_CRS_APPEND_TO_FILES) { fpos_t pos; /* The following line is required for stupid Windows sometimes. Why? * Probably because it's stupid... Won't harm other systems. */ fseek(out, 0, SEEK_END); error = fgetpos(out, &pos) != 0 || fsetpos(in, &pos) != 0; if(!error) { ioeta_update(args->estim, NULL, NULL, 0, get_file_size(dst)); } } /* TODO: use sendfile() if platform supports it. */ while((nread = fread(&block, 1, sizeof(block), in)) != 0U) { if(cancellable && ui_cancellation_requested()) { error = 1; break; } if(fwrite(&block, 1, nread, out) != nread) { (void)ioe_errlst_append(&args->result.errors, dst, errno, strerror(errno)); error = 1; break; } ioeta_update(args->estim, NULL, NULL, 0, nread); } if(nread == 0U && !feof(in) && ferror(in)) { (void)ioe_errlst_append(&args->result.errors, src, errno, strerror(errno)); } if(fclose(in) != 0) { (void)ioe_errlst_append(&args->result.errors, src, errno, strerror(errno)); } if(fclose(out) != 0) { (void)ioe_errlst_append(&args->result.errors, dst, errno, strerror(errno)); } if(error == 0 && os_lstat(src, &src_st) == 0) { error = os_chmod(dst, src_st.st_mode & 07777); if(error != 0) { (void)ioe_errlst_append(&args->result.errors, dst, errno, strerror(errno)); } } ioeta_update(args->estim, NULL, NULL, 1, 0); return error; } #ifdef _WIN32 static DWORD CALLBACK win_progress_cb(LARGE_INTEGER total, LARGE_INTEGER transferred, LARGE_INTEGER stream_size, LARGE_INTEGER stream_transfered, DWORD stream_num, DWORD reason, HANDLE src_file, HANDLE dst_file, LPVOID param) { static LONGLONG last_size; io_args_t *const args = param; const char *const src = args->arg1.src; const char *const dst = args->arg2.dst; ioeta_estim_t *const estim = args->estim; if(transferred.QuadPart < last_size) { last_size = 0; } ioeta_update(estim, src, dst, 0, transferred.QuadPart - last_size); last_size = transferred.QuadPart; if(args->cancellable && ui_cancellation_requested()) { return PROGRESS_CANCEL; } return PROGRESS_CONTINUE; } #endif /* TODO: implement iop_chown(). */ int iop_chown(io_args_t *const args); /* TODO: implement iop_chgrp(). */ int iop_chgrp(io_args_t *const args); /* TODO: implement iop_chmod(). */ int iop_chmod(io_args_t *const args); int iop_ln(io_args_t *const args) { const char *const path = args->arg1.path; const char *const target = args->arg2.target; const int overwrite = args->arg3.crs != IO_CRS_FAIL; int result; #ifdef _WIN32 char cmd[6 + PATH_MAX*2 + 1]; char *escaped_path, *escaped_target; char base_dir[PATH_MAX + 2]; #endif #ifndef _WIN32 result = symlink(path, target); if(result != 0 && errno == EEXIST && overwrite && is_symlink(target)) { result = remove(target); if(result == 0) { result = symlink(path, target); if(result != 0) { (void)ioe_errlst_append(&args->result.errors, path, errno, strerror(errno)); } } else { (void)ioe_errlst_append(&args->result.errors, target, errno, strerror(errno)); } } else if(result != 0 && errno != 0) { (void)ioe_errlst_append(&args->result.errors, target, errno, strerror(errno)); } #else if(!overwrite && path_exists(target, DEREF)) { (void)ioe_errlst_append(&args->result.errors, target, EEXIST, strerror(EEXIST)); return -1; } if(overwrite && !is_symlink(target)) { (void)ioe_errlst_append(&args->result.errors, target, IO_ERR_UNKNOWN, "Target is not a symbolic link"); return -1; } escaped_path = shell_like_escape(path, 0); escaped_target = shell_like_escape(target, 0); if(escaped_path == NULL || escaped_target == NULL) { (void)ioe_errlst_append(&args->result.errors, target, IO_ERR_UNKNOWN, "Not enough memory"); free(escaped_target); free(escaped_path); return -1; } if(GetModuleFileNameA(NULL, base_dir, ARRAY_LEN(base_dir)) == 0) { (void)ioe_errlst_append(&args->result.errors, target, IO_ERR_UNKNOWN, "Failed to find win_helper"); free(escaped_target); free(escaped_path); return -1; } break_atr(base_dir, '\\'); snprintf(cmd, sizeof(cmd), "%s\\win_helper -s %s %s", base_dir, escaped_path, escaped_target); result = os_system(cmd); if(result != 0) { (void)ioe_errlst_append(&args->result.errors, target, IO_ERR_UNKNOWN, "Running win_helper has failed"); } free(escaped_target); free(escaped_path); #endif return result; }
int main(int argc, char *argv[]) { char *fb_buf; char *infile = NULL; pid_t pid = 0, gzippid = 0, deadpid; int ch, fd, outpipe[2]; int ws, gzipstat, cmdstat; int eflag = 0, lflag = 0, zflag = 0; ssize_t nr, nw, off; size_t buffersize; struct stat statb; struct ttysize ts; setprogname(argv[0]); /* defaults: Read from stdin, 0 filesize (no completion estimate) */ fd = STDIN_FILENO; filesize = 0; buffersize = 64 * 1024; prefix = NULL; while ((ch = getopt(argc, argv, "b:ef:l:p:z")) != -1) switch (ch) { case 'b': buffersize = (size_t) strsuftoll("buffer size", optarg, 0, SIZE_T_MAX); break; case 'e': eflag++; break; case 'f': infile = optarg; break; case 'l': lflag++; filesize = strsuftoll("input size", optarg, 0, LLONG_MAX); break; case 'p': prefix = optarg; break; case 'z': zflag++; break; case '?': default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; if (argc < 1) usage(); if (infile && (fd = open(infile, O_RDONLY, 0)) < 0) err(1, "%s", infile); /* stat() to get the filesize unless overridden, or -z */ if (!zflag && !lflag && (fstat(fd, &statb) == 0)) { if (S_ISFIFO(statb.st_mode)) { /* stat(2) on pipe may return only the * first few bytes with more coming. * Don't trust! */ } else { filesize = statb.st_size; } } /* gzip -l the file if we have the name and -z is given */ if (zflag && !lflag && infile != NULL) { FILE *gzipsizepipe; char buf[256], *cp, *cmd; /* * Read second word of last line of gzip -l output. Looks like: * % gzip -l ../etc.tgz * compressed uncompressed ratio uncompressed_name * 119737 696320 82.8% ../etc.tar */ asprintf(&cmd, "gzip -l %s", infile); if ((gzipsizepipe = popen(cmd, "r")) == NULL) err(1, "reading compressed file length"); for (; fgets(buf, 256, gzipsizepipe) != NULL;) continue; strtoimax(buf, &cp, 10); filesize = strtoimax(cp, NULL, 10); if (pclose(gzipsizepipe) < 0) err(1, "closing compressed file length pipe"); free(cmd); } /* Pipe input through gzip -dc if -z is given */ if (zflag) { int gzippipe[2]; if (pipe(gzippipe) < 0) err(1, "gzip pipe"); gzippid = fork(); if (gzippid < 0) err(1, "fork for gzip"); if (gzippid) { /* parent */ dup2(gzippipe[0], fd); close(gzippipe[0]); close(gzippipe[1]); } else { dup2(gzippipe[1], STDOUT_FILENO); dup2(fd, STDIN_FILENO); close(gzippipe[0]); close(gzippipe[1]); if (execlp("gzip", "gzip", "-dc", NULL)) err(1, "exec()ing gzip"); } } /* Initialize progressbar.c's global state */ bytes = 0; progress = 1; ttyout = eflag ? stderr : stdout; if (ioctl(fileno(ttyout), TIOCGSIZE, &ts) == -1) ttywidth = 80; else ttywidth = ts.ts_cols; fb_buf = malloc(buffersize); if (fb_buf == NULL) err(1, "malloc for buffersize"); if (pipe(outpipe) < 0) err(1, "output pipe"); pid = fork(); if (pid < 0) err(1, "fork for output pipe"); if (pid == 0) { /* child */ dup2(outpipe[0], STDIN_FILENO); close(outpipe[0]); close(outpipe[1]); execvp(argv[0], argv); err(1, "could not exec %s", argv[0]); } close(outpipe[0]); signal(SIGPIPE, broken_pipe); progressmeter(-1); while ((nr = read(fd, fb_buf, buffersize)) > 0) for (off = 0; nr; nr -= nw, off += nw, bytes += nw) if ((nw = write(outpipe[1], fb_buf + off, (size_t) nr)) < 0) { progressmeter(1); err(1, "writing %u bytes to output pipe", (unsigned) nr); } close(outpipe[1]); gzipstat = 0; cmdstat = 0; while (pid || gzippid) { deadpid = wait(&ws); /* * We need to exit with an error if the command (or gzip) * exited abnormally. * Unfortunately we can't generate a true 'exited by signal' * error without sending the signal to ourselves :-( */ ws = WIFSIGNALED(ws) ? WTERMSIG(ws) : WEXITSTATUS(ws); if (deadpid != -1 && errno == EINTR) continue; if (deadpid == pid) { pid = 0; cmdstat = ws; continue; } if (deadpid == gzippid) { gzippid = 0; gzipstat = ws; continue; } break; } progressmeter(1); signal(SIGPIPE, SIG_DFL); free(fb_buf); exit(cmdstat ? cmdstat : gzipstat); }
/* * Return the standard ls-like mode string from a file mode. * This is static and so is overwritten on each call. */ const char * modeString(int mode) { static char buf[12]; strcpy(buf, "----------"); /* * Fill in the file type. */ if (S_ISDIR(mode)) buf[0] = 'd'; if (S_ISCHR(mode)) buf[0] = 'c'; if (S_ISBLK(mode)) buf[0] = 'b'; if (S_ISFIFO(mode)) buf[0] = 'p'; #ifdef S_ISLNK if (S_ISLNK(mode)) buf[0] = 'l'; #endif #ifdef S_ISSOCK if (S_ISSOCK(mode)) buf[0] = 's'; #endif /* * Now fill in the normal file permissions. */ if (mode & S_IRUSR) buf[1] = 'r'; if (mode & S_IWUSR) buf[2] = 'w'; if (mode & S_IXUSR) buf[3] = 'x'; if (mode & S_IRGRP) buf[4] = 'r'; if (mode & S_IWGRP) buf[5] = 'w'; if (mode & S_IXGRP) buf[6] = 'x'; if (mode & S_IROTH) buf[7] = 'r'; if (mode & S_IWOTH) buf[8] = 'w'; if (mode & S_IXOTH) buf[9] = 'x'; /* * Finally fill in magic stuff like suid and sticky text. */ if (mode & S_ISUID) buf[3] = ((mode & S_IXUSR) ? 's' : 'S'); if (mode & S_ISGID) buf[6] = ((mode & S_IXGRP) ? 's' : 'S'); if (mode & S_ISVTX) buf[9] = ((mode & S_IXOTH) ? 't' : 'T'); return buf; }
void K3bDataUrlAddingDialog::slotAddUrls() { if( m_bCanceled ) return; // add next url KURL url = m_urlQueue.first().first; K3bDirItem* dir = m_urlQueue.first().second; m_urlQueue.remove( m_urlQueue.begin() ); // // HINT: // we only use QFileInfo::absFilePath() and QFileInfo::isHidden() // both do not cause QFileInfo to stat, thus no speed improvement // can come from removing QFileInfo usage here. // QFileInfo info(url.path()); QString absFilePath( info.absFilePath() ); QString resolved( absFilePath ); bool valid = true; k3b_struct_stat statBuf, resolvedStatBuf; bool isSymLink = false; bool isDir = false; bool isFile = false; ++m_filesHandled; #if 0 m_infoLabel->setText( url.path() ); if( m_totalFiles == 0 ) m_counterLabel->setText( QString("(%1)").arg(m_filesHandled) ); else m_counterLabel->setText( QString("(%1/%2)").arg(m_filesHandled).arg(m_totalFiles) ); #endif // // 1. Check if we want and can add the url // if( !url.isLocalFile() ) { valid = false; m_nonLocalFiles.append( url.path() ); } else if( k3b_lstat( QFile::encodeName(absFilePath), &statBuf ) != 0 ) { valid = false; m_notFoundFiles.append( url.path() ); } else if( !m_encodingConverter->encodedLocally( QFile::encodeName( url.path() ) ) ) { valid = false; m_invalidFilenameEncodingFiles.append( url.path() ); } else { isSymLink = S_ISLNK(statBuf.st_mode); isFile = S_ISREG(statBuf.st_mode); isDir = S_ISDIR(statBuf.st_mode); // symlinks are always readable and can always be added to a project // but we need to know if the symlink points to a directory if( isSymLink ) { resolved = K3b::resolveLink( absFilePath ); k3b_stat( QFile::encodeName(resolved), &resolvedStatBuf ); isDir = S_ISDIR(resolvedStatBuf.st_mode); } else { if( ::access( QFile::encodeName( absFilePath ), R_OK ) != 0 ) { valid = false; m_unreadableFiles.append( url.path() ); } else if( isFile && (unsigned long long)statBuf.st_size >= 0xFFFFFFFFULL ) { if ( !k3bcore->externalBinManager()->binObject( "mkisofs" )->hasFeature( "no-4gb-limit" ) ) { valid = false; m_tooBigFiles.append( url.path() ); } } } // FIXME: if we do not add hidden dirs the progress gets messed up! // // check for hidden and system files // if( valid ) { if( info.isHidden() && !addHiddenFiles() ) valid = false; if( S_ISCHR(statBuf.st_mode) || S_ISBLK(statBuf.st_mode) || S_ISFIFO(statBuf.st_mode) || S_ISSOCK(statBuf.st_mode) ) if( !addSystemFiles() ) valid = false; if( isSymLink ) if( S_ISCHR(resolvedStatBuf.st_mode) || S_ISBLK(resolvedStatBuf.st_mode) || S_ISFIFO(resolvedStatBuf.st_mode) || S_ISSOCK(resolvedStatBuf.st_mode) ) if( !addSystemFiles() ) valid = false; } } // // 2. Handle the url // QString newName = url.fileName(); // filenames cannot end in backslashes (mkisofs problem. See comments in k3bisoimager.cpp (escapeGraftPoint())) bool bsAtEnd = false; while( newName[newName.length()-1] == '\\' ) { newName.truncate( newName.length()-1 ); bsAtEnd = true; } if( bsAtEnd ) m_mkisofsLimitationRenamedFiles.append( url.path() + " -> " + newName ); // backup dummy name if( newName.isEmpty() ) newName = "1"; K3bDirItem* newDirItem = 0; // // The source is valid. Now check if the project already contains a file with that name // and if so handle it properly // if( valid ) { if( K3bDataItem* oldItem = dir->find( newName ) ) { // // reuse an existing dir // if( oldItem->isDir() && isDir ) newDirItem = dynamic_cast<K3bDirItem*>(oldItem); // // we cannot replace files in the old session with dirs and vice versa (I think) // files are handled in K3bFileItem constructor and dirs handled above // else if( oldItem->isFromOldSession() && isDir != oldItem->isDir() ) { if( !getNewName( newName, dir, newName ) ) valid = false; } else if( m_bExistingItemsIgnoreAll ) valid = false; else if( oldItem->localPath() == resolved ) { // // Just ignore if the same file is added again // valid = false; } else if( m_bExistingItemsReplaceAll ) { // if we replace an item from an old session the K3bFileItem constructor takes care // of replacing the item if( !oldItem->isFromOldSession() ) delete oldItem; } // // Let the user choose // else { switch( K3bMultiChoiceDialog::choose( i18n("File already exists"), i18n("<p>File <em>%1</em> already exists in " "project folder <em>%2</em>.") .arg(newName) .arg('/' + dir->k3bPath()), QMessageBox::Warning, this, 0, 6, KGuiItem( i18n("Replace"), QString::null, i18n("Replace the existing file") ), KGuiItem( i18n("Replace All"), QString::null, i18n("Always replace existing files") ), KGuiItem( i18n("Ignore"), QString::null, i18n("Keep the existing file") ), KGuiItem( i18n("Ignore All"), QString::null, i18n("Always keep the existing file") ), KGuiItem( i18n("Rename"), QString::null, i18n("Rename the new file") ), KStdGuiItem::cancel() ) ) { case 2: // replace all m_bExistingItemsReplaceAll = true; // fallthrough case 1: // replace // if we replace an item from an old session the K3bFileItem constructor takes care // of replacing the item if( !oldItem->isFromOldSession() ) delete oldItem; break; case 4: // ignore all m_bExistingItemsIgnoreAll = true; // fallthrough case 3: // ignore valid = false; break; case 5: // rename if( !getNewName( newName, dir, newName ) ) valid = false; break; case 6: // cancel slotCancel(); return; } } } } // // One more thing to warn the user about: We cannot follow links to folders since that // would change the doc. So we simply ask the user what to do with a link to a folder // if( valid ) { // let's see if this link starts a loop // that means if it points to some folder above this one // if so we cannot follow it anyway if( isDir && isSymLink && !absFilePath.startsWith( resolved ) ) { bool followLink = dir->doc()->isoOptions().followSymbolicLinks() || m_bFolderLinksFollowAll; if( !followLink && !m_bFolderLinksAddAll ) { switch( K3bMultiChoiceDialog::choose( i18n("Adding link to folder"), i18n("<p>'%1' is a symbolic link to folder '%2'." "<p>If you intend to make K3b follow symbolic links you should consider letting K3b do this now " "since K3b will not be able to do so afterwards because symbolic links to folders inside a " "K3b project cannot be resolved." "<p><b>If you do not intend to enable the option <em>follow symbolic links</em> you may safely " "ignore this warning and choose to add the link to the project.</b>") .arg(absFilePath) .arg(resolved ), QMessageBox::Warning, this, 0, 5, i18n("Follow link now"), i18n("Always follow links"), i18n("Add link to project"), i18n("Always add links"), KStdGuiItem::cancel() ) ) { case 2: m_bFolderLinksFollowAll = true; case 1: followLink = true; break; case 4: m_bFolderLinksAddAll = true; case 3: followLink = false; break; case 5: slotCancel(); return; } } if( followLink ) { absFilePath = resolved; isSymLink = false; // count the files in the followed dir if( m_dirSizeJob->active() ) m_dirSizeQueue.append( KURL::fromPathOrURL(absFilePath) ); else { m_progressWidget->setTotalSteps( 0 ); m_dirSizeJob->setUrls( KURL::fromPathOrURL(absFilePath) ); m_dirSizeJob->start(); } } } } // // Project valid also (we overwrite or renamed) // now create the new item // if( valid ) { // // Set the volume id from the first added url // only if the doc was not changed yet // if( m_urls.count() == 1 && !dir->doc()->isModified() && !dir->doc()->isSaved() ) { dir->doc()->setVolumeID( K3b::removeFilenameExtension( newName ) ); } if( isDir && !isSymLink ) { if( !newDirItem ) { // maybe we reuse an already existing dir newDirItem = new K3bDirItem( newName , dir->doc(), dir ); newDirItem->setLocalPath( url.path() ); // HACK: see k3bdiritem.h } QDir newDir( absFilePath ); int dirFilter = QDir::All|QDir::Hidden|QDir::System; QStringList dlist = newDir.entryList( dirFilter ); const QString& dot = KGlobal::staticQString( "." ); const QString& dotdot = KGlobal::staticQString( ".." ); dlist.remove( dot ); dlist.remove( dotdot ); for( QStringList::Iterator it = dlist.begin(); it != dlist.end(); ++it ) { m_urlQueue.append( qMakePair( KURL::fromPathOrURL(absFilePath + '/' + *it), newDirItem ) ); } } else { (void)new K3bFileItem( &statBuf, &resolvedStatBuf, url.path(), dir->doc(), dir, newName ); } } if( m_urlQueue.isEmpty() ) { m_dirSizeJob->cancel(); m_progressWidget->setProgress( 100 ); accept(); } else { updateProgress(); QTimer::singleShot( 0, this, SLOT(slotAddUrls()) ); } }
/* open existing file */ int safe_open_no_create_follow(const char *fn, int flags) { int f; int want_trunc = (flags & O_TRUNC); /* check for invalid argument values */ if (!fn || (flags & (O_CREAT | O_EXCL))) { errno = EINVAL; return -1; } /* do open without O_TRUNC and perform with ftruncate after the open */ if (want_trunc) { flags &= ~O_TRUNC; } f = open(fn, flags); if (f == -1) { return -1; } /* At this point the file was opened successfully */ /* check if we need to still truncate the file */ if (want_trunc) { struct stat fstat_buf; int r = fstat(f, &fstat_buf); if (r == -1) { /* fstat failed. This should never happen if 'f' is a valid open * file descriptor. Return the error from fstat. */ int fstat_errno = errno; (void)close(f); errno = fstat_errno; return -1; } /* Check if we still need to truncate the file. POSIX says to ignore * the truncate flag if the file type is a fifo or it is a tty. * Otherwise if it is not * a regular file, POSIX says the behavior is * implementation defined. * * Do not do the truncate if the file is already 0 in size. This also * prevents some unspecified behavior in truncate file types which are * not regular, fifo's or tty's, such as device files like /dev/null. * on some platforms O_CREAT|O_WRONLY|O_TRUNC works properly on * /dev/null, but O_WRONLY|O_TRUNC fails. */ #ifndef WIN32 if (!isatty(f) && !S_ISFIFO(fstat_buf.st_mode) && fstat_buf.st_size != 0) { r = ftruncate(f, 0); if (r == -1) { /* fail if the ftruncate failed */ int ftruncate_errno = errno; (void)close(f); errno = ftruncate_errno; return -1; } } #endif } return f; }
void isofs_read_inode(struct inode * inode) { unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); struct buffer_head * bh; struct iso_directory_record * raw_inode; unsigned char *pnt = NULL; void *cpnt = NULL; int high_sierra; int block; int i; block = inode->i_ino >> ISOFS_BUFFER_BITS(inode); if (!(bh=bread(inode->i_dev,block, bufsize))) { printk("unable to read i-node block"); goto fail; } pnt = ((unsigned char *) bh->b_data + (inode->i_ino & (bufsize - 1))); raw_inode = ((struct iso_directory_record *) pnt); high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra; if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){ int frag1, offset; offset = (inode->i_ino & (bufsize - 1)); frag1 = bufsize - offset; cpnt = kmalloc(*pnt,GFP_KERNEL); if (cpnt == NULL) { printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino); brelse(bh); goto fail; } memcpy(cpnt, bh->b_data + offset, frag1); brelse(bh); if (!(bh = bread(inode->i_dev,++block, bufsize))) { kfree(cpnt); printk("unable to read i-node block"); goto fail; } offset += *pnt - bufsize; memcpy((char *)cpnt+frag1, bh->b_data, offset); pnt = ((unsigned char *) cpnt); raw_inode = ((struct iso_directory_record *) pnt); } inode->i_mode = S_IRUGO; /* Everybody gets to read the file. */ inode->i_nlink = 1; if (raw_inode->flags[-high_sierra] & 2) { inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR; inode->i_nlink = 1; /* Set to 1. We know there are 2, but the find utility tries to optimize if it is 2, and it screws up. It is easier to give 1 which tells find to do it the hard way. */ } else { inode->i_mode = S_IRUGO; /* Everybody gets to read the file. */ inode->i_nlink = 1; inode->i_mode |= S_IFREG; /* If there are no periods in the name, then set the execute permission bit */ for(i=0; i< raw_inode->name_len[0]; i++) if(raw_inode->name[i]=='.' || raw_inode->name[i]==';') break; if(i == raw_inode->name_len[0] || raw_inode->name[i] == ';') inode->i_mode |= S_IXUGO; /* execute permission */ } inode->i_uid = inode->i_sb->u.isofs_sb.s_uid; inode->i_gid = inode->i_sb->u.isofs_sb.s_gid; inode->i_size = isonum_733 (raw_inode->size); /* There are defective discs out there - we do this to protect ourselves. A cdrom will never contain more than 700Mb */ if((inode->i_size < 0 || inode->i_size > 700000000) && inode->i_sb->u.isofs_sb.s_cruft == 'n') { printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n"); inode->i_sb->u.isofs_sb.s_cruft = 'y'; } /* Some dipshit decided to store some other bit of information in the high byte of the file length. Catch this and holler. WARNING: this will make it impossible for a file to be > 16Mb on the CDROM!!!*/ if(inode->i_sb->u.isofs_sb.s_cruft == 'y' && inode->i_size & 0xff000000){ /* printk("Illegal format on cdrom. Pester manufacturer.\n"); */ inode->i_size &= 0x00ffffff; } if (raw_inode->interleave[0]) { printk("Interleaved files not (yet) supported.\n"); inode->i_size = 0; } /* I have no idea what file_unit_size is used for, so we will flag it for now */ if(raw_inode->file_unit_size[0] != 0){ printk("File unit size != 0 for ISO file (%ld).\n",inode->i_ino); } /* I have no idea what other flag bits are used for, so we will flag it for now */ if((raw_inode->flags[-high_sierra] & ~2)!= 0){ printk("Unusual flag settings for ISO file (%ld %x).\n", inode->i_ino, raw_inode->flags[-high_sierra]); } #ifdef DEBUG printk("Get inode %d: %d %d: %d\n",inode->i_ino, block, ((int)pnt) & 0x3ff, inode->i_size); #endif inode->i_mtime = inode->i_atime = inode->i_ctime = iso_date(raw_inode->date, high_sierra); inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) + isonum_711 (raw_inode->ext_attr_length)) << (ISOFS_BLOCK_BITS - ISOFS_BUFFER_BITS(inode)); inode->u.isofs_i.i_backlink = 0xffffffff; /* Will be used for previous directory */ switch (inode->i_sb->u.isofs_sb.s_conversion){ case 'a': inode->u.isofs_i.i_file_format = ISOFS_FILE_UNKNOWN; /* File type */ break; case 'b': inode->u.isofs_i.i_file_format = ISOFS_FILE_BINARY; /* File type */ break; case 't': inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT; /* File type */ break; case 'm': inode->u.isofs_i.i_file_format = ISOFS_FILE_TEXT_M; /* File type */ break; } /* Now test for possible Rock Ridge extensions which will override some of these numbers in the inode structure. */ if (!high_sierra) parse_rock_ridge_inode(raw_inode, inode); #ifdef DEBUG printk("Inode: %x extent: %x\n",inode->i_ino, inode->u.isofs_i.i_first_extent); #endif brelse(bh); inode->i_op = NULL; /* A volume number of 0 is nonsense. Disable checking if we see this */ if (inode->i_sb->u.isofs_sb.s_cruft == 'n' && isonum_723 (raw_inode->volume_sequence_number) == 0) { printk("Warning: defective cdrom. Enabling \"cruft\" mount option.\n"); inode->i_sb->u.isofs_sb.s_cruft = 'y'; } if (inode->i_sb->u.isofs_sb.s_cruft != 'y' && isonum_723 (raw_inode->volume_sequence_number) != 1) { printk("Multi volume CD somehow got mounted.\n"); } else { if (S_ISREG(inode->i_mode)) inode->i_op = &isofs_file_inode_operations; else if (S_ISDIR(inode->i_mode)) inode->i_op = &isofs_dir_inode_operations; else if (S_ISLNK(inode->i_mode)) inode->i_op = &isofs_symlink_inode_operations; else if (S_ISCHR(inode->i_mode)) inode->i_op = &chrdev_inode_operations; else if (S_ISBLK(inode->i_mode)) inode->i_op = &blkdev_inode_operations; else if (S_ISFIFO(inode->i_mode)) init_fifo(inode); } if (cpnt) { kfree (cpnt); cpnt = NULL; } return; fail: /* With a data error we return this information */ inode->i_mtime = inode->i_atime = inode->i_ctime = 0; inode->u.isofs_i.i_first_extent = 0; inode->u.isofs_i.i_backlink = 0xffffffff; inode->i_size = 0; inode->i_nlink = 1; inode->i_uid = inode->i_gid = 0; inode->i_mode = S_IFREG; /*Regular file, no one gets to read*/ inode->i_op = NULL; return; }
int pa__init(pa_module *m) { struct userdata *u; struct stat st; pa_sample_spec ss; pa_channel_map map; pa_modargs *ma; struct pollfd *pollfd; pa_source_new_data data; pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments."); goto fail; } ss = m->core->default_sample_spec; map = m->core->default_channel_map; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log("Invalid sample format specification or channel map"); goto fail; } m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; pa_memchunk_reset(&u->memchunk); u->rtpoll = pa_rtpoll_new(); pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); u->filename = pa_runtime_path(pa_modargs_get_value(ma, "file", DEFAULT_FILE_NAME)); if (mkfifo(u->filename, 0666) < 0) { pa_log("mkfifo('%s'): %s", u->filename, pa_cstrerror(errno)); goto fail; } if ((u->fd = pa_open_cloexec(u->filename, O_RDWR, 0)) < 0) { pa_log("open('%s'): %s", u->filename, pa_cstrerror(errno)); goto fail; } pa_make_fd_nonblock(u->fd); if (fstat(u->fd, &st) < 0) { pa_log("fstat('%s'): %s", u->filename, pa_cstrerror(errno)); goto fail; } if (!S_ISFIFO(st.st_mode)) { pa_log("'%s' is not a FIFO.", u->filename); goto fail; } pa_source_new_data_init(&data); data.driver = __FILE__; data.module = m; pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME)); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->filename); pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Unix FIFO source %s", u->filename); pa_source_new_data_set_sample_spec(&data, &ss); pa_source_new_data_set_channel_map(&data, &map); if (pa_modargs_get_proplist(ma, "source_properties", data.proplist, PA_UPDATE_REPLACE) < 0) { pa_log("Invalid properties"); pa_source_new_data_done(&data); goto fail; } u->source = pa_source_new(m->core, &data, PA_SOURCE_LATENCY); pa_source_new_data_done(&data); if (!u->source) { pa_log("Failed to create source."); goto fail; } u->source->parent.process_msg = source_process_msg; u->source->userdata = u; pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); pa_source_set_rtpoll(u->source, u->rtpoll); pa_source_set_fixed_latency(u->source, pa_bytes_to_usec(pa_pipe_buf(u->fd), &u->source->sample_spec)); u->rtpoll_item = pa_rtpoll_item_new(u->rtpoll, PA_RTPOLL_NEVER, 1); pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); pollfd->fd = u->fd; pollfd->events = pollfd->revents = 0; if (!(u->thread = pa_thread_new("pipe-source", thread_func, u))) { pa_log("Failed to create thread."); goto fail; } pa_source_put(u->source); pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); pa__done(m); return -1; }
static int NativeMatchType( Tcl_Interp *interp, /* Interpreter to receive errors. */ CONST char *nativeEntry, /* Native path to check. */ CONST char *nativeName, /* Native filename to check. */ Tcl_GlobTypeData *types) /* Type description to match against. */ { Tcl_StatBuf buf; if (types == NULL) { /* * Simply check for the file's existence, but do it with lstat, in * case it is a link to a file which doesn't exist (since that case * would not show up if we used 'access' or 'stat') */ if (TclOSlstat(nativeEntry, &buf) != 0) { return 0; } } else { if (types->perm != 0) { if (TclOSstat(nativeEntry, &buf) != 0) { /* * Either the file has disappeared between the 'readdir' call * and the 'stat' call, or the file is a link to a file which * doesn't exist (which we could ascertain with lstat), or * there is some other strange problem. In all these cases, we * define this to mean the file does not match any defined * permission, and therefore it is not added to the list of * files to return. */ return 0; } /* * readonly means that there are NO write permissions (even for * user), but execute is OK for anybody OR that the user immutable * flag is set (where supported). */ if (((types->perm & TCL_GLOB_PERM_RONLY) && #if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) !(buf.st_flags & UF_IMMUTABLE) && #endif (buf.st_mode & (S_IWOTH|S_IWGRP|S_IWUSR))) || ((types->perm & TCL_GLOB_PERM_R) && (access(nativeEntry, R_OK) != 0)) || ((types->perm & TCL_GLOB_PERM_W) && (access(nativeEntry, W_OK) != 0)) || ((types->perm & TCL_GLOB_PERM_X) && (access(nativeEntry, X_OK) != 0)) #ifndef MAC_OSX_TCL || ((types->perm & TCL_GLOB_PERM_HIDDEN) && (*nativeName != '.')) #endif ) { return 0; } } if (types->type != 0) { if (types->perm == 0) { /* * We haven't yet done a stat on the file. */ if (TclOSstat(nativeEntry, &buf) != 0) { /* * Posix error occurred. The only ok case is if this is a * link to a nonexistent file, and the user did 'glob -l'. * So we check that here: */ if (types->type & TCL_GLOB_TYPE_LINK) { if (TclOSlstat(nativeEntry, &buf) == 0) { if (S_ISLNK(buf.st_mode)) { return 1; } } } return 0; } } /* * In order bcdpfls as in 'find -t' */ if (((types->type & TCL_GLOB_TYPE_BLOCK)&& S_ISBLK(buf.st_mode)) || ((types->type & TCL_GLOB_TYPE_CHAR) && S_ISCHR(buf.st_mode)) || ((types->type & TCL_GLOB_TYPE_DIR) && S_ISDIR(buf.st_mode)) || ((types->type & TCL_GLOB_TYPE_PIPE) && S_ISFIFO(buf.st_mode))|| ((types->type & TCL_GLOB_TYPE_FILE) && S_ISREG(buf.st_mode)) #ifdef S_ISSOCK ||((types->type & TCL_GLOB_TYPE_SOCK) && S_ISSOCK(buf.st_mode)) #endif /* S_ISSOCK */ ) { /* * Do nothing - this file is ok. */ } else { #ifdef S_ISLNK if (types->type & TCL_GLOB_TYPE_LINK) { if (TclOSlstat(nativeEntry, &buf) == 0) { if (S_ISLNK(buf.st_mode)) { goto filetypeOK; } } } #endif /* S_ISLNK */ return 0; } } filetypeOK: ; #ifdef MAC_OSX_TCL if (types->macType != NULL || types->macCreator != NULL || (types->perm & TCL_GLOB_PERM_HIDDEN)) { int matchResult; if (types->perm == 0 && types->type == 0) { /* * We haven't yet done a stat on the file. */ if (TclOSstat(nativeEntry, &buf) != 0) { return 0; } } matchResult = TclMacOSXMatchType(interp, nativeEntry, nativeName, &buf, types); if (matchResult != 1) { return matchResult; } } #endif } return 1; }
static u32 build_default_directory_structure() { u32 inode; u32 root_inode; struct dentry dentries = { .filename = "lost+found", .file_type = EXT4_FT_DIR, .mode = S_IRWXU, .uid = 0, .gid = 0, .mtime = 0, }; root_inode = make_directory(0, 1, &dentries, 1); inode = make_directory(root_inode, 0, NULL, 0); *dentries.inode = inode; inode_set_permissions(inode, dentries.mode, dentries.uid, dentries.gid, dentries.mtime); return root_inode; } #ifndef USE_MINGW /* Read a local directory and create the same tree in the generated filesystem. Calls itself recursively with each directory in the given directory */ static u32 build_directory_structure(const char *full_path, const char *dir_path, u32 dir_inode, fs_config_func_t fs_config_func, struct selabel_handle *sehnd) { int entries = 0; struct dentry *dentries; struct dirent **namelist; struct stat stat; int ret; int i; u32 inode; u32 entry_inode; u32 dirs = 0; entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort); if (entries < 0) { error_errno("scandir"); return EXT4_ALLOCATE_FAILED; } dentries = calloc(entries, sizeof(struct dentry)); if (dentries == NULL) critical_error_errno("malloc"); for (i = 0; i < entries; i++) { dentries[i].filename = strdup(namelist[i]->d_name); if (dentries[i].filename == NULL) critical_error_errno("strdup"); asprintf(&dentries[i].path, "%s/%s", dir_path, namelist[i]->d_name); asprintf(&dentries[i].full_path, "%s/%s", full_path, namelist[i]->d_name); free(namelist[i]); ret = lstat(dentries[i].full_path, &stat); if (ret < 0) { error_errno("lstat"); i--; entries--; continue; } dentries[i].size = stat.st_size; dentries[i].mode = stat.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO); dentries[i].mtime = stat.st_mtime; if (fs_config_func != NULL) { #ifdef ANDROID unsigned int mode = 0; unsigned int uid = 0; unsigned int gid = 0; int dir = S_ISDIR(stat.st_mode); fs_config_func(dentries[i].path, dir, &uid, &gid, &mode); dentries[i].mode = mode; dentries[i].uid = uid; dentries[i].gid = gid; #else error("can't set android permissions - built without android support"); #endif } #ifdef HAVE_SELINUX if (sehnd) { char *sepath = NULL; asprintf(&sepath, "/%s", dentries[i].path); if (selabel_lookup(sehnd, &dentries[i].secon, sepath, stat.st_mode) < 0) { error("cannot lookup security context for %s", sepath); } if (dentries[i].secon) printf("Labeling %s as %s\n", sepath, dentries[i].secon); free(sepath); } #endif if (S_ISREG(stat.st_mode)) { dentries[i].file_type = EXT4_FT_REG_FILE; } else if (S_ISDIR(stat.st_mode)) { dentries[i].file_type = EXT4_FT_DIR; dirs++; } else if (S_ISCHR(stat.st_mode)) { dentries[i].file_type = EXT4_FT_CHRDEV; } else if (S_ISBLK(stat.st_mode)) { dentries[i].file_type = EXT4_FT_BLKDEV; } else if (S_ISFIFO(stat.st_mode)) { dentries[i].file_type = EXT4_FT_FIFO; } else if (S_ISSOCK(stat.st_mode)) { dentries[i].file_type = EXT4_FT_SOCK; } else if (S_ISLNK(stat.st_mode)) { dentries[i].file_type = EXT4_FT_SYMLINK; dentries[i].link = calloc(info.block_size, 1); readlink(dentries[i].full_path, dentries[i].link, info.block_size - 1); } else { error("unknown file type on %s", dentries[i].path); i--; entries--; } } free(namelist); inode = make_directory(dir_inode, entries, dentries, dirs); for (i = 0; i < entries; i++) { if (dentries[i].file_type == EXT4_FT_REG_FILE) { entry_inode = make_file(dentries[i].full_path, dentries[i].size); } else if (dentries[i].file_type == EXT4_FT_DIR) { entry_inode = build_directory_structure(dentries[i].full_path, dentries[i].path, inode, fs_config_func, sehnd); } else if (dentries[i].file_type == EXT4_FT_SYMLINK) { entry_inode = make_link(dentries[i].full_path, dentries[i].link); } else { error("unknown file type on %s", dentries[i].path); entry_inode = 0; } *dentries[i].inode = entry_inode; ret = inode_set_permissions(entry_inode, dentries[i].mode, dentries[i].uid, dentries[i].gid, dentries[i].mtime); if (ret) error("failed to set permissions on %s\n", dentries[i].path); ret = inode_set_selinux(entry_inode, dentries[i].secon); if (ret) error("failed to set SELinux context on %s\n", dentries[i].path); free(dentries[i].path); free(dentries[i].full_path); free(dentries[i].link); free((void *)dentries[i].filename); free(dentries[i].secon); } free(dentries); return inode; }
static void output(const struct entry *ent) { struct group *gr; struct passwd *pw; ssize_t len; char buf[BUFSIZ], *fmt, pwname[_SC_LOGIN_NAME_MAX], grname[_SC_LOGIN_NAME_MAX], mode[] = "----------"; if (iflag) printf("%lu ", (unsigned long)ent->ino); if (!lflag) { printf("%s%s\n", ent->name, indicator(ent->mode)); return; } if (S_ISREG(ent->mode)) mode[0] = '-'; else if (S_ISBLK(ent->mode)) mode[0] = 'b'; else if (S_ISCHR(ent->mode)) mode[0] = 'c'; else if (S_ISDIR(ent->mode)) mode[0] = 'd'; else if (S_ISFIFO(ent->mode)) mode[0] = 'p'; else if (S_ISLNK(ent->mode)) mode[0] = 'l'; else if (S_ISSOCK(ent->mode)) mode[0] = 's'; else mode[0] = '?'; if (ent->mode & S_IRUSR) mode[1] = 'r'; if (ent->mode & S_IWUSR) mode[2] = 'w'; if (ent->mode & S_IXUSR) mode[3] = 'x'; if (ent->mode & S_IRGRP) mode[4] = 'r'; if (ent->mode & S_IWGRP) mode[5] = 'w'; if (ent->mode & S_IXGRP) mode[6] = 'x'; if (ent->mode & S_IROTH) mode[7] = 'r'; if (ent->mode & S_IWOTH) mode[8] = 'w'; if (ent->mode & S_IXOTH) mode[9] = 'x'; if (ent->mode & S_ISUID) mode[3] = (mode[3] == 'x') ? 's' : 'S'; if (ent->mode & S_ISGID) mode[6] = (mode[6] == 'x') ? 's' : 'S'; if (ent->mode & S_ISVTX) mode[9] = (mode[9] == 'x') ? 't' : 'T'; if (!nflag && (pw = getpwuid(ent->uid))) snprintf(pwname, LEN(pwname), "%s", pw->pw_name); else snprintf(pwname, LEN(pwname), "%d", ent->uid); if (!nflag && (gr = getgrgid(ent->gid))) snprintf(grname, LEN(grname), "%s", gr->gr_name); else snprintf(grname, LEN(grname), "%d", ent->gid); if (time(NULL) > ent->t + (180 * 24 * 60 * 60)) /* 6 months ago? */ fmt = "%b %d %Y"; else fmt = "%b %d %H:%M"; strftime(buf, sizeof(buf), fmt, localtime(&ent->t)); printf("%s %4ld %-8.8s %-8.8s ", mode, (long)ent->nlink, pwname, grname); if (hflag) printf("%10s ", humansize(ent->size)); else printf("%10lu ", (unsigned long)ent->size); printf("%s %s%s", buf, ent->name, indicator(ent->mode)); if (S_ISLNK(ent->mode)) { if ((len = readlink(ent->name, buf, sizeof(buf) - 1)) < 0) eprintf("readlink %s:", ent->name); buf[len] = '\0'; printf(" -> %s%s", buf, indicator(ent->tmode)); } putchar('\n'); }
RTDECL(int) RTHandleGetStandard(RTHANDLESTD enmStdHandle, PRTHANDLE ph) { /* * Validate and convert input. */ AssertPtrReturn(ph, VERR_INVALID_POINTER); int fd; switch (enmStdHandle) { case RTHANDLESTD_INPUT: fd = 0; break; case RTHANDLESTD_OUTPUT: fd = 1; break; case RTHANDLESTD_ERROR: fd = 2; break; default: AssertFailedReturn(VERR_INVALID_PARAMETER); } /* * Is the requested descriptor valid and which IPRT handle type does it * best map on to? */ struct stat st; int rc = fstat(fd, &st); if (rc == -1) return RTErrConvertFromErrno(errno); rc = fcntl(fd, F_GETFD, 0); if (rc == -1) return RTErrConvertFromErrno(errno); bool const fInherit = !(rc & FD_CLOEXEC); RTHANDLE h; if (S_ISREG(st.st_mode)) h.enmType = RTHANDLETYPE_FILE; else if ( S_ISFIFO(st.st_mode) || (st.st_mode == 0 && st.st_nlink == 0 /*see bugs on bsd manpage*/)) h.enmType = RTHANDLETYPE_PIPE; else if (S_ISSOCK(st.st_mode)) { /** @todo check if it's really a socket... IIRC some OSes reports * anonymouse pips as sockets. */ h.enmType = RTHANDLETYPE_SOCKET; } #if 0 /** @todo re-enable this when the VFS pipe has been coded up. */ else if (isatty(fd)) h.enmType = RTHANDLETYPE_PIPE; #endif else h.enmType = RTHANDLETYPE_FILE; /* * Create the IPRT handle. */ switch (h.enmType) { case RTHANDLETYPE_FILE: rc = RTFileFromNative(&h.u.hFile, fd); break; case RTHANDLETYPE_PIPE: rc = RTPipeFromNative(&h.u.hPipe, fd, (enmStdHandle == RTHANDLESTD_INPUT ? RTPIPE_N_READ : RTPIPE_N_WRITE) | (fInherit ? RTPIPE_N_INHERIT : 0)); break; case RTHANDLETYPE_SOCKET: rc = rtSocketCreateForNative(&h.u.hSocket, fd); break; default: /* shut up gcc */ return VERR_INTERNAL_ERROR; } if (RT_SUCCESS(rc)) *ph = h; return rc; }
__ss_int __ss_S_ISFIFO(__ss_int mode) { return S_ISFIFO(mode); }
static int getentropy_fallback(void *buf, size_t len) { uint8_t results[SHA512_DIGEST_LENGTH]; int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat; static int cnt; struct timespec ts; struct timeval tv; struct rusage ru; sigset_t sigset; struct stat st; SHA512_CTX ctx; static pid_t lastpid; pid_t pid; size_t i, ii, m; char *p; pid = getpid(); if (lastpid == pid) { faster = 1; repeat = 2; } else { faster = 0; lastpid = pid; repeat = REPEAT; } for (i = 0; i < len; ) { int j; SHA512_Init(&ctx); for (j = 0; j < repeat; j++) { HX((e = gettimeofday(&tv, NULL)) == -1, tv); if (e != -1) { cnt += (int)tv.tv_sec; cnt += (int)tv.tv_usec; } dl_iterate_phdr(getentropy_phdr, &ctx); for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++) HX(clock_gettime(cl[ii], &ts) == -1, ts); HX((pid = getpid()) == -1, pid); HX((pid = getsid(pid)) == -1, pid); HX((pid = getppid()) == -1, pid); HX((pid = getpgid(0)) == -1, pid); HX((e = getpriority(0, 0)) == -1, e); if (!faster) { ts.tv_sec = 0; ts.tv_nsec = 1; (void) nanosleep(&ts, NULL); } HX(sigpending(&sigset) == -1, sigset); HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1, sigset); HF(getentropy); /* an addr in this library */ HF(printf); /* an addr in libc */ p = (char *)&p; HD(p); /* an addr on stack */ p = (char *)&errno; HD(p); /* the addr of errno */ if (i == 0) { struct sockaddr_storage ss; struct statvfs stvfs; struct termios tios; struct statfs stfs; socklen_t ssl; off_t off; /* * Prime-sized mappings encourage fragmentation; * thus exposing some address entropy. */ struct mm { size_t npg; void *p; } mm[] = { { 17, MAP_FAILED }, { 3, MAP_FAILED }, { 11, MAP_FAILED }, { 2, MAP_FAILED }, { 5, MAP_FAILED }, { 3, MAP_FAILED }, { 7, MAP_FAILED }, { 1, MAP_FAILED }, { 57, MAP_FAILED }, { 3, MAP_FAILED }, { 131, MAP_FAILED }, { 1, MAP_FAILED }, }; for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { HX(mm[m].p = mmap(NULL, mm[m].npg * pgs, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, (off_t)0), mm[m].p); if (mm[m].p != MAP_FAILED) { size_t mo; /* Touch some memory... */ p = mm[m].p; mo = cnt % (mm[m].npg * pgs - 1); p[mo] = 1; cnt += (int)((long)(mm[m].p) / pgs); } /* Check cnts and times... */ for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++) { HX((e = clock_gettime(cl[ii], &ts)) == -1, ts); if (e != -1) cnt += (int)ts.tv_nsec; } HX((e = getrusage(RUSAGE_SELF, &ru)) == -1, ru); if (e != -1) { cnt += (int)ru.ru_utime.tv_sec; cnt += (int)ru.ru_utime.tv_usec; } } for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) { if (mm[m].p != MAP_FAILED) munmap(mm[m].p, mm[m].npg * pgs); mm[m].p = MAP_FAILED; } HX(stat(".", &st) == -1, st); HX(statvfs(".", &stvfs) == -1, stvfs); HX(statfs(".", &stfs) == -1, stfs); HX(stat("/", &st) == -1, st); HX(statvfs("/", &stvfs) == -1, stvfs); HX(statfs("/", &stfs) == -1, stfs); HX((e = fstat(0, &st)) == -1, st); if (e == -1) { if (S_ISREG(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { HX(fstatvfs(0, &stvfs) == -1, stvfs); HX(fstatfs(0, &stfs) == -1, stfs); HX((off = lseek(0, (off_t)0, SEEK_CUR)) < 0, off); } if (S_ISCHR(st.st_mode)) { HX(tcgetattr(0, &tios) == -1, tios); } else if (S_ISSOCK(st.st_mode)) { memset(&ss, 0, sizeof ss); ssl = sizeof(ss); HX(getpeername(0, (void *)&ss, &ssl) == -1, ss); } } HX((e = getrusage(RUSAGE_CHILDREN, &ru)) == -1, ru); if (e != -1) { cnt += (int)ru.ru_utime.tv_sec; cnt += (int)ru.ru_utime.tv_usec; } } else { /* Subsequent hashes absorb previous result */ HD(results); } HX((e = gettimeofday(&tv, NULL)) == -1, tv); if (e != -1) { cnt += (int)tv.tv_sec; cnt += (int)tv.tv_usec; } HD(cnt); } #ifdef HAVE_GETAUXVAL #ifdef AT_RANDOM /* Not as random as you think but we take what we are given */ p = (char *) getauxval(AT_RANDOM); if (p) HR(p, 16); #endif #ifdef AT_SYSINFO_EHDR p = (char *) getauxval(AT_SYSINFO_EHDR); if (p) HR(p, pgs); #endif #ifdef AT_BASE p = (char *) getauxval(AT_BASE); if (p) HD(p); #endif #endif SHA512_Final(results, &ctx); memcpy((char *)buf + i, results, min(sizeof(results), len - i)); i += min(sizeof(results), len - i); } explicit_bzero(&ctx, sizeof ctx); explicit_bzero(results, sizeof results); if (gotdata(buf, len) == 0) { errno = save_errno; return (0); /* satisfied */ } errno = EIO; return (-1); }
/* Write out a tar header for the specified file/directory/whatever */ static inline int writeTarHeader(struct TarBallInfo *tbInfo, const char *header_name, const char *real_name, struct stat *statbuf) { long chksum = 0; struct TarHeader header; const unsigned char *cp = (const unsigned char *) &header; ssize_t size = sizeof(struct TarHeader); memset(&header, 0, size); strncpy(header.name, header_name, sizeof(header.name)); putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */ putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); strncpy(header.magic, TAR_MAGIC TAR_VERSION, TAR_MAGIC_LEN + TAR_VERSION_LEN); /* Enter the user and group names (default to root if it fails) */ if (my_getpwuid(header.uname, statbuf->st_uid) == NULL) strcpy(header.uname, "root"); if (my_getgrgid(header.gname, statbuf->st_gid) == NULL) strcpy(header.gname, "root"); if (tbInfo->hlInfo) { /* This is a hard link */ header.typeflag = LNKTYPE; strncpy(header.linkname, tbInfo->hlInfo->name, sizeof(header.linkname)); } else if (S_ISLNK(statbuf->st_mode)) { char *lpath = xreadlink(real_name); if (!lpath) /* Already printed err msg inside xreadlink() */ return (FALSE); header.typeflag = SYMTYPE; strncpy(header.linkname, lpath, sizeof(header.linkname)); free(lpath); } else if (S_ISDIR(statbuf->st_mode)) { header.typeflag = DIRTYPE; strncat(header.name, "/", sizeof(header.name)); } else if (S_ISCHR(statbuf->st_mode)) { header.typeflag = CHRTYPE; putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev)); putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev)); } else if (S_ISBLK(statbuf->st_mode)) { header.typeflag = BLKTYPE; putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev)); putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev)); } else if (S_ISFIFO(statbuf->st_mode)) { header.typeflag = FIFOTYPE; } else if (S_ISREG(statbuf->st_mode)) { header.typeflag = REGTYPE; putOctal(header.size, sizeof(header.size), statbuf->st_size); } else { bb_error_msg("%s: Unknown file type", real_name); return (FALSE); } /* Calculate and store the checksum (i.e., the sum of all of the bytes of * the header). The checksum field must be filled with blanks for the * calculation. The checksum field is formatted differently from the * other fields: it has [6] digits, a null, then a space -- rather than * digits, followed by a null like the other fields... */ memset(header.chksum, ' ', sizeof(header.chksum)); cp = (const unsigned char *) &header; while (size-- > 0) chksum += *cp++; putOctal(header.chksum, 7, chksum); /* Now write the header out to disk */ if ((size = bb_full_write(tbInfo->tarFd, (char *) &header, sizeof(struct TarHeader))) < 0) { bb_error_msg(bb_msg_io_error, real_name); return (FALSE); } /* Pad the header up to the tar block size */ for (; size < TAR_BLOCK_SIZE; size++) { write(tbInfo->tarFd, "\0", 1); } /* Now do the verbose thing (or not) */ if (tbInfo->verboseFlag) { FILE *vbFd = stdout; if (tbInfo->tarFd == STDOUT_FILENO) /* If the archive goes to stdout, verbose to stderr */ vbFd = stderr; fprintf(vbFd, "%s\n", header.name); } return (TRUE); }
void hpfs_read_inode(struct inode *i) { struct buffer_head *bh; struct fnode *fnode; struct super_block *sb = i->i_sb; struct hpfs_inode_info *hpfs_inode = hpfs_i(i); void *ea; int ea_size; if (!(fnode = hpfs_map_fnode(sb, i->i_ino, &bh))) { /*i->i_mode |= S_IFREG; i->i_mode &= ~0111; i->i_op = &hpfs_file_iops; i->i_fop = &hpfs_file_ops; clear_nlink(i);*/ make_bad_inode(i); return; } if (hpfs_sb(i->i_sb)->sb_eas) { if ((ea = hpfs_get_ea(i->i_sb, fnode, "UID", &ea_size))) { if (ea_size == 2) { i_uid_write(i, le16_to_cpu(*(__le16*)ea)); hpfs_inode->i_ea_uid = 1; } kfree(ea); } if ((ea = hpfs_get_ea(i->i_sb, fnode, "GID", &ea_size))) { if (ea_size == 2) { i_gid_write(i, le16_to_cpu(*(__le16*)ea)); hpfs_inode->i_ea_gid = 1; } kfree(ea); } if ((ea = hpfs_get_ea(i->i_sb, fnode, "SYMLINK", &ea_size))) { kfree(ea); i->i_mode = S_IFLNK | 0777; i->i_op = &page_symlink_inode_operations; i->i_data.a_ops = &hpfs_symlink_aops; set_nlink(i, 1); i->i_size = ea_size; i->i_blocks = 1; brelse(bh); return; } if ((ea = hpfs_get_ea(i->i_sb, fnode, "MODE", &ea_size))) { int rdev = 0; umode_t mode = hpfs_sb(sb)->sb_mode; if (ea_size == 2) { mode = le16_to_cpu(*(__le16*)ea); hpfs_inode->i_ea_mode = 1; } kfree(ea); i->i_mode = mode; if (S_ISBLK(mode) || S_ISCHR(mode)) { if ((ea = hpfs_get_ea(i->i_sb, fnode, "DEV", &ea_size))) { if (ea_size == 4) rdev = le32_to_cpu(*(__le32*)ea); kfree(ea); } } if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { brelse(bh); set_nlink(i, 1); i->i_size = 0; i->i_blocks = 1; init_special_inode(i, mode, new_decode_dev(rdev)); return; } } } if (fnode_is_dir(fnode)) { int n_dnodes, n_subdirs; i->i_mode |= S_IFDIR; i->i_op = &hpfs_dir_iops; i->i_fop = &hpfs_dir_ops; hpfs_inode->i_parent_dir = le32_to_cpu(fnode->up); hpfs_inode->i_dno = le32_to_cpu(fnode->u.external[0].disk_secno); if (hpfs_sb(sb)->sb_chk >= 2) { struct buffer_head *bh0; if (hpfs_map_fnode(sb, hpfs_inode->i_parent_dir, &bh0)) brelse(bh0); } n_dnodes = 0; n_subdirs = 0; hpfs_count_dnodes(i->i_sb, hpfs_inode->i_dno, &n_dnodes, &n_subdirs, NULL); i->i_blocks = 4 * n_dnodes; i->i_size = 2048 * n_dnodes; set_nlink(i, 2 + n_subdirs); } else { i->i_mode |= S_IFREG; if (!hpfs_inode->i_ea_mode) i->i_mode &= ~0111; i->i_op = &hpfs_file_iops; i->i_fop = &hpfs_file_ops; set_nlink(i, 1); i->i_size = le32_to_cpu(fnode->file_size); i->i_blocks = ((i->i_size + 511) >> 9) + 1; i->i_data.a_ops = &hpfs_aops; hpfs_i(i)->mmu_private = i->i_size; } brelse(bh); }
int fuse_valid_type(int m) { return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); }
/* This runs the 'file' command. */ char * do_file (const char *path) { char *buf = NULL; const char *display_path = path; int is_dev = STRPREFIX (path, "/dev/"); if (!is_dev) { buf = sysroot_path (path); if (!buf) { reply_with_perror ("malloc"); return NULL; } path = buf; /* For non-dev, check this is a regular file, else just return the * file type as a string (RHBZ#582484). */ struct stat statbuf; if (lstat (path, &statbuf) == -1) { reply_with_perror ("lstat: %s", display_path); free (buf); return NULL; } if (! S_ISREG (statbuf.st_mode)) { char *ret; free (buf); if (S_ISDIR (statbuf.st_mode)) ret = strdup ("directory"); else if (S_ISCHR (statbuf.st_mode)) ret = strdup ("character device"); else if (S_ISBLK (statbuf.st_mode)) ret = strdup ("block device"); else if (S_ISFIFO (statbuf.st_mode)) ret = strdup ("FIFO"); else if (S_ISLNK (statbuf.st_mode)) ret = strdup ("symbolic link"); else if (S_ISSOCK (statbuf.st_mode)) ret = strdup ("socket"); else ret = strdup ("unknown, not regular file"); if (ret == NULL) reply_with_perror ("strdup"); return ret; } } /* Which flags to use? For /dev paths, follow links because * /dev/VG/LV is a symbolic link. */ const char *flags = is_dev ? "-zbsL" : "-zb"; char *out, *err; int r = command (&out, &err, str_file, flags, path, NULL); free (buf); if (r == -1) { free (out); reply_with_error ("%s: %s", display_path, err); free (err); return NULL; } free (err); /* We need to remove the trailing \n from output of file(1). */ size_t len = strlen (out); if (len > 0 && out[len-1] == '\n') out[len-1] = '\0'; return out; /* caller frees */ }
/* open existing file, if the last component of fn is a symbolic link fail */ int safe_open_no_create(const char *fn, int flags) { int f; /* the result of the open call */ int r; /* status of other system calls */ int saved_errno = errno; /* used to restore errno on success */ int open_errno; /* errno after the open call */ int want_trunc = (flags & O_TRUNC); #ifndef WIN32 struct stat lstat_buf; struct stat fstat_buf; #endif int num_tries = 0; /* check for invalid argument values */ if (!fn || (flags & (O_CREAT | O_EXCL))) { errno = EINVAL; return -1; } /* do open without O_TRUNC and perform with ftruncate after the open */ if (want_trunc) { flags &= ~O_TRUNC; } /* Try and open the file and check for symbolic links. These steps may * need to be performed multiple time if the directory entry changes * between the open and the lstat. It will eventually complete unless an * attacker can stay perfectly synchronized in changing the directory entry * between the open and the lstat */ #ifndef WIN32 TRY_AGAIN: /* If this is the second or subsequent attempt, then someone is * manipulating the file system object referred to by fn. Call the user * defined callback if registered, and fail if it returns a non-zero value. */ if (++num_tries > 1) { /* the default error is EAGAIN, the callback function may change this */ errno = EAGAIN; if (safe_open_path_warning(fn) != 0) { return -1; } /* check if we tried too many times */ if (num_tries > SAFE_OPEN_RETRY_MAX) { /* let the user decide what to do */ return -1; } } /* If the same file directory entry is accessed by both the lstat and the * open, he errors from open should be strictly a superset of those from * lstat, i.e. if lstat returns an error open should return the same error. * * WARNING: the open must occur before the lstat to prevent cryogenic sleep * attack (see Olaf Kirch message to BugTraq at * http://seclists.org/bugtraq/2000/Jan/0063.html). If the open occurs * first and succeeds, the device and inode pair cannot be reused before * the lstat. If they are done the other way around an attacker can stop * or slow the process and wait for the lstat'd file to be deleted, then a * file with the same device and inode is created by the attacker or a * victim and a symbolic at the filename can point to the new file and it * will appear to match and not be a symbolic link. */ #endif f = open(fn, flags); open_errno = errno; #ifndef WIN32 r = lstat(fn, &lstat_buf); /* handle the case of the lstat failing first */ if (r == -1) { /* check if open also failed */ if (f == -1) { /* open and lstat failed, return the current errno from lstat */ return -1; } /* open worked, lstat failed. Directory entry changed after open, try * again to get a consistent view of the file. */ (void)close(f); goto TRY_AGAIN; } /* Check if lstat fn is a symbolic link. This is an error no matter what * the result of the open was. Return an error of EEXIST. */ if (S_ISLNK(lstat_buf.st_mode)) { if (f != -1) { (void)close(f); } errno = EEXIST; return -1; } /* check if the open failed */ if (f == -1) { /* open failed, lstat worked */ if (open_errno == ENOENT) { /* Since this is not a symbolic link, the only way this could have * happened is if during the open the entry was a dangling symbolic * link or didn't exist, and during the lstat it exists and is not * a symbolic link. Try again to get a consistent open/lstat. */ goto TRY_AGAIN; } else { /* open could have failed due to a symlink, but there is no way to * tell, so fail and return the open errno */ errno = open_errno; return -1; } } /* At this point, we know that both the open and lstat worked, and that we * do not have a symbolic link. */ /* Get the properties of the opened file descriptor */ r = fstat(f, &fstat_buf); if (r == -1) { /* fstat failed. This should never happen if 'f' is a valid open file * descriptor. Return the error from fstat. */ int fstat_errno = errno; (void)close(f); errno = fstat_errno; return -1; } /* Check if the immutable properties (device, inode and type) of the file * system object opened match (fstat_buf) those of the directory entry * (lstat_buf). */ if ( lstat_buf.st_dev != fstat_buf.st_dev || lstat_buf.st_ino != fstat_buf.st_ino || (S_IFMT & lstat_buf.st_mode) != (S_IFMT & fstat_buf.st_mode)) { /* Since the lstat was not a symbolic link, and the file opened does * not match the one in the directory, it must have been replaced * between the open and the lstat, so try again. */ (void)close(f); goto TRY_AGAIN; } /* At this point, we have successfully opened the file, and are sure it is * the correct file and that the last component is not a symbolic link. */ /* Check if we still need to truncate the file. POSIX says to ignore the * truncate flag if the file type is a fifo or it is a tty. Otherwise if * it is not * a regular file, POSIX says the behavior is implementation * defined. * * Do not do the truncate if the file is already 0 in size. This also * prevents some unspecified behavior in truncate file types which are not * regular, fifo's or tty's, such as device files like /dev/null. On some * platforms O_CREAT|O_WRONLY|O_TRUNC works properly on /dev/null, but * O_WRONLY|O_TRUNC fails. */ if (want_trunc && !isatty(f) && !S_ISFIFO(fstat_buf.st_mode) && fstat_buf.st_size != 0) { r = ftruncate(f, 0); if (r == -1) { /* truncate failed, so fail with the errno from ftruncate */ int ftruncate_errno = errno; (void)close(f); errno = ftruncate_errno; return -1; } } errno = saved_errno; #endif /* Success, restore the errno incase we had recoverable failures */ return f; }