/** * Wiped the given entry */ void wipeEntry(direntry_t *entry) { direntry_t longNameEntry; int i; initializeDirentry(&longNameEntry, entry->Dir); for(i=entry->beginSlot; i< entry->endSlot; i++) { int error; longNameEntry.entry=i; dir_read(&longNameEntry, &error); if(error) break; longNameEntry.dir.name[0] = (char) DELMARK; dir_write(&longNameEntry); } entry->dir.name[0] = (char) DELMARK; dir_write(entry); }
/* * Open the named file for read, create the cluster chain, return the * directory structure or NULL on error. */ int makeit(char *dosname, char *longname, void *arg0, direntry_t *targetEntry) { Stream_t *Target; CreateArg_t *arg = (CreateArg_t *) arg0; int fat; direntry_t subEntry; /* will it fit? At least one cluster must be free */ if (!getfreeMinClusters(targetEntry->Dir, 1)) return -1; mk_entry(dosname, ATTR_DIR, 1, 0, arg->mtime, &targetEntry->dir); Target = OpenFileByDirentry(targetEntry); if(!Target){ fprintf(stderr,"Could not open Target\n"); return -1; } /* this allocates the first cluster for our directory */ initializeDirentry(&subEntry, Target); subEntry.entry = 1; GET_DATA(targetEntry->Dir, 0, 0, 0, &fat); if (fat == fat32RootCluster(targetEntry->Dir)) { fat = 0; } mk_entry(".. ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir); dir_write(&subEntry); FLUSH((Stream_t *) Target); subEntry.entry = 0; GET_DATA(Target, 0, 0, 0, &fat); mk_entry(". ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir); dir_write(&subEntry); mk_entry(dosname, ATTR_DIR | arg->attr, fat, 0, arg->mtime, &targetEntry->dir); arg->NewDir = Target; return 0; }
static gboolean mk_dir(struct rdup *e, GHashTable * uidhash, GHashTable * gidhash) { struct stat *s; struct stat st; gchar *parent; if (opt_dry) return TRUE; if (lstat(e->f_name, &st) == 0) { if (S_ISDIR(st.st_mode)) { #if 0 msgd(__func__, __LINE__, _("Updating current dir `%s\'"), e->f_name); #endif /* DEBUG */ /* some dir is here - update the perms and ownership */ mk_meta(e, uidhash, gidhash); return TRUE; } } /* nothing there */ if (mkdir(e->f_name, e->f_mode) == -1) { if (errno == EACCES) { /* make parent dir writable, and try again */ parent = dir_parent(e->f_name); #ifdef DEBUG msgd(__func__, __LINE__, _("EACCES for `%s\'"), parent); #endif /* DEBUG */ s = dir_write(parent); if (!s) msgd(__func__, __LINE__, _("Failed to make parent writable")); if (mkdir(e->f_name, e->f_mode) == -1) { msgd(__func__, __LINE__, _("Failed to create directory `%s\': %s"), e->f_name, strerror(errno)); dir_restore(parent, s); g_free(parent); return FALSE; } dir_restore(parent, s); g_free(parent); } else { msgd(__func__, __LINE__, _("Failed to create directory `%s\': %s"), e->f_name, strerror(errno)); return FALSE; } } mk_meta(e, uidhash, gidhash); return TRUE; }
static int attrib_file(direntry_t *entry, MainParam_t *mp) { Arg_t *arg=(Arg_t *) mp->arg; if(entry->entry != -3) { /* if not root directory, change it */ entry->dir.attr = (entry->dir.attr & arg->remove) | arg->add; dir_write(entry); } return GOT_ONE; }
static int flush_file(Stream_t *Stream) { DeclareThis(File_t); direntry_t *entry = &This->direntry; if(isRootDir(Stream)) { return 0; } if(This->FirstAbsCluNr != getStart(entry->Dir, &entry->dir)) { set_word(entry->dir.start, This->FirstAbsCluNr & 0xffff); set_word(entry->dir.startHi, This->FirstAbsCluNr >> 16); dir_write(entry); }
static gboolean mk_link(struct rdup *e, char *p, GHashTable * uidhash, GHashTable * gidhash) { struct stat *st; gchar *t; gchar *parent; if (opt_dry) return TRUE; if (!rm(e->f_name)) return FALSE; /* symlink */ if (S_ISLNK(e->f_mode)) { if (symlink(e->f_target, e->f_name) == -1) { if (errno == EACCES) { parent = dir_parent(e->f_name); st = dir_write(parent); if (symlink(e->f_target, e->f_name) == -1) { msgd(__func__, __LINE__, _ ("Failed to make symlink `%s -> %s\': %s"), e->f_name, e->f_target, strerror(errno)); dir_restore(parent, st); g_free(parent); return FALSE; } dir_restore(parent, st); g_free(parent); } else { msgd(__func__, __LINE__, _ ("Failed to make symlink `%s -> %s\': %s"), e->f_name, e->f_target, strerror(errno)); return FALSE; } } mk_chown(e, uidhash, gidhash); return TRUE; } /* hardlink */ /* target must also fall in backup dir */ t = g_strdup_printf("%s%s", p, e->f_target); e->f_target = t; hlink_list = g_slist_append(hlink_list, entry_dup(e)); return TRUE; }
VOID dir_close(REG f_node_ptr fnp) { /* Test for invalid f_nodes */ if (fnp == NULL || !(fnp->f_flags & F_DDIR)) return; #ifndef IPL /* Write out the entry */ dir_write(fnp); #endif /* Clear buffers after release */ /* hazard: no error checking! */ flush_buffers(fnp->f_dpb->dpb_unit); /* and release this instance of the fnode */ release_f_node(fnp); }
VOID dir_close(REG f_node_ptr fnp) { REG COUNT disk = fnp->f_dpb->dpb_unit; /* Test for invalid f_nodes */ if (fnp == NULL) return; #ifndef IPL /* Write out the entry */ dir_write(fnp); #endif /* Clear buffers after release */ flush_buffers(disk); /* and release this instance of the fnode */ release_f_node(fnp); }
/* Create the remaining hardlinks in the target directory */ gboolean mk_hlink(GSList * h) { struct rdup *e; GSList *p; struct stat *st; gchar *parent; if (opt_dry) return TRUE; for (p = g_slist_nth(h, 0); p; p = p->next) { e = (struct rdup *)p->data; if (link(e->f_target, e->f_name) == -1) { if (errno == EACCES) { parent = dir_parent(e->f_name); st = dir_write(parent); if (link(e->f_target, e->f_name) == -1) { msgd(__func__, __LINE__, _ ("Failed to create hardlink `%s -> %s\': %s"), e->f_name, e->f_target, strerror(errno)); dir_restore(parent, st); g_free(parent); return FALSE; } dir_restore(parent, st); g_free(parent); return TRUE; } else { msgd(__func__, __LINE__, _ ("Failed to create hardlink `%s -> %s\': %s"), e->f_name, e->f_target, strerror(errno)); return FALSE; } } entry_free(e); } return TRUE; }
static gboolean mk_dev(struct rdup *e, GHashTable * uidhash, GHashTable * gidhash) { gchar *parent; struct stat *st; if (opt_dry) return TRUE; if (!rm(e->f_name)) return FALSE; if (mknod(e->f_name, e->f_mode, e->f_rdev) == -1) { if (errno == EACCES) { parent = dir_parent(e->f_name); st = dir_write(parent); if (mknod(e->f_name, e->f_mode, e->f_rdev) == -1) { msgd(__func__, __LINE__, _("Failed to make device `%s\': %s"), e->f_name, strerror(errno)); dir_restore(parent, st); g_free(parent); return FALSE; } dir_restore(parent, st); g_free(parent); } else { msgd(__func__, __LINE__, _("Failed to make device `%s\': %s"), e->f_name, strerror(errno)); return FALSE; } } mk_meta(e, uidhash, gidhash); return TRUE; }
static gboolean mk_reg(FILE * in, struct rdup *e, GHashTable * uidhash, GHashTable * gidhash) { FILE *out = NULL; char *buf; gchar *parent; size_t bytes; gboolean ok = TRUE; gboolean old_dry = opt_dry; struct stat *st; /* with opt_dry we can't just return TRUE; as we may * need to suck in the file's content - which is thrown * away in that case */ if (!e->f_name) { /* fake an opt_dry */ opt_dry = TRUE; } if (!opt_dry) { if (!rm(e->f_name)) { opt_dry = old_dry; return FALSE; } } if (!opt_dry && !(out = fopen(e->f_name, "w"))) { if (errno == EACCES) { parent = dir_parent(e->f_name); st = dir_write(parent); if (!(out = fopen(e->f_name, "w"))) { msgd(__func__, __LINE__, _("Failed to open file `%s\': %s"), e->f_name, strerror(errno)); g_free(parent); ok = FALSE; } dir_restore(parent, st); g_free(parent); } else { msgd(__func__, __LINE__, _("Failed to open file `%s\': %s"), e->f_name, strerror(errno)); ok = FALSE; } } /* we need to read the input to not upset * the flow into rdup-up, but we are not * creating anything when opt_dry is active */ buf = g_malloc(BUFSIZE + 1); while ((bytes = block_in_header(in)) > 0) { if (block_in(in, bytes, buf) == -1) { if (out) fclose(out); opt_dry = old_dry; g_free(buf); return FALSE; } if (ok && !opt_dry) { if (fwrite(buf, sizeof(char), bytes, out) != bytes) { msgd(__func__, __LINE__, _("Write failure `%s\': %s"), e->f_name, strerror(errno)); if (out) fclose(out); opt_dry = old_dry; g_free(buf); return FALSE; } } } g_free(buf); if (ok && out) fclose(out); if (ok && !opt_dry) mk_meta(e, uidhash, gidhash); #ifdef DEBUG msgd(__func__, __LINE__, "Wrote file `%s\'", e->f_name); #endif /* DEBUG */ opt_dry = old_dry; return TRUE; }
static inline clash_action get_slots(Stream_t *Dir, char *dosname, char *longname, struct scan_state *ssp, ClashHandling_t *ch) { int error; clash_action ret; int match=0; direntry_t entry; int isprimary; int no_overwrite; int reason; int pessimisticShortRename; pessimisticShortRename = (ch->action[0] == NAMEMATCH_AUTORENAME); entry.Dir = Dir; no_overwrite = 1; if((is_reserved(longname,1)) || longname[strspn(longname,". ")] == '\0'){ reason = RESERVED; isprimary = 1; } else if(contains_illegals(longname,long_illegals)) { reason = ILLEGALS; isprimary = 1; } else if(is_reserved(dosname,0)) { reason = RESERVED; ch->use_longname = 1; isprimary = 0; } else if(contains_illegals(dosname,short_illegals)) { reason = ILLEGALS; ch->use_longname = 1; isprimary = 0; } else { reason = EXISTS; clear_scan(longname, ch->use_longname, ssp); switch (lookupForInsert(Dir, dosname, longname, ssp, ch->ignore_entry, ch->source_entry, pessimisticShortRename && ch->use_longname)) { case -1: return NAMEMATCH_ERROR; case 0: return NAMEMATCH_SKIP; /* Single-file error error or skip request */ case 5: return NAMEMATCH_GREW; /* Grew directory, try again */ case 6: return NAMEMATCH_SUCCESS; /* Success */ } match = -2; if (ssp->longmatch > -1) { /* Primary Long Name Match */ #ifdef debug fprintf(stderr, "Got longmatch=%d for name %s.\n", longmatch, longname); #endif match = ssp->longmatch; isprimary = 1; } else if ((ch->use_longname & 1) && (ssp->shortmatch != -1)) { /* Secondary Short Name Match */ #ifdef debug fprintf(stderr, "Got secondary short name match for name %s.\n", longname); #endif match = ssp->shortmatch; isprimary = 0; } else if (ssp->shortmatch >= 0) { /* Primary Short Name Match */ #ifdef debug fprintf(stderr, "Got primary short name match for name %s.\n", longname); #endif match = ssp->shortmatch; isprimary = 1; } else return NAMEMATCH_RENAME; if(match > -1) { entry.entry = match; dir_read(&entry, &error); if (error) return NAMEMATCH_ERROR; /* if we can't overwrite, don't propose it */ no_overwrite = (match == ch->source || IS_DIR(&entry)); } } ret = process_namematch(isprimary ? longname : dosname, longname, isprimary, ch, no_overwrite, reason); if (ret == NAMEMATCH_OVERWRITE && match > -1){ if((entry.dir.attr & 0x5) && (ask_confirmation("file is read only, overwrite anyway (y/n) ? ",0,0))) return NAMEMATCH_RENAME; /* Free up the file to be overwritten */ if(fatFreeWithDirentry(&entry)) return NAMEMATCH_ERROR; #if 0 if(isprimary && match - ssp->match_free + 1 >= ssp->size_needed){ /* reuse old entry and old short name for overwrite */ ssp->free_start = match - ssp->size_needed + 1; ssp->free_size = ssp->size_needed; ssp->slot = match; ssp->got_slots = 1; strncpy(dosname, dir.name, 3); strncpy(dosname + 8, dir.ext, 3); return ret; } else #endif { entry.dir.name[0] = DELMARK; dir_write(&entry); return NAMEMATCH_RENAME; } } return ret; }
// TODO: read/write external should use buffer->valid_db_size instead of passing in additional // parameters void *DiskIOThread::run_thread(void *_thr_info){ DiskIOThread *diskio = (DiskIOThread *) _thr_info; int ret = zmq_socket_monitor(diskio->sock, "inproc://monitor.router_sock", ZMQ_EVENT_CONNECTED | ZMQ_EVENT_ACCEPTED | ZMQ_EVENT_DISCONNECTED); if(ret < 0){ diskio->status = -1; return NULL; } zmq::socket_t monitor_sock(*diskio->zmq_ctx, ZMQ_PAIR); try{ monitor_sock.connect("inproc://monitor.router_sock"); }catch(zmq::error_t &e){ std::cout << "monitor socket create failed" << std::endl; return NULL; } zmq::pollitem_t pollitems[3]; pollitems[0].socket = diskio->sock; pollitems[0].events = ZMQ_POLLIN; pollitems[1].socket = monitor_sock; pollitems[1].events = ZMQ_POLLIN; pollitems[2].socket = diskio->cancel_sock; pollitems[2].events = ZMQ_POLLIN; while(true){ try { zmq::poll(pollitems, 3); }catch(...){ std::cout << "error from poll!" << std::endl; return NULL; } if(pollitems[2].revents){ int32_t cid; boost::shared_array<uint8_t> data; int32_t len = recv_msg(diskio->cancel_sock, cid, data); if(len < 0){ diskio->status = -1; return NULL; } EMsgType type = *((EMsgType *) data.get()); int32_t extern_cid, sock_idx; switch(type){ case DiskIOCancel: extern_cid = zmq_rid_to_cid(cid); sock_idx = cid_to_sock_idx(extern_cid); diskio->client_valid[sock_idx] = false; break; case DiskIOEnable: extern_cid = zmq_rid_to_cid(cid); sock_idx = cid_to_sock_idx(extern_cid); diskio->client_valid[sock_idx] = true; break; default: assert(0); diskio->status = -1; return NULL; } continue; } if(pollitems[0].revents){ int32_t cid; boost::shared_array<uint8_t> data; int32_t len = recv_msg(diskio->sock, cid, data); if(len < 0){ assert(0); diskio->status = -1; return NULL; } //std::cout << "received from cid = " << std::hex << cid << std::dec << std::endl; EMsgType type = *((EMsgType *) data.get()); Buffer *buf; std::string base; // for DiskIOExternal, base is actually fullpath int32_t extern_cid; int32_t sock_idx; if(type == DiskIORead || type == DiskIOWrite || type == DiskIOReadExternal || type == DiskIOWriteExternal || type == DiskIOWriteRead){ len = recv_msg(diskio->sock, data); if(len < 0){ assert(0); diskio->status = -1; return NULL; } buf = *((Buffer **) data.get()); len = recv_msg(diskio->sock, data); if(len < 0){ assert(0); diskio->status = -1; return NULL; } base = std::string((char *) data.get()); } //std::cout << "request type = " << type << std::endl; block_id_t bid; int32_t extern_size; int32_t dbsize; int64_t offset; int32_t fidx; int32_t suc; std::string fname; int32_t rsize; int32_t wsuc; int32_t rd_db_id; EMsgType re_type; switch(type){ case DiskIORead: bid = buf->get_block_id(); dbsize = buf->get_db_size(); fidx = get_file_idx(bid, dbsize, offset); fname = build_filename(diskio->datapath, base, fidx); extern_cid = zmq_rid_to_cid(cid); sock_idx = cid_to_sock_idx(extern_cid); if(!diskio->client_valid[sock_idx]){ rsize = 0; re_type = DiskIOReadNotDone; }else{ // read data from specified file, with rsize = dir_read(buf->get_db_ptr(), dbsize, fname.c_str(), offset); re_type = DiskIOReadDone; } // finished reading send back message suc = send_msg(diskio->sock, cid, (uint8_t *) &re_type, sizeof(Buffer *), ZMQ_SNDMORE); if(suc < 0){ assert(0); diskio->status = -1; return NULL; } send_msg(diskio->sock, (uint8_t *) &buf, sizeof(Buffer *), ZMQ_SNDMORE); if(suc < 0){ assert(0); diskio->status = -1; return NULL; } suc = send_msg(diskio->sock, (uint8_t *) &rsize, sizeof(int32_t), 0); if(suc < 0){ assert(0); diskio->status = -1; return NULL; } break; case DiskIOWrite: bid = buf->get_block_id(); dbsize = buf->get_db_size(); fidx = get_file_idx(bid, dbsize, offset); fname = build_filename(diskio->datapath, base, fidx); // read data from specified file, with wsuc = dir_write(buf->get_db_ptr(), dbsize, fname.c_str(), offset); re_type = DiskIOWriteDone; // finished reading send back message suc = send_msg(diskio->sock, cid, (uint8_t *) &re_type, sizeof(Buffer *), ZMQ_SNDMORE); if(suc < 0){ assert(0); diskio->status = -1; return NULL; } send_msg(diskio->sock, (uint8_t *) &buf, sizeof(Buffer *), ZMQ_SNDMORE); if(suc < 0){ assert(0); diskio->status = -1; return NULL; } suc = send_msg(diskio->sock, (uint8_t *) &wsuc, sizeof(int32_t), 0); if(suc < 0){ assert(0); diskio->status = -1; return NULL; } break; case DiskIOWriteRead: len = recv_msg(diskio->sock, data); if(len < 0){ assert(0); diskio->status = -1; return NULL; } rd_db_id = *((int32_t *) data.get()); bid = buf->get_block_id(); dbsize = buf->get_db_size(); fidx = get_file_idx(bid, dbsize, offset); fname = build_filename(diskio->datapath, base, fidx); // write data to wsuc = dir_write(buf->get_db_ptr(), dbsize, fname.c_str(), offset); int32_t resp_val; extern_cid = zmq_rid_to_cid(cid); sock_idx = cid_to_sock_idx(extern_cid); if(!diskio->client_valid[sock_idx]){ resp_val = 0; re_type = DiskIOWriteReadWriteDone; }else{ if(wsuc == 0){ fidx = get_file_idx(rd_db_id, dbsize, offset); fname = build_filename(diskio->datapath, base, fidx); rsize = dir_read(buf->get_db_ptr(), dbsize, fname.c_str(), offset); } if(wsuc < 0 || rsize < 0){ resp_val = -1; }else{ resp_val = rsize; } re_type = DiskIOWriteReadDone; } // finished reading send back message suc = send_msg(diskio->sock, cid, (uint8_t *) &re_type, sizeof(Buffer *), ZMQ_SNDMORE); if(suc < 0){ assert(0); diskio->status = -1; return NULL; } send_msg(diskio->sock, (uint8_t *) &buf, sizeof(Buffer *), ZMQ_SNDMORE); if(suc < 0){ diskio->status = -1; return NULL; } suc = send_msg(diskio->sock, (uint8_t *) &resp_val, sizeof(int32_t), 0); if(suc < 0){ diskio->status = -1; return NULL; } break; case DiskIOReadExternal: len = recv_msg(diskio->sock, data); if(len < 0){ assert(0); diskio->status = -1; return NULL; } offset = *((int64_t *) data.get()); len = recv_msg(diskio->sock, data); if(len < 0){ assert(0); diskio->status = -1; return NULL; } extern_size = *((int32_t *) data.get()); //std::cout << "size to read = " << extern_size << std::endl; extern_cid = zmq_rid_to_cid(cid); sock_idx = cid_to_sock_idx(extern_cid); if(!diskio->client_valid[sock_idx]){ rsize = 0; re_type = DiskIOReadExternalNotDone; }else{ //std::cout << "received request to read external data" << std::endl; dbsize = buf->get_db_size(); if(extern_size > dbsize){ assert(0); diskio->status = -1; return NULL; } fname = std::string(base); // read data from specified file, with rsize = dir_read(buf->get_db_ptr(), extern_size, fname.c_str(), offset); re_type = DiskIOReadExternalDone; } buf->set_valid_db_size(rsize); // finished reading send back message suc = send_msg(diskio->sock, cid, (uint8_t *) &re_type, sizeof(EMsgType), ZMQ_SNDMORE); if(suc < 0){ assert(0); diskio->status = -1; return NULL; } send_msg(diskio->sock, (uint8_t *) &buf, sizeof(Buffer *), ZMQ_SNDMORE); if(suc < 0){ assert(0); diskio->status = -1; return NULL; } suc = send_msg(diskio->sock, (uint8_t *) &rsize, sizeof(int32_t), 0); if(suc < 0){ assert(0); diskio->status = -1; return NULL; } break; case DiskIOWriteExternal: len = recv_msg(diskio->sock, data); if(len < 0){ assert(0); diskio->status = -1; return NULL; } offset = *((int64_t *) data.get()); len = recv_msg(diskio->sock, data); if(len < 0){ assert(0); diskio->status = -1; return NULL; } // if has been canceled, don't send response extern_cid = zmq_rid_to_cid(cid); sock_idx = cid_to_sock_idx(extern_cid); if(diskio->client_sock[sock_idx] == NULL) continue; extern_size = *((int32_t *) data.get()); dbsize = buf->get_db_size(); //std::cout << "extern_size = " << extern_size << " dbsize = " << dbsize << std::endl; assert(extern_size <= dbsize); fname = std::string(base); // read data from specified file, with rsize = reg_write(buf->get_db_ptr(), extern_size, fname.c_str(), offset); re_type = DiskIOWriteExternalDone; // finished reading send back message suc = send_msg(diskio->sock, cid, (uint8_t *) &re_type, sizeof(Buffer *), ZMQ_SNDMORE); if(suc < 0){ assert(0); diskio->status = -1; return NULL; } send_msg(diskio->sock, (uint8_t *) &buf, sizeof(Buffer *), ZMQ_SNDMORE); if(suc < 0){ assert(0); diskio->status = -1; return NULL; } suc = send_msg(diskio->sock, (uint8_t *) &rsize, sizeof(int32_t), 0); if(suc < 0){ assert(0); diskio->status = -1; return NULL; } break; case DiskIOShutDown: std::cout << "diskio thread received shutdown message" << std::endl; return NULL; break; case DiskIOConn: break; default: std::cout << "!!!!!!!!!diskio thread msgtype = " << type << std::endl; assert(0); diskio->status = -1; return NULL; } continue; } if(pollitems[1].revents){ zmq_event_t *event; boost::shared_array<uint8_t> data; int len; len = recv_msg(monitor_sock, data); if (len < 0){ assert(0); diskio->status = -11; return NULL; } assert(len == sizeof(zmq_event_t)); event = (zmq_event_t *) data.get(); switch (event->event){ case ZMQ_EVENT_CONNECTED: std::cout << "established connection." << std::endl; break; case ZMQ_EVENT_ACCEPTED: std::cout << "connection accepted" << std::endl; break; case ZMQ_EVENT_DISCONNECTED: std::cout << "client disconnected" << std::endl; break; default: std::cout << "unexpected event" << std::endl; return NULL; } continue; } } return NULL; }
gboolean rm(gchar *p) { int ret; gchar *dirp, *q; gchar *parent; GDir *d; struct stat st; struct stat *st2; if (opt_dry || !p) return TRUE; /* noop */ if (lstat(p, &st) == -1) { if (opt_verbose > 0 && errno != ENOENT) msgd(__func__, __LINE__,_("Failed to remove `%s\': %s"), p, strerror(errno)); return TRUE; /* noop */ } if (S_ISDIR(st.st_mode)) { ret = remove(p); if (ret == -1) { switch(errno) { case ENOTEMPTY: /* recursive into this dir and do our bidding */ if (!(d = g_dir_open(p, 0, NULL))) { msgd(__func__, __LINE__,_("Failed to open directory `%s\': %s"), p, strerror(errno)); return FALSE; } while ( (dirp = (gchar*)g_dir_read_name(d))) { dirp = g_strdup_printf("%s/%s", p, dirp); rm(dirp); g_free(dirp); } g_dir_close(d); /* dir should be empty by now */ if ((ret = remove(p)) == -1) msgd(__func__, __LINE__,_("Failed to remove directory `%s\': %s"), p, strerror(errno)); return TRUE; case EACCES: /* no write to dir, make writable */ parent = dir_parent(p); st2 = dir_write(parent); if (remove(p) == -1) { msgd(__func__, __LINE__,_("Failed to remove `%s\': %s"), p, strerror(errno)); dir_restore(parent, st2); g_free(parent); return FALSE; } dir_restore(parent, st2); g_free(parent); return TRUE; default: /* not ENOEMPTY */ msgd(__func__, __LINE__,_("Failed to remove directory `%s\': %s"), p, strerror(errno)); return FALSE; } } return TRUE; } /* dirs are now handled */ if (remove(p) == -1) { switch(errno) { case EACCES: /* we have no access, ok ... */ q = g_strdup(p); parent = dirname(q); st2 = dir_write(parent); if (remove(p) == -1) { msgd(__func__, __LINE__,_("Failed to remove `%s\': %s"), p, strerror(errno)); dir_restore(parent, st2); g_free(q); return FALSE; } dir_restore(parent, st2); g_free(q); return TRUE; case EPERM: /* no write on file, reuse st - and why is this needed again? */ /* this is dead code ... */ stat(p, &st); chmod(p, st.st_mode | S_IWUSR); if (remove(p) == -1) { msgd(__func__, __LINE__,_("Failed to remove `%s\': %s"), p, strerror(errno)); chmod(p, st.st_mode); /* is this usefull then? */ return FALSE; } return TRUE; } msgd(__func__, __LINE__,_("Failed to remove `%s\': %s"), p, strerror(errno)); return FALSE; } return TRUE; }