Пример #1
0
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);
}
Пример #2
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);
	}
}
Пример #3
0
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;
}
Пример #4
0
/*!
 * 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));
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
0
/* 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, &times) < 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;
}
Пример #9
0
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;
}
Пример #10
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;
}
Пример #11
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;
}
Пример #13
0
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;
}
Пример #14
0
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);
}
Пример #15
0
/*
 * 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;
}
Пример #16
0
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()) );
  }
}
Пример #17
0
/* 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;
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
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;
}
Пример #21
0
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;
}
Пример #22
0
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;
}
Пример #24
0
__ss_int __ss_S_ISFIFO(__ss_int mode) {

    return S_ISFIFO(mode);
}
Пример #25
0
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);
}
Пример #26
0
/* 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);
}
Пример #27
0
Файл: inode.c Проект: 7799/linux
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);
}
Пример #28
0
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);
}
Пример #29
0
/* 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 */
}
Пример #30
-1
/* 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;
}