예제 #1
0
/*
 * Remove an option.
 */
void
removeoption(const char *name)
{
	struct nvlist *nv, *nvt;
	char *p, *low, c;
	const char *n;

	if ((nv = ht_lookup(opttab, name)) != NULL) {
		if (options == nv) {
			options = nv->nv_next;
			nvfree(nv);
		} else {
			nvt = options;
			while (nvt->nv_next != NULL) {
				if (nvt->nv_next == nv) {
					nvt->nv_next = nvt->nv_next->nv_next;
					nvfree(nv);
					break;
				} else
					nvt = nvt->nv_next;
			}
		}
	}

	(void)ht_remove(opttab, name);

	low = emalloc(strlen(name) + 1);
	/* make lowercase, then remove from select table */
	for (n = name, p = low; (c = *n) != '\0'; n++)
		*p++ = isupper(c) ? tolower(c) : c;
	*p = 0;
	n = intern(low);
	free(low);
	(void)ht_remove(selecttab, n);
}
예제 #2
0
static int get_passive_sock(UrlResource *rsrc, int control)
{
    unsigned char *addr;
    struct sockaddr_in sa;
    int sock;
    int x;
    char *line, *orig_line;

    send_control(control, "PASV\r\n", NULL);

    if( !((line = get_line(rsrc, control)) &&
          check_numeric("227", line)) ) {
        nvfree(line);
        return 0;
    }

    orig_line = line;

    if (strlen(line) < 4) {
        nvfree(line);
        return 0;
    }

    if (!(sock = sock_init(rsrc->op, &sa, control))) return -1;

    /* skip the numeric response */
    line += 4;

    /* then find the digits */
        
    while (!(isdigit(*line))) line++;
    
    /* ugliness from snarf 1.x */

    sa.sin_family = AF_INET;
    addr = (unsigned char *)&sa.sin_addr;

    for(x = 0; x < 4; x++) {
        addr[x] = atoi(line);
        line = strchr(line,',') + 1;
    }

    addr = (unsigned char *)&sa.sin_port ;
    addr[0] = atoi(line);
    line = strchr(line,',') + 1;
    addr[1] = atoi(line);
        
    if (connect(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
        nvfree(orig_line);
        ui_error(rsrc->op, "unable to connect (%s)", strerror(errno));
        return -1;
    }

    nvfree(orig_line);
    return sock;

} /* get_passive_sock() */
예제 #3
0
/*
 * Free an expression tree.
 */
static void
expr_free(struct nvlist *expr)
{
	struct nvlist *rhs;

	/* This loop traverses down the RHS of each subexpression. */
	for (; expr != NULL; expr = rhs) {
		switch (expr->nv_int) {

		/* Atoms and !-exprs have no left hand side. */
		case FX_ATOM:
		case FX_NOT:
			break;

		/* For AND and OR nodes, free the LHS. */
		case FX_AND:
		case FX_OR:
			expr_free(expr->nv_ptr);
			break;

		default:
			panic("expr_free %d", expr->nv_int);
		}
		rhs = expr->nv_next;
		nvfree(expr);
	}
}
예제 #4
0
파일: sem.c 프로젝트: ajinkya93/OpenBSD
/*
 * Define an attribute, optionally with an interface (a locator list).
 * Since an empty locator list is logically different from "no interface",
 * all locator lists include a dummy head node, which we discard here.
 */
int
defattr(const char *name, struct nvlist *locs)
{
	struct attr *a;
	struct nvlist *nv;
	int len;

	a = emalloc(sizeof *a);
	if (ht_insert(attrtab, name, a)) {
		free(a);
		error("attribute `%s' already defined", name);
		nvfreel(locs);
		return (1);
	}
	a->a_name = name;
	if (locs != NULL) {
		a->a_iattr = 1;
		a->a_locs = locs->nv_next;
		nvfree(locs);
	} else {
		a->a_iattr = 0;
		a->a_locs = NULL;
	}
	len = 0;
	for (nv = a->a_locs; nv != NULL; nv = nv->nv_next)
		len++;
	a->a_loclen = len;
	a->a_devs = NULL;
	a->a_refs = NULL;
	return (0);
}
/*
 * Iterate over the list of kernel modules from the manifest file; generate
 * and store module information records for each module in the Package.
 */
static int parse_kernel_modules_list(Package *p, char *list) {
    char *name;

    p->num_kernel_modules = 0; /* in case this gets called more than once */

    for (name = strtok(list, " "); name; name = strtok(NULL, " ")) {
        KernelModuleInfo *module;
        p->kernel_modules = nvrealloc(p->kernel_modules,
                                      (p->num_kernel_modules + 1) *
                                      sizeof(p->kernel_modules[0]));
        module = p->kernel_modules + p->num_kernel_modules;
        memset(module, 0, sizeof(*module));

        module->module_name = nvstrdup(name);
        module->module_filename = nvstrcat(name, ".ko", NULL);
        module->has_separate_interface_file = has_separate_interface_file(name);
        if (module->has_separate_interface_file) {
            char *core_binary = nvidia_to_nv(name, "-kernel.o_binary");
            module->interface_filename = nvidia_to_nv(name, "-linux.o");
            module->core_object_name = nvstrcat(name, "/", core_binary, NULL);
            nvfree(core_binary);
        }
        populate_optional_module_info(module);

        p->num_kernel_modules++;
    }

    return p->num_kernel_modules;
}
예제 #6
0
void free_devices(DevicesPtr pDevices)
{
    int i;
    
    if (!pDevices) return;
    
    for (i = 0; i < pDevices->nDevices; i++) {
        if (pDevices->devices[i].displayDevices) {
            nvfree(pDevices->devices[i].displayDevices);
        }
    }
    
    if (pDevices->devices) {
        nvfree(pDevices->devices);
    }
        
    nvfree(pDevices);
    
} /* free_devices() */
예제 #7
0
static int get_sock(UrlResource *rsrc, int control)
{
    struct sockaddr_in sa;
    unsigned char *addr;
    unsigned char *port;
    char *line;
    char port_string[SNARF_BUFSIZE];
    unsigned int sock;
    socklen_t i;

    if (!(sock = sock_init(rsrc->op, &sa, control))) return 0;

        
    if (listen(sock, 0) < 0) {
        ui_error(rsrc->op, "unable to listen (%s)", strerror(errno));
        return 0;
    }
        
    i = sizeof(sa);

    getsockname(sock, (struct sockaddr *)&sa, &i);

    addr = (unsigned char *)(&sa.sin_addr.s_addr);
    port = (unsigned char *)(&sa.sin_port);

    sprintf(port_string, "PORT %d,%d,%d,%d,%d,%d\r\n", 
            addr[0], addr[1], addr[2], addr[3],
            port[0],(unsigned char)port[1]);

    send_control(control, port_string, NULL);

    if (!((line = get_line(rsrc, control)) && check_numeric("200", line))) {
        nvfree(line);
        return 0;
    }
    nvfree(line);
        
    return sock;

} /* get_sock() */
예제 #8
0
static void send_control(int sock, char *string, ...)
{
    va_list args;
    char *line = NULL;
    char *newline;
    char *s = NULL;

    line = nvstrdup(string);
        
    va_start(args, string);
    s = va_arg(args, char *);
    while (s) {
        newline = nvstrcat(line, s, NULL);
        nvfree(line);
        line = newline;
        s = va_arg(args, char *);
    }
    va_end(args);

    write(sock, line, strlen(line));
    nvfree(line);

} /* send_control() */
예제 #9
0
/*
 * Read from the given FILE stream until a newline, EOF, or nul
 * terminator is encountered, writing data into a growable buffer.
 * The eof parameter is set to TRUE when EOF is encountered.  In all
 * cases, the returned string is null-terminated.
 *
 * XXX this function will be rather slow because it uses fgetc() to
 * pull each character off the stream one at a time; this is done so
 * that each character can be examined as it's read so that we can
 * appropriately deal with EOFs and newlines.  A better implementation
 * would use fgets(), but that would still require us to parse each
 * read line, checking for newlines or guessing if we hit an EOF.
 */
char *fget_next_line(FILE *fp, int *eof)
{
    char *buf = NULL, *tmpbuf;
    char *c = NULL;
    int len = 0, buflen = 0;
    int ret;

    const int __fget_next_line_len = 32;

    if (eof) {
        *eof = FALSE;
    }

    while (1) {
        if (buflen == len) { /* buffer isn't big enough -- grow it */
            buflen += __fget_next_line_len;
            tmpbuf = nvalloc(buflen);
            if (buf) {
                memcpy(tmpbuf, buf, len);
                nvfree(buf);
            }
            buf = tmpbuf;
            c = buf + len;
        }

        ret = fgetc(fp);

        if ((ret == EOF) && (eof)) {
            *eof = TRUE;
        }

        if ((ret == EOF) || (ret == '\n') || (ret == '\0')) {
            *c = '\0';
            return buf;
        }

        *c = (char) ret;

        len++;
        c++;

    } /* while (1) */

    return NULL; /* should never get here */
}
예제 #10
0
/*
 * Return (possibly in a static buffer) the name of the `source' for a
 * file.  If we have `options source', or if the file is marked `always
 * source', this is always the path from the `file' line; otherwise we
 * get the .o from the obj-directory.
 */
static const char *
srcpath(struct files *fi)
{
	/* Always have source, don't support object dirs for kernel builds. */
	struct nvlist *nv, *nv1;
	char *expand, *source;

	/* Search path list for files we will want to use */
	if (fi->fi_nvpath->nv_next == NULL) {
		nv = fi->fi_nvpath;
		goto onlyone;
	}

	for (nv = fi->fi_nvpath; nv; nv = nv->nv_next) {
		expand = expandname(nv->nv_name);
		source = sourcepath(expand ? expand : nv->nv_name);
		if (access(source, R_OK) == 0) {
			/* XXX poolalloc() prevents freeing old nv_name */
			if (expand)
				nv->nv_name = intern(expand);
			break;
		}
		free(expand);
		free(source);
	}
	if (nv == NULL)
		nv = fi->fi_nvpath;

	/*
	 * Now that we know which path is selected, delete all the
	 * other paths to skip the access() checks next time.
	 */
	while ((nv1 = fi->fi_nvpath)) {
		nv1 = nv1->nv_next;
		if (fi->fi_nvpath != nv)
			nvfree(fi->fi_nvpath);
		fi->fi_nvpath = nv1;
	}
	fi->fi_nvpath = nv;
	nv->nv_next = NULL;
onlyone:
	return (nv->nv_name);
}
예제 #11
0
/*
 * Add a name=value pair to an option list.  The value may be NULL.
 */
static int
do_option(struct hashtab *ht, struct nvlist ***nppp, const char *name,
    const char *value, const char *type)
{
	struct nvlist *nv;

	/* assume it will work */
	nv = newnv(name, value, NULL, 0, NULL);
	if (ht_insert(ht, name, nv) == 0) {
		**nppp = nv;
		*nppp = &nv->nv_next;
		return (0);
	}

	/* oops, already got that option */
	nvfree(nv);
	if ((nv = ht_lookup(ht, name)) == NULL)
		panic("do_option");
	if (nv->nv_str != NULL)
		error("already have %s `%s=%s'", type, name, nv->nv_str);
	else
		error("already have %s `%s'", type, name);
	return (1);
}
예제 #12
0
DevicesPtr find_devices(Options *op)
{
    DevicesPtr pDevices = NULL;
    DisplayDevicePtr pDisplayDevice;
    int i, j, n, count = 0;
    unsigned int mask, bit;
    DeviceRec tmpDevice;
    NvCfgPciDevice *devs = NULL;
    NvCfgBool is_primary_device;
    NvCfgBool ret;
    char *lib_path;
    void *lib_handle;

    NvCfgBool (*__getDevices)(int *n, NvCfgDevice **devs);
    NvCfgBool (*__openDevice)(int bus, int slot, NvCfgDeviceHandle *handle);
    NvCfgBool (*__getPciDevices)(int *n, NvCfgPciDevice **devs);
    NvCfgBool (*__openPciDevice)(int domain, int bus, int slot, int function,
                                 NvCfgDeviceHandle *handle);
    NvCfgBool (*__getNumCRTCs)(NvCfgDeviceHandle handle, int *crtcs);
    NvCfgBool (*__getProductName)(NvCfgDeviceHandle handle, char **name);
    NvCfgBool (*__getDisplayDevices)(NvCfgDeviceHandle handle,
                                     unsigned int *display_device_mask);
    NvCfgBool (*__getEDID)(NvCfgDeviceHandle handle,
                           unsigned int display_device,
                           NvCfgDisplayDeviceInformation *info);
    NvCfgBool (*__isPrimaryDevice)(NvCfgDeviceHandle handle,
                                  NvCfgBool *is_primary_device);
    NvCfgBool (*__closeDevice)(NvCfgDeviceHandle handle);
    NvCfgBool (*__getDeviceUUID)(NvCfgDeviceHandle handle, char **uuid);
    
    /* dlopen() the nvidia-cfg library */
    
#define __LIB_NAME "libnvidia-cfg.so.1"

    if (op->nvidia_cfg_path) {
        lib_path = nvstrcat(op->nvidia_cfg_path, "/", __LIB_NAME, NULL);
    } else {
        lib_path = strdup(__LIB_NAME);
    }
    
    lib_handle = dlopen(lib_path, RTLD_NOW);
    
    nvfree(lib_path);
    
    if (!lib_handle) {
        nv_warning_msg("error opening %s: %s.", __LIB_NAME, dlerror());
        return NULL;
    }
    
#define __GET_FUNC(proc, name)                                        \
    (proc) = dlsym(lib_handle, (name));                               \
    if (!(proc)) {                                                    \
        nv_warning_msg("error retrieving symbol %s from %s: %s",      \
                       (name), __LIB_NAME, dlerror());                \
        dlclose(lib_handle);                                          \
        return NULL;                                                  \
    }

    /* required functions */
    __GET_FUNC(__getDevices, "nvCfgGetDevices");
    __GET_FUNC(__openDevice, "nvCfgOpenDevice");
    __GET_FUNC(__getPciDevices, "nvCfgGetPciDevices");
    __GET_FUNC(__openPciDevice, "nvCfgOpenPciDevice");
    __GET_FUNC(__getNumCRTCs, "nvCfgGetNumCRTCs");
    __GET_FUNC(__getProductName, "nvCfgGetProductName");
    __GET_FUNC(__getDisplayDevices, "nvCfgGetDisplayDevices");
    __GET_FUNC(__getEDID, "nvCfgGetEDID");
    __GET_FUNC(__closeDevice, "nvCfgCloseDevice");
    __GET_FUNC(__getDeviceUUID, "nvCfgGetDeviceUUID");

    /* optional functions */
    __isPrimaryDevice = dlsym(lib_handle, "nvCfgIsPrimaryDevice");
    
    if (__getPciDevices(&count, &devs) != NVCFG_TRUE) {
        return NULL;
    }

    if (count == 0) return NULL;

    pDevices = nvalloc(sizeof(DevicesRec));
    
    pDevices->devices = nvalloc(sizeof(DeviceRec) * count);

    pDevices->nDevices = count;

    for (i = 0; i < count; i++) {
        
        pDevices->devices[i].dev = devs[i];
        
        if (__openPciDevice(devs[i].domain, devs[i].bus, devs[i].slot, 0,
                            &(pDevices->devices[i].handle)) != NVCFG_TRUE) {
            goto fail;
        }
        
        if (__getNumCRTCs(pDevices->devices[i].handle,
                          &pDevices->devices[i].crtcs) != NVCFG_TRUE) {
            goto fail;
        }

        if (__getProductName(pDevices->devices[i].handle,
                             &pDevices->devices[i].name) != NVCFG_TRUE) {
            /* This call may fail with little impact to the Device section */
            pDevices->devices[i].name = NULL;
        }

        if (__getDeviceUUID(pDevices->devices[i].handle,
                            &pDevices->devices[i].uuid) != NVCFG_TRUE) {
            goto fail;
        }
        if (__getDisplayDevices(pDevices->devices[i].handle, &mask) !=
            NVCFG_TRUE) {
            goto fail;
        }
        
        pDevices->devices[i].displayDeviceMask = mask;

        /* count the number of display devices */
        
        for (n = j = 0; j < 32; j++) {
            if (mask & (1 << j)) n++;
        }
        
        pDevices->devices[i].nDisplayDevices = n;

        if (n) {

            /* allocate the info array of the right size */
            
            pDevices->devices[i].displayDevices =
                nvalloc(sizeof(DisplayDeviceRec) * n);
            
            /* fill in the info array */
            
            for (n = j = 0; j < 32; j++) {
                bit = 1 << j;
                if (!(bit & mask)) continue;
                
                pDisplayDevice = &pDevices->devices[i].displayDevices[n];
                pDisplayDevice->mask = bit;

                if (__getEDID(pDevices->devices[i].handle, bit,
                              &pDisplayDevice->info) != NVCFG_TRUE) {
                    pDisplayDevice->info_valid = FALSE;
                } else {
                    pDisplayDevice->info_valid = TRUE;
                }
                n++;
            }
        } else {
            pDevices->devices[i].displayDevices = NULL;
        }

        if ((i != 0) && (__isPrimaryDevice != NULL) &&
            (__isPrimaryDevice(pDevices->devices[i].handle,
                               &is_primary_device) == NVCFG_TRUE) &&
            (is_primary_device == NVCFG_TRUE)) {
            memcpy(&tmpDevice, &pDevices->devices[0], sizeof(DeviceRec));
            memcpy(&pDevices->devices[0], &pDevices->devices[i], sizeof(DeviceRec));
            memcpy(&pDevices->devices[i], &tmpDevice, sizeof(DeviceRec));
        }
        
        ret = __closeDevice(pDevices->devices[i].handle);
        pDevices->devices[i].handle = NULL;

        if (ret != NVCFG_TRUE) {
            goto fail;
        }
    }
    
    goto done;
    
 fail:

    nv_warning_msg("Unable to use the nvidia-cfg library to query NVIDIA "
                   "hardware.");

    for (i = 0; i < pDevices->nDevices; i++) {
        /* close the opened device */
        if (pDevices->devices[i].handle) {
            __closeDevice(pDevices->devices[i].handle);
        }
    }

    free_devices(pDevices);
    pDevices = NULL;

    /* fall through */

 done:
    
    if (devs) free(devs);
    
    return pDevices;
    
} /* find_devices() */
예제 #13
0
char *nv_prepend_to_string_list(char *list, const char *item, const char *delim)
{
    char *new_list = nvstrcat(item, list ? delim : NULL, list, NULL);
    nvfree(list);
    return new_list;
}
예제 #14
0
static int enable_separate_x_screens(Options *op, XConfigPtr config,
                                     XConfigLayoutPtr layout)
{
    XConfigScreenPtr screen, *screenlist = NULL;
    XConfigAdjacencyPtr adj;
    int* screens_to_clone = NULL;

    int i, nscreens = 0;
    int have_busids;
    
    /* step 1: build the list of screens that are candidate to be cloned */
    
    if (op->screen) {
        screen = xconfigFindScreen(op->screen, config->screens);
        if (!screen) {
            nv_error_msg("Unable to find screen '%s'.", op->screen);
            return FALSE;
        }
        
        screenlist = nvalloc(sizeof(XConfigScreenPtr));
        screenlist[0] = screen;
        nscreens = 1;
        
    } else {
        for (adj = layout->adjacencies; adj; adj = adj->next) {
            nscreens++;
            screenlist = realloc(screenlist,
                                 sizeof(XConfigScreenPtr) * nscreens);
            
            screenlist[nscreens-1] = adj->screen;
        }
    }
    
    if (!nscreens) return FALSE;
    
    /* step 2: do all screens in the list have a bus ID? */
    
    have_busids = TRUE;
    
    for (i = 0; i < nscreens; i++) {
        if (screenlist[i] &&
            screenlist[i]->device &&
            screenlist[i]->device->busid) {
            // this screen has a busid
        } else {
            have_busids = FALSE;
            break;
        }
    }
    
    /*
     * if not everyone has a bus id, then let's assign bus ids to all
     * the screens; XXX what if _some_ already have busids?  Too bad,
     * we're going to reassign all of them.
     */
    
    if (!have_busids) {
        DevicesPtr pDevices;
        
        pDevices = find_devices(op);
        if (!pDevices) {
            nv_error_msg("Unable to determine number or location of "
                         "GPUs in system; cannot "
                         "honor '--separate-x-screens' option.");
            return FALSE;
        }
        
        for (i = 0; i < nscreens; i++) {
            if (i >= pDevices->nDevices) {
                /*
                 * we have more screens than GPUs, this screen is no
                 * longer a candidate
                 */
                screenlist[i] = NULL;
                continue;
            }
            
            screenlist[i]->device->busid = nvalloc(32);
            xconfigFormatPciBusString(screenlist[i]->device->busid, 32,
                                      pDevices->devices[i].dev.domain,
                                      pDevices->devices[i].dev.bus,
                                      pDevices->devices[i].dev.slot, 0);

            screenlist[i]->device->board = nvstrdup(pDevices->devices[i].name);
        }

        free_devices(pDevices);
    }

    /* step 3 */
    clean_screen_list(screenlist, config, nscreens);
    
    /* step 4 */
    screens_to_clone = get_screens_to_clone(op, screenlist, nscreens);
    
    /* step 5: clone each eligible screen */
    
    for (i = 0; i < nscreens; i++) {
        if (!screenlist[i]) continue;

        while (--screens_to_clone[i] > 0) {
            clone_screen(screenlist[i], screens_to_clone[i]);
        }
    }

    nvfree(screens_to_clone);
    
    /* step 6: wipe the existing adjacencies and recreate them */
    
    xconfigFreeAdjacencyList(&layout->adjacencies);
    
    create_adjacencies(op, config, layout);

    /* free unused device and monitor sections */
    
    free_unused_devices(op, config);
    free_unused_monitors(op, config);

    /* free stuff */

    free(screenlist);

    return TRUE;

} /* enable_separate_x_screens() */
예제 #15
0
static Package *parse_manifest (Options *op)
{
    char *buf, *c, *tmpstr;
    int line;
    int fd, ret, len = 0;
    struct stat stat_buf;
    Package *p;
    char *manifest = MAP_FAILED, *ptr;
    int opengl_files_packaged = FALSE;

    p = (Package *) nvalloc(sizeof (Package));

    /* open the manifest file */

    if ((fd = open(".manifest", O_RDONLY)) == -1) {
        ui_error(op, "No package found for installation.  Please run "
                 "this utility with the '--help' option for usage "
                 "information.");
        goto fail;
    }
    
    if (fstat(fd, &stat_buf) == -1) goto cannot_open;
    
    len = stat_buf.st_size;

    manifest = mmap(0, len, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0);
    if (manifest == MAP_FAILED) goto cannot_open;
    
    /* the first line is the description */

    line = 1;
    p->description = get_next_line(manifest, &ptr, manifest, len);
    if (!p->description) goto invalid_manifest_file;
    
    /* the second line is the version */
    
    line++;
    p->version = get_next_line(ptr, &ptr, manifest, len);
    if (!p->version) goto invalid_manifest_file;
    
    /* Ignore the third line */

    line++;
    nvfree(get_next_line(ptr, &ptr, manifest, len));

    /* the fourth line is the list of kernel modules. */

    line++;
    tmpstr = get_next_line(ptr, &ptr, manifest, len);
    if (parse_kernel_modules_list(p, tmpstr) == 0) {
        goto invalid_manifest_file;
    }
    nvfree(tmpstr);

    /*
     * set the default value of excluded_kernel_modules to an empty, heap
     * allocated string so that it can be freed and won't prematurely end
     * an nvstrcat()ed string when unset.
     */

    p->excluded_kernel_modules = nvstrdup("");

    /*
     * ignore the fifth and sixth lines
     */

    line++;
    nvfree(get_next_line(ptr, &ptr, manifest, len));
    line++;
    nvfree(get_next_line(ptr, &ptr, manifest, len));

    /* the seventh line is the kernel module build directory */

    line++;
    p->kernel_module_build_directory = get_next_line(ptr, &ptr, manifest, len);
    if (!p->kernel_module_build_directory) goto invalid_manifest_file;
    remove_trailing_slashes(p->kernel_module_build_directory);

    /*
     * the eigth line is the directory containing precompiled kernel
     * interfaces
     */

    line++;
    p->precompiled_kernel_interface_directory =
        get_next_line(ptr, &ptr, manifest, len);
    if (!p->precompiled_kernel_interface_directory)
        goto invalid_manifest_file;
    remove_trailing_slashes(p->precompiled_kernel_interface_directory);

    /* the rest of the file is file entries */

    line++;
    
    for (; (buf = get_next_line(ptr, &ptr, manifest, len)); line++) {
        char *flag = NULL;
        PackageEntry entry;
        int entry_success = FALSE;

        if (buf[0] == '\0') {
            free(buf);
            break;
        }

        /* initialize the new entry */

        memset(&entry, 0, sizeof(PackageEntry));

        /* read the file name and permissions */

        c = buf;

        entry.file = read_next_word(buf, &c);

        if (!entry.file) goto entry_done;

        tmpstr = read_next_word(c, &c);

        if (!tmpstr) goto entry_done;

        /* translate the mode string into an octal mode */

        ret = mode_string_to_mode(op, tmpstr, &entry.mode);

        free(tmpstr);

        if (!ret) goto entry_done;

        /* every file has a type field */

        entry.type = FILE_TYPE_NONE;

        flag = read_next_word(c, &c);
        if (!flag) goto entry_done;

        entry.type = parse_manifest_file_type(flag, &entry.caps);

        if (entry.type == FILE_TYPE_NONE) {
            goto entry_done;
        }

        /* Track whether certain file types were packaged */

        switch (entry.type) {
            case FILE_TYPE_XMODULE_SHARED_LIB:
                op->x_files_packaged = TRUE;
                break;
            default: break;
        }

        /* set opengl_files_packaged if any OpenGL files were packaged */

        if (entry.caps.is_opengl) {
            opengl_files_packaged = TRUE;
        }

        /* some libs/symlinks have an arch field */

        entry.compat_arch = FILE_COMPAT_ARCH_NONE;

        if (entry.caps.has_arch) {
            nvfree(flag);
            flag = read_next_word(c, &c);
            if (!flag) goto entry_done;

            if (strcmp(flag, "COMPAT32") == 0)
                entry.compat_arch = FILE_COMPAT_ARCH_COMPAT32;
            else if (strcmp(flag, "NATIVE") == 0)
                entry.compat_arch = FILE_COMPAT_ARCH_NATIVE;
            else {
                goto entry_done;
            }
        }

        /* if compat32 files are packaged, set compat32_files_packaged */

        if (entry.compat_arch == FILE_COMPAT_ARCH_COMPAT32) {
            op->compat32_files_packaged = TRUE;
        }

        /* some libs/symlinks have a class field */

        entry.tls_class = FILE_TLS_CLASS_NONE;

        if (entry.caps.has_tls_class) {
            nvfree(flag);
            flag = read_next_word(c, &c);
            if (!flag) goto entry_done;

            if (strcmp(flag, "CLASSIC") == 0)
                entry.tls_class = FILE_TLS_CLASS_CLASSIC;
            else if (strcmp(flag, "NEW") == 0)
                entry.tls_class = FILE_TLS_CLASS_NEW;
            else {
                goto entry_done;
            }
        }

        /* some file types have a path field, or inherit their paths */

        if (entry.caps.has_path) {
            entry.path = read_next_word(c, &c);
            if (!entry.path) goto invalid_manifest_file;
        } else if (entry.caps.inherit_path) {
            int i;
            char *path, *depth, *slash;
            const char * const depth_marker = "INHERIT_PATH_DEPTH:";

            depth = read_next_word(c, &c);
            if (!depth ||
                strncmp(depth, depth_marker, strlen(depth_marker)) != 0) {
                goto invalid_manifest_file;
            }
            entry.inherit_path_depth = atoi(depth + strlen(depth_marker));
            nvfree(depth);

            /* Remove the file component from the packaged filename */
            path = entry.path = nvstrdup(entry.file);
            slash = strrchr(path, '/');
            if (slash == NULL) {
                goto invalid_manifest_file;
            }
            slash[1] = '\0';

            /* Strip leading directory components from the path */
            for (i = 0; i < entry.inherit_path_depth; i++) {
                slash = strchr(entry.path, '/');

                if (slash == NULL) {
                    goto invalid_manifest_file;
                }

                entry.path = slash + 1;
            }

            entry.path = nvstrdup(entry.path);
            nvfree(path);
        } else {
            entry.path = NULL;
        }

        /* symlinks have a target */

        if (entry.caps.is_symlink) {
            entry.target = read_next_word(c, &c);
            if (!entry.target) goto invalid_manifest_file;
        } else {
            entry.target = NULL;
        }

        /*
         * as a convenience for later, set the 'name' pointer to
         * the basename contained in 'file' (ie the portion of
         * 'file' without any leading directory components
         */

        entry.name = strrchr(entry.file, '/');
        if (entry.name) entry.name++;

        if (!entry.name) entry.name = entry.file;

        add_package_entry(p,
                          entry.file,
                          entry.path,
                          entry.name,
                          entry.target,
                          entry.dst,
                          entry.type,
                          entry.tls_class,
                          entry.compat_arch,
                          entry.mode);

        entry_success = TRUE;

 entry_done:
        /* clean up */

        nvfree(buf);
        nvfree(flag);
        if (!entry_success) {
            goto invalid_manifest_file;
        }
    }

    /* If no OpenGL files were packaged, we can't install them. Set the
     * no_opengl_files flag so that everything we skip when explicitly
     * excluding OpenGL is also skipped when OpenGL is not packaged. */

    if (!opengl_files_packaged) {
        op->no_opengl_files = TRUE;
    }

    munmap(manifest, len);
    if (fd != -1) close(fd);

    return p;
    
 cannot_open:
    ui_error(op, "Failure opening package's .manifest file (%s).",
             strerror(errno));
    goto fail;

 invalid_manifest_file:

    ui_error(op, "Invalid .manifest file; error on line %d.", line);
    goto fail;

 fail:
    free_package(p);
    if (manifest != MAP_FAILED) munmap(manifest, len);
    if (fd != -1) close(fd);
    return NULL;
       
} /* parse_manifest() */
예제 #16
0
/*
 * get_screens_to_clone() - try to detect automatically how many heads has each
 * device in order to use that number to create more than two separate X
 * screens. If the user specifies the option --num-x-screens <quantity>, that
 * value is used. If neither the user specifies the quantity or the number of
 * heads can be detected automatically, it uses 2 heads (the standard
 * behavior). This function returns an array of size nscreens with the number
 * of screens to clone per screen candidate. The caller is responsible of
 * freeing the memory of that array.
 */
static int* get_screens_to_clone(Options *op,
                                 const XConfigScreenPtr *screen_candidates,
                                 int nscreens)
{
    DevicesPtr pDevices;
    int *screens_to_clone, *supported_screens;
    int i, j, devs_found;

    screens_to_clone = nvalloc(nscreens * sizeof(int));
    supported_screens = nvalloc(nscreens * sizeof(int));

    /* Detect the number of supported screens per screen candidate */
    devs_found = FALSE;
    pDevices = find_devices(op);
    if (pDevices) {
        for (i = 0; i < nscreens; i++) {
            int bus, slot, scratch;

            if (!screen_candidates[i]) {
                continue;
            }

            /* parse the bus id for this candidate screen */
            if (!xconfigParsePciBusString(screen_candidates[i]->device->busid,
                                          &bus, &slot, &scratch)) {
                continue;
            }

            for (j = 0; j < pDevices->nDevices; j++) {
                if ((pDevices->devices[j].dev.bus == bus) &&
                    (pDevices->devices[j].dev.slot == slot)) {

                    if (pDevices->devices[j].crtcs > 0) {
                        supported_screens[i] = pDevices->devices[j].crtcs;
                    }
                    break;
                }
            }
        }
        free_devices(pDevices);
        devs_found = TRUE;
    }

    /* If user has defined a number of screens per GPU, use that value */
    if (op->num_x_screens > 0) {
        for (i = 0; i < nscreens; i++) {
            if (!screen_candidates[i]) {
                continue;
            }

            /* Print error when user specifies more X screens than supported */
            if (devs_found && op->num_x_screens > supported_screens[i]) {
                nv_warning_msg("Number of X screens specified is higher than the "
                               "supported quantity (%d)", supported_screens[i]);
            }

            screens_to_clone[i] = op->num_x_screens;
        }

        goto done;
    }

    for (i = 0; i < nscreens; i++) {
        if (screen_candidates[i]) {
            if (devs_found) {
                /* If devices found, use the supported screens number */
                screens_to_clone[i] = supported_screens[i];
            }
            else {
                /* Default behavior (2 heads per GPU) */
                screens_to_clone[i] = 2;
            }
        }
    }

done:
    nvfree(supported_screens);
    return screens_to_clone;
}
예제 #17
0
static int assisted_module_signing(Options *op, Package *p)
{
    int generate_keys = FALSE, do_sign = FALSE, secureboot, i;

    secureboot = secure_boot_enabled();

    if (secureboot < 0) {
        ui_log(op, "Unable to determine if Secure Boot is enabled: %s",
               strerror(-secureboot));
    }

    if (op->kernel_module_signed) {
        /* The kernel module is already signed, e.g. from linking a precompiled
         * interface + appending a detached signature */
        return TRUE;
    }

    if (test_kernel_config_option(op, p, "CONFIG_DUMMY_OPTION") ==
        KERNEL_CONFIG_OPTION_UNKNOWN) {
        /* Unable to test kernel configuration options, possibly due to
         * missing kernel headers. Since we might be installing on a
         * system that doesn't have the headers, bail out. */
        return TRUE;
    }

    if (op->module_signing_secret_key && op->module_signing_public_key) {
        /* If the user supplied signing keys, sign the module, regardless of
         * whether or not we actually need to. */
        do_sign = TRUE;
    } else if (test_kernel_config_option(op, p, "CONFIG_MODULE_SIG_FORCE") ==
               KERNEL_CONFIG_OPTION_DEFINED) {
        /* If CONFIG_MODULE_SIG_FORCE is set, we must sign. */
        ui_message(op, "The target kernel has CONFIG_MODULE_SIG_FORCE set, "
                   "which means that it requires that kernel modules be "
                   "cryptographically signed by a trusted key.");
        do_sign = TRUE;
    } else if (secureboot != 1 && !op->expert) {
        /* If this is a non-UEFI system, or a UEFI system with secure boot
         * disabled, or we are unable to determine whether the system has
         * secure boot enabled, bail out unless in expert mode. */
        return TRUE;
    } else if (test_kernel_config_option(op, p, "CONFIG_MODULE_SIG") ==
               KERNEL_CONFIG_OPTION_DEFINED){
        /* The kernel may or may not enforce module signatures; ask the user
         * whether to sign the module. */

        const char *choices[2] = {
            "Sign the kernel module",
            "Install without signing"
        };

        const char* sb_message = (secureboot == 1) ?
                                     "This system also has UEFI Secure Boot "
                                     "enabled; many distributions enforce "
                                     "module signature verification on UEFI "
                                     "systems when Secure Boot is enabled. " :
                                     "";

        do_sign = (ui_multiple_choice(op, choices, 2, 1, "The target kernel "
                                      "has CONFIG_MODULE_SIG set, which means "
                                      "that it supports cryptographic "
                                      "signatures on kernel modules. On some "
                                      "systems, the kernel may refuse to load "
                                      "modules without a valid signature from "
                                      "a trusted key. %sWould you like to sign "
                                      "the NVIDIA kernel module?",
                                      sb_message) == 0);
    }

    if (!do_sign) {
        /* The user explicitly opted out of module signing, or the kernel does
         * not support module signatures, and no signing keys were provided;
         * there is nothing for us to do here. */
        return TRUE;
    }

    /* If we're missing either key, we need to get both from the user. */
    if (!op->module_signing_secret_key || !op->module_signing_public_key) {

        const char *choices[2] = {
            "Use an existing key pair",
            "Generate a new key pair"
        };

        generate_keys = (ui_multiple_choice(op, choices, 2, 1, "Would you like "
                                            "to sign the NVIDIA kernel module "
                                            "with an existing key pair, or "
                                            "would you like to generate a new "
                                            "one?") == 1);

        if (generate_keys) {
            char *cmdline, *x509_hash, *private_key_path, *public_key_path;
            int ret, generate_failed = FALSE;

            if (!op->utils[OPENSSL]) {
                ui_error(op, "Unable to generate key pair: openssl not "
                         "found!");
                return FALSE;
            }

            /* Determine what hashing algorithm to use for the generated X.509
             * certificate. XXX The default is to use the same hash that is
             * used for signing modules; the two hashes are actually orthognal
             * to each other, but by choosing the module signing hash we are
             * guaranteed that the chosen hash will be built into the kernel.
             */
            if (op->module_signing_x509_hash) {
                x509_hash = nvstrdup(op->module_signing_x509_hash);
            } else {
                char *guess, *guess_trimmed, *warn = NULL;

                char *no_guess = "Unable to guess the module signing hash.";
                char *common_warn = "The module signing certificate generated "
                                    "by nvidia-installer will be signed with "
                                    "sha256 as a fallback. If the resulting "
                                    "certificate fails to import into your "
                                    "kernel's trusted keyring, please run the "
                                    "installer again, and either use a pre-"
                                    "generated key pair, or set the "
                                    "--module-signing-x509-hash option if you "
                                    "plan to generate a new key pair with "
                                    "nvidia-installer.";

                guess = guess_module_signing_hash(op,
                                                  p->kernel_module_build_directory);

                if (guess == NULL) {
                    warn = no_guess;
                    goto guess_fail;
                }

                guess_trimmed = nv_trim_space(guess);
                guess_trimmed = nv_trim_char_strict(guess_trimmed, '"');

                if (guess_trimmed) {
                    if (strlen(guess_trimmed) == 0) {
                        warn = no_guess;
                        goto guess_fail;
                    }

                    x509_hash = nvstrdup(guess_trimmed);
                } else {
                    warn = "Error while parsing the detected module signing "
                           "hash.";
                    goto guess_fail;
                }

guess_fail:
                nvfree(guess);

                if (warn) {
                    ui_warn(op, "%s %s", warn, common_warn);
                    x509_hash = nvstrdup("sha256");
                }
            }

            log_printf(op, NULL, "Generating key pair for module signing...");

            /* Generate temporary files for the signing key and certificate */

            private_key_path = write_temp_file(op, 0, NULL, 0600);
            public_key_path = write_temp_file(op, 0, NULL, 0644);

            if (!private_key_path || !public_key_path) {
                ui_error(op, "Failed to create one or more temporary files for "
                         "the module signing keys.");
                generate_failed = TRUE;
                goto generate_done;
            }

            /* Generate a key pair using openssl.
             * XXX We assume that sign-file requires the X.509 certificate
             * in DER format; if this changes in the future we will need
             * to be able to accommodate the actual required format. */

            cmdline = nvstrcat("cd ", p->kernel_module_build_directory, "; ",
                               op->utils[OPENSSL], " req -new -x509 -newkey "
                               "rsa:2048 -days 7300 -nodes -subj "
                               "\"/CN=nvidia-installer generated signing key/\""
                               " -keyout ", private_key_path,
                               " -outform DER -out ", public_key_path,
                               " -", x509_hash, NULL);
            nvfree(x509_hash);

            ret = run_command(op, cmdline, NULL, TRUE, 8, TRUE);

            nvfree(cmdline);

            if (ret != 0) {
                ui_error(op, "Failed to generate key pair!");
                generate_failed = TRUE;
                goto generate_done;
            }

            log_printf(op, NULL, "Signing keys generated successfully.");

            /* Set the signing keys to the newly generated pair. */

            op->module_signing_secret_key = nvstrdup(private_key_path);
            op->module_signing_public_key = nvstrdup(public_key_path);

generate_done:
            nvfree(private_key_path);
            nvfree(public_key_path);

            if (generate_failed) {
                return FALSE;
            }
        } else {
            /* The user already has keys; prompt for their locations. */
            op->module_signing_secret_key =
                get_filename(op, op->module_signing_secret_key,
                             "Please provide the path to the private key");
            op->module_signing_public_key =
                get_filename(op, op->module_signing_public_key,
                             "Please provide the path to the public key");
        }
    }

    /* Now that we have keys (user-supplied or installer-generated),
     * sign the kernel module/s which we built earlier. */

    for (i = 0; i < p->num_kernel_modules; i++) {
        if (!sign_kernel_module(op, p->kernel_module_build_directory,
                                p->kernel_modules[i].module_filename, TRUE)) {
            return FALSE;
        }
    }

    if (generate_keys) {

        /* If keys were generated, we should install the verification cert
         * so that the user can make the kernel trust it, and either delete
         * or install the private signing key. */
        char *name, *result = NULL, *fingerprint, *cmdline;
        char short_fingerprint[9];
        int ret, delete_secret_key;

        delete_secret_key = ui_yes_no(op, TRUE, "The NVIDIA kernel module was "
                                      "successfully signed with a newly "
                                      "generated key pair. Would you like to "
                                      "delete the private signing key?");

        /* Get the fingerprint of the X.509 certificate. We already used 
           openssl to create a keypair at this point, so we know we have it;
           otherwise, we would have already returned by now. */
        cmdline = nvstrcat(op->utils[OPENSSL], " x509 -noout -fingerprint ",
                           "-inform DER -in ", op->module_signing_public_key,
                           NULL);
        ret = run_command(op, cmdline, &result, FALSE, 0, FALSE);
        nvfree(cmdline);

        /* Format: "SHA1 Fingerprint=00:00:00:00:..." */
        fingerprint = strchr(result, '=') + 1;

        if (ret != 0 || !fingerprint || strlen(fingerprint) < 40) {
            char *sha1sum = find_system_util("sha1sum");

            if (sha1sum) {
                /* the openssl command failed, or we parsed its output
                 * incorrectly; try to get a sha1sum of the DER certificate */
                cmdline = nvstrcat(sha1sum, " ", op->module_signing_public_key,
                                   NULL);
                ret = run_command(op, cmdline, &result, FALSE, 0, FALSE);
                nvfree(sha1sum);
                nvfree(cmdline);

                fingerprint = result;
            }

            if (!sha1sum || ret != 0 || !fingerprint ||
                strlen(fingerprint) < 40) {
                /* Unable to determine fingerprint */
                fingerprint = "UNKNOWN";
            } else {
                char *end = strchr(fingerprint, ' ');
                *end = '\0';
            }
        } else {
            /* Remove any ':' characters from fingerprint and truncate */
            char *tmp = nv_strreplace(fingerprint, ":", "");
            strncpy(short_fingerprint, tmp, sizeof(short_fingerprint));
            nvfree(tmp);
        }
        short_fingerprint[sizeof(short_fingerprint) - 1] = '\0';

        /* Add the public key to the package */

        /* XXX name will be leaked when freeing package */
        name = nvstrcat("nvidia-modsign-crt-", short_fingerprint, ".der", NULL);

        add_package_entry(p,
                          nvstrdup(op->module_signing_public_key),
                          NULL, /* path */
                          name,
                          NULL, /* target */
                          NULL, /* dst */
                          FILE_TYPE_MODULE_SIGNING_KEY,
                          FILE_TLS_CLASS_NONE,
                          FILE_COMPAT_ARCH_NONE,
                          0444);

        ui_message(op, "An X.509 certificate containing the public signing "
                    "key will be installed to %s/%s. The SHA1 fingerprint of "
                    "this certificate is: %s.\n\nThis certificate must be "
                    "added to a key database which is trusted by your kernel "
                    "in order for the kernel to be able to verify the module "
                    "signature.", op->module_signing_key_path, name,
                    fingerprint);

        nvfree(result);

        /* Delete or install the private key */

        if (delete_secret_key) {
            secure_delete(op, op->module_signing_secret_key);
        } else {

            /* Add the private key to the package */

            name = nvstrcat("nvidia-modsign-key-", short_fingerprint, ".key",
                            NULL);

            add_package_entry(p,
                              nvstrdup(op->module_signing_secret_key),
                              NULL, /* path */
                              name,
                              NULL, /* target */
                              NULL, /* dst */
                              FILE_TYPE_MODULE_SIGNING_KEY,
                              FILE_TLS_CLASS_NONE,
                              FILE_COMPAT_ARCH_NONE,
                              0400);

            ui_message(op, "The private signing key will be installed to %s/%s. "
                       "After the public key is added to a key database which "
                       "is trusted by your kernel, you may reuse the saved "
                       "public/private key pair to sign additional kernel "
                       "modules, without needing to re-enroll the public key. "
                       "Please take some reasonable precautions to secure the "
                       "private key: see the README for suggestions.",
                       op->module_signing_key_path, name);
        }
    } /* if (generate_keys) */

    return TRUE;
} /* assisted_module_signing() */
예제 #18
0
static void free_package(Package *p)
{
    int i;

    if (!p) return;
    
    nvfree(p->description);
    nvfree(p->version);
    
    nvfree(p->kernel_module_build_directory);

    nvfree(p->precompiled_kernel_interface_directory);

    for (i = 0; i < p->num_kernel_modules; i++) {
        free_kernel_module_info(p->kernel_modules[i]);
    }
    nvfree(p->kernel_modules);

    nvfree(p->excluded_kernel_modules);

    for (i = 0; i < p->num_entries; i++) {
        nvfree(p->entries[i].file);
        nvfree(p->entries[i].path);
        nvfree(p->entries[i].target);
        nvfree(p->entries[i].dst);

        /*
         * Note: p->entries[i].name just points into
         * p->entries[i].file, so don't free p->entries[i].name
         */
    }

    nvfree((char *) p->entries);

    nvfree((char *) p);
    
} /* free_package() */
예제 #19
0
int ftp_transfer(UrlResource *rsrc)
{
    Url  *u         = NULL;
    char *line      = NULL;
    int   sock      = 0;
    int   data_sock = 0;
    int   passive   = 1;
    int   retval    = 0;
    
    u = rsrc->url;

    /*
     * first of all, if this is proxied, just pass it off to the
     * http module, since that's how we support proxying.
     */

    rsrc->proxy = get_proxy("FTP_PROXY");

    if (rsrc->proxy && (rsrc->proxy[0] != '\0')) {
        return http_transfer(rsrc);
    }

    ftp_set_defaults(rsrc, u);

    if (!(sock = tcp_connect(rsrc->op, u->host, u->port)))
        return FALSE;

    if (!(line = get_line(rsrc, sock)))
        return FALSE;

    if (!check_numeric("220", line)) {
        ui_error(rsrc->op, "bad ftp server greeting: %s", line);
        nvfree(line);
        return FALSE;
    }
    
    send_control(sock, "USER ", u->username, "\r\n", NULL);

    if (!(line = get_line(rsrc, sock))) return FALSE;
    
    /* do the password dance */
    if (!check_numeric("230", line)) {
        if (!check_numeric("331", line)) {
            ui_error(rsrc->op, "bad/unexpected response: %s", line);
            nvfree(line);
            return FALSE;
        } else {
            nvfree(line);

            send_control(sock, "PASS ", u->password, "\r\n", NULL);
                        
            if (!((line = get_line(rsrc, sock)) &&
                  check_numeric("230", line)) ) {
                nvfree(line);
                ui_error(rsrc->op, "login failed");
                return FALSE;
            }
            nvfree(line);
        }
    }
        
    /* set binmode */
    send_control(sock, "TYPE I\r\n", NULL);

    if (!(line = get_line(rsrc, sock))) return 0;
    nvfree(line);

    if (u->path) {
        send_control(sock, "CWD ", u->path, "\r\n", NULL);
        
        if (!((line = get_line(rsrc, sock)) &&
              check_numeric("250", line))) {
            nvfree(line);
            close_quit(sock);
            return 0;
        }
        nvfree(line);
    }
        
    /* finally, the good stuff */
    
    /* get a socket for reading. try passive first. */
        
    if ((data_sock = get_passive_sock(rsrc, sock)) == -1) {
        return FALSE;
    }
    
    if (!data_sock) {
        if ((data_sock = get_sock(rsrc, sock)) < 1)
            return 0;
        else
            passive = 0;
    }

    if (u->file) {
        send_control(sock, "SIZE ", u->file, "\r\n", NULL);
        line = get_line(rsrc, sock);
        if (line && check_numeric("213", line)) {
            rsrc->outfile_size = atoi(line + 3);
        } else {
            rsrc->outfile_size = 0;
        }
    }
    
    if (u->file)
        send_control(sock, "RETR ", u->file, "\r\n", NULL);
    else
        send_control(sock, "NLST\r\n", NULL);

    if (!((line = get_line(rsrc, sock)) &&
          (check_numeric("150", line) || check_numeric("125", line)))) {
        nvfree(line);
        close_quit(sock);
        return 0;
    }

    if (!passive) 
        data_sock = accept(data_sock, NULL, NULL);

    nvfree(line);

    retval = dump_data(rsrc, data_sock);
    
    line = get_line(rsrc, sock); /* 226 Transfer complete */
    nvfree(line);
    send_control(sock, "QUIT\r\n", NULL);
    line = get_line(rsrc, sock); /* 221 Goodbye */
    nvfree(line);
    
    close(sock);
    close(data_sock);
    return retval;

} /* ftp_transfer() */