Exemplo n.º 1
0
int
main(int argc, char *argv[])
{
	static struct option long_options[] = {
		{"pgdata", required_argument, NULL, 'D'},
		{"verbose", no_argument, NULL, 'v'},
		{NULL, 0, NULL, 0}
	};

	char	   *DataDir = NULL;
	int			c;
	int			option_index;
	bool		crc_ok;

	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_checksums"));

	progname = get_progname(argv[0]);

	if (argc > 1)
	{
		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
		{
			usage();
			exit(0);
		}
		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
		{
			puts("pg_checksums (PostgreSQL) " PG_VERSION);
			exit(0);
		}
	}

	while ((c = getopt_long(argc, argv, "D:r:v", long_options, &option_index)) != -1)
	{
		switch (c)
		{
			case 'v':
				verbose = true;
				break;
			case 'D':
				DataDir = optarg;
				break;
			case 'r':
				if (atoi(optarg) == 0)
				{
					fprintf(stderr, _("%s: invalid relfilenode specification, must be numeric: %s\n"), progname, optarg);
					exit(1);
				}
				only_relfilenode = pstrdup(optarg);
				break;
			default:
				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
				exit(1);
		}
	}

	if (DataDir == NULL)
	{
		if (optind < argc)
			DataDir = argv[optind++];
		else
			DataDir = getenv("PGDATA");

		/* If no DataDir was specified, and none could be found, error out */
		if (DataDir == NULL)
		{
			fprintf(stderr, _("%s: no data directory specified\n"), progname);
			fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
			exit(1);
		}
	}

	/* Complain if any arguments remain */
	if (optind < argc)
	{
		fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
				progname, argv[optind]);
		fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
				progname);
		exit(1);
	}

	/* Check if cluster is running */
	ControlFile = get_controlfile(DataDir, progname, &crc_ok);
	if (!crc_ok)
	{
		fprintf(stderr, _("%s: pg_control CRC value is incorrect\n"), progname);
		exit(1);
	}

	if (ControlFile->pg_control_version != PG_CONTROL_VERSION)
	{
		fprintf(stderr, _("%s: cluster is not compatible with this version of pg_checksums\n"),
				progname);
		exit(1);
	}

	if (ControlFile->state != DB_SHUTDOWNED &&
		ControlFile->state != DB_SHUTDOWNED_IN_RECOVERY)
	{
		fprintf(stderr, _("%s: cluster must be shut down to verify checksums\n"), progname);
		exit(1);
	}

	if (ControlFile->data_checksum_version == 0)
	{
		fprintf(stderr, _("%s: data checksums are not enabled in cluster\n"), progname);
		exit(1);
	}

	/* Scan all files */
	scan_directory(DataDir, "global");
	scan_directory(DataDir, "base");
	scan_directory(DataDir, "pg_tblspc");

	printf(_("Checksum scan completed\n"));
	printf(_("Data checksum version: %d\n"), ControlFile->data_checksum_version);
	printf(_("Files scanned:  %s\n"), psprintf(INT64_FORMAT, files));
	printf(_("Blocks scanned: %s\n"), psprintf(INT64_FORMAT, blocks));
	printf(_("Bad checksums:  %s\n"), psprintf(INT64_FORMAT, badblocks));

	if (badblocks > 0)
		return 1;

	return 0;
}
Exemplo n.º 2
0
/*
 * Show oid, filenode, name, schema and tablespace for each of the
 * given objects in the current database.
 */
void
sql_exec_searchtables(PGconn *conn, struct options * opts)
{
	char	   *todo;
	char	   *qualifiers,
			   *ptr;
	char	   *comma_oids,
			   *comma_filenodes,
			   *comma_tables;
	bool		written = false;
	char	   *addfields = ",c.oid AS \"Oid\", nspname AS \"Schema\", spcname as \"Tablespace\" ";

	/* get tables qualifiers, whether names, filenodes, or OIDs */
	comma_oids = get_comma_elts(opts->oids);
	comma_tables = get_comma_elts(opts->tables);
	comma_filenodes = get_comma_elts(opts->filenodes);

	/* 80 extra chars for SQL expression */
	qualifiers = (char *) pg_malloc(strlen(comma_oids) + strlen(comma_tables) +
									strlen(comma_filenodes) + 80);
	ptr = qualifiers;

	if (opts->oids->num > 0)
	{
		ptr += sprintf(ptr, "c.oid IN (%s)", comma_oids);
		written = true;
	}
	if (opts->filenodes->num > 0)
	{
		if (written)
			ptr += sprintf(ptr, " OR ");
		ptr += sprintf(ptr, "pg_catalog.pg_relation_filenode(c.oid) IN (%s)", comma_filenodes);
		written = true;
	}
	if (opts->tables->num > 0)
	{
		if (written)
			ptr += sprintf(ptr, " OR ");
		sprintf(ptr, "c.relname ~~ ANY (ARRAY[%s])", comma_tables);
	}
	free(comma_oids);
	free(comma_tables);
	free(comma_filenodes);

	/* now build the query */
	todo = psprintf(
					"SELECT pg_catalog.pg_relation_filenode(c.oid) as \"Filenode\", relname as \"Table Name\" %s\n"
					"FROM pg_catalog.pg_class c \n"
		"	LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace \n"
					"	LEFT JOIN pg_catalog.pg_database d ON d.datname = pg_catalog.current_database(),\n"
					"	pg_catalog.pg_tablespace t \n"
					"WHERE relkind IN ('r', 'm', 'i', 'S', 't') AND \n"
					"		t.oid = CASE\n"
			"			WHEN reltablespace <> 0 THEN reltablespace\n"
					"			ELSE dattablespace\n"
					"		END AND \n"
					"  (%s) \n"
					"ORDER BY relname\n",
					opts->extended ? addfields : "",
					qualifiers);

	free(qualifiers);

	sql_exec(conn, todo, opts->quiet);
}
Exemplo n.º 3
0
Datum
pg_tablespace_databases(PG_FUNCTION_ARGS)
{
	FuncCallContext *funcctx;
	struct dirent *de;
	ts_db_fctx *fctx;

	if (SRF_IS_FIRSTCALL())
	{
		MemoryContext oldcontext;
		Oid			tablespaceOid = PG_GETARG_OID(0);

		funcctx = SRF_FIRSTCALL_INIT();
		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

		fctx = palloc(sizeof(ts_db_fctx));

		if (tablespaceOid == GLOBALTABLESPACE_OID)
		{
			fctx->dirdesc = NULL;
			ereport(WARNING,
					(errmsg("global tablespace never has databases")));
		}
		else
		{
			if (tablespaceOid == DEFAULTTABLESPACE_OID)
				fctx->location = psprintf("base");
			else
				fctx->location = psprintf("pg_tblspc/%u/%s", tablespaceOid,
										  TABLESPACE_VERSION_DIRECTORY);

			fctx->dirdesc = AllocateDir(fctx->location);

			if (!fctx->dirdesc)
			{
				/* the only expected error is ENOENT */
				if (errno != ENOENT)
					ereport(ERROR,
							(errcode_for_file_access(),
							 errmsg("could not open directory \"%s\": %m",
									fctx->location)));
				ereport(WARNING,
						(errmsg("%u is not a tablespace OID", tablespaceOid)));
			}
		}
		funcctx->user_fctx = fctx;
		MemoryContextSwitchTo(oldcontext);
	}

	funcctx = SRF_PERCALL_SETUP();
	fctx = (ts_db_fctx *) funcctx->user_fctx;

	if (!fctx->dirdesc)			/* not a tablespace */
		SRF_RETURN_DONE(funcctx);

	while ((de = ReadDir(fctx->dirdesc, fctx->location)) != NULL)
	{
		Oid			datOid = atooid(de->d_name);
		char	   *subdir;
		bool		isempty;

		/* this test skips . and .., but is awfully weak */
		if (!datOid)
			continue;

		/* if database subdir is empty, don't report tablespace as used */

		subdir = psprintf("%s/%s", fctx->location, de->d_name);
		isempty = directory_is_empty(subdir);
		pfree(subdir);

		if (isempty)
			continue;			/* indeed, nothing in it */

		SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(datOid));
	}

	FreeDir(fctx->dirdesc);
	SRF_RETURN_DONE(funcctx);
}
Exemplo n.º 4
0
/*
 * pg_be_scram_init
 *
 * Initialize a new SCRAM authentication exchange status tracker.  This
 * needs to be called before doing any exchange.  It will be filled later
 * after the beginning of the exchange with verifier data.
 *
 * 'selected_mech' identifies the SASL mechanism that the client selected.
 * It should be one of the mechanisms that we support, as returned by
 * pg_be_scram_get_mechanisms().
 *
 * 'shadow_pass' is the role's password verifier, from pg_authid.rolpassword.
 * The username was provided by the client in the startup message, and is
 * available in port->user_name.  If 'shadow_pass' is NULL, we still perform
 * an authentication exchange, but it will fail, as if an incorrect password
 * was given.
 */
void *
pg_be_scram_init(Port *port,
				 const char *selected_mech,
				 const char *shadow_pass)
{
	scram_state *state;
	bool		got_verifier;

	state = (scram_state *) palloc0(sizeof(scram_state));
	state->port = port;
	state->state = SCRAM_AUTH_INIT;

	/*
	 * Parse the selected mechanism.
	 *
	 * Note that if we don't support channel binding, either because the SSL
	 * implementation doesn't support it or we're not using SSL at all, we
	 * would not have advertised the PLUS variant in the first place.  If the
	 * client nevertheless tries to select it, it's a protocol violation like
	 * selecting any other SASL mechanism we don't support.
	 */
#ifdef HAVE_BE_TLS_GET_CERTIFICATE_HASH
	if (strcmp(selected_mech, SCRAM_SHA_256_PLUS_NAME) == 0 && port->ssl_in_use)
		state->channel_binding_in_use = true;
	else
#endif
	if (strcmp(selected_mech, SCRAM_SHA_256_NAME) == 0)
		state->channel_binding_in_use = false;
	else
		ereport(ERROR,
				(errcode(ERRCODE_PROTOCOL_VIOLATION),
				 errmsg("client selected an invalid SASL authentication mechanism")));

	/*
	 * Parse the stored password verifier.
	 */
	if (shadow_pass)
	{
		int			password_type = get_password_type(shadow_pass);

		if (password_type == PASSWORD_TYPE_SCRAM_SHA_256)
		{
			if (parse_scram_verifier(shadow_pass, &state->iterations, &state->salt,
									 state->StoredKey, state->ServerKey))
				got_verifier = true;
			else
			{
				/*
				 * The password looked like a SCRAM verifier, but could not be
				 * parsed.
				 */
				ereport(LOG,
						(errmsg("invalid SCRAM verifier for user \"%s\"",
								state->port->user_name)));
				got_verifier = false;
			}
		}
		else
		{
			/*
			 * The user doesn't have SCRAM verifier. (You cannot do SCRAM
			 * authentication with an MD5 hash.)
			 */
			state->logdetail = psprintf(_("User \"%s\" does not have a valid SCRAM verifier."),
										state->port->user_name);
			got_verifier = false;
		}
	}
	else
	{
		/*
		 * The caller requested us to perform a dummy authentication.  This is
		 * considered normal, since the caller requested it, so don't set log
		 * detail.
		 */
		got_verifier = false;
	}

	/*
	 * If the user did not have a valid SCRAM verifier, we still go through
	 * the motions with a mock one, and fail as if the client supplied an
	 * incorrect password.  This is to avoid revealing information to an
	 * attacker.
	 */
	if (!got_verifier)
	{
		mock_scram_verifier(state->port->user_name, &state->iterations,
							&state->salt, state->StoredKey, state->ServerKey);
		state->doomed = true;
	}

	return state;
}
Exemplo n.º 5
0
PDir::PDir(const pchar *dir)
{
    // Check if the directory exists.
    struct stat s;
    if (stat(dir, &s) != 0 || !S_ISDIR(s.st_mode))
    {
        PLOG_ERROR("%s is not a valid directory.", dir);
        m_exists =  false;
    }
    else
    {
        m_exists = true;
    
        // Fetch the item names in that directory.
        DIR* dirObject;
        dirent* dirEntry;

        m_items = P_NULL;
        m_numberOfItems = 0;

        puint32 capacity = 32;
        puint8* itemData = PNEWARRAY(puint8, capacity * sizeof(PDirItem));
        pmemset(itemData, 0, sizeof(capacity * sizeof(PDirItem)));

        if ((dirObject = opendir(dir)) == NULL)
        {
            PLOG_ERROR("Failed to read directory %s.", dir);
            PDELETEARRAY(itemData);
        }
        else
        {
            char path[4096];
            while ((dirEntry = readdir(dirObject)) != NULL)
            {
                // Find first file will always return "." and ".." 
                // as the first two directories.
                if (pstrcmp(dirEntry->d_name, ".") != 0 && 
                    pstrcmp(dirEntry->d_name, "..") != 0)
                {
                    //Build up our file path using the passed in
                    //  [sDir] and the file/foldername we just found:
                    psprintf(path, 4096, "%s\\%s", dir, dirEntry->d_name);

                    //Is the entity a File or Folder?
                    if (dirEntry->d_type == DT_DIR)
                    {
                        // TODO: use the absolute path.
                        new (itemData + m_numberOfItems * sizeof(PDirItem)) PDirItem(P_DIR_ITEM_DIRECTORY, path);
                        m_numberOfItems++;
                    }
                    else if (dirEntry->d_type == DT_REG)
                    {
                        // TODO: use the absolute path.
                        new (itemData + m_numberOfItems * sizeof(PDirItem)) PDirItem(P_DIR_ITEM_FILE, path);
                        m_numberOfItems++;
                    }
                    else
                    {
                        PLOG_WARNING("%s is not supported.", path);
                    }

                    if (m_numberOfItems > capacity)
                    {
                        resizeItemArray(itemData, capacity, 2 * capacity);
                        capacity *= 2;
                    }
                }
            }

            closedir(dirObject); //Always, Always, clean things up!
        
            m_items = reinterpret_cast<PDirItem*>(itemData);
        }
    }
}
/*
 * Our caller already sent the query associated with this step.  Wait for it
 * to either complete or (if given the STEP_NONBLOCK flag) to block while
 * waiting for a lock.  We assume that any lock wait will persist until we
 * have executed additional steps in the permutation.
 *
 * When calling this function on behalf of a given step for a second or later
 * time, pass the STEP_RETRY flag.  This only affects the messages printed.
 *
 * If the connection returns an error, the message is saved in step->errormsg.
 * Caller should call report_error_message shortly after this, to have it
 * printed and cleared.
 *
 * If the STEP_NONBLOCK flag was specified and the query is waiting to acquire
 * a lock, returns true.  Otherwise, returns false.
 */
static bool
try_complete_step(Step *step, int flags)
{
	PGconn	   *conn = conns[1 + step->session];
	fd_set		read_set;
	struct timeval timeout;
	int			sock = PQsocket(conn);
	int			ret;
	PGresult   *res;

	FD_ZERO(&read_set);

	while ((flags & STEP_NONBLOCK) && PQisBusy(conn))
	{
		FD_SET(sock, &read_set);
		timeout.tv_sec = 0;
		timeout.tv_usec = 10000;	/* Check for lock waits every 10ms. */

		ret = select(sock + 1, &read_set, NULL, NULL, &timeout);
		if (ret < 0)			/* error in select() */
		{
			if (errno == EINTR)
				continue;
			fprintf(stderr, "select failed: %s\n", strerror(errno));
			exit_nicely();
		}
		else if (ret == 0)		/* select() timeout: check for lock wait */
		{
			int			ntuples;

			res = PQexecPrepared(conns[0], PREP_WAITING, 1,
								 &backend_pids[step->session + 1],
								 NULL, NULL, 0);
			if (PQresultStatus(res) != PGRES_TUPLES_OK)
			{
				fprintf(stderr, "lock wait query failed: %s",
						PQerrorMessage(conn));
				exit_nicely();
			}
			ntuples = PQntuples(res);
			PQclear(res);

			if (ntuples >= 1)	/* waiting to acquire a lock */
			{
				if (!(flags & STEP_RETRY))
					printf("step %s: %s <waiting ...>\n",
						   step->name, step->sql);
				return true;
			}
			/* else, not waiting: give it more time */
		}
		else if (!PQconsumeInput(conn)) /* select(): data available */
		{
			fprintf(stderr, "PQconsumeInput failed: %s\n",
					PQerrorMessage(conn));
			exit_nicely();
		}
	}

	if (flags & STEP_RETRY)
		printf("step %s: <... completed>\n", step->name);
	else
		printf("step %s: %s\n", step->name, step->sql);

	while ((res = PQgetResult(conn)))
	{
		switch (PQresultStatus(res))
		{
			case PGRES_COMMAND_OK:
				break;
			case PGRES_TUPLES_OK:
				printResultSet(res);
				break;
			case PGRES_FATAL_ERROR:
				if (step->errormsg != NULL)
				{
					printf("WARNING: this step had a leftover error message\n");
					printf("%s\n", step->errormsg);
				}

				/*
				 * Detail may contain XID values, so we want to just show
				 * primary.  Beware however that libpq-generated error results
				 * may not contain subfields, only an old-style message.
				 */
				{
					const char *sev = PQresultErrorField(res,
														 PG_DIAG_SEVERITY);
					const char *msg = PQresultErrorField(res,
													PG_DIAG_MESSAGE_PRIMARY);

					if (sev && msg)
						step->errormsg = psprintf("%s:  %s", sev, msg);
					else
						step->errormsg = pg_strdup(PQresultErrorMessage(res));
				}
				break;
			default:
				printf("unexpected result status: %s\n",
					   PQresStatus(PQresultStatus(res)));
		}
		PQclear(res);
	}

	return false;
}
Exemplo n.º 7
0
/*
 * Actually do a base backup for the specified tablespaces.
 *
 * This is split out mainly to avoid complaints about "variable might be
 * clobbered by longjmp" from stupider versions of gcc.
 */
static void
perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
{
	XLogRecPtr	startptr;
	TimeLineID	starttli;
	XLogRecPtr	endptr;
	TimeLineID	endtli;
	char	   *labelfile;
	int			datadirpathlen;

	datadirpathlen = strlen(DataDir);

	backup_started_in_recovery = RecoveryInProgress();

	startptr = do_pg_start_backup(opt->label, opt->fastcheckpoint, &starttli,
								  &labelfile);
	/*
	 * Once do_pg_start_backup has been called, ensure that any failure causes
	 * us to abort the backup so we don't "leak" a backup counter. For this reason,
	 * *all* functionality between do_pg_start_backup() and do_pg_stop_backup()
	 * should be inside the error cleanup block!
	 */

	PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
	{
		List	   *tablespaces = NIL;
		ListCell   *lc;
		struct dirent *de;
		tablespaceinfo *ti;

		SendXlogRecPtrResult(startptr, starttli);

		/*
		 * Calculate the relative path of temporary statistics directory in order
		 * to skip the files which are located in that directory later.
		 */
		if (is_absolute_path(pgstat_stat_directory) &&
			strncmp(pgstat_stat_directory, DataDir, datadirpathlen) == 0)
			statrelpath = psprintf("./%s", pgstat_stat_directory + datadirpathlen + 1);
		else if (strncmp(pgstat_stat_directory, "./", 2) != 0)
			statrelpath = psprintf("./%s", pgstat_stat_directory);
		else
			statrelpath = pgstat_stat_directory;

		/* Collect information about all tablespaces */
		while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL)
		{
			char		fullpath[MAXPGPATH];
			char		linkpath[MAXPGPATH];
			char	   *relpath = NULL;
			int			rllen;

			/* Skip special stuff */
			if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
				continue;

			snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);

#if defined(HAVE_READLINK) || defined(WIN32)
			rllen = readlink(fullpath, linkpath, sizeof(linkpath));
			if (rllen < 0)
			{
				ereport(WARNING,
						(errmsg("could not read symbolic link \"%s\": %m",
								fullpath)));
				continue;
			}
			else if (rllen >= sizeof(linkpath))
			{
				ereport(WARNING,
						(errmsg("symbolic link \"%s\" target is too long",
								fullpath)));
				continue;
			}
			linkpath[rllen] = '\0';

			/*
			 * Relpath holds the relative path of the tablespace directory
			 * when it's located within PGDATA, or NULL if it's located
			 * elsewhere.
			 */
			if (rllen > datadirpathlen &&
				strncmp(linkpath, DataDir, datadirpathlen) == 0 &&
				IS_DIR_SEP(linkpath[datadirpathlen]))
				relpath = linkpath + datadirpathlen + 1;

			ti = palloc(sizeof(tablespaceinfo));
			ti->oid = pstrdup(de->d_name);
			ti->path = pstrdup(linkpath);
			ti->rpath = relpath ? pstrdup(relpath) : NULL;
			ti->size = opt->progress ? sendTablespace(fullpath, true) : -1;
			tablespaces = lappend(tablespaces, ti);
#else

			/*
			 * If the platform does not have symbolic links, it should not be
			 * possible to have tablespaces - clearly somebody else created
			 * them. Warn about it and ignore.
			 */
			ereport(WARNING,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				  errmsg("tablespaces are not supported on this platform")));
#endif
		}

		/* Add a node for the base directory at the end */
		ti = palloc0(sizeof(tablespaceinfo));
		ti->size = opt->progress ? sendDir(".", 1, true, tablespaces) : -1;
		tablespaces = lappend(tablespaces, ti);

		/* Send tablespace header */
		SendBackupHeader(tablespaces);

		/* Setup and activate network throttling, if client requested it */
		if (opt->maxrate > 0)
		{
			throttling_sample =
				(int64) opt->maxrate * (int64) 1024 / THROTTLING_FREQUENCY;

			/*
			 * The minimum amount of time for throttling_sample bytes to be
			 * transfered.
			 */
			elapsed_min_unit = USECS_PER_SEC / THROTTLING_FREQUENCY;

			/* Enable throttling. */
			throttling_counter = 0;

			/* The 'real data' starts now (header was ignored). */
			throttled_last = GetCurrentIntegerTimestamp();
		}
		else
		{
			/* Disable throttling. */
			throttling_counter = -1;
		}

		/* Send off our tablespaces one by one */
		foreach(lc, tablespaces)
		{
			tablespaceinfo *ti = (tablespaceinfo *) lfirst(lc);
			StringInfoData buf;

			/* Send CopyOutResponse message */
			pq_beginmessage(&buf, 'H');
			pq_sendbyte(&buf, 0);		/* overall format */
			pq_sendint(&buf, 0, 2);		/* natts */
			pq_endmessage(&buf);

			if (ti->path == NULL)
			{
				struct stat statbuf;

				/* In the main tar, include the backup_label first... */
				sendFileWithContent(BACKUP_LABEL_FILE, labelfile);

				/* ... then the bulk of the files ... */
				sendDir(".", 1, false, tablespaces);

				/* ... and pg_control after everything else. */
				if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0)
					ereport(ERROR,
							(errcode_for_file_access(),
							 errmsg("could not stat control file \"%s\": %m",
									XLOG_CONTROL_FILE)));
				sendFile(XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf, false);
			}
			else
				sendTablespace(ti->path, false);

			/*
			 * If we're including WAL, and this is the main data directory we
			 * don't terminate the tar stream here. Instead, we will append
			 * the xlog files below and terminate it then. This is safe since
			 * the main data directory is always sent *last*.
			 */
			if (opt->includewal && ti->path == NULL)
			{
				Assert(lnext(lc) == NULL);
			}
			else
				pq_putemptymessage('c');		/* CopyDone */
		}
	}
Exemplo n.º 8
0
void CMyPhoneEndPoint::LoadCapabilities()
{

 BOOL sizeChange = FALSE;

 capabilities.RemoveAll();
	
// Add the codecs we know about
 AddAllCapabilities(0, 0, "*"); 

// Удаляю не поддерживаемые видео кодеки из реестра
 PINDEX videoNum = 0;
 for (;;)
 {
  PString key = psprintf("%u", ++videoNum);
  PString name = config.GetString(VideoCodecsConfigSection, key, "");
  if (name.IsEmpty()) break;

  PINDEX suffixPos = name.Find(OnCodecSuffix);
  if (suffixPos != P_MAX_INDEX) 
   name.Delete(suffixPos, P_MAX_INDEX);
  else 
  {
   suffixPos = name.Find(OffCodecSuffix);
   name.Delete(suffixPos, P_MAX_INDEX);
  }

  int res = 0;
  for (PINDEX i = 0; i < capabilities.GetSize(); i++)
  {
   if (capabilities[i].GetMainType() == H323Capability::e_Video)
   {
    if(capabilities[i].GetFormatName() == name)
     { res = 1; break; }
   }
  }
  if(res == 0) 
  {
   PINDEX j = videoNum; videoNum--;
   for (;;)
   {
    PString key1 = psprintf("%u", ++j);
    PString name1 = config.GetString(VideoCodecsConfigSection, key1, "");
    if (name1.IsEmpty()) break;

    config.SetString(VideoCodecsConfigSection, psprintf("%u", j-2), name1);
   }
   config.DeleteKey(VideoCodecsConfigSection, psprintf("%u", j-1));
  }
 }

// добавляю новые видео кодеки если их нет в конфигурации
 for (PINDEX i = 0; i < capabilities.GetSize(); i++)
 {
  if (capabilities[i].GetMainType() == H323Capability::e_Video)
  {
   PINDEX codecNum=0;
   int res = 0;
   int suffix = 0;
   for (;;)
   {
    PString key = psprintf("%u", ++codecNum);
    PString name = config.GetString(VideoCodecsConfigSection, key, "");
    if (name.IsEmpty()) break;   

    suffix = 0;
    PINDEX suffixPos = name.Find(OnCodecSuffix);
    if (suffixPos != P_MAX_INDEX)
     name.Delete(suffixPos, P_MAX_INDEX);
    else
    {
     suffix = 1;
     suffixPos = name.Find(OffCodecSuffix);
     name.Delete(suffixPos, P_MAX_INDEX);
    }
  
    if(capabilities[i].GetFormatName() == name) { res = 1; break; }
   }
   if(res == 0)
   {
    config.SetString(VideoCodecsConfigSection,
        psprintf("%u", codecNum),
        capabilities[i].GetFormatName() + ((suffix==0)?OnCodecSuffix:OffCodecSuffix));
   }
  }
 }

 PINDEX audioNum = 0;
 for (;;)
 {
  PString key = psprintf("%u", ++audioNum);
  PString name = config.GetString(CodecsConfigSection, key, "");
  if (name.IsEmpty()) break;

  PINDEX suffixPos = name.Find(OnCodecSuffix);
  if (suffixPos != P_MAX_INDEX) 
   name.Delete(suffixPos, P_MAX_INDEX);
  else 
  {
   suffixPos = name.Find(OffCodecSuffix);
   name.Delete(suffixPos, P_MAX_INDEX);
  }

  int res = 0;
  for (PINDEX i = 0; i < capabilities.GetSize(); i++)
  {
   if (capabilities[i].GetMainType() == H323Capability::e_Audio)
   {
    if(capabilities[i].GetFormatName() == name)
     { res = 1; break; }
   }
  }
  if(res == 0) 
  {
   PINDEX j = audioNum; audioNum--;
   for (;;)
   {
    PString key1 = psprintf("%u", ++j);
    PString name1 = config.GetString(CodecsConfigSection, key1, "");
    if (name1.IsEmpty()) break;

    config.SetString(CodecsConfigSection, psprintf("%u", j-2), name1);
   }
   config.DeleteKey(CodecsConfigSection, psprintf("%u", j-1));
  }
 }

 for (PINDEX i = 0; i < capabilities.GetSize(); i++)
 {
  if (capabilities[i].GetMainType() == H323Capability::e_Audio)
  {
   PINDEX codecNum=0;
   int res = 0;
   int suffix = 0;
   for (;;)
   {
    PString key = psprintf("%u", ++codecNum);
    PString name = config.GetString(CodecsConfigSection, key, "");
    if (name.IsEmpty()) break;   

    suffix = 0;
    PINDEX suffixPos = name.Find(OnCodecSuffix);
    if (suffixPos != P_MAX_INDEX)
     name.Delete(suffixPos, P_MAX_INDEX);
    else
    {
     suffix = 1;
     suffixPos = name.Find(OffCodecSuffix);
     name.Delete(suffixPos, P_MAX_INDEX);
    }
  
    if(capabilities[i].GetFormatName() == name) { res = 1; break; }
   }
   if(res == 0)
   {
    config.SetString(CodecsConfigSection,
        psprintf("%u", codecNum),
        capabilities[i].GetFormatName() + ((suffix==0)?OnCodecSuffix:OffCodecSuffix));
   }
  }
 }

// Add all the UserInput capabilities
 AddAllUserInputCapabilities(0, 1);

 int videoSizeRx = config.GetInteger(VideoInSizeConfigKey, 2);
 int videoSizeTx = config.GetInteger(VideoOutSizeConfigKey, 2);

 RemoveCapability(H323Capability::e_ExtendVideo);

 autoStartTransmitVideo = config.GetBoolean(AutoTransmitVideoConfigKey, TRUE);
 autoStartReceiveVideo = config.GetBoolean(AutoReceiveVideoConfigKey, TRUE);
	
 localVideo = config.GetBoolean(VideoLocalConfigKey, FALSE);
 localFlip = config.GetBoolean(VideoFlipLocalConfigKey, FALSE);
	
 int videoInMaxBitRate = config.GetInteger(VideoInMaxbandWidthKey, 320);
 videoInMaxBitRate = 1024 * PMAX(16, PMIN(10240, videoInMaxBitRate));

// changing audio codecs
 PStringArray enabledCodecs;
 PINDEX codecNum = 0;
 for (;;) 
 {
  PString key = psprintf("%u", ++codecNum);
  PString name = config.GetString(CodecsConfigSection, key, "");
  if (name.IsEmpty()) break;
		
  PINDEX suffixPos = name.Find(OffCodecSuffix);
  if (suffixPos != P_MAX_INDEX) 
  {
   capabilities.Remove(name(0, suffixPos-1));
   continue;
  }
		
  suffixPos = name.Find(OnCodecSuffix);
  if (suffixPos != P_MAX_INDEX)	name.Delete(suffixPos, P_MAX_INDEX);
  enabledCodecs.AppendString(name);
 }

 codecNum = 0;
 for (;;) 
 {
  PString key = psprintf("%u", ++codecNum);
  PString name = config.GetString(VideoCodecsConfigSection, key, "");
  if (name.IsEmpty()) break;
 }

 int tvNum = 0;
// if(tvCaps==NULL)  this generates error in free
 tvCaps = (char **)calloc(codecNum+1,sizeof(char *));
// while(tvCaps[tvNum]!=NULL) { free(tvCaps[tvNum]); tvCaps[tvNum]=NULL; tvNum++; }

 tvNum = 0;
 codecNum = 0;
 for (;;) 
 {
  PString key = psprintf("%u", ++codecNum);
  PString name = config.GetString(VideoCodecsConfigSection, key, "");
  if (name.IsEmpty()) break;

// удаление отключенных кодеков		
  PINDEX suffixPos = name.Find(OffCodecSuffix);
  if (suffixPos != P_MAX_INDEX) 
  {
   capabilities.Remove(name(0, suffixPos-1)); continue;
  }
// удаление суффикса on из имени кодека
  suffixPos = name.Find(OnCodecSuffix);
  if (suffixPos != P_MAX_INDEX)	name.Delete(suffixPos, P_MAX_INDEX);

// проверка кодека на соответствие размеру принимаемой картинки
// (меньше можно, больше нельзя) и удаление из списка локальных кодеков
  suffixPos = P_MAX_INDEX;
  switch(videoSizeRx)
  {
   case 0: //QCIF
    suffixPos = name.Find("-CIF");   if(suffixPos != P_MAX_INDEX) break;
   case 1: //QVGA
   case 2: //CIF
    suffixPos = name.Find("-4CIF");  if(suffixPos != P_MAX_INDEX) break;
    suffixPos = name.Find("-480P");    if(suffixPos != P_MAX_INDEX) break;
   case 3: //VGA
   case 4: //4CIF
    suffixPos = name.Find("-SD");    if(suffixPos != P_MAX_INDEX) break;
   case 5: //SVGA
    suffixPos = name.Find("-720P");    if(suffixPos != P_MAX_INDEX) break;
   case 6: //XVGA
    suffixPos = name.Find("-HD");    if(suffixPos != P_MAX_INDEX) break;
    suffixPos = name.Find("-16CIF"); if(suffixPos != P_MAX_INDEX) break;
   case 7: //SXGA
    suffixPos = name.Find("-FHD"); if(suffixPos != P_MAX_INDEX) break;
    suffixPos = name.Find("-16CIF"); if(suffixPos != P_MAX_INDEX) break;
    suffixPos = name.Find("-1080P"); if(suffixPos != P_MAX_INDEX) break;
   case 8: //16CIF
   default:
    break;
  }
  if(suffixPos == P_MAX_INDEX) enabledCodecs.AppendString(name);
  else capabilities.Remove(name);

// проверка кодека на соответствие размеру отправляемой картинки
// (меньше можно, больше нельзя) и создание списка допустимых кодеков
  suffixPos = P_MAX_INDEX;
  switch(videoSizeTx)
  {
   case 0: //QCIF
    suffixPos = name.Find("-CIF");   if(suffixPos != P_MAX_INDEX) break;
   case 1: //QVGA
   case 2: //CIF
    suffixPos = name.Find("-4CIF");  if(suffixPos != P_MAX_INDEX) break;
    suffixPos = name.Find("-480P");    if(suffixPos != P_MAX_INDEX) break;
   case 3: //VGA
   case 4: //4CIF
    suffixPos = name.Find("-SD");    if(suffixPos != P_MAX_INDEX) break;
   case 5: //SVGA
   case 6: //XVGA
    suffixPos = name.Find("-HD");    if(suffixPos != P_MAX_INDEX) break;
   case 7: //HD 720
    suffixPos = name.Find("-720P");    if(suffixPos != P_MAX_INDEX) break;
   case 8: //SXGA
    suffixPos = name.Find("-16CIF"); if(suffixPos != P_MAX_INDEX) break;
    suffixPos = name.Find("-FHD"); if(suffixPos != P_MAX_INDEX) break;
    suffixPos = name.Find("-1080P"); if(suffixPos != P_MAX_INDEX) break;
   case 9: //16CIF
   default:
    break;
  }
  if(suffixPos == P_MAX_INDEX) // добавляю в список допустимых
  {
   const char *p2pstr=name;
   tvCaps[tvNum]=strdup(p2pstr);
   tvNum++;
  }
 }

// Reorder the codecs we have
 capabilities.Reorder(enabledCodecs);

 for (PINDEX i = 0; i < capabilities.GetSize(); i++) 
 {
  if (capabilities[i].GetMainType() == H323Capability::e_Video)
  {
   capabilities[i].SetMediaFormatOptionInteger(OpalVideoFormat::MaxBitRateOption, videoInMaxBitRate);
   if((capabilities[i].GetFormatName().Find("H.264")!=P_MAX_INDEX) || (capabilities[i].GetFormatName().Find("VP8-")==0))
   {

    H323GenericVideoCapability *h264cap = (H323GenericVideoCapability *) &capabilities[i];
    h264cap->SetMaxBitRate(videoInMaxBitRate/100);
   }
  }
 }

/*	
	PINDEX audioNum = 1;
	PINDEX videoNum = 1;
	for (PINDEX i = 0; i < capabilities.GetSize(); i++) 
	{
		if (capabilities[i].GetMainType() == H323Capability::e_Audio)
		{
			config.SetString(CodecsConfigSection,
				psprintf("%u", audioNum++),
				capabilities[i].GetFormatName() + OnCodecSuffix);
		} 
		else if (capabilities[i].GetMainType() == H323Capability::e_Video)
		{
			config.SetString(VideoCodecsConfigSection,
				psprintf("%u", videoNum++),
				capabilities[i].GetFormatName() + OnCodecSuffix);
		}
	}
*/

	PTRACE(1, "MyPhone\tCapability Table:\n" << setprecision(4) << capabilities);
}
Datum
pg_control_checkpoint(PG_FUNCTION_ARGS)
{
	Datum		values[19];
	bool		nulls[19];
	TupleDesc	tupdesc;
	HeapTuple	htup;
	ControlFileData *ControlFile;
	XLogSegNo	segno;
	char		xlogfilename[MAXFNAMELEN];
	bool		crc_ok;

	/*
	 * Construct a tuple descriptor for the result row.  This must match this
	 * function's pg_proc entry!
	 */
	tupdesc = CreateTemplateTupleDesc(18);
	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "checkpoint_lsn",
					   LSNOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "redo_lsn",
					   LSNOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 3, "redo_wal_file",
					   TEXTOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 4, "timeline_id",
					   INT4OID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 5, "prev_timeline_id",
					   INT4OID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 6, "full_page_writes",
					   BOOLOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 7, "next_xid",
					   TEXTOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 8, "next_oid",
					   OIDOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 9, "next_multixact_id",
					   XIDOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 10, "next_multi_offset",
					   XIDOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 11, "oldest_xid",
					   XIDOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 12, "oldest_xid_dbid",
					   OIDOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 13, "oldest_active_xid",
					   XIDOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 14, "oldest_multi_xid",
					   XIDOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 15, "oldest_multi_dbid",
					   OIDOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 16, "oldest_commit_ts_xid",
					   XIDOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 17, "newest_commit_ts_xid",
					   XIDOID, -1, 0);
	TupleDescInitEntry(tupdesc, (AttrNumber) 18, "checkpoint_time",
					   TIMESTAMPTZOID, -1, 0);
	tupdesc = BlessTupleDesc(tupdesc);

	/* Read the control file. */
	ControlFile = get_controlfile(DataDir, &crc_ok);
	if (!crc_ok)
		ereport(ERROR,
				(errmsg("calculated CRC checksum does not match value stored in file")));

	/*
	 * Calculate name of the WAL file containing the latest checkpoint's REDO
	 * start point.
	 */
	XLByteToSeg(ControlFile->checkPointCopy.redo, segno, wal_segment_size);
	XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID,
				 segno, wal_segment_size);

	/* Populate the values and null arrays */
	values[0] = LSNGetDatum(ControlFile->checkPoint);
	nulls[0] = false;

	values[1] = LSNGetDatum(ControlFile->checkPointCopy.redo);
	nulls[1] = false;

	values[2] = CStringGetTextDatum(xlogfilename);
	nulls[2] = false;

	values[3] = Int32GetDatum(ControlFile->checkPointCopy.ThisTimeLineID);
	nulls[3] = false;

	values[4] = Int32GetDatum(ControlFile->checkPointCopy.PrevTimeLineID);
	nulls[4] = false;

	values[5] = BoolGetDatum(ControlFile->checkPointCopy.fullPageWrites);
	nulls[5] = false;

	values[6] = CStringGetTextDatum(psprintf("%u:%u",
											 EpochFromFullTransactionId(ControlFile->checkPointCopy.nextFullXid),
											 XidFromFullTransactionId(ControlFile->checkPointCopy.nextFullXid)));
	nulls[6] = false;

	values[7] = ObjectIdGetDatum(ControlFile->checkPointCopy.nextOid);
	nulls[7] = false;

	values[8] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMulti);
	nulls[8] = false;

	values[9] = TransactionIdGetDatum(ControlFile->checkPointCopy.nextMultiOffset);
	nulls[9] = false;

	values[10] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestXid);
	nulls[10] = false;

	values[11] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestXidDB);
	nulls[11] = false;

	values[12] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestActiveXid);
	nulls[12] = false;

	values[13] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestMulti);
	nulls[13] = false;

	values[14] = ObjectIdGetDatum(ControlFile->checkPointCopy.oldestMultiDB);
	nulls[14] = false;

	values[15] = TransactionIdGetDatum(ControlFile->checkPointCopy.oldestCommitTsXid);
	nulls[15] = false;

	values[16] = TransactionIdGetDatum(ControlFile->checkPointCopy.newestCommitTsXid);
	nulls[16] = false;

	values[17] = TimestampTzGetDatum(
									 time_t_to_timestamptz(ControlFile->checkPointCopy.time));
	nulls[17] = false;

	htup = heap_form_tuple(tupdesc, values, nulls);

	PG_RETURN_DATUM(HeapTupleGetDatum(htup));
}
Exemplo n.º 10
0
/*
 * start a psql test process for specified file (including redirection),
 * and return process ID
 */
static PID_TYPE
psql_start_test(const char *testname,
				_stringlist **resultfiles,
				_stringlist **expectfiles,
				_stringlist **tags)
{
	PID_TYPE	pid;
	char		infile[MAXPGPATH];
	char		outfile[MAXPGPATH];
	char		expectfile[MAXPGPATH];
	char		psql_cmd[MAXPGPATH * 3];
	size_t		offset = 0;
	char	   *appnameenv;

	/*
	 * Look for files in the output dir first, consistent with a vpath search.
	 * This is mainly to create more reasonable error messages if the file is
	 * not found.  It also allows local test overrides when running pg_regress
	 * outside of the source tree.
	 */
	snprintf(infile, sizeof(infile), "%s/sql/%s.sql",
			 outputdir, testname);
	if (!file_exists(infile))
		snprintf(infile, sizeof(infile), "%s/sql/%s.sql",
				 inputdir, testname);

	snprintf(outfile, sizeof(outfile), "%s/results/%s.out",
			 outputdir, testname);

	snprintf(expectfile, sizeof(expectfile), "%s/expected/%s.out",
			 outputdir, testname);
	if (!file_exists(expectfile))
		snprintf(expectfile, sizeof(expectfile), "%s/expected/%s.out",
				 inputdir, testname);

	add_stringlist_item(resultfiles, outfile);
	add_stringlist_item(expectfiles, expectfile);

	if (launcher)
		offset += snprintf(psql_cmd + offset, sizeof(psql_cmd) - offset,
						   "%s ", launcher);

	appnameenv = psprintf("PGAPPNAME=pg_regress/%s", testname);
	putenv(appnameenv);

	snprintf(psql_cmd + offset, sizeof(psql_cmd) - offset,
			 "\"%s%spsql\" -X -a -q -d \"%s\" < \"%s\" > \"%s\" 2>&1",
			 bindir ? bindir : "",
			 bindir ? "/" : "",
			 dblist->str,
			 infile,
			 outfile);

	pid = spawn_process(psql_cmd);

	if (pid == INVALID_PID)
	{
		fprintf(stderr, _("could not start process for test %s\n"),
				testname);
		exit(2);
	}

	unsetenv("PGAPPNAME");
	free(appnameenv);

	return pid;
}
Exemplo n.º 11
0
/* Get authority (host:port) for the PXF server URL */
char *
get_authority(void)
{
	return psprintf("%s:%d", get_pxf_host(), get_pxf_port());
}
Exemplo n.º 12
0
/* ------------------------------------------------
 * bt_metap()
 *
 * Get a btree's meta-page information
 *
 * Usage: SELECT * FROM bt_metap('t1_pkey')
 * ------------------------------------------------
 */
Datum
bt_metap(PG_FUNCTION_ARGS)
{
	text	   *relname = PG_GETARG_TEXT_PP(0);
	Datum		result;
	Relation	rel;
	RangeVar   *relrv;
	BTMetaPageData *metad;
	TupleDesc	tupleDesc;
	int			j;
	char	   *values[6];
	Buffer		buffer;
	Page		page;
	HeapTuple	tuple;

	if (!superuser())
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
				 (errmsg("must be superuser to use pageinspect functions"))));

	relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
	rel = relation_openrv(relrv, AccessShareLock);

	if (!IS_INDEX(rel) || !IS_BTREE(rel))
		elog(ERROR, "relation \"%s\" is not a btree index",
			 RelationGetRelationName(rel));

	/*
	 * Reject attempts to read non-local temporary relations; we would be
	 * likely to get wrong data since we have no visibility into the owning
	 * session's local buffers.
	 */
	if (RELATION_IS_OTHER_TEMP(rel))
		ereport(ERROR,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				 errmsg("cannot access temporary tables of other sessions")));

	buffer = ReadBuffer(rel, 0);
	LockBuffer(buffer, BUFFER_LOCK_SHARE);

	page = BufferGetPage(buffer);
	metad = BTPageGetMeta(page);

	/* Build a tuple descriptor for our result type */
	if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
		elog(ERROR, "return type must be a row type");

	j = 0;
	values[j++] = psprintf("%d", metad->btm_magic);
	values[j++] = psprintf("%d", metad->btm_version);
	values[j++] = psprintf("%d", metad->btm_root);
	values[j++] = psprintf("%d", metad->btm_level);
	values[j++] = psprintf("%d", metad->btm_fastroot);
	values[j++] = psprintf("%d", metad->btm_fastlevel);

	tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc),
								   values);

	result = HeapTupleGetDatum(tuple);

	UnlockReleaseBuffer(buffer);
	relation_close(rel, AccessShareLock);

	PG_RETURN_DATUM(result);
}
Exemplo n.º 13
0
/* -----------------------------------------------
 * bt_page_stats()
 *
 * Usage: SELECT * FROM bt_page_stats('t1_pkey', 1);
 * -----------------------------------------------
 */
Datum
bt_page_stats(PG_FUNCTION_ARGS)
{
	text	   *relname = PG_GETARG_TEXT_PP(0);
	uint32		blkno = PG_GETARG_UINT32(1);
	Buffer		buffer;
	Relation	rel;
	RangeVar   *relrv;
	Datum		result;
	HeapTuple	tuple;
	TupleDesc	tupleDesc;
	int			j;
	char	   *values[11];
	BTPageStat	stat;

	if (!superuser())
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
				 (errmsg("must be superuser to use pageinspect functions"))));

	relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
	rel = relation_openrv(relrv, AccessShareLock);

	if (!IS_INDEX(rel) || !IS_BTREE(rel))
		elog(ERROR, "relation \"%s\" is not a btree index",
			 RelationGetRelationName(rel));

	/*
	 * Reject attempts to read non-local temporary relations; we would be
	 * likely to get wrong data since we have no visibility into the owning
	 * session's local buffers.
	 */
	if (RELATION_IS_OTHER_TEMP(rel))
		ereport(ERROR,
				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
				 errmsg("cannot access temporary tables of other sessions")));

	if (blkno == 0)
		elog(ERROR, "block 0 is a meta page");

	CHECK_RELATION_BLOCK_RANGE(rel, blkno);

	buffer = ReadBuffer(rel, blkno);
	LockBuffer(buffer, BUFFER_LOCK_SHARE);

	/* keep compiler quiet */
	stat.btpo_prev = stat.btpo_next = InvalidBlockNumber;
	stat.btpo_flags = stat.free_size = stat.avg_item_size = 0;

	GetBTPageStatistics(blkno, buffer, &stat);

	UnlockReleaseBuffer(buffer);
	relation_close(rel, AccessShareLock);

	/* Build a tuple descriptor for our result type */
	if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
		elog(ERROR, "return type must be a row type");

	j = 0;
	values[j++] = psprintf("%d", stat.blkno);
	values[j++] = psprintf("%c", stat.type);
	values[j++] = psprintf("%d", stat.live_items);
	values[j++] = psprintf("%d", stat.dead_items);
	values[j++] = psprintf("%d", stat.avg_item_size);
	values[j++] = psprintf("%d", stat.page_size);
	values[j++] = psprintf("%d", stat.free_size);
	values[j++] = psprintf("%d", stat.btpo_prev);
	values[j++] = psprintf("%d", stat.btpo_next);
	values[j++] = psprintf("%d", (stat.type == 'd') ? stat.btpo.xact : stat.btpo.level);
	values[j++] = psprintf("%d", stat.btpo_flags);

	tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc),
								   values);

	result = HeapTupleGetDatum(tuple);

	PG_RETURN_DATUM(result);
}
Exemplo n.º 14
0
/*
 * build_function_result_tupdesc_d
 *
 * Build a RECORD function's tupledesc from the pg_proc proallargtypes,
 * proargmodes, and proargnames arrays.  This is split out for the
 * convenience of ProcedureCreate, which needs to be able to compute the
 * tupledesc before actually creating the function.
 *
 * Returns NULL if there are not at least two OUT or INOUT arguments.
 */
TupleDesc
build_function_result_tupdesc_d(Datum proallargtypes,
								Datum proargmodes,
								Datum proargnames)
{
	TupleDesc	desc;
	ArrayType  *arr;
	int			numargs;
	Oid		   *argtypes;
	char	   *argmodes;
	Datum	   *argnames = NULL;
	Oid		   *outargtypes;
	char	  **outargnames;
	int			numoutargs;
	int			nargnames;
	int			i;

	/* Can't have output args if columns are null */
	if (proallargtypes == PointerGetDatum(NULL) ||
		proargmodes == PointerGetDatum(NULL))
		return NULL;

	/*
	 * We expect the arrays to be 1-D arrays of the right types; verify that.
	 * For the OID and char arrays, we don't need to use deconstruct_array()
	 * since the array data is just going to look like a C array of values.
	 */
	arr = DatumGetArrayTypeP(proallargtypes);	/* ensure not toasted */
	numargs = ARR_DIMS(arr)[0];
	if (ARR_NDIM(arr) != 1 ||
		numargs < 0 ||
		ARR_HASNULL(arr) ||
		ARR_ELEMTYPE(arr) != OIDOID)
		elog(ERROR, "proallargtypes is not a 1-D Oid array");
	argtypes = (Oid *) ARR_DATA_PTR(arr);
	arr = DatumGetArrayTypeP(proargmodes);	/* ensure not toasted */
	if (ARR_NDIM(arr) != 1 ||
		ARR_DIMS(arr)[0] != numargs ||
		ARR_HASNULL(arr) ||
		ARR_ELEMTYPE(arr) != CHAROID)
		elog(ERROR, "proargmodes is not a 1-D char array");
	argmodes = (char *) ARR_DATA_PTR(arr);
	if (proargnames != PointerGetDatum(NULL))
	{
		arr = DatumGetArrayTypeP(proargnames);	/* ensure not toasted */
		if (ARR_NDIM(arr) != 1 ||
			ARR_DIMS(arr)[0] != numargs ||
			ARR_HASNULL(arr) ||
			ARR_ELEMTYPE(arr) != TEXTOID)
			elog(ERROR, "proargnames is not a 1-D text array");
		deconstruct_array(arr, TEXTOID, -1, false, 'i',
						  &argnames, NULL, &nargnames);
		Assert(nargnames == numargs);
	}

	/* zero elements probably shouldn't happen, but handle it gracefully */
	if (numargs <= 0)
		return NULL;

	/* extract output-argument types and names */
	outargtypes = (Oid *) palloc(numargs * sizeof(Oid));
	outargnames = (char **) palloc(numargs * sizeof(char *));
	numoutargs = 0;
	for (i = 0; i < numargs; i++)
	{
		char	   *pname;

		if (argmodes[i] == PROARGMODE_IN ||
			argmodes[i] == PROARGMODE_VARIADIC)
			continue;
		Assert(argmodes[i] == PROARGMODE_OUT ||
			   argmodes[i] == PROARGMODE_INOUT ||
			   argmodes[i] == PROARGMODE_TABLE);
		outargtypes[numoutargs] = argtypes[i];
		if (argnames)
			pname = TextDatumGetCString(argnames[i]);
		else
			pname = NULL;
		if (pname == NULL || pname[0] == '\0')
		{
			/* Parameter is not named, so gin up a column name */
			pname = psprintf("column%d", numoutargs + 1);
		}
		outargnames[numoutargs] = pname;
		numoutargs++;
	}

	/*
	 * If there is no output argument, or only one, the function does not
	 * return tuples.
	 */
	if (numoutargs < 2)
		return NULL;

	desc = CreateTemplateTupleDesc(numoutargs, false);
	for (i = 0; i < numoutargs; i++)
	{
		TupleDescInitEntry(desc, i + 1,
						   outargnames[i],
						   outargtypes[i],
						   -1,
						   0);
	}

	return desc;
}
Exemplo n.º 15
0
VOID
SetResolution(
    PDEVDATA    pdev,
    DWORD       res,
    WORD        restype)

/*++

Routine Description:

    Generate commands to set printer resolution.

Arguments:

    pdev    pointer to device data
    res     desired resolution
    bPJL    TRUE this is called at the beginning of a job
            FALSE if this called during the setup section

Return Value:

    NONE

--*/

{
    HPPD        hppd = pdev->hppd;
    PRESOPTION  pResOption;

    // We only need to do something when the requested
    // resolution type matches what the printer can do

    if (restype != hppd->wResType)
        return;

    // Check if the desired resolution is supported

    pResOption = PpdFindResolution(hppd, res);

    // Ignore if the desired resolution is not found

    if (pResOption == NULL) {

        DBGMSG1(DBG_LEVEL_TERSE,
                "No invocation string for resolution option: %d.\n", res);
        return;
    }

    switch (restype) {

    case RESTYPE_NORMAL:        // Use normal PS code

        if (pResOption->pInvocation == NULL) {

            DBGMSG(DBG_LEVEL_ERROR, "Failed to set resolution.");
        } else {

            DscBeginFeature(pdev, "Resolution ");
            psprintf(pdev, "%d\n", res);
            psputs(pdev, pResOption->pInvocation);
            DscEndFeature(pdev);
        }
        break;

    case RESTYPE_JCL:           // Use JCL code

        if (! PpdSupportsProtocol(hppd,PROTOCOL_PJL) ||
                pResOption->pJclCode == NULL)
        {
            DBGMSG(DBG_LEVEL_ERROR,
                   "Cannot set resolution using PJL commands.\n");
        } else {

            psputs(pdev, pResOption->pJclCode);
        }
        break;

    case RESTYPE_EXITSERVER:    // Use exitserver code

        if (pResOption->pSetResCode == NULL) {

            DBGMSG(DBG_LEVEL_ERROR, "Failed to set resolution.");
        } else {

            PSTR    password = hppd->pPassword ? hppd->pPassword : "******";

            psputs(pdev, "%%BeginExitServer: ");
            psputs(pdev, password);
            psprintf(pdev, "\n%%%%Resolution: %d\n", res);
            psputs(pdev, password);
            psputs(pdev, "\n");
            psputs(pdev, pResOption->pSetResCode);
            psputs(pdev, "\n%%EndExitServer\n");
        }
        break;
    }
}
Exemplo n.º 16
0
/*
 * create_tablespace_directories
 *
 *	Attempt to create filesystem infrastructure linking $PGDATA/pg_tblspc/
 *	to the specified directory
 */
static void
create_tablespace_directories(const char *location, const Oid tablespaceoid)
{
	char	   *linkloc;
	char	   *location_with_version_dir;

	linkloc = psprintf("pg_tblspc/%u", tablespaceoid);
	location_with_version_dir = psprintf("%s/%s", location,
			TABLESPACE_VERSION_DIRECTORY);

	/*
	 * Attempt to coerce target directory to safe permissions.	If this fails,
	 * it doesn't exist or has the wrong owner.
	 */
	if (chmod(location, S_IRWXU) != 0)
	{
		if (errno == ENOENT)
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_FILE),
					 errmsg("directory \"%s\" does not exist", location),
					 InRecovery ? errhint("Create this directory for the tablespace before "
										  "restarting the server.") : 0));
		else
			ereport(ERROR,
					(errcode_for_file_access(),
				  errmsg("could not set permissions on directory \"%s\": %m",
						 location)));
	}

	if (InRecovery)
	{
		struct stat st;

		/*
		 * Our theory for replaying a CREATE is to forcibly drop the target
		 * subdirectory if present, and then recreate it. This may be more
		 * work than needed, but it is simple to implement.
		 */
		if (stat(location_with_version_dir, &st) == 0 && S_ISDIR(st.st_mode))
		{
			if (!rmtree(location_with_version_dir, true))
				/* If this failed, mkdir() below is going to error. */
				ereport(WARNING,
						(errmsg("some useless files may be left behind in old database directory \"%s\"",
								location_with_version_dir)));
		}
	}

	/*
	 * The creation of the version directory prevents more than one tablespace
	 * in a single location.
	 */
	if (mkdir(location_with_version_dir, S_IRWXU) < 0)
	{
		if (errno == EEXIST)
			ereport(ERROR,
					(errcode(ERRCODE_OBJECT_IN_USE),
					 errmsg("directory \"%s\" already in use as a tablespace",
							location_with_version_dir)));
		else
			ereport(ERROR,
					(errcode_for_file_access(),
					 errmsg("could not create directory \"%s\": %m",
							location_with_version_dir)));
	}

	/* Remove old symlink in recovery, in case it points to the wrong place */
	if (InRecovery)
	{
		if (unlink(linkloc) < 0 && errno != ENOENT)
			ereport(ERROR,
					(errcode_for_file_access(),
					 errmsg("could not remove symbolic link \"%s\": %m",
							linkloc)));
	}

	/*
	 * Create the symlink under PGDATA
	 */
	if (symlink(location, linkloc) < 0)
		ereport(ERROR,
				(errcode_for_file_access(),
				 errmsg("could not create symbolic link \"%s\": %m",
						linkloc)));

	pfree(linkloc);
	pfree(location_with_version_dir);
}
Exemplo n.º 17
0
Datum
pgstrom_opencl_device_info(PG_FUNCTION_ARGS)
{
	FuncCallContext	*fncxt;
	Datum		values[4];
	bool		isnull[4];
	HeapTuple	tuple;
	uint32		dindex;
	uint32		pindex;
	const pgstrom_device_info *dinfo;
	const char *key;
	const char *value;
	char		buf[256];
	int			ofs = 0;

	if (SRF_IS_FIRSTCALL())
	{
		TupleDesc		tupdesc;
		MemoryContext	oldcxt;

		fncxt = SRF_FIRSTCALL_INIT();
		oldcxt = MemoryContextSwitchTo(fncxt->multi_call_memory_ctx);

		tupdesc = CreateTemplateTupleDesc(4, false);
		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "dnum",
						   INT4OID, -1, 0);
		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "pnum",
						   INT4OID, -1, 0);
		TupleDescInitEntry(tupdesc, (AttrNumber) 3, "property",
						   TEXTOID, -1, 0);
		TupleDescInitEntry(tupdesc, (AttrNumber) 4, "value",
						   TEXTOID, -1, 0);
		fncxt->tuple_desc = BlessTupleDesc(tupdesc);

		fncxt->user_fctx = 0;

		MemoryContextSwitchTo(oldcxt);
	}
	fncxt = SRF_PERCALL_SETUP();

	dindex = fncxt->call_cntr / 55;
	pindex = fncxt->call_cntr % 55;

	if (dindex == pgstrom_get_device_nums())
		SRF_RETURN_DONE(fncxt);

	dinfo = pgstrom_get_device_info(dindex);
	Assert(dinfo != NULL);

	switch (pindex)
	{
		case 0:
			key = "platform index";
			value = psprintf("%u", dinfo->pl_info->pl_index);
			break;
		case 1:
			key = "platform profile";
			value = dinfo->pl_info->pl_profile;
			break;
		case 2:
			key = "platform version";
			value = dinfo->pl_info->pl_version;
			break;
		case 3:
			key = "platform name";
			value = dinfo->pl_info->pl_name;
			break;
		case 4:
			key = "platform vendor";
			value = dinfo->pl_info->pl_vendor;
			break;
		case 5:
			key = "platform extensions";
			value = dinfo->pl_info->pl_extensions;
			break;
		case 6:
			key = "address bits";
			value = psprintf("%u", dinfo->dev_address_bits);
			break;
		case 7:
			key = "device available";
			value = dinfo->dev_available ? "yes" : "no";
			break;
		case 8:
			key = "compiler available";
			value = dinfo->dev_compiler_available ? "yes" : "no";
			break;
		case 9:
			key = "double fp config";
			value = fp_config_to_cstring(dinfo->dev_double_fp_config);
			break;
		case 10:
			key = "little endian";
			value = dinfo->dev_endian_little ? "yes" : "no";
			break;
		case 11:
			key = "error correction support";
			value = dinfo->dev_error_correction_support ? "yes" : "no";
			break;
		case 12:
			key = "execution capabilities";
			if (dinfo->dev_execution_capabilities & CL_EXEC_KERNEL)
				ofs += sprintf(buf + ofs, "OpenCL");
			if (dinfo->dev_execution_capabilities & CL_EXEC_NATIVE_KERNEL)
				ofs += sprintf(buf + ofs, "%sNative", ofs > 0 ? ", " : "");
			value = buf;
			break;
		case 13:
			key = "device extensions";
			value = dinfo->dev_device_extensions;
			break;
		case 14:
			key = "global mem cache size";
			value = psprintf("%lu", dinfo->dev_global_mem_cache_size);
			break;
		case 15:
			key = "global mem cache type";
			switch (dinfo->dev_global_mem_cache_type)
			{
				case CL_NONE:
					value = "none";
					break;
				case CL_READ_ONLY_CACHE:
					value = "read only";
					break;
				case CL_READ_WRITE_CACHE:
					value = "read write";
					break;
				default:
					value = "???";
					break;
			}
			break;
		case 16:
			key = "global mem cacheline size";
			value = psprintf("%u", dinfo->dev_global_mem_cacheline_size);
			break;
		case 17:
			key = "global mem size";
			value = psprintf("%lu", dinfo->dev_global_mem_size);
			break;
		case 18:
			key = "host unified memory";
			value = dinfo->dev_host_unified_memory ? "yes" : "no";
			break;
		case 19:
			key = "local mem size";
			value = psprintf("%lu", dinfo->dev_local_mem_size);
			break;
		case 20:
			key = "local mem type";
			switch (dinfo->dev_local_mem_type)
			{
				case CL_LOCAL:
					value = "local";
					break;
				case CL_GLOBAL:
					value = "global";
					break;
				case CL_NONE:
					value = "none";
					break;
				default:
					value = "???";
					break;
			}
			break;
		case 21:
			key = "max clock frequency";
			value = psprintf("%u", dinfo->dev_max_clock_frequency);
			break;
		case 22:
			key = "max compute units";
			value = psprintf("%u", dinfo->dev_max_compute_units);
			break;
		case 23:
			key = "max constant args";
			value = psprintf("%u", dinfo->dev_max_constant_args);
			break;
		case 24:
			key = "max constant buffer size";
			value = psprintf("%lu", dinfo->dev_max_constant_buffer_size);
			break;
		case 25:
			key = "max mem alloc size";
			value = psprintf("%lu", dinfo->dev_max_mem_alloc_size);
			break;
		case 26:
			key = "max parameter size";
			value = psprintf("%lu", dinfo->dev_max_parameter_size);
			break;
		case 27:
			key = "max samplers";
			value = psprintf("%u", dinfo->dev_max_samplers);
			break;
		case 28:
			key = "max work group size";
			value = psprintf("%zu", dinfo->dev_max_work_group_size);
			break;
		case 29:
			key = "max work group dimensions";
			value = psprintf("%u", dinfo->dev_max_work_item_dimensions);
			break;
		case 30:
			key = "max work item sizes";
			value = psprintf("{%zu, %zu, %zu}",
							 dinfo->dev_max_work_item_sizes[0],
							 dinfo->dev_max_work_item_sizes[1],
							 dinfo->dev_max_work_item_sizes[2]);
			break;
		case 31:
			key = "mem base address align";
			value = psprintf("%u", dinfo->dev_mem_base_addr_align);
			break;
		case 32:
			key = "device name";
			value = dinfo->dev_name;
			break;
		case 33:
			key = "native vector width (char)";
			value = psprintf("%u", dinfo->dev_native_vector_width_char);
			break;
		case 34:
			key = "native vector width (short)";
			value = psprintf("%u", dinfo->dev_native_vector_width_short);
			break;
		case 35:
			key = "native vector width (int)";
			value = psprintf("%u", dinfo->dev_native_vector_width_int);
			break;
		case 36:
			key = "native vector width (long)";
			value = psprintf("%u", dinfo->dev_native_vector_width_long);
			break;
		case 37:
			key = "native vector width (float)";
			value = psprintf("%u", dinfo->dev_native_vector_width_float);
			break;
		case 38:
			key = "native vector width (double)";
			value = psprintf("%u", dinfo->dev_native_vector_width_double);
			break;
		case 39:
			key = "opencl c version";
			value = dinfo->dev_opencl_c_version;
			break;
		case 40:
			key = "preferred vector width (char)";
			value = psprintf("%u", dinfo->dev_preferred_vector_width_char);
			break;
		case 41:
			key = "preferred vector width (short)";
			value = psprintf("%u", dinfo->dev_preferred_vector_width_short);
			break;
		case 42:
			key = "preferred vector width (int)";
			value = psprintf("%u", dinfo->dev_preferred_vector_width_int);
			break;
		case 43:
			key = "preferred vector width (long)";
			value = psprintf("%u", dinfo->dev_preferred_vector_width_long);
			break;
		case 44:
			key = "preferred vector width (float)";
			value = psprintf("%u", dinfo->dev_preferred_vector_width_float);
			break;
		case 45:
			key = "preferred vector width (double)";
			value = psprintf("%u", dinfo->dev_preferred_vector_width_double);
			break;
		case 46:
			key = "device profile";
			value = dinfo->dev_profile;
			break;
		case 47:
			key = "profiling timer resolution";
			value = psprintf("%zu", dinfo->dev_profiling_timer_resolution);
			break;
		case 48:
			key = "command queue properties";
			if (dinfo->dev_queue_properties &
				CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE)
				ofs += sprintf(buf, "%sout of order", ofs > 0 ? ", " : "");
			if (dinfo->dev_queue_properties & CL_QUEUE_PROFILING_ENABLE)
				ofs += sprintf(buf, "%sprofiling", ofs > 0 ? ", " : "");
			value = buf;
			break;
		case 49:
			key = "single fp config";
			value = fp_config_to_cstring(dinfo->dev_single_fp_config);
			break;
		case 50:
			key = "device type";
			if (dinfo->dev_type & CL_DEVICE_TYPE_CPU)
				ofs += sprintf(buf, "%scpu", ofs > 0 ? ", " : "");
			if (dinfo->dev_type & CL_DEVICE_TYPE_GPU)
				ofs += sprintf(buf, "%sgpu", ofs > 0 ? ", " : "");
			if (dinfo->dev_type & CL_DEVICE_TYPE_ACCELERATOR)
				ofs += sprintf(buf, "%saccelerator", ofs > 0 ? ", " : "");
			if (dinfo->dev_type & CL_DEVICE_TYPE_DEFAULT)
				ofs += sprintf(buf, "%sdefault", ofs > 0 ? ", " : "");
			if (dinfo->dev_type & CL_DEVICE_TYPE_CUSTOM)
				ofs += sprintf(buf, "%scustom", ofs > 0 ? ", " : "");
			value = buf;
			break;
		case 51:
			key = "device vendor";
			value = dinfo->dev_vendor;
			break;
		case 52:
			key = "device vendor id";
			value = psprintf("%u", dinfo->dev_vendor_id);
			break;
		case 53:
			key = "device version";
			value = dinfo->dev_version;
			break;
		case 54:
			key = "driver version";
			value = dinfo->driver_version;
			break;
		default:
			elog(ERROR, "unexpected property index");
			break;
	}
	memset(isnull, 0, sizeof(isnull));
	values[0] = Int32GetDatum(dindex);
	values[1] = Int32GetDatum(pindex);
	values[2] = CStringGetTextDatum(key);
	values[3] = CStringGetTextDatum(value);

	tuple = heap_form_tuple(fncxt->tuple_desc, values, isnull);

	SRF_RETURN_NEXT(fncxt, HeapTupleGetDatum(tuple));
}
Exemplo n.º 18
0
/*
 * destroy_tablespace_directories
 *
 * Attempt to remove filesystem infrastructure for the tablespace.
 *
 * 'redo' indicates we are redoing a drop from XLOG; in that case we should
 * not throw an ERROR for problems, just LOG them.	The worst consequence of
 * not removing files here would be failure to release some disk space, which
 * does not justify throwing an error that would require manual intervention
 * to get the database running again.
 *
 * Returns TRUE if successful, FALSE if some subdirectory is not empty
 */
static bool
destroy_tablespace_directories(Oid tablespaceoid, bool redo)
{
	char	   *linkloc;
	char	   *linkloc_with_version_dir;
	DIR		   *dirdesc;
	struct dirent *de;
	char	   *subfile;
	struct stat st;

	linkloc_with_version_dir = psprintf("pg_tblspc/%u/%s", tablespaceoid,
			TABLESPACE_VERSION_DIRECTORY);

	/*
	 * Check if the tablespace still contains any files.  We try to rmdir each
	 * per-database directory we find in it.  rmdir failure implies there are
	 * still files in that subdirectory, so give up.  (We do not have to worry
	 * about undoing any already completed rmdirs, since the next attempt to
	 * use the tablespace from that database will simply recreate the
	 * subdirectory via TablespaceCreateDbspace.)
	 *
	 * Since we hold TablespaceCreateLock, no one else should be creating any
	 * fresh subdirectories in parallel. It is possible that new files are
	 * being created within subdirectories, though, so the rmdir call could
	 * fail.  Worst consequence is a less friendly error message.
	 *
	 * If redo is true then ENOENT is a likely outcome here, and we allow it
	 * to pass without comment.  In normal operation we still allow it, but
	 * with a warning.	This is because even though ProcessUtility disallows
	 * DROP TABLESPACE in a transaction block, it's possible that a previous
	 * DROP failed and rolled back after removing the tablespace directories
	 * and/or symlink.	We want to allow a new DROP attempt to succeed at
	 * removing the catalog entries (and symlink if still present), so we
	 * should not give a hard error here.
	 */
	dirdesc = AllocateDir(linkloc_with_version_dir);
	if (dirdesc == NULL)
	{
		if (errno == ENOENT)
		{
			if (!redo)
				ereport(WARNING,
						(errcode_for_file_access(),
						 errmsg("could not open directory \"%s\": %m",
								linkloc_with_version_dir)));
			/* The symlink might still exist, so go try to remove it */
			goto remove_symlink;
		}
		else if (redo)
		{
			/* in redo, just log other types of error */
			ereport(LOG,
					(errcode_for_file_access(),
					 errmsg("could not open directory \"%s\": %m",
							linkloc_with_version_dir)));
			pfree(linkloc_with_version_dir);
			return false;
		}
		/* else let ReadDir report the error */
	}

	while ((de = ReadDir(dirdesc, linkloc_with_version_dir)) != NULL)
	{
		if (strcmp(de->d_name, ".") == 0 ||
			strcmp(de->d_name, "..") == 0)
			continue;

		subfile = psprintf("%s/%s", linkloc_with_version_dir, de->d_name);

		/* This check is just to deliver a friendlier error message */
		if (!redo && !directory_is_empty(subfile))
		{
			FreeDir(dirdesc);
			pfree(subfile);
			pfree(linkloc_with_version_dir);
			return false;
		}

		/* remove empty directory */
		if (rmdir(subfile) < 0)
			ereport(redo ? LOG : ERROR,
					(errcode_for_file_access(),
					 errmsg("could not remove directory \"%s\": %m",
							subfile)));

		pfree(subfile);
	}

	FreeDir(dirdesc);

	/* remove version directory */
	if (rmdir(linkloc_with_version_dir) < 0)
	{
		ereport(redo ? LOG : ERROR,
				(errcode_for_file_access(),
				 errmsg("could not remove directory \"%s\": %m",
						linkloc_with_version_dir)));
		pfree(linkloc_with_version_dir);
		return false;
	}

	/*
	 * Try to remove the symlink.  We must however deal with the possibility
	 * that it's a directory instead of a symlink --- this could happen during
	 * WAL replay (see TablespaceCreateDbspace), and it is also the case on
	 * Windows where junction points lstat() as directories.
	 *
	 * Note: in the redo case, we'll return true if this final step fails;
	 * there's no point in retrying it.  Also, ENOENT should provoke no more
	 * than a warning.
	 */
remove_symlink:
	linkloc = pstrdup(linkloc_with_version_dir);
	get_parent_directory(linkloc);
	if (lstat(linkloc, &st) == 0 && S_ISDIR(st.st_mode))
	{
		if (rmdir(linkloc) < 0)
			ereport(redo ? LOG : ERROR,
					(errcode_for_file_access(),
					 errmsg("could not remove directory \"%s\": %m",
							linkloc)));
	}
	else
	{
		if (unlink(linkloc) < 0)
			ereport(redo ? LOG : (errno == ENOENT ? WARNING : ERROR),
					(errcode_for_file_access(),
					 errmsg("could not remove symbolic link \"%s\": %m",
							linkloc)));
	}

	pfree(linkloc_with_version_dir);
	pfree(linkloc);

	return true;
}
Exemplo n.º 19
0
/*
 * parseCommandLine()
 *
 *	Parses the command line (argc, argv[]) and loads structures
 */
void
parseCommandLine(int argc, char *argv[])
{
	static struct option long_options[] = {
		{"old-datadir", required_argument, NULL, 'd'},
		{"new-datadir", required_argument, NULL, 'D'},
		{"old-bindir", required_argument, NULL, 'b'},
		{"new-bindir", required_argument, NULL, 'B'},
		{"old-options", required_argument, NULL, 'o'},
		{"new-options", required_argument, NULL, 'O'},
		{"old-port", required_argument, NULL, 'p'},
		{"new-port", required_argument, NULL, 'P'},

		{"username", required_argument, NULL, 'U'},
		{"check", no_argument, NULL, 'c'},
		{"link", no_argument, NULL, 'k'},
		{"retain", no_argument, NULL, 'r'},
		{"jobs", required_argument, NULL, 'j'},
		{"verbose", no_argument, NULL, 'v'},
		{NULL, 0, NULL, 0}
	};
	int			option;			/* Command line option */
	int			optindex = 0;	/* used by getopt_long */
	int			os_user_effective_id;
	FILE	   *fp;
	char	  **filename;
	time_t		run_time = time(NULL);

	user_opts.transfer_mode = TRANSFER_MODE_COPY;

	os_info.progname = get_progname(argv[0]);

	/* Process libpq env. variables; load values here for usage() output */
	old_cluster.port = getenv("PGPORTOLD") ? atoi(getenv("PGPORTOLD")) : DEF_PGUPORT;
	new_cluster.port = getenv("PGPORTNEW") ? atoi(getenv("PGPORTNEW")) : DEF_PGUPORT;

	os_user_effective_id = get_user_info(&os_info.user);
	/* we override just the database user name;  we got the OS id above */
	if (getenv("PGUSER"))
	{
		pg_free(os_info.user);
		/* must save value, getenv()'s pointer is not stable */
		os_info.user = pg_strdup(getenv("PGUSER"));
	}

	if (argc > 1)
	{
		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
		{
			usage();
			exit(0);
		}
		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
		{
			puts("pg_upgrade (PostgreSQL) " PG_VERSION);
			exit(0);
		}
	}

	/* Allow help and version to be run as root, so do the test here. */
	if (os_user_effective_id == 0)
		pg_fatal("%s: cannot be run as root\n", os_info.progname);

	if ((log_opts.internal = fopen_priv(INTERNAL_LOG_FILE, "a")) == NULL)
		pg_fatal("cannot write to log file %s\n", INTERNAL_LOG_FILE);

	while ((option = getopt_long(argc, argv, "d:D:b:B:cj:ko:O:p:P:rU:v",
								 long_options, &optindex)) != -1)
	{
		switch (option)
		{
			case 'b':
				old_cluster.bindir = pg_strdup(optarg);
				break;

			case 'B':
				new_cluster.bindir = pg_strdup(optarg);
				break;

			case 'c':
				user_opts.check = true;
				break;

			case 'd':
				old_cluster.pgdata = pg_strdup(optarg);
				old_cluster.pgconfig = pg_strdup(optarg);
				break;

			case 'D':
				new_cluster.pgdata = pg_strdup(optarg);
				new_cluster.pgconfig = pg_strdup(optarg);
				break;

			case 'j':
				user_opts.jobs = atoi(optarg);
				break;

			case 'k':
				user_opts.transfer_mode = TRANSFER_MODE_LINK;
				break;

			case 'o':
				old_cluster.pgopts = pg_strdup(optarg);
				break;

			case 'O':
				new_cluster.pgopts = pg_strdup(optarg);
				break;

				/*
				 * Someday, the port number option could be removed and passed
				 * using -o/-O, but that requires postmaster -C to be
				 * supported on all old/new versions.
				 */
			case 'p':
				if ((old_cluster.port = atoi(optarg)) <= 0)
				{
					pg_fatal("invalid old port number\n");
					exit(1);
				}
				break;

			case 'P':
				if ((new_cluster.port = atoi(optarg)) <= 0)
				{
					pg_fatal("invalid new port number\n");
					exit(1);
				}
				break;

			case 'r':
				log_opts.retain = true;
				break;

			case 'U':
				pg_free(os_info.user);
				os_info.user = pg_strdup(optarg);
				os_info.user_specified = true;

				/*
				 * Push the user name into the environment so pre-9.1
				 * pg_ctl/libpq uses it.
				 */
				pg_putenv("PGUSER", os_info.user);
				break;

			case 'v':
				pg_log(PG_REPORT, "Running in verbose mode\n");
				log_opts.verbose = true;
				break;

			default:
				pg_fatal("Try \"%s --help\" for more information.\n",
						 os_info.progname);
				break;
		}
	}

	/* label start of upgrade in logfiles */
	for (filename = output_files; *filename != NULL; filename++)
	{
		if ((fp = fopen_priv(*filename, "a")) == NULL)
			pg_fatal("cannot write to log file %s\n", *filename);

		/* Start with newline because we might be appending to a file. */
		fprintf(fp, "\n"
		"-----------------------------------------------------------------\n"
				"  pg_upgrade run on %s"
				"-----------------------------------------------------------------\n\n",
				ctime(&run_time));
		fclose(fp);
	}

	/* Turn off read-only mode;  add prefix to PGOPTIONS? */
	if (getenv("PGOPTIONS"))
	{
		char	   *pgoptions = psprintf("%s %s", FIX_DEFAULT_READ_ONLY,
										 getenv("PGOPTIONS"));

		pg_putenv("PGOPTIONS", pgoptions);
		pfree(pgoptions);
	}
	else
		pg_putenv("PGOPTIONS", FIX_DEFAULT_READ_ONLY);

	/* Get values from env if not already set */
	check_required_directory(&old_cluster.bindir, NULL, "PGBINOLD", "-b",
							 "old cluster binaries reside");
	check_required_directory(&new_cluster.bindir, NULL, "PGBINNEW", "-B",
							 "new cluster binaries reside");
	check_required_directory(&old_cluster.pgdata, &old_cluster.pgconfig,
							 "PGDATAOLD", "-d", "old cluster data resides");
	check_required_directory(&new_cluster.pgdata, &new_cluster.pgconfig,
							 "PGDATANEW", "-D", "new cluster data resides");

#ifdef WIN32
	/*
	 * On Windows, initdb --sync-only will fail with a "Permission denied"
	 * error on file pg_upgrade_utility.log if pg_upgrade is run inside
	 * the new cluster directory, so we do a check here.
	 */
	{
		char	cwd[MAXPGPATH], new_cluster_pgdata[MAXPGPATH];

		strlcpy(new_cluster_pgdata, new_cluster.pgdata, MAXPGPATH);
		canonicalize_path(new_cluster_pgdata);

		if (!getcwd(cwd, MAXPGPATH))
			pg_fatal("cannot find current directory\n");
		canonicalize_path(cwd);
		if (path_is_prefix_of_path(new_cluster_pgdata, cwd))
			pg_fatal("cannot run pg_upgrade from inside the new cluster data directory on Windows\n");
	}
#endif
}
Exemplo n.º 20
0
VOID
PsSelectPrinterFeatures(
    PDEVDATA    pdev,
    WORD        section
)

/*++

Routine Description:

    Select printer specific feature to appear in a
    given section.

Arguments:

    pdev - Pointer to our DEVDATA structure
    section - DSC section we're currently in

Return Value:

    NONE

--*/

{
    WORD         index;
    PFEATUREDATA pFeatureData;
    PUIGROUP     pUiGroup;
    PUIOPTION    pUiOption;

    //
    // Prepare data for handling printer specific feature if it's not done already.
    //

    if (!pdev->pFeatureData && !PrepareFeatureData(pdev)) {

        DBGERRMSG("PrepareFeatureData");
        return;
    }

    //
    // For each requested feature, check if it should be sent to
    // the printer in the current DSC section.
    //

    for (index = 0, pFeatureData = pdev->pFeatureData;
            index < pdev->cSelectedFeature;
            index ++, pFeatureData++)
    {
        //
        // Find the UIOPTION object corresponding to the requested feature/selection.
        //
        // HACK: PageSize feature is handled differently here because it involves
        // lots of legacy stuff which we don't want to touch at this point.
        //

        if (! (pFeatureData->section & section))
            continue;

        if (pdev->hppd->pPageSizes &&
                pdev->hppd->pPageSizes->featureIndex == pFeatureData->feature)
        {
            PsSelectFormAndTray(pdev);

        } else if (PpdFindFeatureSelection(
                       pdev->hppd,
                       pFeatureData->feature,
                       pFeatureData->option,
                       &pUiGroup,
                       &pUiOption))
        {
            DBGMSG1(DBG_LEVEL_VERBOSE, "Feature: %s\n", pUiGroup->pName);
            DBGMSG1(DBG_LEVEL_VERBOSE, "Selection: %s\n", pUiOption->pName);

            //
            // If we're not in JCLSetup section, then enclose the feature
            // invocation in a mark/cleartomark pair.
            //

            if (section != ODS_JCLSETUP) {

                DscBeginFeature(pdev, pUiGroup->pName);
                psprintf(pdev, " %s\n", pUiOption->pName);
            }

            if (pUiOption->pInvocation)
                psputs(pdev, pUiOption->pInvocation);

            if (section != ODS_JCLSETUP)
                DscEndFeature(pdev);
        }
    }
}
Exemplo n.º 21
0
/*
 *
 * main
 *
 */
int
main(int argc, char *argv[])
{
	struct adhoc_opts options;
	int			successResult;
	char	   *password = NULL;
	char	   *password_prompt = NULL;
	bool		new_pass;

	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql"));

	if (argc > 1)
	{
		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
		{
			usage();
			exit(EXIT_SUCCESS);
		}
		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
		{
			showVersion();
			exit(EXIT_SUCCESS);
		}
	}

#ifdef WIN32
	setvbuf(stderr, NULL, _IONBF, 0);
#endif

	pset.progname = get_progname(argv[0]);

	pset.db = NULL;
	setDecimalLocale();
	pset.encoding = PQenv2encoding();
	pset.queryFout = stdout;
	pset.queryFoutPipe = false;
	pset.cur_cmd_source = stdin;
	pset.cur_cmd_interactive = false;

	/* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */
	pset.popt.topt.format = PRINT_ALIGNED;
	pset.popt.topt.border = 1;
	pset.popt.topt.pager = 1;
	pset.popt.topt.start_table = true;
	pset.popt.topt.stop_table = true;
	pset.popt.topt.default_footer = true;
	/* We must get COLUMNS here before readline() sets it */
	pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;

	pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));

	pset.getPassword = TRI_DEFAULT;

	EstablishVariableSpace();

	SetVariable(pset.vars, "VERSION", PG_VERSION_STR);

	/* Default values for variables */
	SetVariableBool(pset.vars, "AUTOCOMMIT");
	SetVariable(pset.vars, "VERBOSITY", "default");
	SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
	SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
	SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);

	parse_psql_options(argc, argv, &options);

	/*
	 * If no action was specified and we're in non-interactive mode, treat it
	 * as if the user had specified "-f -".  This lets single-transaction mode
	 * work in this case.
	 */
	if (options.action == ACT_NOTHING && pset.notty)
	{
		options.action = ACT_FILE;
		options.action_string = NULL;
	}

	/* Bail out if -1 was specified but will be ignored. */
	if (options.single_txn && options.action != ACT_FILE && options.action == ACT_NOTHING)
	{
		fprintf(stderr, _("%s: -1 can only be used in non-interactive mode\n"), pset.progname);
		exit(EXIT_FAILURE);
	}

	if (!pset.popt.topt.fieldSep.separator &&
		!pset.popt.topt.fieldSep.separator_zero)
	{
		pset.popt.topt.fieldSep.separator = pg_strdup(DEFAULT_FIELD_SEP);
		pset.popt.topt.fieldSep.separator_zero = false;
	}
	if (!pset.popt.topt.recordSep.separator &&
		!pset.popt.topt.recordSep.separator_zero)
	{
		pset.popt.topt.recordSep.separator = pg_strdup(DEFAULT_RECORD_SEP);
		pset.popt.topt.recordSep.separator_zero = false;
	}

	if (options.username == NULL)
		password_prompt = pg_strdup(_("Password: "******"Password for user %s: "),
								   options.username);

	if (pset.getPassword == TRI_YES)
		password = simple_prompt(password_prompt, 100, false);

	/* loop until we have a password if requested by backend */
	do
	{
#define PARAMS_ARRAY_SIZE	8
		const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
		const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));

		keywords[0] = "host";
		values[0] = options.host;
		keywords[1] = "port";
		values[1] = options.port;
		keywords[2] = "user";
		values[2] = options.username;
		keywords[3] = "password";
		values[3] = password;
		keywords[4] = "dbname";
		values[4] = (options.action == ACT_LIST_DB &&
					 options.dbname == NULL) ?
			"postgres" : options.dbname;
		keywords[5] = "fallback_application_name";
		values[5] = pset.progname;
		keywords[6] = "client_encoding";
		values[6] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto";
		keywords[7] = NULL;
		values[7] = NULL;

		new_pass = false;
		pset.db = PQconnectdbParams(keywords, values, true);
		free(keywords);
		free(values);

		if (PQstatus(pset.db) == CONNECTION_BAD &&
			PQconnectionNeedsPassword(pset.db) &&
			password == NULL &&
			pset.getPassword != TRI_NO)
		{
			PQfinish(pset.db);
			password = simple_prompt(password_prompt, 100, false);
			new_pass = true;
		}
	} while (new_pass);

	free(password);
	free(password_prompt);

	if (PQstatus(pset.db) == CONNECTION_BAD)
	{
		fprintf(stderr, "%s: %s", pset.progname, PQerrorMessage(pset.db));
		PQfinish(pset.db);
		exit(EXIT_BADCONN);
	}

	setup_cancel_handler();

	PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);

	SyncVariables();

	if (options.action == ACT_LIST_DB)
	{
		int			success;

		if (!options.no_psqlrc)
			process_psqlrc(argv[0]);

		success = listAllDbs(NULL, false);
		PQfinish(pset.db);
		exit(success ? EXIT_SUCCESS : EXIT_FAILURE);
	}

	if (options.logfilename)
	{
		pset.logfile = fopen(options.logfilename, "a");
		if (!pset.logfile)
			fprintf(stderr, _("%s: could not open log file \"%s\": %s\n"),
					pset.progname, options.logfilename, strerror(errno));
	}

	/*
	 * Now find something to do
	 */

	/*
	 * process file given by -f
	 */
	if (options.action == ACT_FILE)
	{
		if (!options.no_psqlrc)
			process_psqlrc(argv[0]);

		successResult = process_file(options.action_string, options.single_txn, false);
	}

	/*
	 * process slash command if one was given to -c
	 */
	else if (options.action == ACT_SINGLE_SLASH)
	{
		PsqlScanState scan_state;

		if (pset.echo == PSQL_ECHO_ALL)
			puts(options.action_string);

		scan_state = psql_scan_create();
		psql_scan_setup(scan_state,
						options.action_string,
						strlen(options.action_string));

		successResult = HandleSlashCmds(scan_state, NULL) != PSQL_CMD_ERROR
			? EXIT_SUCCESS : EXIT_FAILURE;

		psql_scan_destroy(scan_state);
	}

	/*
	 * If the query given to -c was a normal one, send it
	 */
	else if (options.action == ACT_SINGLE_QUERY)
	{
		if (pset.echo == PSQL_ECHO_ALL)
			puts(options.action_string);

		successResult = SendQuery(options.action_string)
			? EXIT_SUCCESS : EXIT_FAILURE;
	}

	/*
	 * or otherwise enter interactive main loop
	 */
	else
	{
		if (!options.no_psqlrc)
			process_psqlrc(argv[0]);

		connection_warnings(true);
		if (!pset.quiet)
			printf(_("Type \"help\" for help.\n\n"));
		initializeInput(options.no_readline ? 0 : 1);
		successResult = MainLoop(stdin);
	}

	/* clean up */
	if (pset.logfile)
		fclose(pset.logfile);
	PQfinish(pset.db);
	setQFout(NULL);

	return successResult;
}
Exemplo n.º 22
0
BOOL
bSendDeviceSetup(
    PDEVDATA pdev
)

/*++

Routine Description:

    Send page setup code to the printer. This is called at the
    beginning of every page.

Arguments:

    pdev - Pointer to our DEVDATA structure

Return Value:

    TRUE if successful, FALSE if error

--*/

{
    PSTR    pstr;
    HPPD    hppd = pdev->hppd;

    //
    // Clear the current page if Negative Output option is selected
    //

    if (pdev->dm.dmPrivate.dwFlags & PSDEVMODE_NEG) {

        psputs(pdev, "gsave clippath 1 setgray fill grestore\n");
    }

    // Rotate 90 degrees counterclockwise for normal landscape
    // or 90 degrees clockwise for rotated landscape

    if (pdev->dm.dmPublic.dmOrientation == DMORIENT_LANDSCAPE) {

        SetLandscape(pdev,
                     (pdev->dm.dmPrivate.dwFlags & PSDEVMODE_LSROTATE) != 0,
                     pdev->CurForm.PaperSize.height,
                     pdev->CurForm.PaperSize.width);
    }

    if (pdev->dm.dmPrivate.dwFlags & PSDEVMODE_MIRROR) {

        psprintf(pdev,
                 "%f %f translate -1 1 scale\n",
                 pdev->CurForm.ImageArea.right - pdev->CurForm.ImageArea.left,
                 0);
    }

    /* Translate origin to upper left corner a la GDI */

    psprintf(pdev, "%f %f translate ",
             pdev->CurForm.ImageArea.left,
             pdev->CurForm.ImageArea.top);

    /* Flip y-axis to point downwards and scale from points to dpi */

    psprintf(pdev, "%d %d div dup neg scale\n", 72, pdev->dm.dmPublic.dmPrintQuality);

    /* Snap to pixel */

    psputs(pdev,
           "0 0 transform .25 add round .25 sub exch .25 add "
           "round .25 sub exch itransform translate\n");

    return TRUE;
}
Exemplo n.º 23
0
/*
 * Actually do a base backup for the specified tablespaces.
 *
 * This is split out mainly to avoid complaints about "variable might be
 * clobbered by longjmp" from stupider versions of gcc.
 */
static void
perform_base_backup(basebackup_options *opt, DIR *tblspcdir)
{
	XLogRecPtr	startptr;
	TimeLineID	starttli;
	XLogRecPtr	endptr;
	TimeLineID	endtli;
	StringInfo	labelfile;
	StringInfo	tblspc_map_file = NULL;
	int			datadirpathlen;
	List	   *tablespaces = NIL;

	datadirpathlen = strlen(DataDir);

	backup_started_in_recovery = RecoveryInProgress();

	labelfile = makeStringInfo();
	tblspc_map_file = makeStringInfo();

	startptr = do_pg_start_backup(opt->label, opt->fastcheckpoint, &starttli,
								  labelfile, tblspcdir, &tablespaces,
								  tblspc_map_file,
								  opt->progress, opt->sendtblspcmapfile);

	/*
	 * Once do_pg_start_backup has been called, ensure that any failure causes
	 * us to abort the backup so we don't "leak" a backup counter. For this
	 * reason, *all* functionality between do_pg_start_backup() and
	 * do_pg_stop_backup() should be inside the error cleanup block!
	 */

	PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
	{
		ListCell   *lc;
		tablespaceinfo *ti;

		SendXlogRecPtrResult(startptr, starttli);

		/*
		 * Calculate the relative path of temporary statistics directory in
		 * order to skip the files which are located in that directory later.
		 */
		if (is_absolute_path(pgstat_stat_directory) &&
			strncmp(pgstat_stat_directory, DataDir, datadirpathlen) == 0)
			statrelpath = psprintf("./%s", pgstat_stat_directory + datadirpathlen + 1);
		else if (strncmp(pgstat_stat_directory, "./", 2) != 0)
			statrelpath = psprintf("./%s", pgstat_stat_directory);
		else
			statrelpath = pgstat_stat_directory;

		/* Add a node for the base directory at the end */
		ti = palloc0(sizeof(tablespaceinfo));
		ti->size = opt->progress ? sendDir(".", 1, true, tablespaces, true) : -1;
		tablespaces = lappend(tablespaces, ti);

		/* Send tablespace header */
		SendBackupHeader(tablespaces);

		/* Setup and activate network throttling, if client requested it */
		if (opt->maxrate > 0)
		{
			throttling_sample =
				(int64) opt->maxrate * (int64) 1024 / THROTTLING_FREQUENCY;

			/*
			 * The minimum amount of time for throttling_sample bytes to be
			 * transferred.
			 */
			elapsed_min_unit = USECS_PER_SEC / THROTTLING_FREQUENCY;

			/* Enable throttling. */
			throttling_counter = 0;

			/* The 'real data' starts now (header was ignored). */
			throttled_last = GetCurrentIntegerTimestamp();
		}
		else
		{
			/* Disable throttling. */
			throttling_counter = -1;
		}

		/* Send off our tablespaces one by one */
		foreach(lc, tablespaces)
		{
			tablespaceinfo *ti = (tablespaceinfo *) lfirst(lc);
			StringInfoData buf;

			/* Send CopyOutResponse message */
			pq_beginmessage(&buf, 'H');
			pq_sendbyte(&buf, 0);		/* overall format */
			pq_sendint(&buf, 0, 2);		/* natts */
			pq_endmessage(&buf);

			if (ti->path == NULL)
			{
				struct stat statbuf;

				/* In the main tar, include the backup_label first... */
				sendFileWithContent(BACKUP_LABEL_FILE, labelfile->data);

				/*
				 * Send tablespace_map file if required and then the bulk of
				 * the files.
				 */
				if (tblspc_map_file && opt->sendtblspcmapfile)
				{
					sendFileWithContent(TABLESPACE_MAP, tblspc_map_file->data);
					sendDir(".", 1, false, tablespaces, false);
				}
				else
					sendDir(".", 1, false, tablespaces, true);

				/* ... and pg_control after everything else. */
				if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0)
					ereport(ERROR,
							(errcode_for_file_access(),
							 errmsg("could not stat control file \"%s\": %m",
									XLOG_CONTROL_FILE)));
				sendFile(XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf, false);
			}
			else
				sendTablespace(ti->path, false);

			/*
			 * If we're including WAL, and this is the main data directory we
			 * don't terminate the tar stream here. Instead, we will append
			 * the xlog files below and terminate it then. This is safe since
			 * the main data directory is always sent *last*.
			 */
			if (opt->includewal && ti->path == NULL)
			{
				Assert(lnext(lc) == NULL);
			}
			else
				pq_putemptymessage('c');		/* CopyDone */
		}
	}
Exemplo n.º 24
0
VOID
PsSelectFormAndTray(
    PDEVDATA    pdev
)

/*++

Routine Description:

    This function pick the tray for a particular form selected, depends on
    the user request in the UI

Arguments:

    pdev - Pointer to our PDEVDATA

Return Value:

    NONE

--*/

{
    BOOL            IsManual;
    PINPUTSLOT      pInputSlot;
    HPPD            hppd = pdev->hppd;
    PSTR            pstr;

    // If a valid input slot is specified, then we'll instruct
    // the printer to draw paper from that slot. Otherwise,
    // we'll tell printer to select input slot based on paper size.

    IsManual = FALSE;
    pInputSlot = NULL;

    if ((pdev->dm.dmPublic.dmFields & DM_DEFAULTSOURCE)    &&
            (pdev->dm.dmPublic.dmDefaultSource != DMBIN_FORMSOURCE))
    {
        DWORD   SlotNum, cInputSlots;

        SlotNum = pdev->dm.dmPublic.dmDefaultSource;
        cInputSlots = UIGROUP_CountOptions(hppd->pInputSlots);

        if (SlotNum == DMBIN_MANUAL || SlotNum == DMBIN_ENVMANUAL) {

            // Manual feed is requested

            IsManual = TRUE;

        } else if (SlotNum >= DMBIN_USER && SlotNum < DMBIN_USER+cInputSlots) {

            // A valid input slot is requested

            pInputSlot = (PINPUTSLOT)
                         LISTOBJ_FindIndexed(
                             (PLISTOBJ) hppd->pInputSlots->pUiOptions,
                             SlotNum - DMBIN_USER);
        }

    } else if (pdev->CurForm.FormName[0] != NUL) {

        // No input slot is specifically requested. Go through
        // the form to tray assignment table and find the input
        // slot matching the requested form.

        pInputSlot = MatchFormToTray(pdev, &IsManual);
    }

    if (IsManual) {

        // If manual feed feature is requested, then
        // generate PostScript code to enable it.

        PsSelectManualFeed(pdev, TRUE);

    } else {

        // Disable manual feed if it's currently enabled

        PsSelectManualFeed(pdev, FALSE);

        if (pInputSlot != NULL) {

            // If an input slot is designated, then generate
            // PostScript code to select it.

            DscBeginFeature(pdev, "InputSlot ");
            psprintf(pdev, "%s\n", pInputSlot->pName);

            if (pInputSlot->pInvocation != NULL)
                psputs(pdev, pInputSlot->pInvocation);

            DscEndFeature(pdev);
        }
    }

    if (IsCustomPrinterForm(& pdev->CurForm)) {

        // If the custom page size is requested, then generate
        // appropriate PostScript code to send to the printer.

        DscBeginFeature(pdev, "CustomPageSize\n");
        PsSelectCustomPageSize(pdev);
        DscEndFeature(pdev);

    } else if (pInputSlot == NULL || pInputSlot->bReqPageRgn) {

        BOOL            bRegion;
        PMEDIAOPTION    pMediaOption;

        // If an input slot was selected and it doesn't require
        // PageRegion, then we are done. Otherwise, we need to
        // generate either PageRegion or PageSize code (depending
        // on whether a tray was selected).

        bRegion = IsManual || (pInputSlot != NULL);

        DscBeginFeature(pdev, bRegion ? "PageRegion" : "PageSize");
        psprintf(pdev, " %s\n", pdev->CurForm.PaperName);

        // Find the invocation string to send to the printer

        pMediaOption = (PMEDIAOPTION)
                       LISTOBJ_FindIndexed(
                           (PLISTOBJ) hppd->pPageSizes->pUiOptions,
                           pdev->CurForm.featureIndex);

        if (pMediaOption != NULL) {

            pstr = bRegion ?
                   pMediaOption->pPageRgnCode :
                   pMediaOption->pPageSizeCode;

            if (pstr != NULL) {
                psputs(pdev, pstr);
            }
        }

        DscEndFeature(pdev);
    }
}
Exemplo n.º 25
0
/* cash_out()
 * Function to convert cash to a dollars and cents representation, using
 * the lc_monetary locale's formatting.
 */
Datum
cash_out(PG_FUNCTION_ARGS)
{
	Cash		value = PG_GETARG_CASH(0);
	char	   *result;
	char		buf[128];
	char	   *bufptr;
	int			digit_pos;
	int			points,
				mon_group;
	char		dsymbol;
	const char *ssymbol,
			   *csymbol,
			   *signsymbol;
	char		sign_posn,
				cs_precedes,
				sep_by_space;
	struct lconv *lconvert = PGLC_localeconv();

	/* see comments about frac_digits in cash_in() */
	points = lconvert->frac_digits;
	if (points < 0 || points > 10)
		points = 2;				/* best guess in this case, I think */

	/*
	 * As with frac_digits, must apply a range check to mon_grouping to avoid
	 * being fooled by variant CHAR_MAX values.
	 */
	mon_group = *lconvert->mon_grouping;
	if (mon_group <= 0 || mon_group > 6)
		mon_group = 3;

	/* we restrict dsymbol to be a single byte, but not the other symbols */
	if (*lconvert->mon_decimal_point != '\0' &&
		lconvert->mon_decimal_point[1] == '\0')
		dsymbol = *lconvert->mon_decimal_point;
	else
		dsymbol = '.';
	if (*lconvert->mon_thousands_sep != '\0')
		ssymbol = lconvert->mon_thousands_sep;
	else						/* ssymbol should not equal dsymbol */
		ssymbol = (dsymbol != ',') ? "," : ".";
	csymbol = (*lconvert->currency_symbol != '\0') ? lconvert->currency_symbol : "$";

	if (value < 0)
	{
		/* make the amount positive for digit-reconstruction loop */
		value = -value;
		/* set up formatting data */
		signsymbol = (*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-";
		sign_posn = lconvert->n_sign_posn;
		cs_precedes = lconvert->n_cs_precedes;
		sep_by_space = lconvert->n_sep_by_space;
	}
	else
	{
		signsymbol = lconvert->positive_sign;
		sign_posn = lconvert->p_sign_posn;
		cs_precedes = lconvert->p_cs_precedes;
		sep_by_space = lconvert->p_sep_by_space;
	}

	/* we build the digits+decimal-point+sep string right-to-left in buf[] */
	bufptr = buf + sizeof(buf) - 1;
	*bufptr = '\0';

	/*
	 * Generate digits till there are no non-zero digits left and we emitted
	 * at least one to the left of the decimal point.  digit_pos is the
	 * current digit position, with zero as the digit just left of the decimal
	 * point, increasing to the right.
	 */
	digit_pos = points;
	do
	{
		if (points && digit_pos == 0)
		{
			/* insert decimal point, but not if value cannot be fractional */
			*(--bufptr) = dsymbol;
		}
		else if (digit_pos < 0 && (digit_pos % mon_group) == 0)
		{
			/* insert thousands sep, but only to left of radix point */
			bufptr -= strlen(ssymbol);
			memcpy(bufptr, ssymbol, strlen(ssymbol));
		}

		*(--bufptr) = ((uint64) value % 10) + '0';
		value = ((uint64) value) / 10;
		digit_pos--;
	} while (value || digit_pos >= 0);

	/*----------
	 * Now, attach currency symbol and sign symbol in the correct order.
	 *
	 * The POSIX spec defines these values controlling this code:
	 *
	 * p/n_sign_posn:
	 *	0	Parentheses enclose the quantity and the currency_symbol.
	 *	1	The sign string precedes the quantity and the currency_symbol.
	 *	2	The sign string succeeds the quantity and the currency_symbol.
	 *	3	The sign string precedes the currency_symbol.
	 *	4	The sign string succeeds the currency_symbol.
	 *
	 * p/n_cs_precedes: 0 means currency symbol after value, else before it.
	 *
	 * p/n_sep_by_space:
	 *	0	No <space> separates the currency symbol and value.
	 *	1	If the currency symbol and sign string are adjacent, a <space>
	 *		separates them from the value; otherwise, a <space> separates
	 *		the currency symbol from the value.
	 *	2	If the currency symbol and sign string are adjacent, a <space>
	 *		separates them; otherwise, a <space> separates the sign string
	 *		from the value.
	 *----------
	 */
	switch (sign_posn)
	{
		case 0:
			if (cs_precedes)
				result = psprintf("(%s%s%s)",
								  csymbol,
								  (sep_by_space == 1) ? " " : "",
								  bufptr);
			else
				result = psprintf("(%s%s%s)",
								  bufptr,
								  (sep_by_space == 1) ? " " : "",
								  csymbol);
			break;
		case 1:
		default:
			if (cs_precedes)
				result = psprintf("%s%s%s%s%s",
								  signsymbol,
								  (sep_by_space == 2) ? " " : "",
								  csymbol,
								  (sep_by_space == 1) ? " " : "",
								  bufptr);
			else
				result = psprintf("%s%s%s%s%s",
								  signsymbol,
								  (sep_by_space == 2) ? " " : "",
								  bufptr,
								  (sep_by_space == 1) ? " " : "",
								  csymbol);
			break;
		case 2:
			if (cs_precedes)
				result = psprintf("%s%s%s%s%s",
								  csymbol,
								  (sep_by_space == 1) ? " " : "",
								  bufptr,
								  (sep_by_space == 2) ? " " : "",
								  signsymbol);
			else
				result = psprintf("%s%s%s%s%s",
								  bufptr,
								  (sep_by_space == 1) ? " " : "",
								  csymbol,
								  (sep_by_space == 2) ? " " : "",
								  signsymbol);
			break;
		case 3:
			if (cs_precedes)
				result = psprintf("%s%s%s%s%s",
								  signsymbol,
								  (sep_by_space == 2) ? " " : "",
								  csymbol,
								  (sep_by_space == 1) ? " " : "",
								  bufptr);
			else
				result = psprintf("%s%s%s%s%s",
								  bufptr,
								  (sep_by_space == 1) ? " " : "",
								  signsymbol,
								  (sep_by_space == 2) ? " " : "",
								  csymbol);
			break;
		case 4:
			if (cs_precedes)
				result = psprintf("%s%s%s%s%s",
								  csymbol,
								  (sep_by_space == 2) ? " " : "",
								  signsymbol,
								  (sep_by_space == 1) ? " " : "",
								  bufptr);
			else
				result = psprintf("%s%s%s%s%s",
								  bufptr,
								  (sep_by_space == 1) ? " " : "",
								  csymbol,
								  (sep_by_space == 2) ? " " : "",
								  signsymbol);
			break;
	}

	PG_RETURN_CSTRING(result);
}
Exemplo n.º 26
0
BOOL
bOutputHeader(
    PDEVDATA pdev
)

/*++

Routine Description:

    Send PostScript output header to the printer

Arguments:

    pdev - Pointer to our DEVDATA

Return Value:

    TRUE if successful, FALSE otherwise

--*/

{
    CHAR           *pstr;
    HPPD            hppd = pdev->hppd;
    ENG_TIME_FIELDS localtime;

    //
    // Process information in the public devmode fields and map it to printer
    // feature selections. This must be called before PsSelectPrinterFeatures.
    //

    HandlePublicDevmodeOptions(pdev);

    //
    // Spit out job control stuff at the beginning of a job if necessary
    //

    if (! bPageIndependence(pdev) &&
            ! (pdev->dm.dmPrivate.dwFlags & PSDEVMODE_NO_JOB_CONTROL))
    {
        if (PpdSupportsProtocol(hppd, PROTOCOL_PJL)) {

            // Universal exit language

            if (hppd->pJclBegin != NULL) {

                psputs(pdev, hppd->pJclBegin);
            } else {

                DBGMSG(DBG_LEVEL_TERSE, "No JCLBegin code.\n");
                psputs(pdev, "\033%-12345X");
            }

            // If the printer uses PJL commands to set resolution,
            // then do it before the job.

            SetResolution(pdev, pdev->dm.dmPublic.dmPrintQuality, RESTYPE_JCL);

            // Select printer specific features - JCLSetup

            PsSelectPrinterFeatures(pdev, ODS_JCLSETUP);

            // if the printer supports job switching, put the printer into
            // postscript mode now.

            if (hppd->pJclToPs != NULL) {

                psputs(pdev, hppd->pJclToPs);
            } else {

                DBGMSG(DBG_LEVEL_TERSE, "No JCLToPSInterpreter code.\n");
                psputs(pdev, "@PJL ENTER LANGUAGE=POSTSCRIPT\n");
            }

        } else if (PpdSupportsProtocol(hppd, PROTOCOL_SIC)) {

            // directly call pswrite to output the necessary escape commands.
            // psputs will NOT output '\000'.

            pswrite(pdev, "\033\133\113\030\000\006\061\010\000\000\000\000\000", 13);
            pswrite(pdev, "\000\000\000\000\000\000\000\000\004\033\133\113\003", 13);
            pswrite(pdev, "\000\006\061\010\004", 5);

        } else if (pdev->dm.dmPrivate.dwFlags & PSDEVMODE_CTRLD_BEFORE) {

            // send a ^D before the job

            pswrite(pdev, "\004", 1);
        }
    }

    psputs(pdev, "%!PS-Adobe-3.0\n");

    // output the title of the document.

    if (pdev->pwstrDocName) {

        CHAR    buf[128];

        CopyUnicode2Str(buf, pdev->pwstrDocName, 128);

        psprintf(pdev, "%%%%Title: %s\n", buf);
    } else
        psputs(pdev, "%%Title: Untitled Document\n");

    // let the world know who we are.

    psputs(pdev, "%%Creator: Windows NT 4.0\n");

    // print the date and time of creation.

    EngQueryLocalTime(&localtime);

    psprintf(pdev, "%%%%CreationDate: %d:%d %d/%d/%d\n",
             localtime.usHour,
             localtime.usMinute,
             localtime.usMonth,
             localtime.usDay,
             localtime.usYear);

    if (! (pdev->dwFlags & PDEV_EPSPRINTING_ESCAPE))
        psputs(pdev, "%%Pages: (atend)\n");

    // mark the bounding box of the document.

    psputs(pdev, "%%BoundingBox: ");

    psprintf(pdev, "%d %d %d %d\n",
             PSREAL2INT(pdev->CurForm.ImageArea.left),
             PSREAL2INT(pdev->CurForm.ImageArea.bottom),
             PSREAL2INT(pdev->CurForm.ImageArea.right),
             PSREAL2INT(pdev->CurForm.ImageArea.top));


    if (pdev->cCopies > 1)
        psprintf(pdev, "%%%%Requirements: numcopies(%d) collate\n", pdev->cCopies);

    DscLanguageLevel(pdev, pdev->hppd->dwLangLevel);
    DscOutputFontComments(pdev, FALSE);

    // we are done with the comments portion of the document.

    psputs(pdev, "%%EndComments\n");

    // If the printer uses exitserver commands to set
    // resolution, then do it before any other PS code.

    SetResolution(pdev, pdev->dm.dmPublic.dmPrintQuality, RESTYPE_EXITSERVER);

    // define our procedure set.

    if (!(pdev->dwFlags & PDEV_EPSPRINTING_ESCAPE)) {

        psputs(pdev, "%%BeginProlog\n");
        DownloadNTProcSet(pdev, TRUE);
        psputs(pdev, "%%EndProlog\n");
    }

    // do the device setup.

    psputs(pdev, "%%BeginSetup\n");

    // set job and wait timeout values

    SetTimeoutValues(pdev);

    // Set number of copies

    psprintf(pdev, "/#copies %d def\n", pdev->cCopies);

    // Select printer specific features - DocumentSetup and AnySetup

    PsSelectPrinterFeatures(pdev, ODS_DOCSETUP|ODS_ANYSETUP);

    // The implemention of EPSPRINTING escape here just follows Win31

    if ((pdev->dwFlags & PDEV_EPSPRINTING_ESCAPE) &&
            (pdev->dm.dmPublic.dmOrientation == DMORIENT_LANDSCAPE))
    {
        SetLandscape(pdev, TRUE, pdev->CurForm.PaperSize.height, pdev->CurForm.PaperSize.width);
    }

    //
    // Invert the default transfer function if Negative Output option is selected
    //

    if (pdev->dm.dmPrivate.dwFlags & PSDEVMODE_NEG) {

        psputs(pdev, "[currenttransfer /exec load {1 exch sub} /exec load] cvx settransfer\n");
    }

    psputs(pdev, "%%EndSetup\n");

    // the form-tray information has already been sent for the first page.

    pdev->dwFlags &= ~PDEV_RESETPDEV;

    return(TRUE);
}
Exemplo n.º 27
0
/*
 * Check given password for given user, and return STATUS_OK or STATUS_ERROR.
 * In the error case, optionally store a palloc'd string at *logdetail
 * that will be sent to the postmaster log (but not the client).
 */
int
md5_crypt_verify(const Port *port, const char *role, char *client_pass,
				 char **logdetail)
{
	int			retval = STATUS_ERROR;
	char	   *shadow_pass,
			   *crypt_pwd;
	TimestampTz vuntil = 0;
	char	   *crypt_client_pass = client_pass;
	HeapTuple	roleTup;
	Datum		datum;
	bool		isnull;

	/* Get role info from pg_authid */
	roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
	if (!HeapTupleIsValid(roleTup))
	{
		*logdetail = psprintf(_("Role \"%s\" does not exist."),
							  role);
		return STATUS_ERROR;	/* no such user */
	}

	datum = SysCacheGetAttr(AUTHNAME, roleTup,
							Anum_pg_authid_rolpassword, &isnull);
	if (isnull)
	{
		ReleaseSysCache(roleTup);
		*logdetail = psprintf(_("User \"%s\" has no password assigned."),
							  role);
		return STATUS_ERROR;	/* user has no password */
	}
	shadow_pass = TextDatumGetCString(datum);

	datum = SysCacheGetAttr(AUTHNAME, roleTup,
							Anum_pg_authid_rolvaliduntil, &isnull);
	if (!isnull)
		vuntil = DatumGetTimestampTz(datum);

	ReleaseSysCache(roleTup);

	if (*shadow_pass == '\0')
	{
		*logdetail = psprintf(_("User \"%s\" has an empty password."),
							  role);
		return STATUS_ERROR;	/* empty password */
	}

	/*
	 * Compare with the encrypted or plain password depending on the
	 * authentication method being used for this connection.  (We do not
	 * bother setting logdetail for pg_md5_encrypt failure: the only possible
	 * error is out-of-memory, which is unlikely, and if it did happen adding
	 * a psprintf call would only make things worse.)
	 */
	switch (port->hba->auth_method)
	{
		case uaMD5:
			crypt_pwd = palloc(MD5_PASSWD_LEN + 1);
			if (isMD5(shadow_pass))
			{
				/* stored password already encrypted, only do salt */
				if (!pg_md5_encrypt(shadow_pass + strlen("md5"),
									port->md5Salt,
									sizeof(port->md5Salt), crypt_pwd))
				{
					pfree(crypt_pwd);
					return STATUS_ERROR;
				}
			}
			else
			{
				/* stored password is plain, double-encrypt */
				char	   *crypt_pwd2 = palloc(MD5_PASSWD_LEN + 1);

				if (!pg_md5_encrypt(shadow_pass,
									port->user_name,
									strlen(port->user_name),
									crypt_pwd2))
				{
					pfree(crypt_pwd);
					pfree(crypt_pwd2);
					return STATUS_ERROR;
				}
				if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"),
									port->md5Salt,
									sizeof(port->md5Salt),
									crypt_pwd))
				{
					pfree(crypt_pwd);
					pfree(crypt_pwd2);
					return STATUS_ERROR;
				}
				pfree(crypt_pwd2);
			}
			break;
		default:
			if (isMD5(shadow_pass))
			{
				/* Encrypt user-supplied password to match stored MD5 */
				crypt_client_pass = palloc(MD5_PASSWD_LEN + 1);
				if (!pg_md5_encrypt(client_pass,
									port->user_name,
									strlen(port->user_name),
									crypt_client_pass))
				{
					pfree(crypt_client_pass);
					return STATUS_ERROR;
				}
			}
			crypt_pwd = shadow_pass;
			break;
	}

	if (strcmp(crypt_client_pass, crypt_pwd) == 0)
	{
		/*
		 * Password OK, now check to be sure we are not past rolvaliduntil
		 */
		if (isnull)
			retval = STATUS_OK;
		else if (vuntil < GetCurrentTimestamp())
		{
			*logdetail = psprintf(_("User \"%s\" has an expired password."),
								  role);
			retval = STATUS_ERROR;
		}
		else
			retval = STATUS_OK;
	}
	else
		*logdetail = psprintf(_("Password does not match for user \"%s\"."),
							  role);

	if (port->hba->auth_method == uaMD5)
		pfree(crypt_pwd);
	if (crypt_client_pass != client_pass)
		pfree(crypt_client_pass);

	return retval;
}
Exemplo n.º 28
0
VOID
PsSelectCustomPageSize(
    PDEVDATA    pdev
)

/*++

Routine Description:

    Generate PostScript code to select custom page size
    on the printer.

Arguments:

    pdev    Pointer to DEVDATA structure

Return Value:

    NONE

--*/

{
    PSREAL  params[MAXPCP];
    INT     index;
    HPPD    hppd = pdev->hppd;
    PSREAL  xlen, ylen;

    // Sanity check: if no custom page size invocation is provided,
    // simply return with emitting anything.

    if (hppd->pCustomSizeCode == NULL) {

        DBGMSG(DBG_LEVEL_WARNING,
               "No invocation string for custom page size.\n");
        return;
    }

    // Generate parameters for custom page size invocation
    // Sort them according to the order specified in PPD file

    for (index=0; index < MAXPCP; index++)
        params[index] = 0;

    // Figure out size of the physical page along x- and y-axis
    //
    // Undo the effect of AdjustForLandscape here:
    // in landscape mode, CurForm.PaperSize.width and
    // and CurForm.PaperSize.height were swapped.

    if (pdev->CurForm.bLandscape) {

        xlen = pdev->CurForm.PaperSize.height;
        ylen = pdev->CurForm.PaperSize.width;
    } else {

        xlen = pdev->CurForm.PaperSize.width;
        ylen = pdev->CurForm.PaperSize.height;
    }

    if (! hppd->bCutSheet) {

        PSREAL  maxWidth, maxHeight, tmpPsreal;

        // For roll-fed devices, choose orientation 0 or 1
        // depending on whether width is bigger than height

        maxWidth = hppd->maxMediaWidth -
                   hppd->customParam[PCP_WIDTHOFFSET].minVal;

        maxHeight = hppd->maxMediaHeight -
                    hppd->customParam[PCP_HEIGHTOFFSET].minVal;

        if (xlen <= ylen && ylen <= maxWidth && xlen <= maxHeight) {

            // Use orientation 0: ylen is used as width parameter
            // and xlen is used as height parameter

            if (hppd->customParam[PCP_ORIENTATION].minVal > 0) {

                DBGMSG(DBG_LEVEL_ERROR,
                       "Device does not support orientation 0.\n");
            }

            tmpPsreal = xlen;
            xlen = ylen;
            ylen = tmpPsreal;

        } else {

            // Use orientation 1

            if (hppd->customParam[PCP_ORIENTATION].maxVal < 1) {

                DBGMSG(DBG_LEVEL_ERROR,
                       "Device does not support orientation 1.\n");
            }

            params[hppd->customParam[PCP_ORIENTATION].dwOrder - 1] = 1;
        }
    }

    params[hppd->customParam[PCP_WIDTH].dwOrder - 1] = xlen;
    params[hppd->customParam[PCP_HEIGHT].dwOrder - 1] = ylen;

    // Use minimum width and height offsets

    params[hppd->customParam[PCP_WIDTHOFFSET].dwOrder - 1] =
        hppd->customParam[PCP_WIDTHOFFSET].minVal;

    params[hppd->customParam[PCP_HEIGHTOFFSET].dwOrder - 1] =
        hppd->customParam[PCP_HEIGHTOFFSET].minVal;

    // Emit custom page size parameters and invocation string

    for (index=0; index < MAXPCP; index++)
        psprintf(pdev, "%f ", params[index]);
    psputs(pdev, hppd->pCustomSizeCode);
    psputs(pdev, "\n");
}
Exemplo n.º 29
0
char *
widget_out(WIDGET *widget)
{
	return psprintf("(%g,%g,%g)",
					widget->center.x, widget->center.y, widget->radius);
}
Exemplo n.º 30
0
BOOL bOutput24bppBitmapAsMask(
    PDEVDATA pdev,
    SURFOBJ *psoSrc,
    PPOINTL pptlSrc,
    PRECTL  prclDst)
{
    RGBTRIPLE *prgbAlt = NULL;
    PBYTE      pjStart,pjBits;
    int        x,y;
    LONG       cx,cy,xLeft,yTop;

// compute the area to actualy draw, the smaller of the src or dest

    xLeft = max(0,pptlSrc->x);
    yTop  = max(0,pptlSrc->y);
    cx    = min(prclDst->right - prclDst->left,psoSrc->sizlBitmap.cx - xLeft);
    cy    = min(prclDst->bottom - prclDst->top,psoSrc->sizlBitmap.cy - yTop);

// first go over the bitmap to find the first non white pixel

    pjStart = (PBYTE)psoSrc->pvScan0 +
             xLeft * sizeof(RGBTRIPLE) +
             yTop  * psoSrc->lDelta;

    pjBits = pjStart;

    for (y = yTop; (prgbAlt == NULL) && (y < (yTop + cy));
         ++y, pjBits += psoSrc->lDelta)
    {
        RGBTRIPLE *prgb = (RGBTRIPLE*)pjBits;

        for (x = xLeft; x < (xLeft + cx); ++x, ++prgb)
        {
            if ((prgb->rgbtBlue & prgb->rgbtGreen & prgb->rgbtRed) != 0xff)
            {
            // found a non white pixel

                prgbAlt = prgb;
                break;
            }
        }
    }

    if (prgbAlt == NULL)
        return(TRUE);

// prgbAlt now points to an RGB value for the alternate color.  If we didn't
// find an alternate color we use white.  In the future for performance we could
// replace the ROP by SRCCOPY.  Not much reason to optimize for this case now
// since it shouldn't happen

// output the header information

    psputs(pdev, "gsave\n");

    psprintf(pdev, "%d %d translate\n", prclDst->left, prclDst->top);
    psprintf(pdev, "%d %d scale\n", cx, cy);

// r g b setrgbcolor

    psprintf(pdev, "%d 256 div ", prgbAlt->rgbtRed);
    psprintf(pdev, "%d 256 div ", prgbAlt->rgbtGreen);
    psprintf(pdev, "%d 256 div setrgbcolor\n", prgbAlt->rgbtBlue);

	psprintf(pdev, "/str2 %d string def\n", (cx+7) / 8);

// size of mask

    psprintf(pdev, "%d %d", cx, cy);

// paint the 0's, leave the 1's alone

    psputs(pdev, "\nfalse\n");

// [cx 0 0 cy 0 0]

	psprintf(pdev, "[%d 0 0 %d 0 0]\n", cx, cy);

// get ready for the data

    psputs (pdev, "{currentfile str2 readhexstring pop}bind imagemask\n");

// Now go through the bitmap output ascii hex values for each byte of the mask.
// 1's should be left alone, 0's should be set to the alternate color.

    pjBits = pjStart;

    for (y = yTop; y < (yTop + cy); ++y, pjBits += psoSrc->lDelta)
    {
        RGBTRIPLE *prgb = (RGBTRIPLE*)pjBits;
        int c = 0;

        for (x = xLeft; x < (xLeft + cx);)
        {
            BYTE jMask;
            int  i;

            for (i = 0; (i < 8) && (x < (xLeft + cx)); ++i, ++x, ++prgb)
            {

                jMask <<= 1;

                if ((prgb->rgbtBlue & prgb->rgbtGreen & prgb->rgbtRed) == 0xff)
                {
                // non white pixel

                    jMask |= 1;
                }
            }

        // if we got to the end without filling up the last byte, fill it with 1's

            jMask = (jMask << (8 - i)) | ajOrBits[i];

            psputhex(pdev, 1, &jMask);

        // add a line feed every 80 bytes of data

            if ((c++ == 80) &&
                (x < (xLeft + cx)))
            {
                c = 0;
                psputs(pdev,"\n");
            }
        }
        psputs(pdev,"\n");
    }

// restore the state

    psputs(pdev,"grestore\n");

    return(TRUE);
}