void ManifestDtor(struct Manifest *manifest) { int i; int j; if(manifest == NULL) return; /* channels */ for(i = 0; i < manifest->channels->len; ++i) { struct ChannelDesc *channel = g_ptr_array_index(manifest->channels, i); /* sources */ for(j = 0; j < channel->source->len; ++j) { struct File *file = g_ptr_array_index(channel->source, j); if(IS_FILE(file)) g_free(file->name); g_free(file); } g_ptr_array_free(channel->source, TRUE); g_free(channel->alias); TagDtor(channel->tag); g_free(channel); } g_ptr_array_free(manifest->channels, TRUE); /* other */ g_free(manifest->etag); TagDtor(manifest->mem_tag); g_free(manifest->name_server); g_free(manifest->program); g_free(manifest); }
CScriptFile* lua_tofile ( lua_State* luaVM, int iArgument ) { CElement* pElement = lua_toelement ( luaVM, iArgument ); if ( pElement && IS_FILE ( pElement ) ) return static_cast < CScriptFile* > ( pElement ); else return NULL; }
int print_conflicts(struct hash *hash) { int i; struct tree_node *t, *s; char *pkgname; for (i = 0; i < TBLSIZE; i++) { t = tree_first(hash->tbl[i]->root); while (t) { if (!IS_FILE(t->n->name) || IS_DIR(t->n) || tree_count(t->n->providedby) < 2) { t = tree_next(t); continue; } printf("%s: ", t->n->name); s = tree_first(t->n->providedby->root); while (s) { if (IS_PKG(s->n)) { printf("%s", s->n->name); } else if (is_virtual_file(s->n->name)) { pkgname = get_pkgname(s->n->name); printf("%s", pkgname); free(pkgname); } else { fprintf(stderr, "bee-dep: print_conflicts: " "could not get pkgname for \"%s\"\n", s->n->name); return 1; } s = tree_next(s); if (!s) puts(""); else printf(" "); } t = tree_next(t); } } return 0; }
/** mkworld(): * Compiles the sources, and eventually builds with biblatex */ void mkworld() { //struct stat okbiblio; do_argv(2,LATEX_COMPILER,"main.tex"); do_argv(2,BIBTEX_COMPILER,"main.aux"); do_argv(2,LATEX_COMPILER,"main.tex"); do_argv(2,LATEX_COMPILER,"main.tex"); if (IS_FILE("main.idx")) { printf("\033[35mThere is main.idx...\033[0m\n"); do_argv(2,MAKEINDEX_COMP,"main.idx"); } do_argv(2,LATEX_COMPILER,"main.tex"); }
static int count_all_files(struct node *n) { struct tree_node *t; int count; t = tree_first(n->provide->root); count = 0; while (t) { if (IS_FILE(t->n->name)) count++; count += list_all_files(t->n, 0); t = tree_next(t); } return count; }
int fs_getdents(int fd, char *buf, size_t n) { unsigned int i, pos; struct inode_s *dir, *ino; struct dir_entry_s dentry; struct dirent *dent; struct file_s *flip; flip = get_file(fd); dir = flip->f_ino; if (!IS_DIR(dir->i_mode)) return ERROR; i = 0; pos = flip->f_pos; while (n >= sizeof(struct dirent) + 1) { if (next_entry(dir, &pos, &dentry) == ERROR) break; ino = get_inode(dentry.num); dent = (struct dirent *) (buf + i); dent->d_ino = dentry.num; dent->d_off = pos - sizeof(struct dir_entry_s); dent->d_reclen = mystrncpy(dent->d_name, dentry.name, MAX_NAME) + 1 + /* add the \0 */ sizeof(ino_t) + /* add the d_ino */ sizeof(off_t) + /* add the d_off */ sizeof(unsigned short) + /* add the d_reclen */ 1; /* add the d_type */ /* add d_type */ *(buf + i + dent->d_reclen - 1) = (IS_DIR(ino->i_mode) ? DT_DIR : IS_FILE(ino->i_mode) ? DT_REG : IS_CHAR(ino->i_mode) ? DT_CHR : DT_UNK); i += dent->d_reclen; n -= dent->d_reclen; release_inode(ino); } flip->f_pos = pos; return i; }
static int fatfs_remove(vnode_t dvp, vnode_t vp, char *name) { struct fatfsmount *fmp; struct fatfs_node np; struct fat_dirent *de; int error; if (*name == '\0') return ENOENT; fmp = dvp->v_mount->m_data; mutex_lock(&fmp->lock); error = fatfs_lookup_node(dvp, name, &np); if (error) goto out; de = &np.dirent; if (IS_DIR(de)) { error = EISDIR; goto out; } if (!IS_FILE(de)) { error = EPERM; goto out; } /* Remove clusters */ error = fat_free_clusters(fmp, (de->cluster_hi << 16) | de->cluster); if (error) goto out; /* remove directory */ de->name[0] = 0xe5; error = fatfs_put_node(fmp, &np); out: mutex_unlock(&fmp->lock); return error; }
void search_removable(struct hash *hash, struct node *n, struct tree *t, char *remove) { struct tree_node *e; char *pkgname; e = tree_first(n->provide->root); while (e) { search_removable(hash, e->n, t, remove); e = tree_next(e); } if (IS_FILE(n->name) && tree_count(n->providedby) <= 1) { pkgname = get_pkgname(n->providedby->root->n->name); if (!strcmp(pkgname, remove)) tree_insert(t, n); free(pkgname); } }
static int list_all_files(struct node *n, char print) { struct tree_node *t; int count; t = tree_first(n->provide->root); count = 0; while (t) { if (IS_FILE(t->n->name)) { count++; if (print) puts(t->n->name); } count += list_all_files(t->n, print); t = tree_next(t); } return count; }
int graph_insert_nodes(struct hash *hash, char *filename) { FILE *file; register char *s, *p, *a; char type_flag, u; char line[LINE_MAX], prop[LINE_MAX], value[LINE_MAX], pkgname[NODENAME_MAX] = {0}, nodename[NODENAME_MAX] = {0}; int l, line_cnt; struct node *n, *h, *v, *c; if ((file = fopen(filename, "r")) == NULL) { perror("bee-dep: graph_insert_nodes: fopen"); return 1; } line_cnt = type_flag = u = 0; n = NULL; while (fgets(line, LINE_MAX, file)) { line_cnt++; if (!line[0]) continue; /* remove unnecessary characters */ l = strlen(line); s = line; p = line + (l - 1) * sizeof(char); h = NULL; while (p - s && *p && IS_WHITESPACE(*p)) *(p--) = 0; while (*s && (*s == ' ' || *s == '\t')) s++; l = p - s; if (l <= 0 || *s == '#') continue; /* read node name */ if (*s == '[') { s++; if (*p != ']') { fprintf(stderr, "bee-dep: %s: error at line %d: missing bracket\n", filename, line_cnt); return 1; } *p = '\0'; if (p - s == 0) { fprintf(stderr, "bee-dep: %s: error at line %d: empty node name\n", filename, line_cnt); return 1; } if (IS_FILE(s)) { if (!pkgname[0]) { fprintf(stderr, "bee-dep: %s: error at line %d: " "dont know to which package" "\"%s\" belongs to\n", filename, line_cnt, s); return 1; } sprintf(nodename, "%s%s", pkgname, s); } else { sprintf(nodename, "%s", s); } c = node_new(nodename, UNKNOWN); n = hash_safe_insert(hash, c); if (c != n) node_free(c); type_flag = 0; continue; } /* read node properties */ a = s; while (*a && *a != ' ' && *a != '\t' && *a != '=') a++; l = a - s; memset(prop, '\0', LINE_MAX); strncpy(prop, s, l * sizeof(char)); while (*a && (*a == ' ' || *a == '\t' || *a == '=')) a++; l = p - a + 1; if (!l) { fprintf(stderr, "bee-dep: warning: %s: line %d: missing value " "for property \"%s\"\n", filename, line_cnt, prop); } memset(value, '\0', LINE_MAX); strncpy(value, a, l * sizeof(char)); if (strcasecmp(prop, TYPE) == 0) { if (type_flag) { fprintf(stderr, "bee-dep: %s: error at line %d: " "ambiguous type \"%s\"\n", filename, line_cnt, value); return 1; } node_set_type(n, value); if (is_virtual_file(n->name)) node_set_type(hash_search(hash, get_filename(n->name)), value); if (strcasecmp(PACKAGE, value) == 0) sprintf(pkgname, "%s", n->name); type_flag = 1; } else if (strcasecmp(prop, PROVIDES) == 0) { c = node_new(value, UNKNOWN); h = hash_safe_insert(hash, c); if (c != h) node_free(c); if (IS_FILE(value)) { sprintf(nodename, "%s%s", pkgname, value); c = node_new(nodename, UNKNOWN); v = hash_safe_insert(hash, c); if (v != c) node_free(c); add_provide(n, v); add_provide(v, h); } else { add_provide(n, h); } } else if (strcasecmp(prop, NEEDS) == 0) { c = node_new(value, UNKNOWN); h = hash_safe_insert(hash, c); if (c != h) node_free(c); add_need(n, h); } } if (fclose(file) == EOF) { perror("bee-dep: graph_insert_nodes: fclose"); return 1; } if (line_cnt == 0) { fprintf(stderr, "bee-dep: error: file '%s' is empty\n", filename); return 1; } return 0; }
*/ static REB_R File_Actor(struct Reb_Call *call_, REBSER *port, REBCNT action) /* ** Internal port handler for files. ** ***********************************************************************/ { REBVAL *spec; REBVAL *path; REBREQ *file = 0; REBCNT args = 0; REBCNT len; REBOOL opened = FALSE; // had to be opened (shortcut case) //Print("FILE ACTION: %r", Get_Action_Word(action)); Validate_Port(port, action); *D_OUT = *D_ARG(1); // Validate PORT fields: spec = BLK_SKIP(port, STD_PORT_SPEC); if (!IS_OBJECT(spec)) Trap1_DEAD_END(RE_INVALID_SPEC, spec); path = Obj_Value(spec, STD_PORT_SPEC_HEAD_REF); if (!path) Trap1_DEAD_END(RE_INVALID_SPEC, spec); if (IS_URL(path)) path = Obj_Value(spec, STD_PORT_SPEC_HEAD_PATH); else if (!IS_FILE(path)) Trap1_DEAD_END(RE_INVALID_SPEC, path); // Get or setup internal state data: file = (REBREQ*)Use_Port_State(port, RDI_FILE, sizeof(*file)); switch (action) { case A_READ: args = Find_Refines(call_, ALL_READ_REFS); // Handle the READ %file shortcut case: if (!IS_OPEN(file)) { REBCNT nargs = AM_OPEN_READ; if (args & AM_READ_SEEK) nargs |= AM_OPEN_SEEK; Setup_File(file, nargs, path); Open_File_Port(port, file, path); opened = TRUE; } if (args & AM_READ_SEEK) Set_Seek(file, D_ARG(ARG_READ_INDEX)); len = Set_Length( file, D_REF(ARG_READ_PART) ? VAL_INT64(D_ARG(ARG_READ_LENGTH)) : -1 ); Read_File_Port(D_OUT, port, file, path, args, len); if (opened) { OS_DO_DEVICE(file, RDC_CLOSE); Cleanup_File(file); } if (file->error) Trap_Port_DEAD_END(RE_READ_ERROR, port, file->error); break; case A_APPEND: if (!(IS_BINARY(D_ARG(2)) || IS_STRING(D_ARG(2)) || IS_BLOCK(D_ARG(2)))) Trap1_DEAD_END(RE_INVALID_ARG, D_ARG(2)); file->special.file.index = file->special.file.size; SET_FLAG(file->modes, RFM_RESEEK); case A_WRITE: args = Find_Refines(call_, ALL_WRITE_REFS); spec = D_ARG(2); // data (binary, string, or block) // Handle the READ %file shortcut case: if (!IS_OPEN(file)) { REBCNT nargs = AM_OPEN_WRITE; if (args & AM_WRITE_SEEK || args & AM_WRITE_APPEND) nargs |= AM_OPEN_SEEK; else nargs |= AM_OPEN_NEW; Setup_File(file, nargs, path); Open_File_Port(port, file, path); opened = TRUE; } else { if (!GET_FLAG(file->modes, RFM_WRITE)) Trap1_DEAD_END(RE_READ_ONLY, path); } // Setup for /append or /seek: if (args & AM_WRITE_APPEND) { file->special.file.index = -1; // append SET_FLAG(file->modes, RFM_RESEEK); } if (args & AM_WRITE_SEEK) Set_Seek(file, D_ARG(ARG_WRITE_INDEX)); // Determine length. Clip /PART to size of string if needed. len = VAL_LEN(spec); if (args & AM_WRITE_PART) { REBCNT n = Int32s(D_ARG(ARG_WRITE_LENGTH), 0); if (n <= len) len = n; } Write_File_Port(file, spec, len, args); if (opened) { OS_DO_DEVICE(file, RDC_CLOSE); Cleanup_File(file); } if (file->error) Trap1_DEAD_END(RE_WRITE_ERROR, path); break; case A_OPEN: args = Find_Refines(call_, ALL_OPEN_REFS); // Default file modes if not specified: if (!(args & (AM_OPEN_READ | AM_OPEN_WRITE))) args |= (AM_OPEN_READ | AM_OPEN_WRITE); Setup_File(file, args, path); Open_File_Port(port, file, path); // !!! needs to change file modes to R/O if necessary break; case A_COPY: if (!IS_OPEN(file)) Trap1_DEAD_END(RE_NOT_OPEN, path); //!!!! wrong msg len = Set_Length(file, D_REF(2) ? VAL_INT64(D_ARG(3)) : -1); Read_File_Port(D_OUT, port, file, path, args, len); break; case A_OPENQ: if (IS_OPEN(file)) return R_TRUE; return R_FALSE; case A_CLOSE: if (IS_OPEN(file)) { OS_DO_DEVICE(file, RDC_CLOSE); Cleanup_File(file); } break; case A_DELETE: if (IS_OPEN(file)) Trap1_DEAD_END(RE_NO_DELETE, path); Setup_File(file, 0, path); if (OS_DO_DEVICE(file, RDC_DELETE) < 0 ) Trap1_DEAD_END(RE_NO_DELETE, path); break; case A_RENAME: if (IS_OPEN(file)) Trap1_DEAD_END(RE_NO_RENAME, path); else { REBSER *target; Setup_File(file, 0, path); // Convert file name to OS format: if (!(target = Value_To_OS_Path(D_ARG(2), TRUE))) Trap1_DEAD_END(RE_BAD_FILE_PATH, D_ARG(2)); file->common.data = BIN_DATA(target); OS_DO_DEVICE(file, RDC_RENAME); Free_Series(target); if (file->error) Trap1_DEAD_END(RE_NO_RENAME, path); } break; case A_CREATE: // !!! should it leave file open??? if (!IS_OPEN(file)) { Setup_File(file, AM_OPEN_WRITE | AM_OPEN_NEW, path); if (OS_DO_DEVICE(file, RDC_CREATE) < 0) Trap_Port_DEAD_END(RE_CANNOT_OPEN, port, file->error); OS_DO_DEVICE(file, RDC_CLOSE); } break; case A_QUERY: if (!IS_OPEN(file)) { Setup_File(file, 0, path); if (OS_DO_DEVICE(file, RDC_QUERY) < 0) return R_NONE; } Ret_Query_File(port, file, D_OUT); // !!! free file path? break; case A_MODIFY: Set_Mode_Value(file, Get_Mode_Id(D_ARG(2)), D_ARG(3)); if (!IS_OPEN(file)) { Setup_File(file, 0, path); if (OS_DO_DEVICE(file, RDC_MODIFY) < 0) return R_NONE; } return R_TRUE; break; case A_INDEXQ: SET_INTEGER(D_OUT, file->special.file.index + 1); break; case A_LENGTHQ: SET_INTEGER(D_OUT, file->special.file.size - file->special.file.index); // !clip at zero break; case A_HEAD: file->special.file.index = 0; goto seeked; case A_TAIL: file->special.file.index = file->special.file.size; goto seeked; case A_NEXT: file->special.file.index++; goto seeked; case A_BACK: if (file->special.file.index > 0) file->special.file.index--; goto seeked; case A_SKIP: file->special.file.index += Get_Num_Arg(D_ARG(2)); goto seeked; case A_HEADQ: DECIDE(file->special.file.index == 0); case A_TAILQ: DECIDE(file->special.file.index >= file->special.file.size); case A_PASTQ: DECIDE(file->special.file.index > file->special.file.size); case A_CLEAR: // !! check for write enabled? SET_FLAG(file->modes, RFM_RESEEK); SET_FLAG(file->modes, RFM_TRUNCATE); file->length = 0; if (OS_DO_DEVICE(file, RDC_WRITE) < 0) Trap1_DEAD_END(RE_WRITE_ERROR, path); break; /* Not yet implemented: A_AT, // 38 A_PICK, // 41 A_PATH, // 42 A_PATH_SET, // 43 A_FIND, // 44 A_SELECT, // 45 A_TAKE, // 49 A_INSERT, // 50 A_REMOVE, // 52 A_CHANGE, // 53 A_POKE, // 54 A_QUERY, // 64 A_FLUSH, // 65 */ default: Trap_Action_DEAD_END(REB_PORT, action); } return R_OUT; seeked: SET_FLAG(file->modes, RFM_RESEEK); return R_ARG1; is_true: return R_TRUE; is_false: return R_FALSE; }
*/ static int Dir_Actor(REBVAL *ds, REBSER *port, REBCNT action) /* ** Internal port handler for file directories. ** ***********************************************************************/ { REBVAL *spec; REBVAL *path; REBVAL *state; REBREQ dir; REBCNT args = 0; REBINT result; REBCNT len; //REBYTE *flags; Validate_Port(port, action); *D_RET = *D_ARG(1); CLEARS(&dir); // Validate and fetch relevant PORT fields: spec = BLK_SKIP(port, STD_PORT_SPEC); if (!IS_OBJECT(spec)) Trap1(RE_INVALID_SPEC, spec); path = Obj_Value(spec, STD_PORT_SPEC_HEAD_REF); if (!path) Trap1(RE_INVALID_SPEC, spec); if (IS_URL(path)) path = Obj_Value(spec, STD_PORT_SPEC_HEAD_PATH); else if (!IS_FILE(path)) Trap1(RE_INVALID_SPEC, path); state = BLK_SKIP(port, STD_PORT_STATE); // if block, then port is open. //flags = Security_Policy(SYM_FILE, path); // Get or setup internal state data: dir.port = port; dir.device = RDI_FILE; switch (action) { case A_READ: //Trap_Security(flags[POL_READ], POL_READ, path); args = Find_Refines(ds, ALL_READ_REFS); if (!IS_BLOCK(state)) { // !!! ignores /SKIP and /PART, for now Init_Dir_Path(&dir, path, 1, POL_READ); Set_Block(state, Make_Block(7)); // initial guess result = Read_Dir(&dir, VAL_SERIES(state)); ///OS_FREE(dir.file.path); if (result < 0) Trap_Port(RE_CANNOT_OPEN, port, dir.error); *D_RET = *state; SET_NONE(state); } else { len = VAL_BLK_LEN(state); // !!? Why does this need to copy the block?? Set_Block(D_RET, Copy_Block_Values(VAL_SERIES(state), 0, len, TS_STRING)); } break; case A_CREATE: //Trap_Security(flags[POL_WRITE], POL_WRITE, path); if (IS_BLOCK(state)) Trap1(RE_ALREADY_OPEN, path); // already open create: Init_Dir_Path(&dir, path, 0, POL_WRITE | REMOVE_TAIL_SLASH); // Sets RFM_DIR too result = OS_DO_DEVICE(&dir, RDC_CREATE); ///OS_FREE(dir.file.path); if (result < 0) Trap1(RE_NO_CREATE, path); if (action == A_CREATE) return R_ARG2; SET_NONE(state); break; case A_RENAME: if (IS_BLOCK(state)) Trap1(RE_ALREADY_OPEN, path); // already open else { REBSER *target; Init_Dir_Path(&dir, path, 0, POL_WRITE | REMOVE_TAIL_SLASH); // Sets RFM_DIR too // Convert file name to OS format: if (!(target = Value_To_OS_Path(D_ARG(2)))) Trap1(RE_BAD_FILE_PATH, D_ARG(2)); dir.data = BIN_DATA(target); OS_DO_DEVICE(&dir, RDC_RENAME); Free_Series(target); if (dir.error) Trap1(RE_NO_RENAME, path); } break; case A_DELETE: //Trap_Security(flags[POL_WRITE], POL_WRITE, path); SET_NONE(state); Init_Dir_Path(&dir, path, 0, POL_WRITE); // !!! add *.r deletion // !!! add recursive delete (?) result = OS_DO_DEVICE(&dir, RDC_DELETE); ///OS_FREE(dir.file.path); if (result < 0) Trap1(RE_NO_DELETE, path); return R_ARG2; case A_OPEN: // !! If open fails, what if user does a READ w/o checking for error? if (IS_BLOCK(state)) Trap1(RE_ALREADY_OPEN, path); // already open //Trap_Security(flags[POL_READ], POL_READ, path); args = Find_Refines(ds, ALL_OPEN_REFS); if (args & AM_OPEN_NEW) goto create; //if (args & ~AM_OPEN_READ) Trap1(RE_INVALID_SPEC, path); Set_Block(state, Make_Block(7)); Init_Dir_Path(&dir, path, 1, POL_READ); result = Read_Dir(&dir, VAL_SERIES(state)); ///OS_FREE(dir.file.path); if (result < 0) Trap_Port(RE_CANNOT_OPEN, port, dir.error); break; case A_OPENQ: if (IS_BLOCK(state)) return R_TRUE; return R_FALSE; case A_CLOSE: SET_NONE(state); break; case A_QUERY: //Trap_Security(flags[POL_READ], POL_READ, path); SET_NONE(state); Init_Dir_Path(&dir, path, -1, REMOVE_TAIL_SLASH | POL_READ); if (OS_DO_DEVICE(&dir, RDC_QUERY) < 0) return R_NONE; Ret_Query_File(port, &dir, D_RET); ///OS_FREE(dir.file.path); break; //-- Port Series Actions (only called if opened as a port) case A_LENGTHQ: len = IS_BLOCK(state) ? VAL_BLK_LEN(state) : 0; SET_INTEGER(D_RET, len); break; default: Trap_Action(REB_PORT, action); } return R_RET; }
static int romfs_readdir(FAR struct inode *mountpt, FAR struct fs_dirent_s *dir) { FAR struct romfs_mountpt_s *rm; uint32_t linkoffset; uint32_t next; uint32_t info; uint32_t size; int ret; fvdbg("Entry\n"); /* Sanity checks */ DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL); /* Recover our private data from the inode instance */ rm = mountpt->i_private; /* Make sure that the mount is still healthy */ romfs_semtake(rm); ret = romfs_checkmount(rm); if (ret != OK) { fdbg("romfs_checkmount failed: %d\n", ret); goto errout_with_semaphore; } /* Loop, skipping over unsupported items in the file system */ for (;;) { /* Have we reached the end of the directory */ if (!dir->u.romfs.fr_curroffset) { /* We signal the end of the directory by returning the * special error -ENOENT */ fdbg("End of directory\n"); ret = -ENOENT; goto errout_with_semaphore; } /* Parse the directory entry */ ret = romfs_parsedirentry(rm, dir->u.romfs.fr_curroffset, &linkoffset, &next, &info, &size); if (ret < 0) { fdbg("romfs_parsedirentry failed: %d\n", ret); goto errout_with_semaphore; } /* Save the filename */ ret = romfs_parsefilename(rm, dir->u.romfs.fr_curroffset, dir->fd_dir.d_name); if (ret < 0) { fdbg("romfs_parsefilename failed: %d\n", ret); goto errout_with_semaphore; } /* Set up the next directory entry offset */ dir->u.romfs.fr_curroffset = next & RFNEXT_OFFSETMASK; /* Check the file type */ if (IS_DIRECTORY(next)) { dir->fd_dir.d_type = DTYPE_DIRECTORY; break; } else if (IS_FILE(next)) { dir->fd_dir.d_type = DTYPE_FILE; break; } } errout_with_semaphore: romfs_semgive(rm); return ret; }
static int romfs_stat(FAR struct inode *mountpt, FAR const char *relpath, FAR struct stat *buf) { FAR struct romfs_mountpt_s *rm; FAR struct romfs_dirinfo_s dirinfo; int ret; fvdbg("Entry\n"); /* Sanity checks */ DEBUGASSERT(mountpt && mountpt->i_private); /* Get the mountpoint private data from the inode structure */ rm = mountpt->i_private; /* Check if the mount is still healthy */ romfs_semtake(rm); ret = romfs_checkmount(rm); if (ret != OK) { fdbg("romfs_checkmount failed: %d\n", ret); goto errout_with_semaphore; } /* Find the directory entry corresponding to relpath. */ ret = romfs_finddirentry(rm, &dirinfo, relpath); /* If nothing was found, then we fail with EEXIST */ if (ret < 0) { fvdbg("Failed to find directory: %d\n", ret); goto errout_with_semaphore; } memset(buf, 0, sizeof(struct stat)); if (IS_DIRECTORY(dirinfo.rd_next)) { /* It's a read-only directory name */ buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR; if (IS_EXECUTABLE(dirinfo.rd_next)) { buf->st_mode |= S_IXOTH|S_IXGRP|S_IXUSR; } } else if (IS_FILE(dirinfo.rd_next)) { /* It's a read-only file name */ buf->st_mode = S_IFREG|S_IROTH|S_IRGRP|S_IRUSR; if (IS_EXECUTABLE(dirinfo.rd_next)) { buf->st_mode |= S_IXOTH|S_IXGRP|S_IXUSR; } } else { /* Otherwise, pretend like the unsupported node does not exist */ fvdbg("Unsupported inode: %d\n", dirinfo.rd_next); ret = -ENOENT; goto errout_with_semaphore; } /* File/directory size, access block size */ buf->st_size = dirinfo.rd_size; buf->st_blksize = rm->rm_hwsectorsize; buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize; ret = OK; errout_with_semaphore: romfs_semgive(rm); return ret; }
static int fatfs_rename(vnode_t dvp1, vnode_t vp1, char *name1, vnode_t dvp2, vnode_t vp2, char *name2) { struct fatfsmount *fmp; struct fatfs_node np1; struct fat_dirent *de1, *de2; int error; fmp = dvp1->v_mount->m_data; mutex_lock(&fmp->lock); error = fatfs_lookup_node(dvp1, name1, &np1); if (error) goto out; de1 = &np1.dirent; if (IS_FILE(de1)) { /* Remove destination file, first */ error = fatfs_remove(dvp2, vp1, name2); if (error == EIO) goto out; /* Change file name of directory entry */ fat_convert_name(name2, (char *)de1->name); /* Same directory ? */ if (dvp1 == dvp2) { /* Change the name of existing file */ error = fatfs_put_node(fmp, &np1); if (error) goto out; } else { /* Create new directory entry */ error = fatfs_add_node(dvp2, &np1); if (error) goto out; /* Remove souce file */ error = fatfs_remove(dvp1, vp2, name1); if (error) goto out; } } else { /* remove destination directory */ error = fatfs_rmdir(dvp2, NULL, name2); if (error == EIO) goto out; /* Change file name of directory entry */ fat_convert_name(name2, (char *)de1->name); /* Same directory ? */ if (dvp1 == dvp2) { /* Change the name of existing directory */ error = fatfs_put_node(fmp, &np1); if (error) goto out; } else { /* Create new directory entry */ error = fatfs_add_node(dvp2, &np1); if (error) goto out; /* Update "." and ".." for renamed directory */ if (fat_read_cluster(fmp,(de1->cluster_hi << 16) | de1->cluster)) { error = EIO; goto out; } de2 = (struct fat_dirent *)fmp->io_buf; de2->cluster_hi = de1->cluster_hi; de2->cluster = de1->cluster; de2->time = TEMP_TIME; de2->date = TEMP_DATE; de2++; de2->cluster_hi = (dvp2->v_blkno & 0xFFFF0000) >> 16; de2->cluster = dvp2->v_blkno & 0x0000FFFF; de2->time = TEMP_TIME; de2->date = TEMP_DATE; if (fat_write_cluster(fmp,(de1->cluster_hi << 16) | de1->cluster)) { error = EIO; goto out; } /* Remove souce directory */ error = fatfs_rmdir(dvp1, NULL, name1); if (error) goto out; } } out: mutex_unlock(&fmp->lock); return error; }
// // Serial_Actor: C // static REB_R Serial_Actor(REBFRM *frame_, REBCTX *port, REBSYM action) { REBREQ *req; // IO request REBVAL *spec; // port spec REBVAL *arg; // action argument value REBVAL *val; // e.g. port number value REBINT result; // IO result REBCNT refs; // refinement argument flags REBCNT len; // generic length REBSER *ser; // simplifier REBVAL *path; Validate_Port(port, action); *D_OUT = *D_ARG(1); // Validate PORT fields: spec = CTX_VAR(port, STD_PORT_SPEC); if (!IS_OBJECT(spec)) fail (Error(RE_INVALID_PORT)); path = Obj_Value(spec, STD_PORT_SPEC_HEAD_REF); if (!path) fail (Error(RE_INVALID_SPEC, spec)); //if (!IS_FILE(path)) fail (Error(RE_INVALID_SPEC, path)); req = cast(REBREQ*, Use_Port_State(port, RDI_SERIAL, sizeof(*req))); // Actions for an unopened serial port: if (!IS_OPEN(req)) { switch (action) { case SYM_OPEN: arg = Obj_Value(spec, STD_PORT_SPEC_SERIAL_PATH); if (! (IS_FILE(arg) || IS_STRING(arg) || IS_BINARY(arg))) fail (Error(RE_INVALID_PORT_ARG, arg)); req->special.serial.path = ALLOC_N(REBCHR, MAX_SERIAL_DEV_PATH); OS_STRNCPY( req->special.serial.path, // // !!! This is assuming VAL_DATA contains native chars. // Should it? (2 bytes on windows, 1 byte on linux/mac) // SER_AT(REBCHR, VAL_SERIES(arg), VAL_INDEX(arg)), MAX_SERIAL_DEV_PATH ); arg = Obj_Value(spec, STD_PORT_SPEC_SERIAL_SPEED); if (! IS_INTEGER(arg)) fail (Error(RE_INVALID_PORT_ARG, arg)); req->special.serial.baud = VAL_INT32(arg); //Secure_Port(SYM_SERIAL, ???, path, ser); arg = Obj_Value(spec, STD_PORT_SPEC_SERIAL_DATA_SIZE); if (!IS_INTEGER(arg) || VAL_INT64(arg) < 5 || VAL_INT64(arg) > 8 ) { fail (Error(RE_INVALID_PORT_ARG, arg)); } req->special.serial.data_bits = VAL_INT32(arg); arg = Obj_Value(spec, STD_PORT_SPEC_SERIAL_STOP_BITS); if (!IS_INTEGER(arg) || VAL_INT64(arg) < 1 || VAL_INT64(arg) > 2 ) { fail (Error(RE_INVALID_PORT_ARG, arg)); } req->special.serial.stop_bits = VAL_INT32(arg); arg = Obj_Value(spec, STD_PORT_SPEC_SERIAL_PARITY); if (IS_BLANK(arg)) { req->special.serial.parity = SERIAL_PARITY_NONE; } else { if (!IS_WORD(arg)) fail (Error(RE_INVALID_PORT_ARG, arg)); switch (VAL_WORD_SYM(arg)) { case SYM_ODD: req->special.serial.parity = SERIAL_PARITY_ODD; break; case SYM_EVEN: req->special.serial.parity = SERIAL_PARITY_EVEN; break; default: fail (Error(RE_INVALID_PORT_ARG, arg)); } } arg = Obj_Value(spec, STD_PORT_SPEC_SERIAL_FLOW_CONTROL); if (IS_BLANK(arg)) { req->special.serial.flow_control = SERIAL_FLOW_CONTROL_NONE; } else { if (!IS_WORD(arg)) fail (Error(RE_INVALID_PORT_ARG, arg)); switch (VAL_WORD_SYM(arg)) { case SYM_HARDWARE: req->special.serial.flow_control = SERIAL_FLOW_CONTROL_HARDWARE; break; case SYM_SOFTWARE: req->special.serial.flow_control = SERIAL_FLOW_CONTROL_SOFTWARE; break; default: fail (Error(RE_INVALID_PORT_ARG, arg)); } } if (OS_DO_DEVICE(req, RDC_OPEN)) fail (Error_On_Port(RE_CANNOT_OPEN, port, -12)); SET_OPEN(req); return R_OUT; case SYM_CLOSE: return R_OUT; case SYM_OPEN_Q: return R_FALSE; default: fail (Error_On_Port(RE_NOT_OPEN, port, -12)); } } // Actions for an open socket: switch (action) { case SYM_READ: refs = Find_Refines(frame_, ALL_READ_REFS); // Setup the read buffer (allocate a buffer if needed): arg = CTX_VAR(port, STD_PORT_DATA); if (!IS_STRING(arg) && !IS_BINARY(arg)) { Val_Init_Binary(arg, Make_Binary(32000)); } ser = VAL_SERIES(arg); req->length = SER_AVAIL(ser); // space available if (req->length < 32000/2) Extend_Series(ser, 32000); req->length = SER_AVAIL(ser); // This used STR_TAIL (obsolete, equivalent to BIN_TAIL) but was it // sure the series was byte sized? Added in a check. assert(BYTE_SIZE(ser)); req->common.data = BIN_TAIL(ser); // write at tail //if (SER_LEN(ser) == 0) req->actual = 0; // Actual for THIS read, not for total. #ifdef DEBUG_SERIAL printf("(max read length %d)", req->length); #endif result = OS_DO_DEVICE(req, RDC_READ); // recv can happen immediately if (result < 0) fail (Error_On_Port(RE_READ_ERROR, port, req->error)); #ifdef DEBUG_SERIAL for (len = 0; len < req->actual; len++) { if (len % 16 == 0) printf("\n"); printf("%02x ", req->common.data[len]); } printf("\n"); #endif *D_OUT = *arg; return R_OUT; case SYM_WRITE: refs = Find_Refines(frame_, ALL_WRITE_REFS); // Determine length. Clip /PART to size of string if needed. spec = D_ARG(2); len = VAL_LEN_AT(spec); if (refs & AM_WRITE_PART) { REBCNT n = Int32s(D_ARG(ARG_WRITE_LIMIT), 0); if (n <= len) len = n; } // Setup the write: *CTX_VAR(port, STD_PORT_DATA) = *spec; // keep it GC safe req->length = len; req->common.data = VAL_BIN_AT(spec); req->actual = 0; //Print("(write length %d)", len); result = OS_DO_DEVICE(req, RDC_WRITE); // send can happen immediately if (result < 0) fail (Error_On_Port(RE_WRITE_ERROR, port, req->error)); break; case SYM_UPDATE: // Update the port object after a READ or WRITE operation. // This is normally called by the WAKE-UP function. arg = CTX_VAR(port, STD_PORT_DATA); if (req->command == RDC_READ) { if (ANY_BINSTR(arg)) { SET_SERIES_LEN( VAL_SERIES(arg), VAL_LEN_HEAD(arg) + req->actual ); } } else if (req->command == RDC_WRITE) { SET_BLANK(arg); // Write is done. } return R_BLANK; case SYM_OPEN_Q: return R_TRUE; case SYM_CLOSE: if (IS_OPEN(req)) { OS_DO_DEVICE(req, RDC_CLOSE); SET_CLOSED(req); } break; default: fail (Error_Illegal_Action(REB_PORT, action)); } return R_OUT; }
int make_assumptions(child_args_t *args) { char TmpStr[80]; struct stat stat_buf; int rv; if (!(args->flags & CLD_FLG_IOTYPS)) { /* use stat to get file properties, and use to set -I */ rv = stat(args->device, &stat_buf); if (0 == rv) { if (IS_FILE(stat_buf.st_mode)) { strncat(args->argstr, "(-I f) ", (MAX_ARG_LEN-1)-strlen(args->argstr)); args->flags |= CLD_FLG_FILE; } else if (IS_BLK(stat_buf.st_mode)) { strncat(args->argstr, "(-I b) ", (MAX_ARG_LEN-1)-strlen(args->argstr)); args->flags |= CLD_FLG_BLK; #ifndef WINDOWS } else if (S_ISCHR(stat_buf.st_mode)) { strncat(args->argstr, "(-I r) ", (MAX_ARG_LEN-1)-strlen(args->argstr)); args->flags |= CLD_FLG_RAW; #endif } } else { pMsg(WARN, args, "Can't get status on %s, defaulting to file, errno = %d\n", args->device, GETLASTERROR()); strncat(args->argstr, "(-I f) ", (MAX_ARG_LEN-1)-strlen(args->argstr)); args->flags |= CLD_FLG_FILE; } } if ((args->flags & CLD_FLG_WFSYNC) && (0 == args->sync_interval)) { pMsg(INFO, args, "Sync interval set to zero, assuming interval of 1.\n"); args->sync_interval = 1; } if (args->ltrsiz <= 0) { sprintf(TmpStr, "(-B %d) ", TRSIZ*BLK_SIZE); strncat(args->argstr, TmpStr, (MAX_ARG_LEN-1)-strlen(args->argstr)); args->ltrsiz=TRSIZ; args->htrsiz=TRSIZ; } if (args->flags & CLD_FLG_LBA_RNG) { args->start_blk = args->start_lba / args->htrsiz; if (!(args->stop_lba < 0)) args->stop_blk = args->stop_lba / args->htrsiz; } if (args->flags & CLD_FLG_BLK_RNG) { args->start_lba = args->start_blk * args->htrsiz; if (!(args->stop_blk < 0)) args->stop_lba = (args->stop_blk * args->htrsiz) + (args->htrsiz - 1); } /* if vsiz is still not set, try and get it from the file */ if ((args->vsiz <=0) && (args->flags & CLD_FLG_FILE)) { if (0 != get_file_size(args->device)) { /* file size retrieved */ args->vsiz=get_file_size(args->device); } } /* if vsiz is still not set, try and get it from the device */ if ((args->vsiz <= 0) && !(args->flags & CLD_FLG_FILE)) { args->vsiz=get_vsiz(args->device); } /* if vsiz is still not set, set based on given range */ if ((args->vsiz <=0) && (args->flags & (CLD_FLG_LBA_RNG|CLD_FLG_BLK_RNG))) { if (!(args->stop_lba < 0)) args->vsiz=args->stop_lba+1; else args->vsiz=args->start_lba+1; } /* if vsiz is still not set, then set it to the default size */ if (args->vsiz <= 0) { args->vsiz=VSIZ; } if (!(args->flags & CLD_FLG_VSIZ)) { sprintf(TmpStr, N_ASSUME, args->vsiz); strncat(args->argstr, TmpStr, (MAX_ARG_LEN-1)-strlen(args->argstr)); } if (args->stop_lba == -1) { args->stop_lba=args->vsiz-1; } if (args->stop_blk == -1) { args->stop_blk=(args->stop_lba / (OFF_T) args->htrsiz); } if (args->t_kids == 0) { sprintf(TmpStr, "(-K %d) ", KIDS); strncat(args->argstr, TmpStr, (MAX_ARG_LEN-1)-strlen(args->argstr)); args->t_kids=KIDS; } if ((args->flags & (CLD_FLG_W|CLD_FLG_R)) == 0) { if (args->flags & CLD_FLG_DUTY) { /* no read/write but duty cycle specified */ if (args->rperc > 0) { args->flags |= CLD_FLG_R; strncat(args->argstr, "(-r) ", (MAX_ARG_LEN-1)-strlen(args->argstr)); } if (args->wperc > 0) { args->flags |= CLD_FLG_W; strncat(args->argstr, "(-w) ", (MAX_ARG_LEN-1)-strlen(args->argstr)); } } else { strncat(args->argstr, "(-r) ", (MAX_ARG_LEN-1)-strlen(args->argstr)); args->flags |= CLD_FLG_R; } } if (!(args->flags & CLD_FLG_PTYPS)) { strncat(args->argstr, "(-c) ", (MAX_ARG_LEN-1)-strlen(args->argstr)); args->flags |= CLD_FLG_CPTYPE; } if (!(args->flags & CLD_FLG_SKTYPS)) { strncat(args->argstr, "(-p R) ", (MAX_ARG_LEN-1)-strlen(args->argstr)); args->flags |= CLD_FLG_RANDOM; } if (!(args->flags & CLD_FLG_SKS)) { if (args->start_blk == args->stop_blk) { /* diskcache test, w/ no seek count set */ args->seeks = SEEKS; } else if (args->flags & (CLD_FLG_BLK_RNG|CLD_FLG_LBA_RNG)) { /* range set, w/ no seek count */ args->seeks = args->stop_blk - args->start_blk + 1; } else { /* if vsiz is available, calculated seeks are in terms of the largest transfer size */ args->seeks = (args->vsiz > 0) ? (args->vsiz / args->htrsiz) : SEEKS; } if ((args->flags & CLD_FLG_LINEAR) && (args->flags & CLD_FLG_R) && (args->flags & CLD_FLG_W)) { args->seeks *= 2; } if (!(args->flags & CLD_FLG_TMD)) { sprintf(TmpStr, L_ASSUME, args->seeks); strncat(args->argstr, TmpStr, (MAX_ARG_LEN-1)-strlen(args->argstr)); } } if (!(args->flags & (CLD_FLG_SKS|CLD_FLG_TMD)) || ((args->flags & CLD_FLG_CYC) && !(args->flags & (CLD_FLG_SKS|CLD_FLG_TMD)))) { args->flags |= CLD_FLG_SKS; } if (args->flags & (CLD_FLG_LINEAR)) { if (!(args->flags & (CLD_FLG_LUNU|CLD_FLG_LUND))) { strncat(args->argstr, "(-p u) ", (MAX_ARG_LEN-1)-strlen(args->argstr)); args->flags |= CLD_FLG_LUNU; } } normalize_percs(args); if (!(args->flags & CLD_FLG_DUTY) && (args->flags & CLD_FLG_RANDOM) && !(args->flags & CLD_FLG_NTRLVD)) { sprintf(TmpStr, "(-D %d:%d) ", args->rperc, args->wperc); strncat(args->argstr, TmpStr, (MAX_ARG_LEN-1)-strlen(args->argstr)); args->flags |= CLD_FLG_DUTY; } if ((args->delayTimeMin == 0) && (args->delayTimeMax == 0) && (args->ioTimeout == DEFAULT_IO_TIMEOUT)) { strncat(args->argstr, "(-t 0:2m) ", (MAX_ARG_LEN-1)-strlen(args->argstr)); } if (!(args->flags & CLD_FLG_OFFSET)) { strncat(args->argstr, "(-o 0) ", (MAX_ARG_LEN-1)-strlen(args->argstr)); } return 0; }
/* * checks validity of data after parsing * args and make assumtions. returns 0 on * success and -1 on failure. */ int check_conclusions(child_args_t *args) { extern unsigned long glb_flags; struct stat stat_buf; int rv; if ((args->flags & CLD_FLG_DUTY) && ((args->flags & CLD_FLG_LINEAR) || (args->flags & CLD_FLG_NTRLVD))) { pMsg(WARN, args, "Duty cycle testing is supported for random (-pR) tests only.\n"); return(-1); } if ((args->flags & CLD_FLG_BLK_RNG) && (args->flags & CLD_FLG_RTRSIZ)) { pMsg(WARN, args, "Can't have unfixed block sizes and specify seek range in terms of blocks.\n"); return(-1); } if ((args->vsiz < 0) || (args->ltrsiz < 1) || (args->htrsiz < 1)) { pMsg(WARN, args, "Bounds exceeded for transfer size and/or volume size.\n"); pMsg(WARN, args, MAXTRSIZ, (args->htrsiz*BLK_SIZE),args->vsiz); return(-1); } if (args->htrsiz < args->ltrsiz) { pMsg(ERR, args, "Min transfer size, %lu, greater then Max transfer size, %lu.\n", args->ltrsiz, args->htrsiz); return(-1); } if (args->vsiz < (args->stop_lba-args->start_lba+1)) { pMsg(ERR, args, "Volume stop block/lba exceeds volume size.\n"); return(-1); } if (args->vsiz < args->htrsiz) { pMsg(WARN, args, VSIZETS, args->vsiz, args->htrsiz); return(-1); } if ((args->flags & CLD_FLG_TMD) == 0 && (args->seeks <= 0)) { pMsg(WARN,args, TSEEK, args->seeks); return(-1); } if ((args->flags & CLD_FLG_SKS) && (args->t_kids > args->seeks)) { pMsg(WARN, args, "Can't have more children then max number of seeks, use -K/-L to adjust.\n"); return(-1); } if ((args->start_blk > args->vsiz) && !(args->flags & (CLD_FLG_BLK_RNG|CLD_FLG_LBA_RNG))) { pMsg(WARN, args, STBGTTLBA, args->start_blk, (args->vsiz / args->htrsiz)); return(-1); } if ((args->stop_blk > args->vsiz) && !(args->flags & (CLD_FLG_BLK_RNG|CLD_FLG_LBA_RNG))) { pMsg(WARN, args, SBGTTLBA, args->stop_blk, (args->vsiz / args->htrsiz)); return(-1); } if ((args->start_lba > args->vsiz) && !(args->flags & (CLD_FLG_BLK_RNG|CLD_FLG_LBA_RNG))) { pMsg(WARN, args, STLBAGTLBA, args->start_lba, args->vsiz); return(-1); } if ((args->stop_lba > args->vsiz) && !(args->flags & (CLD_FLG_BLK_RNG|CLD_FLG_LBA_RNG))) { pMsg(WARN, args, SLBAGTLBA, args->stop_lba, args->vsiz); return(-1); } if (args->start_blk > args->stop_blk) { pMsg(WARN, args, SBRSB, args->stop_blk, args->start_blk); return(-1); } if (args->start_lba > args->stop_lba) { pMsg(ERR, args, SLBARSLBA, args->stop_lba, args->start_lba); return(-1); } if ((args->flags & CLD_FLG_LBA_RNG) && (args->flags & CLD_FLG_BLK_RNG)) { pMsg(ERR, args, "Can't specify range in both block and LBA, use -s or -S.\n"); return(-1); } /* use stat to get file properties, and test then agains specified -I */ rv = stat(args->device, &stat_buf); if (0 == rv) { /* no error on call to stat, compare against -I option */ /* files are usually file type */ if ((args->flags & CLD_FLG_FILE) && !IS_FILE(stat_buf.st_mode)) { pMsg(ERR, args, "Can't open non-file filespec with file device type, -If.\n"); return(-1); } /* block devices, are usually block type */ if ((args->flags & CLD_FLG_BLK) && !IS_BLK(stat_buf.st_mode)) { pMsg(ERR, args, "Can't open non-block filespec with block device type, -Ib.\n"); return(-1); } #ifndef WINDOWS /* raw devices, are usually character type */ if ((args->flags & CLD_FLG_RAW) && !S_ISCHR(stat_buf.st_mode)) { pMsg(ERR, args, "Can't open non-raw filespec with raw device type, -Ir.\n"); return(-1); } #else if (args->flags & CLD_FLG_RAW) { pMsg(ERR, args, "RAW IO type not supported in Windows, use direct IO instead.\n"); return(-1); } #endif #ifdef _DEBUG } else { PDBG1(DBUG, args, "Can't get status on %s, assuming a new file, errno = %d\n", args->device, GETLASTERROR()); #endif } if ((args->hbeat > 0) && (args->flags & CLD_FLG_TMD) && (args->hbeat > args->run_time)) { pMsg(ERR, args, "Heartbeat should be at least equal to runtime, use -h/-T to adjust.\n"); return(-1); } if ((args->hbeat > 0) && !(args->flags & CLD_FLG_PRFTYPS)) { pMsg(ERR, args, "At least one performance option, -P, must be specified when using -h.\n"); return(-1); } if ((args->flags & CLD_FLG_W) && !(args->flags & CLD_FLG_R) && (args->flags & CLD_FLG_CMPR)) { pMsg(ERR, args, "Write only, ignoring option -E.\n"); } if ((args->flags & CLD_FLG_TMD) && (args->flags & CLD_FLG_SKS)) { pMsg(ERR, args, "Can't specify both -L and -T they are mutually exclusive.\n"); return(-1); } if (((args->flags & CLD_FLG_R) && !(args->flags & CLD_FLG_W)) && (args->flags & CLD_FLG_ERR_MARK)) { pMsg(ERR, args, "Can't specify mark on error, -Am, in read only mode.\n"); return(-1); } if (!(args->flags & CLD_FLG_ALLDIE) && (args->flags & CLD_FLG_ERR_MARK)) { pMsg(ERR, args, "Can't specify mark on error, -Am, when continue on error is set.\n"); return(-1); } if ((glb_flags & GLB_FLG_KILL) && !(args->flags & CLD_FLG_ALLDIE)) { pMsg(ERR, args, "Can't specify global kill, -Ag, when continue on error is set, -Ac.\n"); return(-1); } if ((args->flags & CLD_FLG_LINEAR) && !(args->flags & CLD_FLG_NTRLVD) && (args->flags & CLD_FLG_TMD)) { pMsg(ERR, args, "Linear read / write test can not be timed.\n"); return(-1); } if ((args->flags & CLD_FLG_CMPR) && (args->cmp_lng > (args->ltrsiz*BLK_SIZE))) { pMsg(ERR, args, "Compare length, %lu, is greater then transfer size, %lu\n", args->cmp_lng, args->ltrsiz*BLK_SIZE); return(-1); } if ((args->flags & CLD_FLG_OFFSET) && (args->offset > args->stop_lba)) { pMsg(ERR, args, LBAOFFGSLBA, args->offset, args->stop_lba); return(-1); } if ((args->flags & CLD_FLG_OFFSET) && ((args->offset+args->ltrsiz-1) > args->stop_lba)) { pMsg(ERR, args, LBAOTSGSLBA, args->offset, args->ltrsiz, args->stop_lba); return(-1); } return 0; }
*/ static REB_R Dir_Actor(struct Reb_Call *call_, REBSER *port, REBCNT action) /* ** Internal port handler for file directories. ** ***********************************************************************/ { REBVAL *spec; REBVAL *path; REBVAL *state; REBREQ dir; REBCNT args = 0; REBINT result; REBCNT len; //REBYTE *flags; Validate_Port(port, action); *D_OUT = *D_ARG(1); CLEARS(&dir); // Validate and fetch relevant PORT fields: spec = BLK_SKIP(port, STD_PORT_SPEC); if (!IS_OBJECT(spec)) raise Error_1(RE_INVALID_SPEC, spec); path = Obj_Value(spec, STD_PORT_SPEC_HEAD_REF); if (!path) raise Error_1(RE_INVALID_SPEC, spec); if (IS_URL(path)) path = Obj_Value(spec, STD_PORT_SPEC_HEAD_PATH); else if (!IS_FILE(path)) raise Error_1(RE_INVALID_SPEC, path); state = BLK_SKIP(port, STD_PORT_STATE); // if block, then port is open. //flags = Security_Policy(SYM_FILE, path); // Get or setup internal state data: dir.port = port; dir.device = RDI_FILE; switch (action) { case A_READ: //Trap_Security(flags[POL_READ], POL_READ, path); args = Find_Refines(call_, ALL_READ_REFS); if (!IS_BLOCK(state)) { // !!! ignores /SKIP and /PART, for now Init_Dir_Path(&dir, path, 1, POL_READ); Val_Init_Block(state, Make_Array(7)); // initial guess result = Read_Dir(&dir, VAL_SERIES(state)); ///OS_FREE(dir.file.path); if (result < 0) raise Error_On_Port(RE_CANNOT_OPEN, port, dir.error); *D_OUT = *state; SET_NONE(state); } else { // !!! This copies the strings in the block, shallowly. What is // the purpose of doing this? Why copy at all? Val_Init_Block( D_OUT, Copy_Array_Core_Managed( VAL_SERIES(state), 0, VAL_BLK_LEN(state), FALSE, // !deep TS_STRING ) ); } break; case A_CREATE: //Trap_Security(flags[POL_WRITE], POL_WRITE, path); if (IS_BLOCK(state)) raise Error_1(RE_ALREADY_OPEN, path); create: Init_Dir_Path(&dir, path, 0, POL_WRITE | REMOVE_TAIL_SLASH); // Sets RFM_DIR too result = OS_DO_DEVICE(&dir, RDC_CREATE); ///OS_FREE(dir.file.path); if (result < 0) raise Error_1(RE_NO_CREATE, path); if (action == A_CREATE) { // !!! Used to return R_ARG2, but create is single arity. :-/ return R_ARG1; } SET_NONE(state); break; case A_RENAME: if (IS_BLOCK(state)) raise Error_1(RE_ALREADY_OPEN, path); else { REBSER *target; Init_Dir_Path(&dir, path, 0, POL_WRITE | REMOVE_TAIL_SLASH); // Sets RFM_DIR too // Convert file name to OS format: if (!(target = Value_To_OS_Path(D_ARG(2), TRUE))) raise Error_1(RE_BAD_FILE_PATH, D_ARG(2)); dir.common.data = BIN_DATA(target); OS_DO_DEVICE(&dir, RDC_RENAME); Free_Series(target); if (dir.error) raise Error_1(RE_NO_RENAME, path); } break; case A_DELETE: //Trap_Security(flags[POL_WRITE], POL_WRITE, path); SET_NONE(state); Init_Dir_Path(&dir, path, 0, POL_WRITE); // !!! add *.r deletion // !!! add recursive delete (?) result = OS_DO_DEVICE(&dir, RDC_DELETE); ///OS_FREE(dir.file.path); if (result < 0) raise Error_1(RE_NO_DELETE, path); // !!! Returned R_ARG2 before, but there is no second argument :-/ return R_ARG1; case A_OPEN: // !! If open fails, what if user does a READ w/o checking for error? if (IS_BLOCK(state)) raise Error_1(RE_ALREADY_OPEN, path); //Trap_Security(flags[POL_READ], POL_READ, path); args = Find_Refines(call_, ALL_OPEN_REFS); if (args & AM_OPEN_NEW) goto create; //if (args & ~AM_OPEN_READ) raise Error_1(RE_INVALID_SPEC, path); Val_Init_Block(state, Make_Array(7)); Init_Dir_Path(&dir, path, 1, POL_READ); result = Read_Dir(&dir, VAL_SERIES(state)); ///OS_FREE(dir.file.path); if (result < 0) raise Error_On_Port(RE_CANNOT_OPEN, port, dir.error); break; case A_OPENQ: if (IS_BLOCK(state)) return R_TRUE; return R_FALSE; case A_CLOSE: SET_NONE(state); break; case A_QUERY: //Trap_Security(flags[POL_READ], POL_READ, path); SET_NONE(state); Init_Dir_Path(&dir, path, -1, REMOVE_TAIL_SLASH | POL_READ); if (OS_DO_DEVICE(&dir, RDC_QUERY) < 0) return R_NONE; Ret_Query_File(port, &dir, D_OUT); ///OS_FREE(dir.file.path); break; //-- Port Series Actions (only called if opened as a port) case A_LENGTH: len = IS_BLOCK(state) ? VAL_BLK_LEN(state) : 0; SET_INTEGER(D_OUT, len); break; default: raise Error_Illegal_Action(REB_PORT, action); } return R_OUT; }