Ejemplo n.º 1
0
Archivo: cd.c Proyecto: oleiade/Ash
int		xchdir(char *path, t_sllist **myenv)
{
  clear_path(path);
  if (chdir(path) == -1)
    {
      fprintf(stderr, "%s%s", path, ERR_ISNOTFOLD);
      return (EXIT_FAILURE);
    }
  else
    {
      my_setenv("OLDPWD", my_getenv("PWD", *myenv), myenv);
      my_setenv("PWD", path, myenv);
    }
  return (EXIT_SUCCESS);
}
Ejemplo n.º 2
0
static void setup_torque_env()
{
  char *ptr;
  if ((ptr = getenv("PBS_HOME"))) {
    torque_home() = ptr;
  }else if ((ptr = getenv("PBS_SERVER_HOME"))) {
    torque_home() = ptr;
  } else if ((ptr = getenv("PBS_NODEFILE"))) {
      torque_home() = torque_home_nodefile(ptr);
  }

  if( torque_home().size() ){
    clear_path(torque_home());
    rem_trailing_slash(torque_home());
  }
}
Ejemplo n.º 3
0
boolean
linedup(xchar ax, xchar ay, xchar bx, xchar by)
{
    tbx = ax - bx;      /* These two values are set for use */
    tby = ay - by;      /* after successful return.  */

    /* sometimes displacement makes a monster think that you're at its own
       location; prevent it from throwing and zapping in that case */
    if (!tbx && !tby)
        return FALSE;

    if ((!tbx || !tby || abs(tbx) == abs(tby))  /* straight line or diagonal */
        && distmin(tbx, tby, 0, 0) < BOLT_LIM) {
        if (clear_path(ax, ay, bx, by, viz_array))
            return TRUE;
    }
    return FALSE;
}
Ejemplo n.º 4
0
char	*cd_init(int fd, FILE *fp, char *param, char **pwds)
{
  char	*ret;

  if (!pwds || !strcmp(param, "-"))
    {
      if (!pwds || !pwds[OLD])
	return (my_rerror(EBADSEQ, fd, fp));
      ret = pwds[OLD];
      pwds[OLD] = NULL;
      return (ret);
    }
  if (!strncmp(param, "..", 2))
    return (clear_path(fd, fp, param, pwds));
  ret = strdup(param);
  if (!ret)
    return (alloc_err(fd, fp, 0));
  return (ret);
}
int check_path(int *maze, int rows, int columns, int x1, int y1, int x2, int y2, int *visited)
{
	if (x1 == x2 && y1 == y2)
	{
		*((visited + x1*columns) + y1) = 1;
		return 1;
	}
	if (clear_path(maze, rows, columns, x1, y1) == 1)
	{
		*((visited + x1*columns) + y1) = 1;
		if (*((visited + (x1 + 1)*columns) + y1) == 0)
		{
			if (check_path(maze, rows, columns, x1 + 1, y1, x2, y2, visited) == 1)
			{
				return 1;
			}
		}
		if (*((visited + x1*columns) + (y1 + 1)) == 0)
		{
			if (check_path(maze, rows, columns, x1, y1 + 1, x2, y2, visited) == 1)
			{
				return 1;
			}
		}
		if (*((visited + (x1 - 1)*columns) + y1) == 0)
		{
			if (check_path(maze, rows, columns, x1 - 1, y1, x2, y2, visited) == 1)
			{
				return 1;
			}
		}
		if (*((visited + x1*columns) + (y1 - 1)) == 0)
		{
			if (check_path(maze, rows, columns, x1, y1 - 1, x2, y2, visited) == 1)
			{
				return 1;
			}
		}
		*((visited + x1*columns) + y1) = 0;
		return 0;
	}
	return 0;
}
Ejemplo n.º 6
0
std::vector<tripoint> map::route( const tripoint &f, const tripoint &t,
                                  const int bash, const int maxdist ) const
{
    /* TODO: If the origin or destination is out of bound, figure out the closest
     * in-bounds point and go to that, then to the real origin/destination.
     */

    int linet1 = 0, linet2 = 0;
    if( !inbounds( f ) || !inbounds( t ) ) {
        // Note: The creature needs to understand not-moving upwards
        // or else the plans can cause it to do so.
        if( sees( f, t, -1, linet1, linet2 ) ) {
            return line_to( f, t, linet1, linet2 );
        } else {
            std::vector<tripoint> empty;
            return empty;
        }
    }
    // First, check for a simple straight line on flat ground
    // Except when the player is on the line - we need to do regular pathing then
    const tripoint &pl_pos = g->u.pos();
    if( f.z == t.z && clear_path( f, t, -1, 2, 2, linet1, linet2 ) ) {
        const auto line_path = line_to( f, t, linet1, linet2 );
        if( pl_pos.z != f.z ) {
            // Player on different z-level, certainly not on the line
            return line_path;
        }

        if( std::find( line_path.begin(), line_path.end(), pl_pos ) == line_path.end() ) {
            return line_path;
        }
    }

    const int pad = 8;  // Should be much bigger - low value makes pathfinders dumb!
    int minx = std::min( f.x, t.x ) - pad;
    int miny = std::min( f.y, t.y ) - pad;
    int minz = std::min( f.z, t.z ); // TODO: Make this way bigger
    int maxx = std::max( f.x, t.x ) + pad;
    int maxy = std::max( f.y, t.y ) + pad;
    int maxz = std::max( f.z, t.z ); // Same TODO as above
    clip_to_bounds( minx, miny, minz );
    clip_to_bounds( maxx, maxy, maxz );

    pathfinder pf( minx, miny, maxx, maxy );
    pf.add_point( 0, 0, f, f );
    // Make NPCs not want to path through player
    // But don't make player pathing stop working
    if( f != pl_pos && t != pl_pos ) {
        pf.close_point( pl_pos );
    }

    bool done = false;

    do {
        auto cur = pf.get_next();

        const int parent_index = flat_index( cur.x, cur.y );
        auto &layer = pf.get_layer( cur.z );
        auto &cur_state = layer.state[parent_index];
        if( cur_state == ASL_CLOSED ) {
            continue;
        }

        if( layer.gscore[parent_index] > maxdist ) {
            // Shortest path would be too long, return empty vector
            return std::vector<tripoint>();
        }

        if( cur == t ) {
            done = true;
            break;
        }

        cur_state = ASL_CLOSED;
        std::vector<tripoint> neighbors = closest_tripoints_first( 1, cur );

        for( const auto &p : neighbors ) {
            const int index = flat_index( p.x, p.y );

            // TODO: Remove this and instead have sentinels at the edges
            if( p.x < minx || p.x >= maxx || p.y < miny || p.y >= maxy ) {
                continue;
            }

            if( layer.state[index] == ASL_CLOSED ) {
                continue;
            }

            int part = -1;
            const maptile &tile = maptile_at_internal( p );
            const auto &terrain = tile.get_ter_t();
            const auto &furniture = tile.get_furn_t();
            const vehicle *veh = veh_at_internal( p, part );

            const int cost = move_cost_internal( furniture, terrain, veh, part );
            // Don't calculate bash rating unless we intend to actually use it
            const int rating = ( bash == 0 || cost != 0 ) ? -1 :
                                 bash_rating_internal( bash, furniture, terrain, false, veh, part );

            if( cost == 0 && rating <= 0 && terrain.open.empty() ) {
                layer.state[index] = ASL_CLOSED; // Close it so that next time we won't try to calc costs
                continue;
            }

            int newg = layer.gscore[parent_index] + cost + ( (cur.x != p.x && cur.y != p.y ) ? 1 : 0);
            if( cost == 0 ) {
                // Handle all kinds of doors
                // Only try to open INSIDE doors from the inside

                if( !terrain.open.empty() &&
                    ( !terrain.has_flag( "OPENCLOSE_INSIDE" ) || !is_outside( cur ) ) ) {
                    newg += 4; // To open and then move onto the tile
                } else if( veh != nullptr ) {
                    part = veh->obstacle_at_part( part );
                    int dummy = -1;
                    if( !veh->part_flag( part, "OPENCLOSE_INSIDE" ) || veh_at_internal( cur, dummy ) == veh ) {
                        // Handle car doors, but don't try to path through curtains
                        newg += 10; // One turn to open, 4 to move there
                    } else {
                        // Car obstacle that isn't a door
                        newg += veh->parts[part].hp / bash + 8 + 4;
                    }
                } else if( rating > 1 ) {
                    // Expected number of turns to bash it down, 1 turn to move there
                    // and 2 turns of penalty not to trash everything just because we can
                    newg += ( 20 / rating ) + 2 + 4;
                } else if( rating == 1 ) {
                    // Desperate measures, avoid whenever possible
                    newg += 500;
                } else {
                    continue; // Unbashable and unopenable from here
                }
            }

            // If not visited, add as open
            // If visited, add it only if we can do so with better score
            if( layer.state[index] == ASL_NONE || newg < layer.gscore[index] ) {
                pf.add_point( newg, newg + 2 * rl_dist( p, t ), cur, p );
            }
        }

        if( !has_zlevels() ) {
            // The part below is only for z-level pathing
            continue;
        }

        const maptile &parent_tile = maptile_at_internal( cur );
        const auto &parent_terrain = parent_tile.get_ter_t();
        if( cur.z > minz && parent_terrain.has_flag( TFLAG_GOES_DOWN ) ) {
            tripoint dest( cur.x, cur.y, cur.z - 1 );
            dest = vertical_move_destination<TFLAG_GOES_UP>( *this, dest );
            if( inbounds( dest ) ) {
                auto &layer = pf.get_layer( dest.z );
                pf.add_point( layer.gscore[parent_index] + 2,
                              layer.score[parent_index] + 2 * rl_dist( dest, t ),
                              cur, dest );
            }
        }
        if( cur.z < maxz && parent_terrain.has_flag( TFLAG_GOES_UP ) ) {
            tripoint dest( cur.x, cur.y, cur.z + 1 );
            dest = vertical_move_destination<TFLAG_GOES_DOWN>( *this, dest );
            if( inbounds( dest ) ) {
                auto &layer = pf.get_layer( dest.z );
                pf.add_point( layer.gscore[parent_index] + 2,
                              layer.score[parent_index] + 2 * rl_dist( dest, t ),
                              cur, dest );
            }
        }
    } while( !done && !pf.empty() );

    std::vector<tripoint> ret;
    ret.reserve( rl_dist( f, t ) * 2 );
    if( done ) {
        tripoint cur = t;
        // Just to limit max distance, in case something weird happens
        for( int fdist = maxdist; fdist != 0; fdist-- ) {
            const int cur_index = flat_index( cur.x, cur.y );
            const auto &layer = pf.get_layer( cur.z );
            const tripoint &par = layer.parent[cur_index];
            if( cur == f ) {
                break;
            }

            ret.push_back( cur );
            // Jumps are acceptable on 1 z-level changes
            // This is because stairs teleport the player too
            if( rl_dist( cur, par ) > 1 && abs( cur.z - par.z ) != 1 ) {
                debugmsg( "Jump in our route! %d:%d:%d->%d:%d:%d",
                          cur.x, cur.y, cur.z, par.x, par.y, par.z );
                return ret;
            }

            cur = par;
        }

        std::reverse( ret.begin(), ret.end() );
    }

    return ret;
}
Ejemplo n.º 7
0
/**
 * Move all files from temp to destination directory if at end of group
 */
void move_files(struct group_list_t *group)
{
    char temppath[MAXPATHNAME], destpath[MAXPATHNAME];
    char *filelist[10000];  // TODO: no magic number
    int len, filecount, i;

    if (!strcmp(tempdir, "") || (group->file_id != 0)) {
        return;
    }
    if (move_individual) {
        len = snprintf(temppath, sizeof(temppath), "%s%c_group_%08X",
                       tempdir, PATH_SEP, group->group_id);
        if ((len >= sizeof(temppath)) || (len == -1)) {
            glog0(group, "Max pathname length exceeded: %s%c_group_%08X",
                         tempdir, PATH_SEP, group->group_id);
        } else {
            move_files_individual(group, temppath, destdir[0]);
        }
        return;
    }

    {
#ifdef WINDOWS
        intptr_t ffhandle;
        struct _finddatai64_t finfo;
        char dirglob[MAXPATHNAME];

        snprintf(dirglob, sizeof(dirglob), "%s%c_group_%08X%c*", tempdir,
                 PATH_SEP, group->group_id, PATH_SEP);
        if ((ffhandle = _findfirsti64(dirglob, &finfo)) == -1) {
            gsyserror(group, "Failed to open directory %s", dirglob);
            return;
        }
        filecount = 0;
        do {
            len = snprintf(temppath, sizeof(temppath), "%s%c_group_%08X%c%s",
                           tempdir, PATH_SEP, group->group_id,
                           PATH_SEP, finfo.name);
            if ((len >= sizeof(temppath)) || (len == -1)) {
                glog0(group,"Max pathname length exceeded: %s%c_group_%08X%c%s",
                      tempdir, PATH_SEP, group->group_id, PATH_SEP, finfo.name);
                continue;
            }
            len = snprintf(destpath, sizeof(destpath), "%s%c%s",
                           destdir[0], PATH_SEP, finfo.name);
            if ((len >= sizeof(destpath)) || (len == -1)) {
                glog0(group, "Max pathname length exceeded: %s%c%s",
                             destdir[0], PATH_SEP, finfo.name);
                continue;
            }
            // do the move
            if (strcmp(finfo.name, ".") && strcmp(finfo.name, "..")) {
                clear_path(destpath, group);
                if (!MoveFile(temppath, destpath)) {
                    char errbuf[300];
                    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL,
                            GetLastError(), 0, errbuf, sizeof(errbuf), NULL);
                    glog0(group, "error (%d): %s", GetLastError(), errbuf);
                }
                filelist[filecount] = strdup(destpath);
                if (filelist[filecount] == NULL) {
                    gsyserror(group, "strdup failed!");
                    exit(ERR_ALLOC);
                }
                filecount++;
            }
        } while (_findnexti64(ffhandle, &finfo) == 0);
        _findclose(ffhandle);
#else
        DIR *dir;
        struct dirent *de;
        char dirname[MAXPATHNAME];

        snprintf(dirname, sizeof(dirname), "%s%c_group_%08X", tempdir,
                 PATH_SEP, group->group_id);
        if ((dir = opendir(dirname)) == NULL) {
            gsyserror(group, "Failed to open directory %s", dirname);
            return;
        }
        filecount = 0;
        // errno needs to be set to 0 before calling readdir, otherwise
        // we'll report a false error when we exhaust the directory
        while ((errno = 0, de = readdir(dir)) != NULL) {
            len = snprintf(temppath, sizeof(temppath), "%s%c%s", dirname,
                           PATH_SEP, de->d_name);
            if ((len >= sizeof(temppath)) || (len == -1)) {
                glog0(group, "Max pathname length exceeded: %s%c%s", dirname,
                             PATH_SEP, de->d_name);
                continue;
            }
            len = snprintf(destpath, sizeof(destpath), "%s%c%s", destdir[0],
                           PATH_SEP, de->d_name);
            if ((len >= sizeof(destpath)) || (len == -1)) {
                glog0(group, "Max pathname length exceeded: %s%c%s", destdir[0],
                             PATH_SEP, de->d_name);
                continue;
            }
            if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) {
                clear_path(destpath, group);
                if (rename(temppath, destpath) == -1) {
                    gsyserror(group, "Couldn't move file");
                }
                filelist[filecount] = strdup(destpath);
                if (filelist[filecount] == NULL) {
                    gsyserror(group, "strdup failed!");
                    exit(ERR_ALLOC);
                }
                filecount++;
            }
        }
        if (errno && (errno != ENOENT)) {
            gsyserror(group, "Failed to read directory %s", dirname);
        }
        closedir(dir);
#endif
    }
    run_postreceive_multi(group, filelist, filecount);
    for (i = 0; i < filecount; i++) {
        free(filelist[i]);
    }
    snprintf(temppath, sizeof(temppath), "%s%c_group_%08X", tempdir,
             PATH_SEP, group->group_id);
    if (rmdir(temppath) == -1) {
        gsyserror(group, "Failed remove temp directory %s", temppath);
    }
}
Ejemplo n.º 8
0
/* Mark locations that are temporarily lit via mobile light sources. */
void do_light_sources(char **cs_rows)
{
    int x, y, min_x, max_x, max_y, offset;
    const char *limits;
    short at_hero_range = 0;
    light_source *ls;
    char *row;

    for (ls = level->lev_lights; ls; ls = ls->next) {
	ls->flags &= ~LSF_SHOW;

	/*
	 * Check for moved light sources.  It may be possible to
	 * save some effort if an object has not moved, but not in
	 * the current setup -- we need to recalculate for every
	 * vision recalc.
	 */
	if (ls->type == LS_OBJECT) {
	    if (get_obj_location((struct obj *) ls->id, &ls->x, &ls->y, 0))
		ls->flags |= LSF_SHOW;
	} else if (ls->type == LS_MONSTER) {
	    if (get_mon_location((struct monst *) ls->id, &ls->x, &ls->y, 0))
		ls->flags |= LSF_SHOW;
	}

	/* minor optimization: don't bother with duplicate light sources */
	/* at hero */
	if (ls->x == u.ux && ls->y == u.uy) {
	    if (at_hero_range >= ls->range)
		ls->flags &= ~LSF_SHOW;
	    else
		at_hero_range = ls->range;
	}

	if (ls->flags & LSF_SHOW) {
	    /*
	     * Walk the points in the circle and see if they are
	     * visible from the center.  If so, mark'em.
	     *
	     * Kevin's tests indicated that doing this brute-force
	     * method is faster for radius <= 3 (or so).
	     */
	    limits = circle_ptr(ls->range);
	    if ((max_y = (ls->y + ls->range)) >= ROWNO) max_y = ROWNO-1;
	    if ((y = (ls->y - ls->range)) < 0) y = 0;
	    for (; y <= max_y; y++) {
		row = cs_rows[y];
		offset = limits[abs(y - ls->y)];
		if ((min_x = (ls->x - offset)) < 0) min_x = 0;
		if ((max_x = (ls->x + offset)) >= COLNO) max_x = COLNO-1;

		if (ls->x == u.ux && ls->y == u.uy) {
		    /*
		     * If the light source is located at the hero, then
		     * we can use the COULD_SEE bits already calcualted
		     * by the vision system.  More importantly than
		     * this optimization, is that it allows the vision
		     * system to correct problems with clear_path().
		     * The function clear_path() is a simple LOS
		     * path checker that doesn't go out of its way
		     * make things look "correct".  The vision system
		     * does this.
		     */
		    for (x = min_x; x <= max_x; x++)
			if (row[x] & COULD_SEE)
			    row[x] |= TEMP_LIT;
		} else {
		    for (x = min_x; x <= max_x; x++)
			if ((ls->x == x && ls->y == y)
				|| clear_path((int)ls->x, (int) ls->y, x, y))
			    row[x] |= TEMP_LIT;
		}
	    }
	}
    }
}
Ejemplo n.º 9
0
/* return TRUE if successful, FALSE if not */
boolean
rloc(struct monst *mtmp,        /* mx==COLNO implies migrating monster arrival */
     boolean suppress_impossible)
{
    int x, y, trycount;
    int relaxed_goodpos;

    if (mtmp == u.usteed) {
        tele();
        return TRUE;
    }

    if (mtmp->iswiz && mtmp->mx != COLNO) {      /* Wizard, not just arriving */
        if (!In_W_tower(u.ux, u.uy, &u.uz))
            x = level->upstair.sx, y = level->upstair.sy;
        else if (!isok(level->dnladder.sx, level->dnladder.sy))
            x = level->upladder.sx, y = level->upladder.sy;/* bottom of tower */
        else
            x = level->dnladder.sx, y = level->dnladder.sy;
        /* if the wiz teleports away to heal, try the up staircase, to block
           the player's escaping before he's healed (deliberately use `goodpos'
           rather than `rloc_pos_ok' here) */
        if (goodpos(level, x, y, mtmp, 0))
            goto found_xy;
    }

    for (relaxed_goodpos = -1; relaxed_goodpos < 2; relaxed_goodpos++) {

        /* If this is a monster that blinks, try to do that first. */
        if (relaxed_goodpos < 0) {
            if ((isok(mtmp->mx, mtmp->my)) &&
                mtmp->data->mflags3 & M3_BLINKAWAY) {
                /* We're going to do a polar-to-rectangular conversion here,
                   because it's a convenient way to select positions at the
                   correct distance from where we're starting.  We'll try
                   with the maximum radius then back it off. */
                int maxradius = 2 * mtmp->data->mlevel;
                int minradius = 2;
                int theta[24] = {   0,  15,  30,  45,  60,  75,
                                    90, 105, 120, 135, 150, 165,
                                    180, 195, 210, 225, 240, 255,
                                    270, 285, 300, 315, 330, 345 };
                int angle, fineangle, swi, sw;
                coord rectcoord;
                if (maxradius < minradius + 3)
                    maxradius = minradius + 3;
                /* Shuffle the order of the angles so we don't always get the same
                   one tried first. */
                for (angle = 0; angle < 24; angle++) {
                    swi          = rn2(24);
                    sw           = theta[swi];
                    theta[swi]   = theta[angle];
                    theta[angle] = sw;
                }
                for (trycount = maxradius; trycount >= minradius; trycount--) {
                    for (angle = 0; angle < 24; angle++)
                        for (fineangle = 0; fineangle < 15; fineangle += 3) {
                            /* theta is shuffled so that the angle isn't the
                               same all the time, but it isn't necessary to
                               shuffle over a hundred different angles; we use
                               fineangle to allow positions that don't line up
                               to the 15-degree increments, but the randomness
                               of the blink direction doesn't need that much
                               precision. */
                            rectcoord = polartorect(trycount, theta[angle] +
                                                    fineangle);
                            x = mtmp->mx + rectcoord.x;
                            y = mtmp->my + rectcoord.y;
                            if (isok(x,y) && !m_at(level,x,y) &&
                                /* TODO: evaluate whether goodpos() should be
                                 * used here */
                                (level->locations[x][y].typ >= CORR) &&
                                /* Blinking only works with line-of-sight, but
                                   for now I am not requiring the monster to
                                   actually _see_ the tile, so e.g. blinking
                                   into the dark works ok. */
                                clear_path(mtmp->mx, mtmp->my, x, y, viz_array)
                                ) {
                                goto found_xy;
                            }
                        }
                }
            }
            continue;
        }

        /* first try sensible terrain; if none exists, ignore water,
           doors and boulders */
        int gpflags = relaxed_goodpos ? MM_IGNOREWATER | MM_IGNOREDOORS : 0;

        /* try several pairs of positions; try the more restrictive rloc_pos_ok
           before we use the less restrictive goodpos */
        trycount = 0;
        do {
            x = rn2(COLNO);
            y = rn2(ROWNO);
            if ((trycount < 500) ? rloc_pos_ok(x, y, mtmp)
                : goodpos(level, x, y, mtmp, gpflags))
                goto found_xy;
        } while (++trycount < 1000);

        /* try every square on the level as a fallback */
        for (x = 0; x < COLNO; x++)
            for (y = 0; y < ROWNO; y++)
                if (goodpos(level, x, y, mtmp, gpflags))
                    goto found_xy;
    }

    /* level either full of monsters or somehow faulty */
    if (!suppress_impossible)
        impossible("rloc(): couldn't relocate monster");
    return FALSE;

found_xy:
    rloc_to(mtmp, x, y);
    return TRUE;
}
Ejemplo n.º 10
0
/**
 * For the current file in a group, move the existing file to
 * the appropriate backup directory, if it exists.
 * In the event of a failure, delete the original file
 */
void move_to_backup(int listidx)
{
    stat_struct statbuf;
    char backup_file[MAXBACKUPPATHNAME], *trim_name;
    int len;

    if (lstat_func(group_list[listidx].fileinfo.filepath, &statbuf) == -1) {
        return;
    }

    if (backupcnt == 0) {
        clear_path(group_list[listidx].fileinfo.filepath, listidx);
        return;
    }

#ifdef WINDOWS
    if ((group_list[listidx].fileinfo.filepath[1] == ':') &&
            (group_list[listidx].fileinfo.filepath[2] == '\\')) {
        trim_name = &group_list[listidx].fileinfo.filepath[3];
    } else {
        trim_name = group_list[listidx].fileinfo.filepath;
    }
#else
    trim_name = group_list[listidx].fileinfo.filepath;
#endif
    len = snprintf(backup_file, sizeof(backup_file), "%s%c%s%c%s%c%s",
                   backupdir[group_list[listidx].fileinfo.destdiridx], PATH_SEP,
                   group_list[listidx].start_date, PATH_SEP,
                   group_list[listidx].start_time, PATH_SEP, trim_name);
    if (len >= sizeof(backup_file)) {
        log0(group_list[listidx].group_id, group_list[listidx].file_id,
                "Max pathname length exceeded for backup file, deleting",
                group_list[listidx].fileinfo.filepath);
        clear_path(group_list[listidx].fileinfo.filepath, listidx);
        return;
    }
    clear_path(backup_file, listidx);
    if (!create_path_to_file(listidx, backup_file)) {
        log0(group_list[listidx].group_id, group_list[listidx].file_id,
                "Error creating path to backup file");
        clear_path(group_list[listidx].fileinfo.filepath, listidx);
    }
#ifdef WINDOWS
    if (!MoveFile(group_list[listidx].fileinfo.filepath, backup_file)) {
        char errbuf[300];
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL,
                GetLastError(), 0, errbuf, sizeof(errbuf), NULL);
        log0(group_list[listidx].group_id, group_list[listidx].file_id,
                "Couldn't rename from %s to %s, deleting: (%d): %s",
                group_list[listidx].fileinfo.filepath, backup_file,
                GetLastError(), errbuf);
        clear_path(group_list[listidx].fileinfo.filepath, listidx);
    } else {
        log1(group_list[listidx].group_id, group_list[listidx].file_id,
                "Backed up existing file to %s", backup_file);
    }
#else
    if (rename(group_list[listidx].fileinfo.filepath, backup_file) == -1) {
        syserror(group_list[listidx].group_id, group_list[listidx].file_id,
                 "Couldn't rename from %s to %s, deleting",
                 group_list[listidx].fileinfo.filepath, backup_file);
        clear_path(group_list[listidx].fileinfo.filepath, listidx);
    } else {
        log1(group_list[listidx].group_id, group_list[listidx].file_id,
                "Backed up existing file to %s", backup_file);
    }
#endif
}
Ejemplo n.º 11
0
/* Returns the bitwise OR of all MSENSE_ values that explain how "viewer" can
   see "viewee". &youmonst is accepted as either argument. If both arguments
   are the same, this tests if/how a monster/player can detect itself. */
unsigned
msensem(const struct monst *viewer, const struct monst *viewee)
{
    unsigned sensemethod = 0;

    /* sanity checks, so the caller doesn't have to */
    if (viewer != &youmonst)
        if (!onmap(viewer) || DEADMONSTER(viewer))
            return 0;
    if (viewee != &youmonst)
        if (!onmap(viewee) || DEADMONSTER(viewee))
            return 0;
    if (!level) {
        impossible("vision calculations during level creation");
        return 0;
    }

    /* TODO: once levels rewrite is done, this code can be simplified (and won't
       work in its present form). */
    d_level *sz = m_mz(viewer), *tz = m_mz(viewee);
    if (sz->dnum != tz->dnum || sz->dlevel != tz->dlevel)
        return 0;
    struct level *lev = level;
    if (viewer != &youmonst)
        lev = viewer->dlevel;

    int sx = m_mx(viewer), sy = m_my(viewer),
        tx = m_mx(viewee), ty = m_my(viewee);

    int distance = dist2(sx, sy, tx, ty);

    /* Special case: if either endpoint is an engulfing monster, then we want
       LOE to the square specifically, ignoring players on that square (because
       the edge of an engulfing monster blocks LOE to the player). */
    char **msensem_vizarray =
        (Engulfed && (viewer == u.ustuck || viewee == u.ustuck)) ?
        NULL : viz_array;

    /* Line of effect. clear_path is like couldsee(), but doesn't require the
       player to be at either endpoint. (If the player happens to be at one of
       the endpoints, it just calls couldsee() directly.) */
    boolean loe = clear_path(sx, sy, tx, ty, msensem_vizarray);

    /* A special case for many vision methods: water or the ground blocking
       vision. A hiding target is also included in these, because hiding is
       often a case of using an object, part of the floor, a cranny in the
       ceiling, etc., to block vision (and even when it isn't, it should block
       vision in the same cases). */
    boolean vertical_loe =
        !(m_mburied(viewer) || m_mburied(viewee) ||
          ((!!m_underwater(viewee)) ^ (!!m_underwater(viewer))) ||
          m_mundetected(viewee));

    boolean invisible = !!m_has_property(viewee, INVIS, ANY_PROPERTY, 0);

    /* For normal vision, one necessary condition is that the target must be
       adjacent or on a lit square (we assume there's just enough light in the
       dungeon that even in dark areas, adjacent squares are visible to normal
       vision). We test "lit" by testing that the square is either temporarily
       lit, or permanently lit. (We can't use the normal cansee() check because
       that doesn't work for squares outside the player's LOE, and it's possible
       that neither the viewer nor the viewee is the player.)

       TODO: templit off-level. That's very hard to implement because we don't
       run lighting calculations off-level. */
    boolean target_lit = distance <= 2 || (lev == level && templit(tx, ty)) ||
        lev->locations[tx][ty].lit;

    /* TODO: Maybe infravision (and perhaps even infravisibility) should be
       properties? */
    boolean infravision_ok = infravision(viewer->data) &&
        infravisible(viewee->data);

    boolean blinded = !!m_has_property(viewer, BLINDED, ANY_PROPERTY, 0);
    boolean see_invisible =
        !!m_has_property(viewer, SEE_INVIS, ANY_PROPERTY, 0);

    if (loe && vertical_loe && !blinded) {
        if (!invisible && target_lit)
            sensemethod |= MSENSE_VISION;
        if (!invisible && infravision_ok)
            sensemethod |= MSENSE_INFRAVISION;
        if (invisible && (target_lit || infravision_ok) && see_invisible)
            sensemethod |= MSENSE_SEEINVIS | MSENSEF_KNOWNINVIS;
    }

    /* Telepathy. The viewee needs a mind; the viewer needs either to be blind,
       or for the telepathy to be extrinsic and the viewer within BOLT_LIM. */
    if (!mindless(viewee->data) && !m_helpless(viewer, hm_unconscious)) {
        unsigned telepathy_reason =
            m_has_property(viewer, TELEPAT, ANY_PROPERTY, 0);
        if ((telepathy_reason && blinded) ||
            (telepathy_reason & (W_EQUIP | W_ARTIFACT) &&
             distance <= BOLT_LIM * BOLT_LIM))
            sensemethod |= MSENSE_TELEPATHY;
    }

    /* Astral vision. Like regular vision, but has a distance check rather than
       an LOE check. It's unclear whether this pierces blindness, because the
       only item that gives astral vision also gives blindness immunity; this
       code assumes not. */
    boolean xray = m_has_property(viewer, XRAY_VISION, ANY_PROPERTY, 0) &&
        (!invisible || see_invisible);
    if (vertical_loe && distance <= XRAY_RANGE * XRAY_RANGE && xray &&
        (target_lit || infravision_ok)) {
        sensemethod |= MSENSE_XRAY;
        if (invisible && see_invisible)
            sensemethod |= MSENSEF_KNOWNINVIS;
    }

    /* Ideally scent should work around corners, but not through walls. That's
       awkward to write, though, because it'd require pathfinding. */
    if (vertical_loe && loe && distance <= 5 && has_scent(viewer->data))
        sensemethod |= MSENSE_SCENT;

    /* Monster detection. All that is needed (apart from same-level, which was
       checked earlier) is the property itself. */
    if (m_has_property(viewer, DETECT_MONSTERS, ANY_PROPERTY, 0))
        sensemethod |= MSENSE_MONDETECT;

    /* Warning versus monster class. (Actually implemented as monster
       /race/.) */
    if (mworn_warntype(viewer) & viewee->data->mflags2)
        sensemethod |= MSENSE_WARNOFMON;

    /* Covetous sense. Note that the player can benefit from this too, e.g. a
       player in master lich form will be able to detect the Wizard of Yendor
       holding the Book of the Dead. */
    if (covetous_sense(viewer, viewee))
        sensemethod |= MSENSE_COVETOUS;

    /* Smell of gold, approximating 3.4.3 behaviour (which was previously in
       set_apparxy in monmove.c). Xorns can sense any monster with gold in their
       inventory. */
    if (viewer->data == &mons[PM_XORN] && money_cnt(m_minvent(viewee)))
        sensemethod |= MSENSE_GOLDSMELL;

    /* Warning. This partial-senses monsters that are hostile to the viewer, and
       have a level of 4 or greater, and a distance of 100 or less. */
    if (distance <= 100 && m_mlev(viewee) >= 4 &&
        m_has_property(viewer, WARNING, ANY_PROPERTY, 0) &&
        mm_aggression(viewee, viewer) & ALLOW_M)
        sensemethod |= MSENSE_WARNING;

    /* Deducing the existence of a long worm via seeing a segment.

       Based on the code that was formerly worm_known in worm.c, but expanded to
       handle monster viewing.

       Note: assumes that normal vision, possibly modified by astral vision and
       see invisible, is the only way to see a long worm tail. Infravision
       doesn't work (they're cold-blooded), and currently no other types of
       vision are implemented. Detection would find the head. */
    if (viewee->wormno && (!invisible || see_invisible) &&
        vertical_loe && !blinded) {
        struct wseg *curr = viewee->dlevel->wtails[viewee->wormno];

        while (curr) {
            boolean seg_dist = dist2(sx, sy, curr->wx, curr->wy);
            boolean seg_loe =
                clear_path(sx, sy, curr->wx, curr->wy, msensem_vizarray) ||
                (xray && seg_dist <= XRAY_RANGE * XRAY_RANGE);
            boolean seg_lit = seg_dist <= 2 ||
                (lev == level && templit(curr->wx, curr->wy)) ||
                lev->locations[curr->wx][curr->wy].lit;

            if (seg_loe && seg_lit)
                sensemethod |= MSENSE_WORM;

            curr = curr->nseg;
        }
    }

    /* Calculate known invisibility, because we have all the information to
       hand, and it's a complex calculation without it. We need to be able to
       see the monster's location with normal vision, but not the monster
       itself. Also don't include warning in this (because then, we can't match
       the monster to the message). */
    if (loe && vertical_loe && !blinded && sensemethod && target_lit &&
        !(sensemethod & (MSENSE_ANYVISION | MSENSE_WARNING)))
        sensemethod |= MSENSEF_KNOWNINVIS;

    /* If the target is in item form, it's not being seen properly. Any
       vision-style detection of the target is going to not see it as a
       monster. */
    if (m_helpless(viewee, 1 << hr_mimicking) &&
        (lev != level || !Protection_from_shape_changers) &&
        (sensemethod & MSENSE_ANYVISION)) {
        sensemethod &= ~MSENSE_ANYVISION;
        sensemethod |= MSENSE_ITEMMIMIC;
    }

    return sensemethod;
}
Ejemplo n.º 12
0
std::vector<tripoint> map::route( const tripoint &f, const tripoint &t,
                                  const int bash, const int maxdist,
                                  const std::set<tripoint> &pre_closed ) const
{
    /* TODO: If the origin or destination is out of bound, figure out the closest
     * in-bounds point and go to that, then to the real origin/destination.
     */
    std::vector<tripoint> ret;

    if( !inbounds( f ) ) {
        return ret;
    }

    if( !inbounds( t ) ) {
        tripoint clipped = t;
        clip_to_bounds( clipped );
        return route( f, clipped, bash, maxdist );
    }
    // First, check for a simple straight line on flat ground
    // Except when the line contains a pre-closed tile - we need to do regular pathing then
    if( f.z == t.z && clear_path( f, t, -1, 2, 2 ) ) {
        const auto line_path = line_to( f, t );
        const std::set<tripoint> sorted_line( line_path.begin(), line_path.end() );

        if( is_disjoint( sorted_line, pre_closed ) ) {
            return line_path;
        }
    }

    const int pad = 16;  // Should be much bigger - low value makes pathfinders dumb!
    int minx = std::min( f.x, t.x ) - pad;
    int miny = std::min( f.y, t.y ) - pad;
    int minz = std::min( f.z, t.z ); // TODO: Make this way bigger
    int maxx = std::max( f.x, t.x ) + pad;
    int maxy = std::max( f.y, t.y ) + pad;
    int maxz = std::max( f.z, t.z ); // Same TODO as above
    clip_to_bounds( minx, miny, minz );
    clip_to_bounds( maxx, maxy, maxz );

    pathfinder pf( minx, miny, maxx, maxy );
    // Make NPCs not want to path through player
    // But don't make player pathing stop working
    for( const auto &p : pre_closed ) {
        if( p.x >= minx && p.x < maxx && p.y >= miny && p.y < maxy ) {
            pf.close_point( p );
        }
    }

    // Start and end must not be closed
    pf.unclose_point( f );
    pf.unclose_point( t );
    pf.add_point( 0, 0, f, f );

    bool done = false;

    do {
        auto cur = pf.get_next();

        const int parent_index = flat_index( cur.x, cur.y );
        auto &layer = pf.get_layer( cur.z );
        auto &cur_state = layer.state[parent_index];
        if( cur_state == ASL_CLOSED ) {
            continue;
        }

        if( layer.gscore[parent_index] > maxdist ) {
            // Shortest path would be too long, return empty vector
            return std::vector<tripoint>();
        }

        if( cur == t ) {
            done = true;
            break;
        }

        cur_state = ASL_CLOSED;

        const auto &pf_cache = get_pathfinding_cache_ref( cur.z );
        const auto cur_special = pf_cache.special[cur.x][cur.y];

        // 7 3 5
        // 1 . 2
        // 6 4 8
        constexpr std::array<int, 8> x_offset{{ -1,  1,  0,  0,  1, -1, -1, 1 }};
        constexpr std::array<int, 8> y_offset{{  0,  0, -1,  1, -1,  1, -1, 1 }};
        for( size_t i = 0; i < 8; i++ ) {
            const tripoint p( cur.x + x_offset[i], cur.y + y_offset[i], cur.z );
            const int index = flat_index( p.x, p.y );

            // @todo Remove this and instead have sentinels at the edges
            if( p.x < minx || p.x >= maxx || p.y < miny || p.y >= maxy ) {
                continue;
            }

            if( layer.state[index] == ASL_CLOSED ) {
                continue;
            }

            // Penalize for diagonals or the path will look "unnatural"
            int newg = layer.gscore[parent_index] + ( ( cur.x != p.x && cur.y != p.y ) ? 1 : 0 );

            const auto p_special = pf_cache.special[p.x][p.y];

            constexpr auto non_normal = PF_SLOW | PF_WALL | PF_VEHICLE | PF_TRAP;
            // @todo De-uglify, de-huge-n
            if( !( p_special & non_normal ) ) {
                // Boring flat dirt - the most common case above the ground
                newg += 2;
            } else {
                int part = -1;
                const maptile &tile = maptile_at_internal( p );
                const auto &terrain = tile.get_ter_t();
                const auto &furniture = tile.get_furn_t();
                const vehicle *veh = veh_at_internal( p, part );

                const int cost = move_cost_internal( furniture, terrain, veh, part );
                // Don't calculate bash rating unless we intend to actually use it
                const int rating = ( bash == 0 || cost != 0 ) ? -1 :
                                   bash_rating_internal( bash, furniture, terrain, false, veh, part );

                if( cost == 0 && rating <= 0 && !terrain.open && veh == nullptr ) {
                    layer.state[index] = ASL_CLOSED; // Close it so that next time we won't try to calc costs
                    continue;
                }

                newg += cost;
                if( cost == 0 ) {
                    // Handle all kinds of doors
                    // Only try to open INSIDE doors from the inside
                    if( terrain.open &&
                        ( !terrain.has_flag( "OPENCLOSE_INSIDE" ) || !is_outside( cur ) ) ) {
                        newg += 4; // To open and then move onto the tile
                    } else if( veh != nullptr ) {
                        part = veh->obstacle_at_part( part );
                        int dummy = -1;
                        if( veh->part_flag( part, VPFLAG_OPENABLE ) &&
                            ( !veh->part_flag( part, "OPENCLOSE_INSIDE" ) ||
                              veh_at_internal( cur, dummy ) == veh ) ) {
                            // Handle car doors, but don't try to path through curtains
                            newg += 10; // One turn to open, 4 to move there
                        } else if( part != -1 && bash > 0 ) {
                            // Car obstacle that isn't a door
                            // Or there is no car obstacle, but the car is wedged into an obstacle,
                            //  in which case part == -1
                            newg += 2 * veh->parts[part].hp / bash + 8 + 4;
                        } else {
                            if( !veh->part_flag( part, VPFLAG_OPENABLE ) ) {
                                // Won't be openable, don't try from other sides
                                layer.state[index] = ASL_CLOSED;
                            }

                            continue;
                        }
                    } else if( rating > 1 ) {
                        // Expected number of turns to bash it down, 1 turn to move there
                        // and 5 turns of penalty not to trash everything just because we can
                        newg += ( 20 / rating ) + 2 + 10;
                    } else if( rating == 1 ) {
                        // Desperate measures, avoid whenever possible
                        newg += 500;
                    } else {
                        continue; // Unbashable and unopenable from here
                    }
                }

                if( p_special & PF_TRAP ) {
                    const auto &ter_trp = terrain.trap.obj();
                    const auto &trp = ter_trp.is_benign() ? tile.get_trap_t() : ter_trp;
                    if( !trp.is_benign() ) {
                        // For now make them detect all traps
                        if( has_zlevels() && terrain.has_flag( TFLAG_NO_FLOOR ) ) {
                            // Special case - ledge in z-levels
                            // Warning: really expensive, needs a cache
                            if( valid_move( p, tripoint( p.x, p.y, p.z - 1 ), false, true ) ) {
                                tripoint below( p.x, p.y, p.z - 1 );
                                if( !has_flag( TFLAG_NO_FLOOR, below ) ) {
                                    // Otherwise this would have been a huge fall
                                    auto &layer = pf.get_layer( p.z - 1 );
                                    // From cur, not p, because we won't be walking on air
                                    pf.add_point( layer.gscore[parent_index] + 10,
                                                  layer.score[parent_index] + 10 + 2 * rl_dist( below, t ),
                                                  cur, below );
                                }

                                // Close p, because we won't be walking on it
                                layer.state[index] = ASL_CLOSED;
                                continue;
                            }
                        } else {
                            // Otherwise it's walkable
                            newg += 500;
                        }
                    }
                }
            }

            // If not visited, add as open
            // If visited, add it only if we can do so with better score
            if( layer.state[index] == ASL_NONE || newg < layer.gscore[index] ) {
                pf.add_point( newg, newg + 2 * rl_dist( p, t ), cur, p );
            }
        }

        if( !has_zlevels() || !( cur_special & PF_UPDOWN ) ) {
            // The part below is only for z-level pathing
            continue;
        }

        const maptile &parent_tile = maptile_at_internal( cur );
        const auto &parent_terrain = parent_tile.get_ter_t();
        if( cur.z > minz && parent_terrain.has_flag( TFLAG_GOES_DOWN ) ) {
            tripoint dest( cur.x, cur.y, cur.z - 1 );
            dest = vertical_move_destination<TFLAG_GOES_UP>( *this, dest );
            if( inbounds( dest ) ) {
                auto &layer = pf.get_layer( dest.z );
                pf.add_point( layer.gscore[parent_index] + 2,
                              layer.score[parent_index] + 2 * rl_dist( dest, t ),
                              cur, dest );
            }
        }
        if( cur.z < maxz && parent_terrain.has_flag( TFLAG_GOES_UP ) ) {
            tripoint dest( cur.x, cur.y, cur.z + 1 );
            dest = vertical_move_destination<TFLAG_GOES_DOWN>( *this, dest );
            if( inbounds( dest ) ) {
                auto &layer = pf.get_layer( dest.z );
                pf.add_point( layer.gscore[parent_index] + 2,
                              layer.score[parent_index] + 2 * rl_dist( dest, t ),
                              cur, dest );
            }
        }
        if( cur.z < maxz && parent_terrain.has_flag( TFLAG_RAMP ) &&
            valid_move( cur, tripoint( cur.x, cur.y, cur.z + 1 ), false, true ) ) {
            auto &layer = pf.get_layer( cur.z + 1 );
            for( size_t it = 0; it < 8; it++ ) {
                const tripoint above( cur.x + x_offset[it], cur.y + y_offset[it], cur.z + 1 );
                pf.add_point( layer.gscore[parent_index] + 4,
                              layer.score[parent_index] + 4 + 2 * rl_dist( above, t ),
                              cur, above );
            }
        }
    } while( !done && !pf.empty() );

    ret.reserve( rl_dist( f, t ) * 2 );
    if( done ) {
        tripoint cur = t;
        // Just to limit max distance, in case something weird happens
        for( int fdist = maxdist; fdist != 0; fdist-- ) {
            const int cur_index = flat_index( cur.x, cur.y );
            const auto &layer = pf.get_layer( cur.z );
            const tripoint &par = layer.parent[cur_index];
            if( cur == f ) {
                break;
            }

            ret.push_back( cur );
            // Jumps are acceptable on 1 z-level changes
            // This is because stairs teleport the player too
            if( rl_dist( cur, par ) > 1 && abs( cur.z - par.z ) != 1 ) {
                debugmsg( "Jump in our route! %d:%d:%d->%d:%d:%d",
                          cur.x, cur.y, cur.z, par.x, par.y, par.z );
                return ret;
            }

            cur = par;
        }

        std::reverse( ret.begin(), ret.end() );
    }

    return ret;
}
Ejemplo n.º 13
0
void pgfgd_path_clear(pgfgd_Edge* e)
{
  clear_path (e->path);
}
Ejemplo n.º 14
0
/* Mark locations that are temporarily lit via mobile light sources. */
void
do_light_sources(char **cs_rows)
{
    int x, y, min_x, max_x, max_y, offset;
    const char *limits;
    short at_hero_range = 0;
    light_source *ls;
    char *row;

    for (ls = level->lev_lights; ls; ls = ls->next) {
        ls->flags &= ~LSF_SHOW;

        /* 
         * Check for moved light sources.  It may be possible to
         * save some effort if an object has not moved, but not in
         * the current setup -- we need to recalculate for every
         * vision recalc.
         */
        if (ls->type == LS_OBJECT) {
            if (get_obj_location((struct obj *)ls->id, &ls->x, &ls->y, 0))
                ls->flags |= LSF_SHOW;
        } else if (ls->type == LS_MONSTER) {
            if (get_mon_location((struct monst *)ls->id, &ls->x, &ls->y, 0))
                ls->flags |= LSF_SHOW;
        }

        /* minor optimization: don't bother with duplicate light sources at
           hero */
        if (ls->x == u.ux && ls->y == u.uy) {
            if (at_hero_range >= ls->range)
                ls->flags &= ~LSF_SHOW;
            else
                at_hero_range = ls->range;
        }

        if (ls->flags & LSF_SHOW) {
            /* 
             * Walk the points in the circle and see if they are
             * visible from the center.  If so, mark'em.
             *
             * Kevin's tests indicated that doing this brute-force
             * method is faster for radius <= 3 (or so).
             */
            limits = circle_ptr(ls->range);
            if ((max_y = (ls->y + ls->range)) >= ROWNO)
                max_y = ROWNO - 1;
            if ((y = (ls->y - ls->range)) < 0)
                y = 0;
            for (; y <= max_y; y++) {
                row = cs_rows[y];
                offset = limits[abs(y - ls->y)];
                if ((min_x = (ls->x - offset)) < 0)
                    min_x = 0;
                if ((max_x = (ls->x + offset)) >= COLNO)
                    max_x = COLNO - 1;

                for (x = min_x; x <= max_x; x++)
                    if (clear_path((int)ls->x, (int)ls->y, x, y, cs_rows))
                        row[x] |= TEMP_LIT;
            }
        }
    }
}
Ejemplo n.º 15
0
void process_cmd(struct cmd_frame_t *cmd)
{
        int res;
        
        reply.status = ACK; // change to NACK as necessary
        reply.cmd = cmd->cmd;

        switch (cmd->cmd) {
        case CMD_ECHO:
                reply.data[0] = cmd->echo.length;
                memcpy(&reply.data[1], cmd->echo.data, cmd->echo.length);
                send_reply(&reply, cmd->echo.length+3);
                break;

        case CMD_RESET:
                if (cmd->reset_magic == RESET_MAGIC) {
                        usb_peripheral_reset();
                        CREG_M4MEMMAP = 0x10400000;
                        scb_reset_system();
                } else {
                        send_nack();
                }
                break;

        case CMD_GET_EVENT_COUNTERS:
        {
                struct event_counters counters = get_last_event_counters();
                memcpy(reply.data, &counters, sizeof(struct event_counters));
                send_reply(&reply, 2+sizeof(struct event_counters));
                break;
        }

        case CMD_GET_STAGE_GAINS:
                memcpy(reply.data, stage_fb_gains, sizeof(stage_fb_gains));
                send_reply(&reply, 2+sizeof(stage_fb_gains));
                break;

        case CMD_SET_STAGE_GAINS:
                memcpy(stage_fb_gains, cmd->set_stage_gains, sizeof(stage_fb_gains));
                send_ack();
                break;
                
        case CMD_GET_STAGE_SETPOINT:
                memcpy(reply.data, stage_fb_setpoint, sizeof(stage_fb_setpoint));
                send_reply(&reply, 2+sizeof(stage_fb_setpoint));
                break;

        case CMD_SET_STAGE_SETPOINT:
                memcpy(stage_fb_setpoint, cmd->set_stage_setpoint, sizeof(stage_fb_setpoint));
                send_ack();
                break;

        case CMD_GET_PSD_GAINS:
                memcpy(reply.data, psd_fb_gains, sizeof(psd_fb_gains));
                send_reply(&reply, 2+sizeof(psd_fb_gains));
                break;

        case CMD_SET_PSD_GAINS:
                memcpy(psd_fb_gains, cmd->set_psd_gains, sizeof(psd_fb_gains));
                send_ack();
                break;

        case CMD_GET_PSD_SETPOINT:
                memcpy(reply.data, psd_fb_setpoint, sizeof(psd_fb_setpoint));
                send_reply(&reply, 2+sizeof(psd_fb_setpoint));
                break;

        case CMD_SET_PSD_SETPOINT:
                memcpy(psd_fb_setpoint, cmd->set_psd_setpoint, sizeof(psd_fb_setpoint));
                send_ack();
                break;
        
        case CMD_GET_MAX_ERROR:
                memcpy(reply.data, &max_error, sizeof(max_error));
                send_reply(&reply, 2+sizeof(max_error));
                break;

        case CMD_SET_MAX_ERROR:
                max_error = cmd->set_max_error;
                send_ack();
                break;

        case CMD_GET_OUTPUT_GAINS:
        {
                fixed16_t* tmp = (fixed16_t*) reply.data;
                for (unsigned int i=0; i<STAGE_OUTPUTS; i++) {
                        *tmp = stage_outputs[i].p_gain; tmp++;
                        *tmp = stage_outputs[i].i_gain; tmp++;
                }
                send_reply(&reply, 2+2*STAGE_OUTPUTS*sizeof(fixed16_t));
                break;
        }

        case CMD_SET_OUTPUT_GAINS:
        {
                for (unsigned int i=0; i<STAGE_OUTPUTS; i++) {
                        stage_outputs[i].p_gain = cmd->set_output_gains[i][0];
                        stage_outputs[i].i_gain = cmd->set_output_gains[i][1];
                }
                send_ack();
                break;
        }

        case CMD_GET_OUTPUT_TAUS:
        {
                for (unsigned int i=0; i<STAGE_OUTPUTS; i++) {
                        reply.data[i] = pi_get_tau(&stage_outputs[i]);
                }
                send_reply(&reply, 2+3);
                break;
        }

        case CMD_SET_OUTPUT_TAUS:
        {
                for (unsigned int i=0; i<STAGE_OUTPUTS; i++) {
                        pi_set_tau(&stage_outputs[i], cmd->set_output_taus[i]);
                }
                send_ack();
                break;
        }

        case CMD_GET_ADC_FREQ:
                reply.data32[0] = 0; //TODO adc_get_trigger_freq();
                send_reply(&reply, 2+4);
                break;

        case CMD_SET_ADC_FREQ:
                adc_set_trigger_freq(cmd->set_adc_freq);
                send_ack();
                break;
                
        case CMD_GET_ADC_TRIGGER_MODE:
                reply.data[0] = adc_get_trigger_mode();
                send_reply(&reply, 2+1);
                break;

        case CMD_SET_ADC_TRIGGER_MODE:
                adc_set_trigger_mode(cmd->set_adc_trigger_mode);
                send_ack();
                break;

        case CMD_START_ADC_STREAM:
                adc_streaming = true;
                send_ack();
                break;

        case CMD_STOP_ADC_STREAM:
                adc_streaming = false;
                adc_flush();
                send_ack();
                break;

        case CMD_FLUSH_ADC_STREAM:
                if (adc_flush() == 0) {
                        send_ack();
                } else {
                        send_nack();
                }
                break;

        case CMD_GET_ADC_DECIMATION:
        {
                reply.data32[0] = adc_get_decimation();
                send_reply(&reply, 2+4);
                break;
        }
                
        case CMD_SET_ADC_DECIMATION:
                if (adc_set_decimation(cmd->set_adc_decimation) == 0) {
                        send_ack();
                } else {
                        send_nack();
                }
                break;

        case CMD_GET_FEEDBACK_FREQ:
        {
                unsigned int freq = feedback_get_loop_freq();
                reply.data32[0] = freq;
                send_reply(&reply, 2+4);
                break;
        }

        case CMD_SET_FEEDBACK_FREQ:
                feedback_set_loop_freq(cmd->set_feedback_freq);
                send_ack();
                break;

        case CMD_GET_FEEDBACK_MODE:
                reply.data[0] = feedback_get_mode();
                send_reply(&reply, 3);
                break;

        case CMD_SET_FEEDBACK_MODE:
                feedback_set_mode(cmd->set_feedback_mode);
                send_ack();
                break;

        case CMD_SET_RAW_POS:
                if (feedback_set_position(cmd->set_raw_pos) == 0) {
                        send_ack();
                } else {
                        send_nack();
                }
                break;

        case CMD_CLEAR_PATH:
                clear_path();
                send_ack();
                break;
                
        case CMD_ENQUEUE_POINTS:
                res = 0;
                if (cmd->enqueue_points.npts > 0)
                        res = enqueue_points((uint16_t*) &cmd->enqueue_points.points, cmd->enqueue_points.npts);
                if (res == -1 || res == 0) {
                        reply.data[0] = res != -1; // were the points added?
                        reply.data[1] = is_path_running();
                        send_reply(&reply, 4);
                } else {
                        send_nack();
                }
                break;

        case CMD_START_PATH:
                if (start_path(cmd->start_path.freq, cmd->start_path.synchronous_adc) == 0) {
                        send_ack();
                } else {
                        send_nack();
                }
                break;

        case CMD_SET_EXCITATION:
        {
                struct set_excitation* const se = &cmd->set_excitation;
                struct excitation_buffer* const exc = &excitations[se->channel];

                if ((se->length + se->offset > MAX_EXCITATION_LENGTH)
                    || (se->channel >= 3))
                {
                        send_nack();
                        break;
                }

                exc->length = 0;
                exc->offset = 0;
                if (se->length != 0) {
                        memcpy(&exc->samples[se->offset],
                               &se->samples,
                               sizeof(uint16_t) * se->length);
                }
                exc->length = se->total_length;
                send_ack();
                break;
        }

        case CMD_GET_SEARCH_STEP:
                memcpy(reply.data, search_fb_step,
                       sizeof(search_fb_step));
                send_reply(&reply, 2+sizeof(search_fb_step));
                break;

        case CMD_SET_SEARCH_STEP:
                memcpy(search_fb_step, cmd->set_search_step,
                       sizeof(search_fb_step));
                send_ack();
                break;

        case CMD_GET_SEARCH_OBJ_GAINS:
                memcpy(reply.data, search_obj_gains,
                       sizeof(search_obj_gains));
                send_reply(&reply, 2+sizeof(search_obj_gains));
                break;

        case CMD_SET_SEARCH_OBJ_GAINS:
                memcpy(search_obj_gains, cmd->set_search_obj_gains,
                       sizeof(search_obj_gains));
                send_ack();
                break;

        case CMD_GET_SEARCH_OBJ_THRESH:
                memcpy(reply.data, &search_obj_thresh,
                       sizeof(search_obj_thresh));
                send_reply(&reply, 2+sizeof(search_obj_thresh));
                break;

        case CMD_SET_SEARCH_OBJ_THRESH:
                search_obj_thresh = cmd->set_search_obj_thresh,
                send_ack();
                break;

        case CMD_GET_COARSE_FB_PARAMS:
                memcpy(reply.data, &coarse_fb_channels,
                       sizeof(coarse_fb_channels));
                send_reply(&reply, 2+sizeof(coarse_fb_channels));
                break;

        case CMD_SET_COARSE_FB_PARAMS:
                memcpy(coarse_fb_channels, cmd->set_coarse_fb_params,
                       sizeof(coarse_fb_channels));
                send_ack();
                break;

        default:
                send_nack();
                return;
        }
}
Ejemplo n.º 16
0
/**
 * Process an incoming FILEINFO message.
 * Expected in the middle of a group with no current file.
 */
void handle_fileinfo(struct group_list_t *group, const unsigned char *message,
                     unsigned meslen, struct timeval rxtime)
{
    stat_struct statbuf;
    int found_dir;

    if (!read_fileinfo(group, message, meslen, rxtime)) {
        return;
    }

    glog2(group, "Name of file to receive: %s", group->fileinfo.name);
    switch (group->fileinfo.ftype) {
    case FTYPE_REG:
        glog2(group, "Bytes: %s, Blocks: %d, Sections: %d",
                     printll(group->fileinfo.size),
                     group->fileinfo.blocks, group->fileinfo.sections);
        glog3(group, "small section size: %d, "
                     "big section size: %d, # big sections: %d",
                     group->fileinfo.secsize_small, group->fileinfo.secsize_big,
                     group->fileinfo.big_sections);
        break;
    case FTYPE_DIR:
        glog2(group, "Empty directory");
        break;
    case FTYPE_LINK:
        glog2(group, "Symbolic link to %s", group->fileinfo.linkname);
        break;
    case FTYPE_DELETE:
        glog2(group, "Deleting file/directory");
        break;
    case FTYPE_FREESPACE:
        glog2(group, "Get free space for path");
        break;
    default:
        glog1(group, "Invalid file type: %d", group->fileinfo.ftype);
        send_abort(group, "Invalid file type");
        return;
    }

    if (!setup_dest_file(group)) {
        // A rejected file is still a success because we responded with a
        // COMPLETE with status=rejected instead of with an ABORT
        return;
    }

    // Make sure the path to the destination file exists and
    // remove or back up any existing file
    if (!create_path_to_file(group, group->fileinfo.filepath)) {
        glog0(group, "Error creating path to data file");
        early_complete(group, COMP_STAT_REJECTED, 0);
        return;
    }
    found_dir = 0;
    if (tempfile && !group->sync_preview) {
        clear_path(group->fileinfo.temppath, group);
    }
    if ((group->fileinfo.ftype != FTYPE_DELETE) ||
            (group->fileinfo.ftype != FTYPE_FREESPACE)) {
        // Don't do path checks for metafile commands
    } else if (lstat_func(group->fileinfo.filepath, &statbuf) != -1) {
        glog3(group, "checking existing file");
        if ((group->fileinfo.ftype != FTYPE_DIR) || !S_ISDIR(statbuf.st_mode)) {
            if ((group->fileinfo.ftype != FTYPE_REG) ||
                    !S_ISREG(statbuf.st_mode) ||
                    ((!group->restart) && (!group->sync_mode))) {
                // Don't clear/backup if we're receiving a regular file
                // and we're in either restart mode or sync mode
                glog3(group, "calling move_to_backup");
                if (!tempfile) {
                    move_to_backup(group);
                }
            }
        } else {
            glog3(group, "found dir");
            found_dir = 1;
        }
    } else if (errno != ENOENT) {
        gsyserror(group, "Error checking file %s",group->fileinfo.filepath);
    }

    switch (group->fileinfo.ftype) {
    case FTYPE_REG:
        handle_fileinfo_regular(group);
        break;
    case FTYPE_DIR:
        handle_fileinfo_dir(group, found_dir);
        break;
    case FTYPE_LINK:
        handle_fileinfo_link(group);
        break;
    case FTYPE_DELETE:
        handle_fileinfo_delete(group);
        break;
    case FTYPE_FREESPACE:
        handle_fileinfo_freespace(group);
        break;
    default:
        glog0(group, "Error handling FILEINFO: shouldn't get here!");
    }
}
Ejemplo n.º 17
0
/**
 * Removes a full path from disk
 */
void clear_path(const char *path, int listidx)
{
    stat_struct statbuf;
    char filename[MAXPATHNAME];
    int len;

    if (lstat_func(path, &statbuf) == -1) {
        if (errno != ENOENT) {
            syserror(group_list[listidx].group_id, group_list[listidx].file_id,
                     "Error getting file status for %s", path);
        }
        return;
    }
    if (!S_ISDIR(statbuf.st_mode)) {
        unlink(path);
    } else {
#ifdef WINDOWS
        intptr_t ffhandle;
        struct _finddatai64_t finfo;
        char dirglob[MAXPATHNAME];

        snprintf(dirglob, sizeof(dirglob), "%s%c*", path,
                 PATH_SEP, group_list[listidx].group_id, PATH_SEP);
        if ((ffhandle = _findfirsti64(dirglob, &finfo)) == -1) {
            syserror(group_list[listidx].group_id, group_list[listidx].file_id,
                     "Failed to open directory %s", path);
            return;
        }
        do {
            len = snprintf(filename, sizeof(filename), "%s%c%s", path,
                           PATH_SEP, finfo.name);
            if ((len >= sizeof(filename)) || (len == -1)) {
                log0(group_list[listidx].group_id, group_list[listidx].file_id,
                        "Max pathname length exceeded: %s%c%s",
                        filename, PATH_SEP, finfo.name);
                continue;
            }
            if (strcmp(finfo.name, ".") && strcmp(finfo.name, "..")) {
                clear_path(filename, listidx);
            }
        } while (_findnexti64(ffhandle, &finfo) == 0);
        _findclose(ffhandle);
#else
        DIR *dir;
        struct dirent *de;

        if ((dir = opendir(path)) == NULL) {
            syserror(group_list[listidx].group_id, group_list[listidx].file_id,
                     "Failed to open directory %s", path);
            return;
        }
        // errno needs to be set to 0 before calling readdir, otherwise
        // we'll report a false error when we exhaust the directory
        while ((errno = 0, de = readdir(dir)) != NULL) {
            len = snprintf(filename, sizeof(filename), "%s%c%s", path, PATH_SEP,
                           de->d_name);
            if ((len >= sizeof(filename)) || (len == -1)) {
                log0(group_list[listidx].group_id, group_list[listidx].file_id,
                        "Max pathname length exceeded: %s%c%s", path,
                        PATH_SEP, de->d_name);
                continue;
            }
            if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) {
                clear_path(filename, listidx);
            }
        }
        if (errno && (errno != ENOENT)) {
            syserror(group_list[listidx].group_id, group_list[listidx].file_id,
                     "Failed to read directory %s", path);
        }
        closedir(dir);
#endif
        if (rmdir(path) == -1) {
            syserror(group_list[listidx].group_id, group_list[listidx].file_id,
                     "Failed remove directory %s", path);
        }
    }
}