Blame fdtput.c

Packit Service 87beb7
// SPDX-License-Identifier: GPL-2.0-or-later
Packit Service 87beb7
/*
Packit Service 87beb7
 * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
Packit Service 87beb7
 */
Packit Service 87beb7
Packit Service 87beb7
#include <assert.h>
Packit Service 87beb7
#include <ctype.h>
Packit Service 87beb7
#include <getopt.h>
Packit Service 87beb7
#include <stdio.h>
Packit Service 87beb7
#include <stdlib.h>
Packit Service 87beb7
#include <string.h>
Packit Service 87beb7
Packit Service 87beb7
#include <libfdt.h>
Packit Service 87beb7
Packit Service 87beb7
#include "util.h"
Packit Service 87beb7
Packit Service 87beb7
/* These are the operations we support */
Packit Service 87beb7
enum oper_type {
Packit Service 87beb7
	OPER_WRITE_PROP,		/* Write a property in a node */
Packit Service 87beb7
	OPER_CREATE_NODE,		/* Create a new node */
Packit Service 87beb7
	OPER_REMOVE_NODE,		/* Delete a node */
Packit Service 87beb7
	OPER_DELETE_PROP,		/* Delete a property in a node */
Packit Service 87beb7
};
Packit Service 87beb7
Packit Service 87beb7
struct display_info {
Packit Service 87beb7
	enum oper_type oper;	/* operation to perform */
Packit Service 87beb7
	int type;		/* data type (s/i/u/x or 0 for default) */
Packit Service 87beb7
	int size;		/* data size (1/2/4) */
Packit Service 87beb7
	int verbose;		/* verbose output */
Packit Service 87beb7
	int auto_path;		/* automatically create all path components */
Packit Service 87beb7
};
Packit Service 87beb7
Packit Service 87beb7
Packit Service 87beb7
/**
Packit Service 87beb7
 * Report an error with a particular node.
Packit Service 87beb7
 *
Packit Service 87beb7
 * @param name		Node name to report error on
Packit Service 87beb7
 * @param namelen	Length of node name, or -1 to use entire string
Packit Service 87beb7
 * @param err		Error number to report (-FDT_ERR_...)
Packit Service 87beb7
 */
Packit Service 87beb7
static void report_error(const char *name, int namelen, int err)
Packit Service 87beb7
{
Packit Service 87beb7
	if (namelen == -1)
Packit Service 87beb7
		namelen = strlen(name);
Packit Service 87beb7
	fprintf(stderr, "Error at '%1.*s': %s\n", namelen, name,
Packit Service 87beb7
		fdt_strerror(err));
Packit Service 87beb7
}
Packit Service 87beb7
Packit Service 87beb7
/**
Packit Service 87beb7
 * Encode a series of arguments in a property value.
Packit Service 87beb7
 *
Packit Service 87beb7
 * @param disp		Display information / options
Packit Service 87beb7
 * @param arg		List of arguments from command line
Packit Service 87beb7
 * @param arg_count	Number of arguments (may be 0)
Packit Service 87beb7
 * @param valuep	Returns buffer containing value
Packit Service 87beb7
 * @param value_len	Returns length of value encoded
Packit Service 87beb7
 */
Packit Service 87beb7
static int encode_value(struct display_info *disp, char **arg, int arg_count,
Packit Service 87beb7
			char **valuep, int *value_len)
Packit Service 87beb7
{
Packit Service 87beb7
	char *value = NULL;	/* holding area for value */
Packit Service 87beb7
	int value_size = 0;	/* size of holding area */
Packit Service 87beb7
	char *ptr;		/* pointer to current value position */
Packit Service 87beb7
	int len;		/* length of this cell/string/byte */
Packit Service 87beb7
	int ival;
Packit Service 87beb7
	int upto;	/* the number of bytes we have written to buf */
Packit Service 87beb7
	char fmt[3];
Packit Service 87beb7
Packit Service 87beb7
	upto = 0;
Packit Service 87beb7
Packit Service 87beb7
	if (disp->verbose)
Packit Service 87beb7
		fprintf(stderr, "Decoding value:\n");
Packit Service 87beb7
Packit Service 87beb7
	fmt[0] = '%';
Packit Service 87beb7
	fmt[1] = disp->type ? disp->type : 'd';
Packit Service 87beb7
	fmt[2] = '\0';
Packit Service 87beb7
	for (; arg_count > 0; arg++, arg_count--, upto += len) {
Packit Service 87beb7
		/* assume integer unless told otherwise */
Packit Service 87beb7
		if (disp->type == 's')
Packit Service 87beb7
			len = strlen(*arg) + 1;
Packit Service 87beb7
		else
Packit Service 87beb7
			len = disp->size == -1 ? 4 : disp->size;
Packit Service 87beb7
Packit Service 87beb7
		/* enlarge our value buffer by a suitable margin if needed */
Packit Service 87beb7
		if (upto + len > value_size) {
Packit Service 87beb7
			value_size = (upto + len) + 500;
Packit Service 87beb7
			value = xrealloc(value, value_size);
Packit Service 87beb7
		}
Packit Service 87beb7
Packit Service 87beb7
		ptr = value + upto;
Packit Service 87beb7
		if (disp->type == 's') {
Packit Service 87beb7
			memcpy(ptr, *arg, len);
Packit Service 87beb7
			if (disp->verbose)
Packit Service 87beb7
				fprintf(stderr, "\tstring: '%s'\n", ptr);
Packit Service 87beb7
		} else {
Packit Service 87beb7
			fdt32_t *iptr = (fdt32_t *)ptr;
Packit Service 87beb7
			sscanf(*arg, fmt, &ival);
Packit Service 87beb7
			if (len == 4)
Packit Service 87beb7
				*iptr = cpu_to_fdt32(ival);
Packit Service 87beb7
			else
Packit Service 87beb7
				*ptr = (uint8_t)ival;
Packit Service 87beb7
			if (disp->verbose) {
Packit Service 87beb7
				fprintf(stderr, "\t%s: %d\n",
Packit Service 87beb7
					disp->size == 1 ? "byte" :
Packit Service 87beb7
					disp->size == 2 ? "short" : "int",
Packit Service 87beb7
					ival);
Packit Service 87beb7
			}
Packit Service 87beb7
		}
Packit Service 87beb7
	}
Packit Service 87beb7
	*value_len = upto;
Packit Service 87beb7
	*valuep = value;
Packit Service 87beb7
	if (disp->verbose)
Packit Service 87beb7
		fprintf(stderr, "Value size %d\n", upto);
Packit Service 87beb7
	return 0;
Packit Service 87beb7
}
Packit Service 87beb7
Packit Service 87beb7
#define ALIGN(x)		(((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1))
Packit Service 87beb7
Packit Service 87beb7
static char *realloc_fdt(char *fdt, int delta)
Packit Service 87beb7
{
Packit Service 87beb7
	int new_sz = fdt_totalsize(fdt) + delta;
Packit Service 87beb7
	fdt = xrealloc(fdt, new_sz);
Packit Service 87beb7
	fdt_open_into(fdt, fdt, new_sz);
Packit Service 87beb7
	return fdt;
Packit Service 87beb7
}
Packit Service 87beb7
Packit Service 87beb7
static char *realloc_node(char *fdt, const char *name)
Packit Service 87beb7
{
Packit Service 87beb7
	int delta;
Packit Service 87beb7
	/* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */
Packit Service 87beb7
	delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1)
Packit Service 87beb7
			+ FDT_TAGSIZE;
Packit Service 87beb7
	return realloc_fdt(fdt, delta);
Packit Service 87beb7
}
Packit Service 87beb7
Packit Service 87beb7
static char *realloc_property(char *fdt, int nodeoffset,
Packit Service 87beb7
		const char *name, int newlen)
Packit Service 87beb7
{
Packit Service 87beb7
	int delta = 0;
Packit Service 87beb7
	int oldlen = 0;
Packit Service 87beb7
Packit Service 87beb7
	if (!fdt_get_property(fdt, nodeoffset, name, &oldlen))
Packit Service 87beb7
		/* strings + property header */
Packit Service 87beb7
		delta = sizeof(struct fdt_property) + strlen(name) + 1;
Packit Service 87beb7
Packit Service 87beb7
	if (newlen > oldlen)
Packit Service 87beb7
		/* actual value in off_struct */
Packit Service 87beb7
		delta += ALIGN(newlen) - ALIGN(oldlen);
Packit Service 87beb7
Packit Service 87beb7
	return realloc_fdt(fdt, delta);
Packit Service 87beb7
}
Packit Service 87beb7
Packit Service 87beb7
static int store_key_value(char **blob, const char *node_name,
Packit Service 87beb7
		const char *property, const char *buf, int len)
Packit Service 87beb7
{
Packit Service 87beb7
	int node;
Packit Service 87beb7
	int err;
Packit Service 87beb7
Packit Service 87beb7
	node = fdt_path_offset(*blob, node_name);
Packit Service 87beb7
	if (node < 0) {
Packit Service 87beb7
		report_error(node_name, -1, node);
Packit Service 87beb7
		return -1;
Packit Service 87beb7
	}
Packit Service 87beb7
Packit Service 87beb7
	err = fdt_setprop(*blob, node, property, buf, len);
Packit Service 87beb7
	if (err == -FDT_ERR_NOSPACE) {
Packit Service 87beb7
		*blob = realloc_property(*blob, node, property, len);
Packit Service 87beb7
		err = fdt_setprop(*blob, node, property, buf, len);
Packit Service 87beb7
	}
Packit Service 87beb7
	if (err) {
Packit Service 87beb7
		report_error(property, -1, err);
Packit Service 87beb7
		return -1;
Packit Service 87beb7
	}
Packit Service 87beb7
	return 0;
Packit Service 87beb7
}
Packit Service 87beb7
Packit Service 87beb7
/**
Packit Service 87beb7
 * Create paths as needed for all components of a path
Packit Service 87beb7
 *
Packit Service 87beb7
 * Any components of the path that do not exist are created. Errors are
Packit Service 87beb7
 * reported.
Packit Service 87beb7
 *
Packit Service 87beb7
 * @param blob		FDT blob to write into
Packit Service 87beb7
 * @param in_path	Path to process
Packit Service 87beb7
 * @return 0 if ok, -1 on error
Packit Service 87beb7
 */
Packit Service 87beb7
static int create_paths(char **blob, const char *in_path)
Packit Service 87beb7
{
Packit Service 87beb7
	const char *path = in_path;
Packit Service 87beb7
	const char *sep;
Packit Service 87beb7
	int node, offset = 0;
Packit Service 87beb7
Packit Service 87beb7
	/* skip leading '/' */
Packit Service 87beb7
	while (*path == '/')
Packit Service 87beb7
		path++;
Packit Service 87beb7
Packit Service 87beb7
	for (sep = path; *sep; path = sep + 1, offset = node) {
Packit Service 87beb7
		/* equivalent to strchrnul(), but it requires _GNU_SOURCE */
Packit Service 87beb7
		sep = strchr(path, '/');
Packit Service 87beb7
		if (!sep)
Packit Service 87beb7
			sep = path + strlen(path);
Packit Service 87beb7
Packit Service 87beb7
		node = fdt_subnode_offset_namelen(*blob, offset, path,
Packit Service 87beb7
				sep - path);
Packit Service 87beb7
		if (node == -FDT_ERR_NOTFOUND) {
Packit Service 87beb7
			*blob = realloc_node(*blob, path);
Packit Service 87beb7
			node = fdt_add_subnode_namelen(*blob, offset, path,
Packit Service 87beb7
						       sep - path);
Packit Service 87beb7
		}
Packit Service 87beb7
		if (node < 0) {
Packit Service 87beb7
			report_error(path, sep - path, node);
Packit Service 87beb7
			return -1;
Packit Service 87beb7
		}
Packit Service 87beb7
	}
Packit Service 87beb7
Packit Service 87beb7
	return 0;
Packit Service 87beb7
}
Packit Service 87beb7
Packit Service 87beb7
/**
Packit Service 87beb7
 * Create a new node in the fdt.
Packit Service 87beb7
 *
Packit Service 87beb7
 * This will overwrite the node_name string. Any error is reported.
Packit Service 87beb7
 *
Packit Service 87beb7
 * TODO: Perhaps create fdt_path_offset_namelen() so we don't need to do this.
Packit Service 87beb7
 *
Packit Service 87beb7
 * @param blob		FDT blob to write into
Packit Service 87beb7
 * @param node_name	Name of node to create
Packit Service 87beb7
 * @return new node offset if found, or -1 on failure
Packit Service 87beb7
 */
Packit Service 87beb7
static int create_node(char **blob, const char *node_name)
Packit Service 87beb7
{
Packit Service 87beb7
	int node = 0;
Packit Service 87beb7
	char *p;
Packit Service 87beb7
Packit Service 87beb7
	p = strrchr(node_name, '/');
Packit Service 87beb7
	if (!p) {
Packit Service 87beb7
		report_error(node_name, -1, -FDT_ERR_BADPATH);
Packit Service 87beb7
		return -1;
Packit Service 87beb7
	}
Packit Service 87beb7
	*p = '\0';
Packit Service 87beb7
Packit Service 87beb7
	*blob = realloc_node(*blob, p + 1);
Packit Service 87beb7
Packit Service 87beb7
	if (p > node_name) {
Packit Service 87beb7
		node = fdt_path_offset(*blob, node_name);
Packit Service 87beb7
		if (node < 0) {
Packit Service 87beb7
			report_error(node_name, -1, node);
Packit Service 87beb7
			return -1;
Packit Service 87beb7
		}
Packit Service 87beb7
	}
Packit Service 87beb7
Packit Service 87beb7
	node = fdt_add_subnode(*blob, node, p + 1);
Packit Service 87beb7
	if (node < 0) {
Packit Service 87beb7
		report_error(p + 1, -1, node);
Packit Service 87beb7
		return -1;
Packit Service 87beb7
	}
Packit Service 87beb7
Packit Service 87beb7
	return 0;
Packit Service 87beb7
}
Packit Service 87beb7
Packit Service 87beb7
/**
Packit Service 87beb7
 * Delete a property of a node in the fdt.
Packit Service 87beb7
 *
Packit Service 87beb7
 * @param blob		FDT blob to write into
Packit Service 87beb7
 * @param node_name	Path to node containing the property to delete
Packit Service 87beb7
 * @param prop_name	Name of property to delete
Packit Service 87beb7
 * @return 0 on success, or -1 on failure
Packit Service 87beb7
 */
Packit Service 87beb7
static int delete_prop(char *blob, const char *node_name, const char *prop_name)
Packit Service 87beb7
{
Packit Service 87beb7
	int node = 0;
Packit Service 87beb7
Packit Service 87beb7
	node = fdt_path_offset(blob, node_name);
Packit Service 87beb7
	if (node < 0) {
Packit Service 87beb7
		report_error(node_name, -1, node);
Packit Service 87beb7
		return -1;
Packit Service 87beb7
	}
Packit Service 87beb7
Packit Service 87beb7
	node = fdt_delprop(blob, node, prop_name);
Packit Service 87beb7
	if (node < 0) {
Packit Service 87beb7
		report_error(node_name, -1, node);
Packit Service 87beb7
		return -1;
Packit Service 87beb7
	}
Packit Service 87beb7
Packit Service 87beb7
	return 0;
Packit Service 87beb7
}
Packit Service 87beb7
Packit Service 87beb7
/**
Packit Service 87beb7
 * Delete a node in the fdt.
Packit Service 87beb7
 *
Packit Service 87beb7
 * @param blob		FDT blob to write into
Packit Service 87beb7
 * @param node_name	Name of node to delete
Packit Service 87beb7
 * @return 0 on success, or -1 on failure
Packit Service 87beb7
 */
Packit Service 87beb7
static int delete_node(char *blob, const char *node_name)
Packit Service 87beb7
{
Packit Service 87beb7
	int node = 0;
Packit Service 87beb7
Packit Service 87beb7
	node = fdt_path_offset(blob, node_name);
Packit Service 87beb7
	if (node < 0) {
Packit Service 87beb7
		report_error(node_name, -1, node);
Packit Service 87beb7
		return -1;
Packit Service 87beb7
	}
Packit Service 87beb7
Packit Service 87beb7
	node = fdt_del_node(blob, node);
Packit Service 87beb7
	if (node < 0) {
Packit Service 87beb7
		report_error(node_name, -1, node);
Packit Service 87beb7
		return -1;
Packit Service 87beb7
	}
Packit Service 87beb7
Packit Service 87beb7
	return 0;
Packit Service 87beb7
}
Packit Service 87beb7
Packit Service 87beb7
static int do_fdtput(struct display_info *disp, const char *filename,
Packit Service 87beb7
		    char **arg, int arg_count)
Packit Service 87beb7
{
Packit Service 87beb7
	char *value = NULL;
Packit Service 87beb7
	char *blob;
Packit Service 87beb7
	char *node;
Packit Service 87beb7
	int len, ret = 0;
Packit Service 87beb7
Packit Service 87beb7
	blob = utilfdt_read(filename, NULL);
Packit Service 87beb7
	if (!blob)
Packit Service 87beb7
		return -1;
Packit Service 87beb7
Packit Service 87beb7
	switch (disp->oper) {
Packit Service 87beb7
	case OPER_WRITE_PROP:
Packit Service 87beb7
		/*
Packit Service 87beb7
		 * Convert the arguments into a single binary value, then
Packit Service 87beb7
		 * store them into the property.
Packit Service 87beb7
		 */
Packit Service 87beb7
		assert(arg_count >= 2);
Packit Service 87beb7
		if (disp->auto_path && create_paths(&blob, *arg))
Packit Service 87beb7
			return -1;
Packit Service 87beb7
		if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
Packit Service 87beb7
			store_key_value(&blob, *arg, arg[1], value, len))
Packit Service 87beb7
			ret = -1;
Packit Service 87beb7
		break;
Packit Service 87beb7
	case OPER_CREATE_NODE:
Packit Service 87beb7
		for (; ret >= 0 && arg_count--; arg++) {
Packit Service 87beb7
			if (disp->auto_path)
Packit Service 87beb7
				ret = create_paths(&blob, *arg);
Packit Service 87beb7
			else
Packit Service 87beb7
				ret = create_node(&blob, *arg);
Packit Service 87beb7
		}
Packit Service 87beb7
		break;
Packit Service 87beb7
	case OPER_REMOVE_NODE:
Packit Service 87beb7
		for (; ret >= 0 && arg_count--; arg++)
Packit Service 87beb7
			ret = delete_node(blob, *arg);
Packit Service 87beb7
		break;
Packit Service 87beb7
	case OPER_DELETE_PROP:
Packit Service 87beb7
		node = *arg;
Packit Service 87beb7
		for (arg++; ret >= 0 && arg_count-- > 1; arg++)
Packit Service 87beb7
			ret = delete_prop(blob, node, *arg);
Packit Service 87beb7
		break;
Packit Service 87beb7
	}
Packit Service 87beb7
	if (ret >= 0) {
Packit Service 87beb7
		fdt_pack(blob);
Packit Service 87beb7
		ret = utilfdt_write(filename, blob);
Packit Service 87beb7
	}
Packit Service 87beb7
Packit Service 87beb7
	free(blob);
Packit Service 87beb7
Packit Service 87beb7
	if (value) {
Packit Service 87beb7
		free(value);
Packit Service 87beb7
	}
Packit Service 87beb7
Packit Service 87beb7
	return ret;
Packit Service 87beb7
}
Packit Service 87beb7
Packit Service 87beb7
/* Usage related data. */
Packit Service 87beb7
static const char usage_synopsis[] =
Packit Service 87beb7
	"write a property value to a device tree\n"
Packit Service 87beb7
	"	fdtput <options> 
<node> <property> [<value>...]\n"
Packit Service 87beb7
	"	fdtput -c <options> 
[<node>...]\n"
Packit Service 87beb7
	"	fdtput -r <options> 
[<node>...]\n"
Packit Service 87beb7
	"	fdtput -d <options> 
<node> [<property>...]\n"
Packit Service 87beb7
	"\n"
Packit Service 87beb7
	"The command line arguments are joined together into a single value.\n"
Packit Service 87beb7
	USAGE_TYPE_MSG;
Packit Service 87beb7
static const char usage_short_opts[] = "crdpt:v" USAGE_COMMON_SHORT_OPTS;
Packit Service 87beb7
static struct option const usage_long_opts[] = {
Packit Service 87beb7
	{"create",           no_argument, NULL, 'c'},
Packit Service 87beb7
	{"remove",	     no_argument, NULL, 'r'},
Packit Service 87beb7
	{"delete",	     no_argument, NULL, 'd'},
Packit Service 87beb7
	{"auto-path",        no_argument, NULL, 'p'},
Packit Service 87beb7
	{"type",              a_argument, NULL, 't'},
Packit Service 87beb7
	{"verbose",          no_argument, NULL, 'v'},
Packit Service 87beb7
	USAGE_COMMON_LONG_OPTS,
Packit Service 87beb7
};
Packit Service 87beb7
static const char * const usage_opts_help[] = {
Packit Service 87beb7
	"Create nodes if they don't already exist",
Packit Service 87beb7
	"Delete nodes (and any subnodes) if they already exist",
Packit Service 87beb7
	"Delete properties if they already exist",
Packit Service 87beb7
	"Automatically create nodes as needed for the node path",
Packit Service 87beb7
	"Type of data",
Packit Service 87beb7
	"Display each value decoded from command line",
Packit Service 87beb7
	USAGE_COMMON_OPTS_HELP
Packit Service 87beb7
};
Packit Service 87beb7
Packit Service 87beb7
int main(int argc, char *argv[])
Packit Service 87beb7
{
Packit Service 87beb7
	int opt;
Packit Service 87beb7
	struct display_info disp;
Packit Service 87beb7
	char *filename = NULL;
Packit Service 87beb7
Packit Service 87beb7
	memset(&disp, '\0', sizeof(disp));
Packit Service 87beb7
	disp.size = -1;
Packit Service 87beb7
	disp.oper = OPER_WRITE_PROP;
Packit Service 87beb7
	while ((opt = util_getopt_long()) != EOF) {
Packit Service 87beb7
		/*
Packit Service 87beb7
		 * TODO: add options to:
Packit Service 87beb7
		 * - rename node
Packit Service 87beb7
		 * - pack fdt before writing
Packit Service 87beb7
		 * - set amount of free space when writing
Packit Service 87beb7
		 */
Packit Service 87beb7
		switch (opt) {
Packit Service 87beb7
		case_USAGE_COMMON_FLAGS
Packit Service 87beb7
Packit Service 87beb7
		case 'c':
Packit Service 87beb7
			disp.oper = OPER_CREATE_NODE;
Packit Service 87beb7
			break;
Packit Service 87beb7
		case 'r':
Packit Service 87beb7
			disp.oper = OPER_REMOVE_NODE;
Packit Service 87beb7
			break;
Packit Service 87beb7
		case 'd':
Packit Service 87beb7
			disp.oper = OPER_DELETE_PROP;
Packit Service 87beb7
			break;
Packit Service 87beb7
		case 'p':
Packit Service 87beb7
			disp.auto_path = 1;
Packit Service 87beb7
			break;
Packit Service 87beb7
		case 't':
Packit Service 87beb7
			if (utilfdt_decode_type(optarg, &disp.type,
Packit Service 87beb7
					&disp.size))
Packit Service 87beb7
				usage("Invalid type string");
Packit Service 87beb7
			break;
Packit Service 87beb7
Packit Service 87beb7
		case 'v':
Packit Service 87beb7
			disp.verbose = 1;
Packit Service 87beb7
			break;
Packit Service 87beb7
		}
Packit Service 87beb7
	}
Packit Service 87beb7
Packit Service 87beb7
	if (optind < argc)
Packit Service 87beb7
		filename = argv[optind++];
Packit Service 87beb7
	if (!filename)
Packit Service 87beb7
		usage("missing filename");
Packit Service 87beb7
Packit Service 87beb7
	argv += optind;
Packit Service 87beb7
	argc -= optind;
Packit Service 87beb7
Packit Service 87beb7
	if (disp.oper == OPER_WRITE_PROP) {
Packit Service 87beb7
		if (argc < 1)
Packit Service 87beb7
			usage("missing node");
Packit Service 87beb7
		if (argc < 2)
Packit Service 87beb7
			usage("missing property");
Packit Service 87beb7
	}
Packit Service 87beb7
Packit Service 87beb7
	if (disp.oper == OPER_DELETE_PROP)
Packit Service 87beb7
		if (argc < 1)
Packit Service 87beb7
			usage("missing node");
Packit Service 87beb7
Packit Service 87beb7
	if (do_fdtput(&disp, filename, argv, argc))
Packit Service 87beb7
		return 1;
Packit Service 87beb7
	return 0;
Packit Service 87beb7
}