Exemple #1
0
static void print_stack_trace(pid_t pid, int * count)
{
	void *		    pinfo = NULL;
	unw_addr_space_t    aspace = NULL;
	unw_cursor_t	    cursor;
	unw_word_t	    ip, sp;

	char		    nbuf[256];
	unw_word_t	    off;

	int ret;

	if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
		fprintf(stderr,
			"Failed to attach to process %llu: %s\n",
			(unsigned long long)pid, strerror(errno));
		return;
	}

	/* Wait until the attach is complete. */
	waitpid(pid, NULL, 0);

	if (((pinfo = _UPT_create(pid)) == NULL) ||
	    ((aspace = unw_create_addr_space(&_UPT_accessors, 0)) == NULL)) {
		/* Probably out of memory. */
		fprintf(stderr,
			"Unable to initialize stack unwind for process %llu\n",
			(unsigned long long)pid);
		goto cleanup;
	}

	if ((ret = unw_init_remote(&cursor, aspace, pinfo))) {
		fprintf(stderr,
			"Unable to unwind stack for process %llu: %s\n",
			(unsigned long long)pid, unw_strerror(ret));
		goto cleanup;
	}

	if (*count > 0) {
		printf("\n");
	}

	if (procname(pid, nbuf, sizeof(nbuf))) {
		printf("Stack trace for process %llu (%s):\n",
			(unsigned long long)pid, nbuf);
	} else {
		printf("Stack trace for process %llu:\n",
			(unsigned long long)pid);
	}

	while (unw_step(&cursor) > 0) {
		ip = sp = off = 0;
		unw_get_reg(&cursor, UNW_REG_IP, &ip);
		unw_get_reg(&cursor, UNW_REG_SP, &sp);

		ret = unw_get_proc_name(&cursor, nbuf, sizeof(nbuf), &off);
		if (ret != 0 && ret != -UNW_ENOMEM) {
			snprintf(nbuf, sizeof(nbuf), "<unknown symbol>");
		}
		printf("    %s + %#llx [ip=%#llx] [sp=%#llx]\n",
			nbuf, (long long)off, (long long)ip,
			(long long)sp);
	}

	(*count)++;

cleanup:
	if (aspace) {
		unw_destroy_addr_space(aspace);
	}

	if (pinfo) {
		_UPT_destroy(pinfo);
	}

	ptrace(PTRACE_DETACH, pid, NULL, NULL);
}
Exemple #2
0
char *format_c()    { return procname(); }
/**
 * @brief Method to determine the rank and size on the local node
 *
 * If the program is running on multiple nodes, it can be useful to know the
 * rank and size of the part of the program running on the local node, e.g. to
 * write output files per node.
 *
 * MPI does not provide standard functions to do this, so we have to do it
 * ourselves. The method below is based on a suggestion by Markus Wittmann on
 * his blog
 * (https://blogs.fau.de/wittmann/2013/02/mpi-node-local-rank-determination/).
 *
 * We use MPI_Comm_split to create a new communicator based on a color which is
 * derived from the processor name, obtained from MPI_Get_processor_name. The
 * local rank and size are then obtained by calling MPI_Comm_rank and
 * MPI_Comm_size on this new communicator.
 *
 * Because it is impossible to define a completely unique hash function to
 * convert node names to integer colors, we do a collective gather on the
 * newly created communicator for the node names. We then check if the names
 * are really different. If not, we do a second communicator split, where this
 * time we use the index of the own node name in the node name list as a color.
 * Since this second collective operation is done on a much smaller
 * communicator (which should be the local node for most cases), it is much
 * faster than using the same method at the start.
 *
 * @param rank Variable to store the local rank of this process in
 * @param size Variable to store the local size of the node in
 * @param noderank Rank of the node in the space of all nodes
 * @param nodesize Size of the space of all nodes
 * @param nodecomm Variable to store the local node communicator in
 */
inline void MyMPI_Comm_local_vars(int* rank, int* size, int* noderank,
                                  int* nodesize, MPI_Comm* nodecomm) {
    MPIGlobal::commtimer.start();

    char* name = new char[MPI_MAX_PROCESSOR_NAME];
    int namesize;
    int status = MyMPI_Get_processor_name(name, &namesize);
    if(status != MPI_SUCCESS) {
        std::cerr << "Error while obtaining MPI processor name!" << std::endl;
        my_exit();
    }

    name[namesize] = '\0';
    std::string procname(name);

    int color = MyMPI_hash(procname);
    MPI_Comm local_world = MPI_COMM_NULL;
    status = MPI_Comm_split(MPI_COMM_WORLD, color, MPIGlobal::rank,
                            &local_world);
    if(status != MPI_SUCCESS) {
        std::cerr << "Error while splitting MPI communicator in local MPI "
                     "communicators!"
                  << std::endl;
        my_exit();
    }

    status = MPI_Comm_rank(local_world, rank);
    if(status != MPI_SUCCESS) {
        std::cerr << "Error while obtaining local MPI rank!" << std::endl;
        my_exit();
    }
    status = MPI_Comm_size(local_world, size);
    if(status != MPI_SUCCESS) {
        std::cerr << "Error while obtaining local MPI size!" << std::endl;
        my_exit();
    }

    // check if the processes in local_world are really on a single node
    char* allnames = new char[(*size) * MPI_MAX_PROCESSOR_NAME];
    status = MPI_Allgather(name, MPI_MAX_PROCESSOR_NAME, MPI_CHAR, allnames,
                           MPI_MAX_PROCESSOR_NAME, MPI_CHAR, local_world);
    if(status != MPI_SUCCESS) {
        std::cerr << "Error while gathering processor names on the presumably "
                     "local communicator!"
                  << std::endl;
        my_exit();
    }

    int owni = 0;
    bool is_single = true;
    for(int i = 0; i < (*size); i++) {
        std::string othername(&allnames[i * MPI_MAX_PROCESSOR_NAME]);
        if(othername != procname) {
            is_single = false;
        } else {
            owni = i;
        }
    }
    if(!is_single) {
        MPI_Comm real_local_world = MPI_COMM_NULL;
        status = MPI_Comm_split(local_world, owni, (*rank), &real_local_world);
        if(status != MPI_SUCCESS) {
            std::cerr << "Error while splitting the local communicator in the "
                         "real node communicators!"
                      << std::endl;
            my_exit();
        }

        status = MPI_Comm_rank(real_local_world, rank);
        if(status != MPI_SUCCESS) {
            std::cerr << "Error while obtaining real local MPI rank!"
                      << std::endl;
            my_exit();
        }

        status = MPI_Comm_size(real_local_world, size);
        if(status != MPI_SUCCESS) {
            std::cerr << "Error while obtaining real local MPI size!"
                      << std::endl;
            my_exit();
        }

        status = MPI_Comm_free(&real_local_world);
        if(status != MPI_SUCCESS) {
            std::cerr << "Error while freeing real local MPI communicator!"
                      << std::endl;
            my_exit();
        }

        status = MPI_Comm_dup(real_local_world, nodecomm);
        if(status != MPI_SUCCESS) {
            std::cerr << "Error while duplicating local MPI communicator!"
                      << std::endl;
            my_exit();
        }
    } else {
        status = MPI_Comm_dup(local_world, nodecomm);
        if(status != MPI_SUCCESS) {
            std::cerr << "Error while duplicating local MPI communicator!"
                      << std::endl;
            my_exit();
        }
    }

    status = MPI_Comm_free(&local_world);
    if(status != MPI_SUCCESS) {
        std::cerr << "Error while freeing local MPI communicator!" << std::endl;
        my_exit();
    }

    delete[] name;

    // obtain noderank and nodesize
    MPI_Comm nodeworld;
    int nodemaster = (*rank == 0);
    status = MPI_Comm_split(MPI_COMM_WORLD, nodemaster, MPIGlobal::rank,
                            &nodeworld);
    if(status != MPI_SUCCESS) {
        std::cerr << "Error while obtaining node world!" << std::endl;
        my_exit();
    }
    if(*rank == 0) {
        status = MPI_Comm_rank(nodeworld, noderank);
        if(status != MPI_SUCCESS) {
            std::cerr << "Error while obtaining noderank!" << std::endl;
            my_exit();
        }

        status = MPI_Comm_size(nodeworld, nodesize);
        if(status != MPI_SUCCESS) {
            std::cerr << "Error while obtaining nodesize!" << std::endl;
            my_exit();
        }
    }

    status = MPI_Comm_free(&nodeworld);
    if(status != MPI_SUCCESS) {
        std::cerr << "Error while freeing nodeworld!" << std::endl;
        my_exit();
    }

    status = MPI_Bcast(noderank, 1, MPI_INT, 0, *nodecomm);
    if(status != MPI_SUCCESS) {
        std::cerr << "Error while broadcasting noderank!" << std::endl;
        my_exit();
    }

    status = MPI_Bcast(nodesize, 1, MPI_INT, 0, *nodecomm);
    if(status != MPI_SUCCESS) {
        std::cerr << "Error while broadcasting nodesize!" << std::endl;
        my_exit();
    }

    MPIGlobal::commtimer.stop();
}
Exemple #4
0
/* ===========================================================================
 * Process a name or wildcard expression to operate on (or exclude).
 * We will only arrive here if we do a Freshen or Delete.
 * Return an error code in the ZEN_ class.
 * ZEN_OK, ZEN_ABORT, ZEN_MISS03, ZEN_MISS04, ZEN_MISS05, ZEN_MEM22, ZEN_MEM23
	*ArgName :: Name to process.
 */
int procname( char *ArgName, bool RecurseDir, struct Globals *pG ) {
	char         *a;       /* path and name for recursion     */
	zDIR         *d;       /* directory stream from opendir() */
	char         *e;       /* pointer to name from readd()    */
	int           m;       /* matched flag                    */
	char         *p;       /* path for recursion              */
	int           pnError; /* ProcName error                  */
	struct stat   StatRes; /* result of stat()                */
	struct zlist *z;       /* steps through zfiles list       */

	// sprintf( ewemsg, "in procname  name=>%s<=  recurse=%d", ArgName, RecurseDir );
	// diag( ewemsg );

	m = 1;  /* set dflt for success indicator (0=success) */

	if ( pG->global_abort_sw )  return ZEN_ABORT;		/* RCV changed was ZEN_MISS? */
	if ( *ArgName == '\0' ) return ZEN_MISS03;

	/* LSSTAT returns 0 if it's arg is any kind of file (even a dir). */
	/* IsShExp returns true if a wildcard symbol is found, or
	 * NULL if none were found -- IsShExp is in util.c
	 */

	if ( LSSTAT( GetFullPath( pG, ArgName ), &StatRes ) || (IsShExp( ArgName ) != NULL) ) {
		// diag( "not a file or dir - 'ArgName' must be a wildcard fspec" );

		// Upon finding a wildcard fspec, we need to mark entries in
		// the "zfiles" list that are included by the wildcard.

		/* convert the "external" (native) filename to an internal
		 * ZIP-archive-compatible filename.
		 */
		p = ex2in( ArgName, (int *)NULL, pG );   /* shouldn't affect matching chars */

		/* does any file already in the archive match this spec? */
		/* Note that we need the pathname and filename together for this */
		for ( z = pG->zfiles; z; z = z->nxt ) {
			if ( dosmatch( p, z->zname, pG ) ) {
				/* name is in archive - mark it for updating */
				z->mark = pG->pcount ? filter( z->zname, pG ) : 1;
				FREE( z->name );	// RCV added + next 8 lines needed for FRESHEN mode.
				if ( (z->name = MALLOC( lstrlen( z->zname ) + 4 )) == NULL ) return ZEN_MEM34;
				z->name[0] = '\0';	//v1.55
				if ( isalpha( ArgName[0] ) && ArgName[1] == ':' && ArgName[2] == '\\') {
					z->name[0] = ArgName[0];
					z->name[1] = ArgName[1];
					z->name[2] = ArgName[2];
					z->name[3] = '\0';
				}
				lstrcat( z->name, z->zname );
				if ( pG->verbose ) printf( "%scluding %s\n", z->mark ? "in" : "ex", z->name );
				m = 0; /* we had at least one file in the archive that we marked */
			}
		}
		FREE( p );

		/* returns 1 if no "zfiles" entries were marked,
		 * 0 if at least one entry was marked
		 */
		if ( m ) {
			// diag( "returning ZEN_MISS04 from procname" );
			return ZEN_MISS04;
		}
		// diag( "returning ZEN_OK from procname" );
		return ZEN_OK;
	} /* end of "if (LSSTAT..." */

	/* Existing and good filename or directory-- add the name if it's a file, recurse if directory */
	// diag( "good entry to add, or a dir to go into" );

	/* check the status returned by LSSTAT earlier to see if 'ArgName' is a dir */
	pnError = ZEN_OK;
	if ( !(StatRes.st_mode & S_IFDIR) ) {
		/* it's not a directory - add file to found list */
		sprintf( pG->ewemsg, "spot 1: Add file %s to found list", ArgName );
		diag( pG->ewemsg, pG );
		/* newname (fileio.c) adds to found list. If error m!=0 on return */
		if ( (m = newname( ArgName, StatRes.st_size, pG )) != ZEN_OK ) {
			sprintf( pG->ewemsg, "returning %d from procname after newname call", m );
			diag( pG->ewemsg, pG );
			return m;
		}
	} else {
		/* It is a directory - Add trailing / to the directory name */
		// diag( "Spot 2, directory found" );
		if ( (p = MALLOC( lstrlen( ArgName )+ 2) ) == NULL ) return ZEN_MEM22;
		if ( !strcmp( ArgName, "." ) || !strcmp( ArgName, "\\." ) ) {		// SLASH
			*p = '\0';  /* avoid "./" prefix and do not create zip entry */
		} else {
			// diag( "spot 3" );
			lstrcpy( p, ArgName );
			a = p + lstrlen( p );
			if ( a[-1] != '\\' ) lstrcpy( a, "\\" );		// SLASH
			/* newname (fileio.c) adds to found list. If error m != 0 on return */
			if ( pG->dirnames && (m = newname( p, 0, pG )) != ZEN_OK ) {
				FREE( p );
				sprintf( pG->ewemsg, "returning %d from procname after 2nd newname call", m );
				diag( pG->ewemsg, pG );
				return m;
			}
		}

		/* recurse into directory */
		// diag( "spot 4: optional recurse into dir" );
		if ( RecurseDir && ((d = Opendir( ArgName, pG )) != NULL) ) {     /* Open new dir (like chdir) */
			// diag( "good open of dir" );
			while ( (e = readd( d, pG )) != NULL ) {
				if ( pG->global_abort_sw ) {	// RCV changed error handling
					pnError = ZEN_ABORT;
					break;
				}
				/* e is pointing to the new filename we just read from dir */
				/* ignore dir entries of . and .. */
				if ( strcmp( e, "." ) && strcmp( e, ".." ) ) {
					/* get a new tmp buffer for the path and fname */
					if ( (a = MALLOC( lstrlen( p ) + lstrlen( e ) + 1 )) == NULL ) {
						pnError = ZEN_MEM23;		/* RCV error handling changed */
						break;
					}
					/* form the new dir's pathname followed by the fname just read */
					/* (we need to send in the dir and fname, or it won't be
					 * detected as a valid file by LSSTAT)
					 */
					lstrcat( lstrcpy( a, p ), e );

					// diag( "DOING RECURSIVE CALL TO PROCNAME FROM PROCNAME" );
					if ( (m = procname( a, RecurseDir, pG )) != ZEN_OK ) {
						/* recursive call failed; return code not ZEN_OK */
						if ( m != ZEN_OK && m != ZEN_MISS05 ) {	/* unknown error; RCV error handling changed */
							pnError = m;
							FREE( a );
							break;
						} else if ( (int)(char)(m & 0xFF) == ZEN_MISS ) zipwarn( "name not matched: ", a );
					}
					FREE( a );
				}
			} /* end while */
			Closedir( d );
		} /* end if (spot 4) */
		FREE( p );
	} /* (StatRes.st_mode & S_IFDIR) == 0) */
	// diag( "returning ZEN_ class from procname" );
	return pnError;
}
Exemple #5
0
/* ===========================================================================
 * If not in exclude mode, expand the pattern based on the contents
 * of the file system.
 * This function is used while gathering filenames to be added or updated
	*w :: Path/pattern to match.
   Possible return values: ZEN_MISS, ZEN_OK, ZEN_ABORT, ZEN_MEM or ZEN_PARMS.
 */
int Wild( char *w, struct Globals *pG ) {
	zDIR *d;                   /* Stream for reading directory       */
	char *e;                   /* File or directory name found.      */
	char *n;                   /* Constructed name from directory    */
	int   WError;              /* Result of Wild()                   */
	char *p, *a;               /* path originale and fixed.          */
	char *q;                   /* Filename / pattern.                */
	int   r;                   /* Result / temp var.                 */
	char  v[5];                /* space for device current directory.*/
	bool  StopRecurs = false;  /* No recursion if filespec is file.  */

	//	sprintf( pG->ewemsg, "in Wild of win32zip.c, pattern=%s recurse=%d", w, pG->recurse );
	//	diag( pG->ewemsg, pG );

	// "zip -$ foo a:" can be used to force a drive name once. 	// v1.6017
	if ( pG->volume_label == 1 ) {
		pG->volume_label = 2;
		pG->label = getVolumeLabel( pG, (w != NULL && w[ 1 ] == ':') ? to_up( w[ 0 ] ) : '\0', &pG->label_time, &pG->label_mode, &pG->label_utim );
		if ( pG->label != NULL )
			(void)newname( pG->label, 0, pG );
		if ( w == NULL || (w[1] == ':' && w[2] == '\0') ) return ZEN_OK;
	}

	/* Allocate and copy pattern */
	if ( (p = a = MALLOC( lstrlen( w ) + 1) ) == NULL ) return ZEN_MEM19;
	lstrcpy( p, w );

	/* Separate path and name into p and q */
   // We have '\' or '\name' or 'path1\path2\name2' or 'C:\path\name' but NOT 'C:\name'
	if ( (q = strrchr( p, '\\' )) != NULL && (q == p || q[-1] != ':') ) {		// SLASH
		*q++ = '\0';
		if ( *p == '\0' ) p = lstrcpy( v, "\\." );	   /* if path is just '\' SLASH               */
	} else if ( (q = strrchr( p, ':' )) != NULL ) {	/* We have 'C:' or 'C:\' or 'C:\name' */
		*q++ = '\0';
		p = lstrcat( lstrcpy( v, p ), ":" );          /* copy device as path eg. 'C:'       */
		if ( *q == '\\' ) {                          /* -> device:/., name  eg. 'C:\.' SLASH     */
			lstrcat( p, "\\" );		// SLASH
			q++;										         /* name or nothing.                   */
		}
		lstrcat( p, "." );   						         /* eg. 'C:.' or 'C:\.'                */
	} else if ( pG->recurse && (!strcmp( p, "." ) || !strcmp( p, ".." )) ) {
		/* current or parent directory */
		/* Get "zip -r foo ." to work. Allow the dubious "zip -r foo .." but
		 * reject "zip -r -m foo ..".  "dispose" means wipe out source path.
		 */
		if ( pG->dispose && !strcmp( p, ".." ) ) ziperr( ZEN_PARMS15, pG );
		q = (char *)pG->wild_match_all;
	}
	else {  /* no path or device */
		q = p;
		p = lstrcpy( v, "." );
	}
	if ( pG->recurse && *q == '\0' ) q = (char *)pG->wild_match_all;
	/* take out a possibly redundant dir name of "." */
	if ( (r = lstrlen( p )) > 1 && (strcmp( p + r - 2, ":." ) == 0 || strcmp( p + r - 2, "\\." ) == 0) )	// SLASH
		*(p + r - 1) = '\0';

	/* Only filename (not the path) can have special matching characters */
	if ( IsShExp( p ) ) {
		diag( "path has illegal chars", pG );
		FREE( a );
		return ZEN_PARMS16;
	}
	// sprintf( ewemsg, "at break up place in Wild: path=%s  name=%s", p, q );
	// diag( ewemsg );

	if ( !IsShExp( q ) ) {	// Speed up checking if file exits in case there are no wildcards
		struct stat s;       // and no recursion and no archiving v1.6016

		if ( !pG->recurse && !pG->ArchiveFiles ) {
			if ( !LSSTAT( GetFullPath( pG, w ), &s ) )                 /* file exists ? */
				return procname( w, false, pG );
			return ZEN_MISS02;                      /* woops, no wildcards where is the file! */
		}
		if ( pG->norecursefiles ) StopRecurs = true;
	}

	/* Now that we have a dir spec, along with an fspec, we'll step
	 * in the dir specified to see if there's any matches against the fspec.
	 */
	WError = ZEN_MISS02;
	if ( (d = Opendir( p, pG )) != NULL ) {
		while ( (e = readd( d, pG )) != NULL ) {
			if ( pG->global_abort_sw ) {
				WError = ZEN_ABORT;
				break;
			}
			// sprintf( ewemsg, "Found %s: %s", d->d_attr & FILE_ATTRIBUTE_DIRECTORY ? "directory" : "file", e );
			// diag( ewemsg );
			/* if e is NOT '.' or '..', and is a dir or match fspec. */
			if ( strcmp( e, "." ) && strcmp( e, ".." ) && (d->d_attr & FILE_ATTRIBUTE_DIRECTORY || dosmatch( q, e, pG )) ) {
				// diag( "Matched" );
				/* we matched fspec or it's a dir and entry is not '.' or '..' */
				if ( d->d_attr & FILE_ATTRIBUTE_DIRECTORY ) {
					// We do not save dirs or go into dirs if norecursefiles==1 and we a file without * or ? specs.
					if ( !StopRecurs && (pG->dirnames || pG->recurse) ) {
						if ( (n = MALLOC( lstrlen( p ) + lstrlen( e ) + lstrlen( q ) + 3 )) == NULL ) {
							WError = ZEN_MEM20;
							break;
						}
						*n = '\0';
						if ( *p != '.' ) AddSlash( lstrcpy( n, p ) );	// No ./ as first dir.
						lstrcat( n, e );
						if ( pG->dirnames ) {		// Save directory names also.
							r = procname( n, false, pG );
							if ( (int)(char)(r & 0xFF) > ZEN_OK || !pG->recurse ) FREE( n );
							if ( (int)(char)(r & 0xFF) > (int)(char)(WError & 0xFF) ) WError = r;
							if ( (int)(char)(r & 0xFF) > ZEN_OK ) break;
						}
						if ( pG->recurse ) {	// Recursively go into dir and check for other pattern matches.
							r = Wild( lstrcat( AddSlash( n ), q ), pG );	// Add the original pattern.
							FREE( n );
							// We keep a ZEN_OK even when ZEN_MISS occurs.
							if ( (int)(char)(r & 0xFF) > (int)(char)(WError & 0xFF) ) WError = r;
							if ( (int)(char)(r & 0xFF) > ZEN_OK ) break;						// An error, stop processing.
						}
   		      }
				} else {
					if ( (n = MALLOC( lstrlen( p ) + lstrlen( e ) + 2 )) == NULL ) {
						WError = ZEN_MEM21;
						break;
					}
					if ( !strcmp( p, "." ) ) r = procname( e, false, pG );
					else r = procname( lstrcat( AddSlash( lstrcpy( n, p ) ), e ), false, pG );
					FREE( n );
					if ( (int)(char)(r & 0xFF) > (int)(char)(WError & 0xFF) ) WError = r;
					if ( (int)(char)(r & 0xFF) > ZEN_OK ) break;
				}
			} /* end "if (strcmp..." */
		} /* end while */
		Closedir( d );
	} else diag( "can't open dir", pG );
	FREE( a );
	// sprintf( ewemsg, "Wild returned: %d", WError );
	// diag( ewemsg );
	return WError;
}
Exemple #6
0
/* =========================================================================== select files to be processed */
int ZipSelect(struct Globals *pG, const ZCL2 *C)
{
  int i; // arg counter, root directory flag
  int k; // next argument type, marked counter,

  const char *p; // steps through option arguments
  int r; // temporary variable
  long g_before; // 1.74 global 'before'
  int argno, arg1;


  if ((p = getenv("TZ")) == NULL ||  *p == '\0')
    pG->extra_fields = 0;
  // disable storing "Unix" time stamps

  SetExclFilters(pG);
  // Process arguments
  diag("ready to read zip file", pG);

  // the read will be done in file: zipfile.c
  if ((r = readzipfile(pG)) != ZEN_OK)
  {
    diag("err returned from \"readzipfile\"", pG);
    return (ziperr(r, pG));
  }

  if (pG->action == UPDATE || pG->action == FRESHEN)
    pG->doall = 1;
  r = 0;
  arg1 =  - 1;
  g_before = pG->before;
  for (argno = 0; !r && argno < C->fTotFileSpecs; argno++)
  {
    char *fspec;
    FileData *fileArg = &C->fFDS[argno];
    if (!fileArg)
      continue;
    fspec = fileArg->fFileSpec;
    if (!fspec ||  *fspec == '>')
      continue;
    pG->FileArg = fileArg;
    pG->key = 0; //pG->user_key;   // set globals
    pG->recurse = fileArg->fRecurse;
    r = C->fLevel;
    r = r < 0 ? 0 : (r > 9 ? 9 : r);
    if (r != pG->level)
    {
      pG->level = r;
      pG->method = r ? DEFLATE : STORE;
      if (pG->verbose)
        Inform(pG, 0, IDIAG, "setting compression level to %d", r);
    }
    // Set the new RootDir if needed; DLL v1.608, Component v1.60L
    if (fileArg->fRootDir)
    {
      // We can't use SetCurrentDirectory() because there is only one cd
      // in each process
      // when a user uses threads it went wrong.
      FREE(pG->OrigCurrentDir); // DLL v1.6017

      pG->OCDlength = lstrlen(fileArg->fRootDir);
      if ((pG->OrigCurrentDir = (char*)MALLOC(pG->OCDlength + 2)) == NULL)
      {
        // RP allow space for '\'
        Inform(pG, ZEN_MEM36, 0, "CurrentDir allocation error");

        return ziperr(ZEN_MEM36, pG);
      }

      lstrcpy(pG->OrigCurrentDir, fileArg->fRootDir);
      if (pG->verbose)
        Inform(pG, 0, IERROR, "Root dir now %s", pG->OrigCurrentDir);
    }
    if (C->fVersion > 178)
    {
      if (fileArg->fLevel)
      {
        r = fileArg->fLevel;
        r = r < 0 ? 0 : (r > 9 ? 9 : r);
        if (r != pG->level)
        {
          pG->level = r;
          pG->method = r ? DEFLATE : STORE;
          if (pG->verbose)
            Inform(pG, 0, IDIAG, "setting compression level to %d", r);
        }
      }
      if (fileArg->fFromDate)
        pG->before = fileArg->fFromDate == (unsigned) - 1 ? 0 : fileArg
          ->fFromDate;
      else
        pG->before = g_before;
    }

    #ifdef USE_STRM_INPUT
      if (arg1 < 0)
      {
        arg1 = argno;
        if (pG->UseInStream)
        {
          // Here we fill in the FoundList from the input stream data
          // newname (fileio.c) adds to found list. If error m!=0 on return
          if ((r = newname(fspec, pG->InStreamSize, pG)) != ZEN_OK)
          {
            if (pG->verbose)
              Inform(pG, 0, IDIAG,
                "Stream filename could not be added in newname call");

            if (pG->zcount)
              FREE(pG->zsort);
            return r;
          }
          break;
        }
      }
    #endif
    #ifdef CRYPT
      if (fileArg->fEncrypt)
      {
        pG->key = fileArg->fPassword;
        if (!pG->key || !*(pG->key))
        {
          // use global
          if ((r = GetUserPW(pG)) != ZEN_OK)
            break;
          pG->key = pG->user_key;
        }
        //       pG->doesEncrypt = 1;			// 1.73
      }
    #endif
    pG->doall = 0; // do selected
    if ((pG->action == ADD) || (pG->action == UPDATE))
    {
      if (pG->verbose)
        Inform(pG, 0, IDIAG, "collecting %s %s", fspec, pG->recurse ? "recurse"
          : " ");
      r = Wild(fspec, pG);
    }
    else
    // Freshen or Delete - must be internal file
    {
      if (pG->verbose)
        Inform(pG, 0, IDIAG, "collecting %s %s", fspec, pG->recurse ? "recurse"
          : " ");
      r = procname(fspec, pG->recurse, pG);
    }
    if (r != ZEN_OK)
    {
      if ((int)(char)(r &0xFF) == ZEN_MISS)
      {
        /* this occurs if new file wasn't found */
        Inform(pG, r, IERROR, "File specification \"%s\" skipped", fspec);
        r = 0;
      }
    }
    if (r)
      return ziperr(r, pG);
  }
  return 0;
}